Et toujours du dev pour la béta

* Evolution de l'histoire avec de nouveaux dialogues, une plus grande durée de vie du jeu, des nouvelles zones d'histoire...
* Suppression du mode infini
* Ajout d'un écran des mutations découvertes
* Ajout d'un nouveau mécanisme de respawn situé dans le vaissau
* Ajout de 2 nouveaux modificateurs de région
* Quatre nouveaux artefacts
* Visuel de la décontamination de la planète 3D en cours de la partie
* Ajout d'une annonce visuelle des scène du jeu
* Fix sur la mutation Généreux pour être en accord avec sa description
* Amélioration de l'effet de la mutation Purification
* Fix de la mutation sociale aux niveau supérieurs
* Ajout d'un effet visuel de réacteur sur le joueur 3D
* Fix sur l'annonce de nouveaux objets qui se déclenchaient à une nouvelle run
* Amélioration des animation et des informations données dans le vaisseau
* Correction mineure des traductions
This commit is contained in:
2026-04-28 23:41:36 +02:00
parent 7ae362a3a5
commit 91e266ec85
269 changed files with 4393 additions and 1699 deletions

View File

@@ -1,7 +1,6 @@
[gd_scene format=3 uid="uid://tsi5j1uxppa4"]
[ext_resource type="Script" uid="uid://d1mp5sguc0b6u" path="res://stages/terrain/region/scripts/region.gd" id="1_441sk"]
[ext_resource type="PackedScene" uid="uid://dt6mptqg80dew" path="res://gui/game/tutorial/tutorial.tscn" id="2_2f6js"]
[ext_resource type="Shader" uid="uid://cfj18vc04cgkg" path="res://common/vfx/materials/shaders/blur_vignette.gdshader" id="2_ktnx3"]
[ext_resource type="PackedScene" uid="uid://yk78ubpu5ghq" path="res://gui/game/pass_day/pass_day.tscn" id="3_ktnx3"]
[ext_resource type="Shader" uid="uid://btgk5l0a6ii44" path="res://common/vfx/materials/shaders/screen_fog.gdshader" id="3_qdnee"]
@@ -9,14 +8,9 @@
[ext_resource type="PackedScene" uid="uid://12nak7amd1uq" path="res://gui/game/game_gui.tscn" id="4_qdnee"]
[ext_resource type="PackedScene" uid="uid://bgvbgeq46wee2" path="res://entities/player/player.tscn" id="5_ovqi1"]
[ext_resource type="PackedScene" uid="uid://d324mlmgls4fs" path="res://entities/interactables/truck/recharge/truck_recharge.tscn" id="7_6d8m3"]
[ext_resource type="PackedScene" uid="uid://b8m537op75gib" path="res://entities/interactables/door/door.tscn" id="8_2f6js"]
[ext_resource type="PackedScene" uid="uid://dj7gp3crtg2yt" path="res://entities/camera/camera.tscn" id="8_fwgig"]
[ext_resource type="PackedScene" uid="uid://fnv0qhkh40mv" path="res://gui/game/announce/announce.tscn" id="8_mlppq"]
[ext_resource type="Texture2D" uid="uid://rdrhi3r11ey6" path="res://common/icons/square-rounded.svg" id="10_ktnx3"]
[ext_resource type="Texture2D" uid="uid://b752eqq4cm7ve" path="res://common/icons/building-factory-2.svg" id="11_fwgig"]
[ext_resource type="Texture2D" uid="uid://dg00xnpp6ixls" path="res://common/icons/server-2.svg" id="12_mlppq"]
[ext_resource type="Texture2D" uid="uid://1ynlp05wj0hm" path="res://common/icons/rocket.svg" id="13_r4e5h"]
[ext_resource type="Texture2D" uid="uid://bmersnaoira20" path="res://common/icons/building-store.svg" id="16_0e2h6"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_qdnee"]
shader = ExtResource("2_ktnx3")
@@ -117,17 +111,10 @@ camera = NodePath("../../Camera")
[node name="PassDay" parent="." unique_id=1144772570 instance=ExtResource("3_ktnx3")]
unique_name_in_owner = true
visible = false
[node name="RegionGui" type="CanvasLayer" parent="." unique_id=2024485651]
layer = 2
[node name="Tutorial" parent="RegionGui" unique_id=762436685 node_paths=PackedStringArray("player", "region", "game_gui") instance=ExtResource("2_2f6js")]
unique_name_in_owner = true
player = NodePath("../../Entities/Player")
region = NodePath("../..")
game_gui = NodePath("../../GameGui")
[node name="GameGui" parent="." unique_id=1970837239 instance=ExtResource("4_qdnee")]
[node name="Announce" parent="." unique_id=1659074958 instance=ExtResource("8_mlppq")]
@@ -142,49 +129,6 @@ y_sort_enabled = true
unique_name_in_owner = true
position = Vector2(-405, -151)
[node name="AstraDoor" parent="Entities" unique_id=2053096538 instance=ExtResource("8_2f6js")]
unique_name_in_owner = true
visible = false
icon = ExtResource("11_fwgig")
present = null
default_info_title = "ASTRA_FACTORY"
default_info_desc = "ASTRA_FACTORY_TEXT"
[node name="BoreaDoor" parent="Entities" unique_id=135926916 instance=ExtResource("8_2f6js")]
unique_name_in_owner = true
visible = false
position = Vector2(91, -177)
to_scene_id = "BOREA"
icon = ExtResource("12_mlppq")
present = null
default_interact_text = "ENTER"
available = true
default_info_title = "BOREA_BASE"
default_info_desc = "BOREA_BASE_DESC_TEXT"
[node name="ShipGarageDoor" parent="Entities" unique_id=1073871193 instance=ExtResource("8_2f6js")]
unique_name_in_owner = true
visible = false
position = Vector2(91, -177)
to_scene_id = "GARAGE"
icon = ExtResource("13_r4e5h")
present = null
default_interact_text = "ENTER"
default_info_title = "MYSTERIOUS_DOOR"
default_info_desc = "MYSTERIOUS_DOOR_TEXT"
[node name="VendingMachineDoor" parent="Entities" unique_id=580707365 instance=ExtResource("8_2f6js")]
unique_name_in_owner = true
visible = false
position = Vector2(91, -177)
to_scene_id = "VENDING_MACHINE_DOOR"
icon = ExtResource("16_0e2h6")
present = null
default_interact_text = "ENTER"
available = true
default_info_title = "VENDING_MACHINES"
default_info_desc = "MYSTERIOUS_DOOR_TEXT"
[node name="Camera" parent="." unique_id=1399042986 node_paths=PackedStringArray("following") instance=ExtResource("8_fwgig")]
following = NodePath("../Entities/Player")

View File

@@ -0,0 +1,36 @@
extends RegionModifier
class_name DestinationModifier
@export var destination_scene : Scene
func get_modifier_name() -> String:
return tr("DESTINATION")
func get_description() -> String:
return tr("INTERNODE_PROGRAMMED_DESTINATION")
func get_icon() -> Texture:
return preload("res://common/icons/map-pin.svg")
func get_card_section_color() -> Color:
return Color("25c147")
func disable_objective() -> bool:
return true
func modify_region_name(_name : String) -> String:
return destination_scene.get_scene_title()
func region_ready(region : Region) -> void:
var door = generate_door(
destination_scene.get_scene_title(),
"",
destination_scene
)
door.available = true
region.add_entity(door)
region.random_move_object(door,Region.DOORS_RANDOM_MOVEMENT)
region.recharge_station.available = false
region.recharge_station.visible = false

View File

@@ -0,0 +1 @@
uid://dcdleyf4tgj27

View File

@@ -0,0 +1,17 @@
extends RegionModifier
class_name InstableModifier
func get_modifier_name() -> String:
return tr("INSTABLE")
func get_description() -> String:
return tr("INSTABLE_MODIFIER_DESC_TEXT")
func get_icon() -> Texture:
return preload("res://common/icons/atom.svg")
func get_card_section_color() -> Color:
return Color("25c147")
func modify_mutation_probability(plant_mutation_probability) -> float:
return plant_mutation_probability * 1.5

View File

@@ -0,0 +1 @@
uid://benwcbtijith7

View File

@@ -7,16 +7,13 @@ const DEFAULT_ICON = preload("res://common/icons/cloud.svg")
const DOOR_SCENE = preload("res://entities/interactables/door/door.tscn")
var level : int = 1
var modifier_name : String : get = get_modifier_name
var description : String : get = get_description
var flags : Array[String] : get = get_flags
@export var modifier_seed : int = 0
func _init(_level : int = 1):
func _init():
if modifier_seed == 0:
modifier_seed = randi()
level = _level
@abstract func get_modifier_name() -> String
@@ -28,14 +25,11 @@ func get_icon() -> Texture:
func get_card_section_color() -> Color:
return DEFAULT_MODIFIER_COLOR
func get_difficulty_score() -> float:
return float(level)
func get_flags() -> Array[String]:
return []
func region_ready(_region : Region) -> void:
pass
pass
func modify_region_name(name : String) -> String:
return name
func modify_charge(charge : int) -> int:
return charge
@@ -76,6 +70,15 @@ func modify_plant_seed_random_loose(plant_seed_random_loose : int) -> int:
func modify_plant_influence_radius(plant_influence_radius : float) -> float:
return plant_influence_radius
func modify_mutation_probability(plant_mutation_probability) -> float:
return plant_mutation_probability
func modify_mutation_max_number(plant_mutation_max_number) -> int:
return plant_mutation_max_number
func disable_objective() -> bool:
return false
func card_section() -> CardSectionInfo:
var section := CardSectionInfo.new(
get_modifier_name(),
@@ -90,15 +93,14 @@ func card_section() -> CardSectionInfo:
func generate_door(
title : String,
desc : String,
scene_id : String,
icon : Texture
to_scene : Scene = null,
) -> Door:
var new_door = DOOR_SCENE.instantiate() as Door
new_door.name = "Door%d" % modifier_seed
new_door.to_scene_id = scene_id
new_door.door_id = modifier_seed
new_door.to_scene = to_scene
new_door.default_info_title = title
new_door.default_info_desc = desc
new_door.icon = icon
new_door.present = true
return new_door

View File

@@ -14,6 +14,7 @@ func get_card_section_color() -> Color:
return Color("25c147")
func modify_seed_rarity_pool(seed_rarity_pool : Array[int]) -> Array[int]:
for i in range(len(seed_rarity_pool)):
seed_rarity_pool[i] += 1
return seed_rarity_pool
var rarity = seed_rarity_pool.duplicate_deep()
for i in range(len(rarity)):
rarity[i] += 1
return rarity

View File

@@ -0,0 +1,14 @@
extends RegionModifier
class_name StormModifier
func get_modifier_name() -> String:
return tr("STORM")
func get_description() -> String:
return tr("STORM_MODIFIER_DESC_TEXT")
func get_icon() -> Texture:
return preload("res://common/icons/tornado.svg")
func modify_objective(objective : int) -> int:
return roundi(objective * 2)

View File

@@ -0,0 +1 @@
uid://cf4ljloq40v0p

View File

@@ -0,0 +1,66 @@
extends RegionModifier
class_name TutorialModifier
const TUTORIAL_SCENE_PATH = ("res://gui/game/tutorial/tutorial.tscn")
func get_modifier_name() -> String:
return tr("TUTORIAL")
func get_description() -> String:
return tr("")
func get_icon() -> Texture:
return preload("res://common/icons/help-hexagon.svg")
func modify_charge(charge : int) -> int:
return charge+10
func get_card_section_color() -> Color:
return Color("25c147")
func modify_region_name(_name : String) -> String:
return "ASTRA_BASE"
func region_ready(region : Region) -> void:
generate_astra_door(region)
var garage_door := generate_garage_door(region)
var tutorial := generate_tutorial(region)
tutorial.succeded.connect(
func ():
garage_door.available = true
)
func generate_astra_door(region : Region) -> Door:
var astra_door = generate_door(
tr("ASTRA_FACTORY"),
tr("ASTRA_FACTORY_TEXT"),
AstraScene.new()
)
astra_door.available = false
astra_door.name = "AstraDoor"
region.add_entity(astra_door)
astra_door.global_position = region.data.player_spawn + Vector2.UP * 100
return astra_door
func generate_garage_door(region : Region) -> Door:
var garage_door = generate_door(
tr("MYSTERIOUS_DOOR"),
tr("MYSTERIOUS_DOOR_TEXT"),
GarageScene.new()
)
garage_door.available = region.data.state == RegionData.State.SUCCEEDED
garage_door.name = "GarageDoor"
region.add_entity(garage_door)
region.random_move_object(garage_door,Region.SPAWN_OBJECT_RANDOM_MOVEMENT + 100)
return garage_door
func generate_tutorial(region : Region) -> Tutorial:
var tutorial := load(TUTORIAL_SCENE_PATH).instantiate() as Tutorial
region.add_child(tutorial)
tutorial.region = region
tutorial.game_gui = region.find_child("GameGui")
tutorial.player = region.entity_container.find_child("Player")
return tutorial

View File

@@ -0,0 +1 @@
uid://dbqf4v74j1le

View File

@@ -18,14 +18,10 @@ func get_card_section_color() -> Color:
func region_ready(region) -> void:
var new_vending_machine_door = generate_door(
tr("VENDING_MACHINES"),
tr("VENDING_MACHINES_DOOR_DESC_TEXT"),
"VENDING_MACHINE_ROOM",
VENDING_MACHINES_ICON
tr("VENDING_MACHINES_DOOR_DESC_TEXT")
)
new_vending_machine_door.available = region.data.completed_doors.find(new_vending_machine_door.name) == -1
new_vending_machine_door.to_scene = VendingMachineScene.new(new_vending_machine_door.door_id)
new_vending_machine_door.available = region.data.completed_doors.find(new_vending_machine_door.door_id) == -1
region.add_entity(new_vending_machine_door)
region.random_move_object(new_vending_machine_door,Region.DOORS_RANDOM_MOVEMENT)
func get_difficulty_score() -> float:
return 0

View File

@@ -34,6 +34,8 @@ var score_by_plant : Dictionary[PlantData, int] = {}
var generated_chunks : Array[Chunk] = []
var generation_semaphore : Semaphore
@onready var recharge_station : TruckRecharge = %RechargeStation
# Cheat Code
func _input(_e):
if (
@@ -42,7 +44,6 @@ func _input(_e):
and Input.is_action_pressed("move_left")
and Input.is_action_just_pressed("action")
):
%Tutorial.finish_tutorial()
data.succeded.emit()
data.state = RegionData.State.SUCCEEDED
data.update()
@@ -70,20 +71,17 @@ func _ready():
if e is Plant:
data.add_plant_data(e.data, false)
%AstraDoor.global_position = data.player_spawn + Vector2.UP * 100
player.global_position = data.player_position
setup_flagged_properties()
generate_near_chunks(player)
random_move_object(%RechargeStation, SPAWN_OBJECT_RANDOM_MOVEMENT)
%RechargeStation.update()
random_move_object(recharge_station, SPAWN_OBJECT_RANDOM_MOVEMENT)
recharge_station.update()
for m in data.modifiers:
m.region_ready(self)
if not "tutorial" in data.flags:
if not GameInfo.game_data.current_run.story_step is TutorialStoryStep:
GameInfo.game_data.player_data.inventory.add_item(Detector.new())
GameInfo.game_data.player_data.inventory.add_item(Pickaxe.new())
GameInfo.game_data.player_data.inventory.add_item(Fork.new())
@@ -171,36 +169,21 @@ func random_move_object(
rng.randf_range(-random_movement,random_movement)
) + offset
dig_hole(object.position, 3)
func setup_flagged_properties():
for i in range(len(data.flags)):
var f = data.flags[i]
match f:
"tutorial":
%AstraDoor.present = true
%ShipGarageDoor.present = true
random_move_object(%ShipGarageDoor,SPAWN_OBJECT_RANDOM_MOVEMENT)
%AstraDoor.available = false
%ShipGarageDoor.available = data.state == RegionData.State.SUCCEEDED
%Tutorial.succeded.connect(
func ():
await get_tree().create_timer(1.).timeout
%ShipGarageDoor.available = true
)
"borea":
%BoreaDoor.present = true
random_move_object(%BoreaDoor,SPAWN_OBJECT_RANDOM_MOVEMENT)
%RechargeStation.visible = false
%RechargeStation.process_mode = Node.PROCESS_MODE_DISABLED
dig_hole(object.position, 5)
func is_chunk_generated(coord : Vector2i):
return generated_chunks.find_custom(
func (c: Chunk) : return get_chunk_key(c.chunk_coord) == get_chunk_key(coord)
) != -1
func finish_generation():
var fall_anim = (
not GameInfo.game_data.current_run.story_step is TutorialStoryStep
and data.entered_door == ""
)
player.appear(fall_anim)
data.entered_door = ""
#endregion
#region ------------------ Usage ------------------
@@ -213,6 +196,11 @@ func plant(
data.add_plant_data(new_plant_data)
var new_plant = Plant.new(new_plant_data)
add_entity(new_plant, plant_position)
for m in new_plant_data.mutations:
if not m.get_mutation_id() in GameInfo.game_data.progression_data.planted_mutation_ids:
GameInfo.game_data.progression_data.planted_mutation_ids.append(m.get_mutation_id())
return true
func pass_day():
@@ -302,4 +290,7 @@ func decontaminate(tiles_coords : Array[Vector2i], save_tiles_diff := true):
chunk.decontamination_layer.place_decontamination(local_coord)
func finishing_region_animation():
pass #TODO
#endregion

View File

@@ -19,7 +19,6 @@ const PLAYER_ROCK_HOLE_RADIUS = 5
@export var region_seed : int
@export var region_name : String
@export var region_level : int = 0
@export var rock_threshold : float
@export var decontamination_threshold : float
@@ -29,7 +28,6 @@ const PLAYER_ROCK_HOLE_RADIUS = 5
@export var day : int = 1
@export var entities_saved_data : Array[EntityData] = []
@export var flags : Array[String] = []
@export var plants : Array[PlantData]
@export var state : State = State.IN_PROGRESS
@@ -39,7 +37,7 @@ const PLAYER_ROCK_HOLE_RADIUS = 5
@export var player_spawn : Vector2
@export var entered_door = ""
@export var completed_doors : Array[String] = [] # List of completed doors
@export var completed_doors : Array[int] = [] # List of completed doors
@export var modifiers : Array[RegionModifier]
@@ -53,6 +51,7 @@ const PLAYER_ROCK_HOLE_RADIUS = 5
objective = v
if GameInfo:
update()
@export var objective_disabled : bool
@export var rock_tiles_data : TilesDiffData
@export var decontamination_tiles_data : TilesDiffData
@@ -65,33 +64,35 @@ func _init(
charges = parameter.get_charge()
objective = parameter.get_objective()
region_name = parameter.get_region_name()
region_level = parameter.get_region_level()
region_seed = parameter.get_region_seed()
rock_threshold = parameter.get_rock_threshold()
decontamination_threshold = parameter.get_decontamination_threshold()
cristal_threshold = parameter.get_cristal_threshold()
start_decontamination_hole_radius = parameter.get_start_decontamination_zone_radius()
flags = parameter.get_region_flags()
seed_rarity_pool = parameter.get_seed_rarity_pool()
modifiers = parameter.modifiers
player_spawn = get_random_spawn_position()
player_position = player_spawn
objective_disabled = parameter.is_objective_disabled()
rock_tiles_data = TilesDiffData.new()
decontamination_tiles_data = TilesDiffData.new()
edit_map_origin()
func update():
if objective > 0 and get_score() >= objective and not "tutorial" in flags:
if state != State.SUCCEEDED:
succeded.emit()
state = State.SUCCEEDED
if state != State.SUCCEEDED and charges == 0:
if state != State.FAILED:
failed.emit()
state = State.FAILED
updated.emit(self)
if not in_passing_day_animation and not objective_disabled:
if objective > 0 and get_score() >= objective and not GameInfo.game_data.current_run.story_step is TutorialStoryStep:
if state != State.SUCCEEDED:
succeded.emit()
state = State.SUCCEEDED
if state != State.SUCCEEDED and charges == 0:
if state != State.FAILED:
failed.emit()
state = State.FAILED
updated.emit(self)
#endregion
@@ -122,6 +123,7 @@ func proceed_pass_day():
func end_pass_day():
pass_day_ended.emit(self)
in_passing_day_animation = false
update()
#endregion

View File

@@ -9,67 +9,49 @@ const DEFAULT_START_DECONTAMINATION_ZONE_RADIUS = 3
const DEFAULT_SEED_RARITY_POOL: Array[int] = [0,0,0,0,0,0,0,1,1,1]
@export var region_name : String
@export var region_flags : Array[String]
@export var level : int
@export var objective : int
@export var region_seed : int
@export var modifiers : Array[RegionModifier]
static func get_objective_by_level(l : int) -> int:
if GameInfo and GameInfo.game_data.game_mode == GameData.GameMode.STORY:
match l:
0: return 5
1: return 8
2: return 10
3: return 15
4: return 20
5: return 30
_: return get_objective_by_level(l-1) + (l-3) * 5
else :
match l:
0: return 8
1: return 15
_: return get_objective_by_level(l-1) + l * 5
func _init(
_level = 0,
_name = Random.generate_random_word(),
_flags : Array[String] = [],
_modifiers : Array[RegionModifier] = [],
_region_seed = randi(),
):
region_name = _name
region_flags = _flags
level = _level
modifiers = _modifiers
region_seed = _region_seed
func get_region_name() -> String:
return region_name
func get_region_flags() -> Array[String]:
var f := region_flags
var n := region_name
for m in modifiers:
f.append_array(m.get_flags())
n = m.modify_region_name(n)
return f
func get_region_level() -> int:
return level
return n
func get_region_seed() -> int:
return region_seed
func get_objective() -> int:
if "tutorial" in region_flags:
return 1
var o = get_objective_by_level(get_region_level())
var o = objective
for m in modifiers:
o = m.modify_objective(o)
return o
func is_objective_disabled() -> bool:
var d = false
for m in modifiers:
print(m.modifier_name)
print(m.disable_objective())
if m.disable_objective():
d = true
return d
func get_charge() -> int:
var c = DEFAULT_CHARGE
@@ -110,10 +92,10 @@ func get_start_decontamination_zone_radius() -> int:
return zone_radius
func get_seed_rarity_pool() -> int:
func get_seed_rarity_pool() -> Array[int]:
var seed_rarity_pool = DEFAULT_SEED_RARITY_POOL
for m in modifiers:
seed_rarity_pool = m.modify_seed_rarity_pool(seed_rarity_pool)
return seed_rarity_pool
return seed_rarity_pool

View File

@@ -11,7 +11,7 @@ func setup():
func place_decontamination(coord : Vector2i, save = false):
place_decontaminations([coord], save)
func place_decontaminations(coords : Array[Vector2i], save := false):
func place_decontaminations(coords : Array[Vector2i], _save := false):
place_terrain_cells(
coords,
DECONTAMINATION_TILE_TERRAIN_SET,

View File

@@ -19,7 +19,7 @@ func place_rocks(coords : Array[Vector2i], type := TileType.ROCK):
ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN,
)
func remove_rocks(coords : Array[Vector2i], save = false):
func remove_rocks(coords : Array[Vector2i], _save = false):
place_terrain_cells(
coords,
ROCK_TILE_TERRAIN_SET,