diff --git a/Translation/localization.csv b/Translation/localization.csv
index f30f2fa..8c80704 100644
--- a/Translation/localization.csv
+++ b/Translation/localization.csv
@@ -95,6 +95,8 @@ SHOVEL,Shovel,Pelle
SHOVEL_DESC_TEXT,"Use it to [b]dig up seeds[/b] and [b]harvest mature plants[/b].","Utilise-la pour [b]déterrer les graines[/b] et pour [b]récolter les plantes mature[/b]."
TROWEL,Trowel,Truelle
TROWEL_DESC_TEXT,"Use it to [b]harvest mature plants[/b]. Can grant a [b]bonus seed[/b].","Utilise-la pour [b]récolter les plantes mature[/b]. Peut donner une [b]graine supplémentaire[/b]."
+PICKAXE,Pickaxe,Pioche
+PICKAXE_DESC_TEXT,Can dig rock and precious materials,Peut creuser la roche et des matériaux précieux
DIG,Dig,Creuser
OPEN,Open,Ouvrir
%s_SEED,%s Seed,Graine de %s
diff --git a/common/icons/pick.svg b/common/icons/pick.svg
new file mode 100644
index 0000000..dbc7d4d
--- /dev/null
+++ b/common/icons/pick.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/entities/underground_loot/assets/sprites/underground_loot.svg.import b/common/icons/pick.svg.import
similarity index 59%
rename from entities/underground_loot/assets/sprites/underground_loot.svg.import
rename to common/icons/pick.svg.import
index 068af1b..f221293 100644
--- a/entities/underground_loot/assets/sprites/underground_loot.svg.import
+++ b/common/icons/pick.svg.import
@@ -2,22 +2,24 @@
importer="texture"
type="CompressedTexture2D"
-uid="uid://bu26h0iqutnky"
-path="res://.godot/imported/underground_loot.svg-94513f7cc11df7cda1992e530bcff786.ctex"
+uid="uid://ds4m14vl7he6v"
+path="res://.godot/imported/pick.svg-b8cbf14d632089bea5ad3faa09f4cc83.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://entities/underground_loot/assets/sprites/underground_loot.svg"
-dest_files=["res://.godot/imported/underground_loot.svg-94513f7cc11df7cda1992e530bcff786.ctex"]
+source_file="res://common/icons/pick.svg"
+dest_files=["res://.godot/imported/pick.svg-b8cbf14d632089bea5ad3faa09f4cc83.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
@@ -25,6 +27,10 @@ mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
@@ -32,6 +38,6 @@ process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
-svg/scale=1.0
+svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
diff --git a/common/tools/scripts/math.gd b/common/tools/scripts/math.gd
new file mode 100644
index 0000000..704e4fa
--- /dev/null
+++ b/common/tools/scripts/math.gd
@@ -0,0 +1,69 @@
+class_name Math
+
+static func get_chunk_from_pos(coord) -> Vector2i:
+ return Vector2i(
+ floori(coord.x / (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE)),
+ floori(coord.y / (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE))
+ )
+
+static func get_tile_from_pos(coord) -> Vector2i:
+ return Vector2i(
+ floori(coord.x / (Planet.TILE_SIZE)),
+ floori(coord.y / (Planet.TILE_SIZE)),
+ )
+
+static func get_tiles_in_circle(center: Vector2, radius : float) -> Array[Vector2i]:
+ var tiles : Array[Vector2i] = []
+
+ for x in range(
+ floori((center.x - radius/2.) / Planet.TILE_SIZE),
+ ceili((center.x + radius/2.) / Planet.TILE_SIZE),
+ ):
+ for y in range(
+ floori((center.y - radius/2.) / Planet.TILE_SIZE),
+ ceili((center.y + radius/2.) / Planet.TILE_SIZE),
+ ):
+ if is_tile_on_circle(Vector2i(x,y), center, radius):
+ tiles.append(Vector2i(x,y))
+ return tiles
+
+static func is_tile_on_circle(tile_coord : Vector2i, circle_center: Vector2, circle_radius : float) -> bool:
+ var absolute_tile_pos : Vector2 = tile_coord * Planet.TILE_SIZE
+
+ # Loop over tile corners to know if the area collide
+ var corners : Array[Vector2] = []
+ for x in [0,1]:
+ for y in [0,1]:
+ corners.append(
+ absolute_tile_pos
+ + Vector2.RIGHT * x * Planet.TILE_SIZE
+ + Vector2.DOWN * y * Planet.TILE_SIZE
+ )
+
+ # Check if segment touch area
+ for i in range(4):
+ var a = corners[i%4]
+ var b = corners[(i+1)%4]
+ if segment_intersect_circle(a,b,circle_center,circle_radius):
+ return true
+
+ return false
+
+
+# Stolen here https://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm
+static func segment_intersect_circle(
+ a : Vector2,
+ b : Vector2,
+ c : Vector2,
+ radius: float
+) -> bool:
+ var a_circle = c - a
+ var b_a = b - a
+
+ var proj_point = proj(a_circle,b_a) + a
+
+ return proj_point.distance_to(c) < radius
+
+static func proj(a : Vector2,b : Vector2) -> Vector2:
+ var k = a.dot(b) / b.dot(b)
+ return Vector2(k * b.x, k * b.y)
\ No newline at end of file
diff --git a/common/tools/scripts/math.gd.uid b/common/tools/scripts/math.gd.uid
new file mode 100644
index 0000000..547bc32
--- /dev/null
+++ b/common/tools/scripts/math.gd.uid
@@ -0,0 +1 @@
+uid://b8i5lkk4md657
diff --git a/common/vfx/materials/shaders/texture_color_filter.gdshader b/common/vfx/materials/shaders/texture_color_filter.gdshader
new file mode 100644
index 0000000..78d4c17
--- /dev/null
+++ b/common/vfx/materials/shaders/texture_color_filter.gdshader
@@ -0,0 +1,29 @@
+shader_type canvas_item;
+
+uniform sampler2D red_overlay_tex: repeat_enable, filter_nearest;
+uniform sampler2D green_overlay_tex: repeat_enable, filter_nearest;
+uniform sampler2D blue_overlay_tex: repeat_enable, filter_nearest;
+uniform float scale = 0.006944444; // calculated by 1/texture size e.g. 1/144
+varying vec2 world_position;
+
+void vertex(){
+ // calculate the world position for use in the fragment shader
+ world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
+}
+
+void fragment() {
+ float mix_amount = floor(COLOR.r);
+
+ // sample the overlay_tex using worldPos
+ vec4 red_overlay_color = texture(red_overlay_tex, world_position * scale);
+ vec4 green_overlay_color = texture(green_overlay_tex, world_position * scale);
+ vec4 blue_overlay_color = texture(blue_overlay_tex, world_position * scale);
+
+ float origin_alpha = COLOR.a;
+
+ // combine original color and overlay color together
+ COLOR = mix(COLOR, red_overlay_color, floor(COLOR.r));
+ COLOR = mix(COLOR, green_overlay_color, floor(COLOR.g));
+ COLOR = mix(COLOR, blue_overlay_color, floor(COLOR.b));
+ COLOR.a = origin_alpha;
+}
\ No newline at end of file
diff --git a/common/vfx/materials/shaders/tilemap_repeat_texture.gdshader.uid b/common/vfx/materials/shaders/texture_color_filter.gdshader.uid
similarity index 100%
rename from common/vfx/materials/shaders/tilemap_repeat_texture.gdshader.uid
rename to common/vfx/materials/shaders/texture_color_filter.gdshader.uid
diff --git a/common/vfx/materials/shaders/tilemap_repeat_texture.gdshader b/common/vfx/materials/shaders/tilemap_repeat_texture.gdshader
deleted file mode 100644
index 054cbe9..0000000
--- a/common/vfx/materials/shaders/tilemap_repeat_texture.gdshader
+++ /dev/null
@@ -1,21 +0,0 @@
-shader_type canvas_item;
-
-uniform sampler2D overlay_tex: repeat_enable, filter_nearest;
-uniform float scale = 0.006944444; // calculated by 1/texture size e.g. 1/144
-varying vec2 world_position;
-
-void vertex(){
- // calculate the world position for use in the fragment shader
- world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
-}
-
-void fragment() {
- // only apply overlay_tex on the fully red parts of the original tiles
- float mix_amount = floor(COLOR.r);
-
- // sample the overlay_tex using worldPos
- vec4 overlay_color = texture(overlay_tex, world_position * scale);
-
- // combine original color and overlay color together
- COLOR = mix(COLOR, overlay_color, mix_amount);
-}
\ No newline at end of file
diff --git a/entities/interactables/truck/ladder/scripts/truck_ladder.gd b/entities/interactables/truck/ladder/scripts/truck_ladder.gd
index d996982..a681aff 100644
--- a/entities/interactables/truck/ladder/scripts/truck_ladder.gd
+++ b/entities/interactables/truck/ladder/scripts/truck_ladder.gd
@@ -4,6 +4,6 @@ class_name TruckLadder
const TRUCK_SCENE_PATH = "res://stages/terrain/truck/truck.tscn"
func interact(p : Player):
- p.planet.save()
- get_tree().change_scene_to_file(TRUCK_SCENE_PATH)
- return true
+ p.planet.save()
+ get_tree().change_scene_to_file(TRUCK_SCENE_PATH)
+ return true
diff --git a/entities/plants/scripts/plant_effects/decontaminate_terrain_effect.gd b/entities/plants/scripts/plant_effects/decontaminate_terrain_effect.gd
index af34ac4..9773dc0 100644
--- a/entities/plants/scripts/plant_effects/decontaminate_terrain_effect.gd
+++ b/entities/plants/scripts/plant_effects/decontaminate_terrain_effect.gd
@@ -2,7 +2,7 @@ extends PlantEffect
class_name DecontaminateTerrainEffect
func get_decontamination_radius():
- return 50 + 50 * level
+ return (1 + level)
func get_effect_name() -> String:
return tr("DECONTAMINATE")
@@ -12,9 +12,9 @@ func get_effect_description() -> String:
return ret
func effect(plant):
- var radius = get_decontamination_radius()
-
- plant.planet.garden.impact_contamination(
+ var tiles := Math.get_tiles_in_circle(
plant.global_position,
- radius
- )
\ No newline at end of file
+ get_decontamination_radius() * Planet.TILE_SIZE + Planet.TILE_SIZE/2.
+ )
+
+ plant.planet.decontamination_layer.place_decontaminations(tiles, true)
diff --git a/entities/player/inventory/scripts/items/pickaxe.gd b/entities/player/inventory/scripts/items/pickaxe.gd
new file mode 100644
index 0000000..6fb58d9
--- /dev/null
+++ b/entities/player/inventory/scripts/items/pickaxe.gd
@@ -0,0 +1,41 @@
+extends Item
+class_name Pickaxe
+
+const USE_INTERVAL = 0.15
+
+func get_item_name() -> String:
+ return tr("PICKAXE")
+
+func get_description() -> String:
+ return tr("PICKAXE_DESC_TEXT")
+
+func get_icon() -> Texture2D:
+ return preload("res://common/icons/pick.svg")
+
+func get_energy_used() -> int:
+ return 1
+
+func get_usage_zone_radius() -> int:
+ return 50
+
+func use_text() -> String:
+ return tr("DIG")
+
+func can_use(_player : Player, zone : Player.ActionZone) -> bool:
+ if zone and zone.area:
+ var bodies = zone.area.get_overlapping_bodies()
+ for body in bodies :
+ if body is RockLayer:
+ return true
+ return false
+
+func use(_player : Player, zone : Player.ActionZone) -> bool:
+
+ var bodies = zone.area.get_overlapping_bodies()
+ var rock_layer_id = bodies.find_custom(func (b) : return b is RockLayer)
+ if rock_layer_id != -1:
+ var rock_layer : RockLayer = bodies[rock_layer_id]
+
+ return rock_layer.dig_rocks(zone.get_tiles())
+
+ return false
diff --git a/entities/player/inventory/scripts/items/pickaxe.gd.uid b/entities/player/inventory/scripts/items/pickaxe.gd.uid
new file mode 100644
index 0000000..6e63f8f
--- /dev/null
+++ b/entities/player/inventory/scripts/items/pickaxe.gd.uid
@@ -0,0 +1 @@
+uid://ctucfh72pxut8
diff --git a/entities/player/inventory/scripts/items/seed.gd b/entities/player/inventory/scripts/items/seed.gd
index d401ac2..b557c28 100644
--- a/entities/player/inventory/scripts/items/seed.gd
+++ b/entities/player/inventory/scripts/items/seed.gd
@@ -11,192 +11,191 @@ const SCORE_ICON = preload("res://common/icons/growth.svg")
@export var plant_mutations: Array[PlantMutation]
func get_item_name() -> String:
- return tr("%s_SEED") % plant_type.name
+ return tr("%s_SEED") % plant_type.name
func get_description() -> String:
- return tr("PLANT_%s_MUST_BE_USED_IN_DECONTAMINATED_ZONE") % plant_type.name
+ return tr("PLANT_%s_MUST_BE_USED_IN_DECONTAMINATED_ZONE") % plant_type.name
func get_icon() -> Texture2D:
- return plant_type.seed_texture
+ return plant_type.seed_texture
func get_energy_used() -> int:
- return 1
+ return 1
func get_usage_zone_radius() -> int:
- return 35
+ return 35
func get_usage_object_affected(i : InspectableEntity) -> bool:
- return i is Plant
+ return i is Plant
func _init(
- _plant_type : PlantType = null,
- _parent_mutation : Array[PlantMutation] = []
+ _plant_type : PlantType = null,
+ _parent_mutation : Array[PlantMutation] = []
):
- plant_type = _plant_type
- plant_mutations = Seed.mutate(_parent_mutation)
+ plant_type = _plant_type
+ plant_mutations = Seed.mutate(_parent_mutation)
func use_text() -> String:
- return tr("PLANT_%s") % plant_type.name
+ return tr("PLANT_%s") % plant_type.name
func is_one_time_use():
- return true
+ return true
func can_use(player : Player, zone : Player.ActionZone) -> bool:
- if (
- player.planet == null
- or not player.planet.garden.is_in_garden(zone.get_global_position())
- ):
- return false
+ if (
+ player.planet == null
+ ):
+ return false
- var is_there_a_plant_here = false
- for area in zone.get_affected_areas():
- if area is Plant:
- is_there_a_plant_here = true
-
- var is_there_contamination_in_zone = false
- for point in zone.get_points_in_zone():
- if player.planet.garden.is_there_contamination(point):
- is_there_contamination_in_zone = true
+ var is_there_a_plant_here = false
+ for area in zone.get_affected_areas():
+ if area is Plant:
+ is_there_a_plant_here = true
+
+ var is_there_contamination_in_zone = false
+ for tile in zone.get_tiles():
+ if not player.planet.decontamination_layer.is_decontamined(tile):
+ is_there_contamination_in_zone = true
- return not is_there_a_plant_here and not is_there_contamination_in_zone
+ return not is_there_a_plant_here and not is_there_contamination_in_zone
func use(player : Player, zone : Player.ActionZone) -> bool:
- if player.planet == null:
- return false
+ if player.planet == null:
+ return false
- AudioManager.play_sfx("Dig")
- return player.planet.plant(
- plant_type,
- zone.get_global_position(),
- plant_mutations
- )
+ AudioManager.play_sfx("Dig")
+ return player.planet.plant(
+ plant_type,
+ zone.get_global_position(),
+ plant_mutations
+ )
func card_info() -> CardInfo:
- var info = CardInfo.new(
- get_item_name()
- )
- info.texture = icon
- info.type_icon = TYPE_ICON
+ var info = CardInfo.new(
+ get_item_name()
+ )
+ info.texture = icon
+ info.type_icon = TYPE_ICON
- info.stats.append(
- CardStatInfo.new(
- tr("COST_%d_ENERGY") % energy_usage,
- ENERGY_ICON
- )
- )
+ info.stats.append(
+ CardStatInfo.new(
+ tr("COST_%d_ENERGY") % energy_usage,
+ ENERGY_ICON
+ )
+ )
- if is_one_time_use():
- info.stats.append(
- CardStatInfo.new(
- tr("ONE_TIME_USE"),
- ONE_TIME_ICON
- )
- )
+ if is_one_time_use():
+ info.stats.append(
+ CardStatInfo.new(
+ tr("ONE_TIME_USE"),
+ ONE_TIME_ICON
+ )
+ )
- var effect_section = CardSectionInfo.new(
- tr("EFFECT"),
- get_description()
- )
- effect_section.title_icon = ACTION_ICON
+ var effect_section = CardSectionInfo.new(
+ tr("EFFECT"),
+ get_description()
+ )
+ effect_section.title_icon = ACTION_ICON
- if energy_usage > 0:
- effect_section.title_icon = ENERGY_ICON
-
- info.sections.append(effect_section)
+ if energy_usage > 0:
+ effect_section.title_icon = ENERGY_ICON
+
+ info.sections.append(effect_section)
- if len(plant_mutations) != 0:
- var rarest : int = plant_mutations.map(
- func(m : PlantMutation) : return m.get_rarity()
- ).max()
- info.bg_color = PlantMutation.get_rarity_color(rarest)
- for m in plant_mutations:
- info.sections.append(m.card_section())
-
- return info
+ if len(plant_mutations) != 0:
+ var rarest : int = plant_mutations.map(
+ func(m : PlantMutation) : return m.get_rarity()
+ ).max()
+ info.bg_color = PlantMutation.get_rarity_color(rarest)
+ for m in plant_mutations:
+ info.sections.append(m.card_section())
+
+ return info
func get_particles() -> Array[Particles.Parameters]:
- var param : Array[Particles.Parameters] = []
+ var param : Array[Particles.Parameters] = []
- for m in plant_mutations:
- param.append(
- Particles.Parameters.new(
- m.get_icon(),
- PlantMutation.get_rarity_color(m.get_rarity())
- )
- )
+ for m in plant_mutations:
+ param.append(
+ Particles.Parameters.new(
+ m.get_icon(),
+ PlantMutation.get_rarity_color(m.get_rarity())
+ )
+ )
- return param
+ return param
static func mutate(parent_mutation : Array[PlantMutation] = []) -> Array[PlantMutation]:
- if randf() > MUTATION_PROBABILITY:
- return parent_mutation
+ if randf() > MUTATION_PROBABILITY:
+ return parent_mutation
- var possible_mutations : Array[MutationPossibility] = [
- AddMutation.new()
- ]
+ var possible_mutations : Array[MutationPossibility] = [
+ AddMutation.new()
+ ]
- if (
- len(parent_mutation) >= 2
- ):
- possible_mutations = [
- UpgradeMutation.new(),
- RemoveMutation.new(),
- ]
- elif len(parent_mutation) > 0:
- possible_mutations = [
- AddMutation.new(),
- UpgradeMutation.new(),
- RemoveMutation.new(),
- ]
-
- var chosen_mutation = possible_mutations.pick_random()
+ if (
+ len(parent_mutation) >= 2
+ ):
+ possible_mutations = [
+ UpgradeMutation.new(),
+ RemoveMutation.new(),
+ ]
+ elif len(parent_mutation) > 0:
+ possible_mutations = [
+ AddMutation.new(),
+ UpgradeMutation.new(),
+ RemoveMutation.new(),
+ ]
+
+ var chosen_mutation = possible_mutations.pick_random()
- return chosen_mutation.mutate(parent_mutation)
+ return chosen_mutation.mutate(parent_mutation)
class MutationPossibility:
- func mutate(_parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
- return []
+ func mutate(_parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
+ return []
class DontMutate extends MutationPossibility:
- func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
- return parent_mutation
+ func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
+ return parent_mutation
class AddMutation extends MutationPossibility:
- func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
- var new_mutations = parent_mutation.duplicate_deep()
- var mut = PlantMutation.random_mutation(parent_mutation)
+ func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
+ var new_mutations = parent_mutation.duplicate_deep()
+ var mut = PlantMutation.random_mutation(parent_mutation)
- if mut:
- var existing_mut_id = new_mutations.find_custom(func(m:PlantMutation): return m.get_mutation_name() == mut.get_mutation_name())
-
- if existing_mut_id >= 0:
- new_mutations[existing_mut_id].level += 1
- else :
- new_mutations.append(mut)
+ if mut:
+ var existing_mut_id = new_mutations.find_custom(func(m:PlantMutation): return m.get_mutation_name() == mut.get_mutation_name())
+
+ if existing_mut_id >= 0:
+ new_mutations[existing_mut_id].level += 1
+ else :
+ new_mutations.append(mut)
- return new_mutations
+ return new_mutations
class UpgradeMutation extends MutationPossibility:
- func mutate(
- parent_mutation : Array[PlantMutation] = []
- ) -> Array[PlantMutation]:
- var new_mutations = parent_mutation.duplicate_deep()
+ func mutate(
+ parent_mutation : Array[PlantMutation] = []
+ ) -> Array[PlantMutation]:
+ var new_mutations = parent_mutation.duplicate_deep()
- new_mutations.pick_random().level += 1
+ new_mutations.pick_random().level += 1
- return new_mutations
+ return new_mutations
class RemoveMutation extends MutationPossibility:
- func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
- var new_mutations :Array[PlantMutation] = parent_mutation.duplicate_deep()
+ func mutate(parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
+ var new_mutations :Array[PlantMutation] = parent_mutation.duplicate_deep()
- var mut_to_remove = new_mutations.pick_random()
- if mut_to_remove.level > 1:
- mut_to_remove.level -= 1
- else:
- new_mutations.remove_at(new_mutations.find(mut_to_remove))
+ var mut_to_remove = new_mutations.pick_random()
+ if mut_to_remove.level > 1:
+ mut_to_remove.level -= 1
+ else:
+ new_mutations.remove_at(new_mutations.find(mut_to_remove))
- return new_mutations
+ return new_mutations
diff --git a/entities/player/inventory/scripts/items/shovel.gd b/entities/player/inventory/scripts/items/shovel.gd
index ecd225f..1ac9a4a 100644
--- a/entities/player/inventory/scripts/items/shovel.gd
+++ b/entities/player/inventory/scripts/items/shovel.gd
@@ -4,41 +4,45 @@ class_name Shovel
const SHOVEL_ZONE_RADIUS = 50
func get_item_name() -> String:
- return tr("SHOVEL")
+ return tr("SHOVEL")
func get_description() -> String:
- return tr("SHOVEL_DESC_TEXT")
+ return tr("SHOVEL_DESC_TEXT")
func get_icon() -> Texture2D:
- return preload("res://common/icons/shovel.svg")
+ return preload("res://common/icons/shovel.svg")
func get_usage_zone_radius() -> int:
- return SHOVEL_ZONE_RADIUS
+ return SHOVEL_ZONE_RADIUS
func get_usage_object_affected(i : InspectableEntity) -> bool:
- return i is Plant or i is UndergroundLoot
+ return i is Plant
func use_text() -> String:
- return tr("DIG")
+ return tr("DIG")
func can_use(_player : Player, zone : Player.ActionZone) -> bool:
- var areas = zone.get_affected_areas()
- for area in areas :
- if area is Plant or area is UndergroundLoot:
- return true
- return false
+ var areas = zone.get_affected_areas()
+ var bodies = zone.area.get_overlapping_bodies()
+ for body in bodies :
+ if body is RockLayer:
+ return true
+ for area in areas :
+ if area is Plant:
+ return true
+ return false
func use(player : Player, zone : Player.ActionZone) -> bool:
- for area in zone.get_affected_areas():
- if area and area is Plant:
- harvest(area, player)
- await player.get_tree().create_timer(USE_INTERVAL).timeout
- if area and area is UndergroundLoot:
- dig(area, player)
- await player.get_tree().create_timer(USE_INTERVAL).timeout
-
- return true
+ for area in zone.get_affected_areas():
+ if area and area is Plant:
+ harvest(area, player)
+ await player.get_tree().create_timer(USE_INTERVAL).timeout
+
+ var bodies = zone.area.get_overlapping_bodies()
+ var rock_layer_id = bodies.find_custom(func (b) : return b is RockLayer)
+ if rock_layer_id != -1:
+ var rock_layer : RockLayer = bodies[rock_layer_id]
-func dig(u: UndergroundLoot, player: Player):
- AudioManager.play_sfx("Dig")
- u.dig()
+ rock_layer.dig_rocks(zone.get_tiles())
+
+ return true
diff --git a/entities/player/scripts/player.gd b/entities/player/scripts/player.gd
index f0c779f..7b90809 100644
--- a/entities/player/scripts/player.gd
+++ b/entities/player/scripts/player.gd
@@ -10,320 +10,324 @@ signal upgraded
var terrain : Terrain
var planet : Planet :
- get(): return terrain if terrain is Planet else null
+ get(): return terrain if terrain is Planet else null
@export var speed = 350
var data : PlayerData
var last_action_area_movement_timer : float = 100.
var controlling_player : bool = true :
- set(v):
- controlling_player = v
- velocity = Vector2.ZERO
+ set(v):
+ controlling_player = v
+ velocity = Vector2.ZERO
var instruction : Instruction = null
-@onready var preview_zone : ActionZone = setup_action_zone(Vector2.ZERO, null)
-@onready var action_zone : ActionZone = setup_action_zone(Vector2.ZERO, null)
+@onready var preview_zone : ActionZone = await setup_action_zone(Vector2.ZERO, null)
+@onready var action_zone : ActionZone = await setup_action_zone(Vector2.ZERO, null)
func _ready():
- data = GameInfo.game_data.player_data
- data.inventory.updated.connect(_on_inventory_updated)
- player_updated.emit(self)
- Pointer.player = self
+ data = GameInfo.game_data.player_data
+ data.inventory.updated.connect(_on_inventory_updated)
+ player_updated.emit(self)
+ Pointer.player = self
+ setup_preview_zone(data.inventory.get_item())
func _input(_event) -> void:
- if Input.is_action_pressed("change_item_left"):
- data.inventory.change_current_item(1)
- if Input.is_action_pressed("change_item_right"):
- data.inventory.change_current_item(-1)
- for i in range(1, 10):
- if Input.is_action_pressed("item_" + str(i)):
- data.inventory.set_current_item(i - 1)
+ if Input.is_action_pressed("change_item_left"):
+ data.inventory.change_current_item(1)
+ if Input.is_action_pressed("change_item_right"):
+ data.inventory.change_current_item(-1)
+ for i in range(1, 10):
+ if Input.is_action_pressed("item_" + str(i)):
+ data.inventory.set_current_item(i - 1)
# Méthode déclenchée par la classe planet
func _start_pass_day():
- controlling_player = false
- instruction = null
+ controlling_player = false
+ instruction = null
# Méthode déclenchée par la classe planet
func _pass_day():
- full_recharge()
+ full_recharge()
# Méthode déclenchée par la classe planet
func _end_pass_day():
- controlling_player = true
+ controlling_player = true
func _process(delta):
- last_action_area_movement_timer += delta
- if controlling_player:
- calculate_direction()
+ last_action_area_movement_timer += delta
+ if controlling_player:
+ calculate_direction()
- if (
- last_action_area_movement_timer >= ACTION_AREA_UPDATE_TIME
- and instruction and instruction.can_be_done(self)
- ):
- instruction.do(self)
- instruction = null
- move_preview_zone(get_global_mouse_position())
- else:
- velocity = Vector2.ZERO
- move_and_slide()
+ if (
+ last_action_area_movement_timer >= ACTION_AREA_UPDATE_TIME
+ and instruction and instruction.can_be_done(self)
+ ):
+ instruction.do(self)
+ instruction = null
+ move_preview_zone(get_global_mouse_position())
+ else:
+ velocity = Vector2.ZERO
+ move_and_slide()
func _on_inventory_updated(_inventory: Inventory):
- setup_preview_zone(data.inventory.get_item())
- var item : Item = data.inventory.get_item()
- if item:
- var item_texture = item.icon
- %ItemSprite.texture = item_texture
- %ItemSprite.scale = Vector2(
- 1./(item_texture.get_width()/HOLDING_ITEM_SPRITE_SIZE),
- 1./(item_texture.get_height()/HOLDING_ITEM_SPRITE_SIZE)
- )
- %HideEyes.visible = item != null
- %ItemSprite.visible = item != null
- emit_signal("player_updated", self)
+ setup_preview_zone(data.inventory.get_item())
+ var item : Item = data.inventory.get_item()
+ if item:
+ var item_texture = item.icon
+ %ItemSprite.texture = item_texture
+ %ItemSprite.scale = Vector2(
+ 1./(item_texture.get_width()/HOLDING_ITEM_SPRITE_SIZE),
+ 1./(item_texture.get_height()/HOLDING_ITEM_SPRITE_SIZE)
+ )
+ %HideEyes.visible = item != null
+ %ItemSprite.visible = item != null
+ emit_signal("player_updated", self)
func calculate_direction():
- var input_direction: Vector2 = Input.get_vector("move_left", "move_right", "move_up", "move_down")
+ var input_direction: Vector2 = Input.get_vector("move_left", "move_right", "move_up", "move_down")
- if input_direction.length() != 0:
- instruction = null
+ if input_direction.length() != 0:
+ instruction = null
- if instruction and instruction.position.distance_to(global_position) > (MAX_REACH - 1.):
- input_direction = self.global_position.direction_to(instruction.position)
+ if (
+ instruction
+ and (
+ instruction.position.distance_to(global_position) > (MAX_REACH - 1.)
+ or instruction is MoveInstruction
+ )
+ ):
+ input_direction = self.global_position.direction_to(instruction.position)
- velocity = input_direction * speed
- if input_direction.x:
- flip_character(input_direction.x > 0)
+ velocity = input_direction * speed
+ if input_direction.x:
+ flip_character(input_direction.x > 0)
func flip_character(face_right = true):
- $Sprite.flip_h = not face_right
- %ItemSprite.position.x = abs(%ItemSprite.position.x) * (1 if face_right else -1)
- %HideEyes.position.x = abs(%ItemSprite.position.x) * (1 if face_right else -1)
+ $Sprite.flip_h = not face_right
+ %ItemSprite.position.x = abs(%ItemSprite.position.x) * (1 if face_right else -1)
+ %HideEyes.position.x = abs(%ItemSprite.position.x) * (1 if face_right else -1)
func can_interact(interactable : Interactable):
- return interactable.can_interact(self)
+ return interactable.can_interact(self)
func try_interact(interactable : Interactable):
- if interactable:
- instruction = InteractableInstruction.new(
- interactable
- )
+ if interactable:
+ instruction = InteractableInstruction.new(
+ interactable
+ )
func try_move(move_to : Vector2):
- instruction = MoveInstruction.new(move_to)
+ instruction = MoveInstruction.new(move_to)
func pick_item(item : Item) -> Item:
- AudioManager.play_sfx("PickUp")
- if data.inventory.is_full():
- drop_item()
+ AudioManager.play_sfx("PickUp")
+ if data.inventory.is_full():
+ drop_item()
- var available_slot_ind = data.inventory.get_best_available_slot_ind()
- if (
- available_slot_ind == data.inventory.current_item_ind
- && data.inventory.items[available_slot_ind] != null
- ):
- var current_item : Item = data.inventory.get_item()
- data.inventory.set_item(item, available_slot_ind)
- return current_item
- else :
- if data.inventory.set_item(item, available_slot_ind):
- data.inventory.set_current_item(available_slot_ind);
- return null
+ var available_slot_ind = data.inventory.get_best_available_slot_ind()
+ if (
+ available_slot_ind == data.inventory.current_item_ind
+ && data.inventory.items[available_slot_ind] != null
+ ):
+ var current_item : Item = data.inventory.get_item()
+ data.inventory.set_item(item, available_slot_ind)
+ return current_item
+ else :
+ if data.inventory.set_item(item, available_slot_ind):
+ data.inventory.set_current_item(available_slot_ind);
+ return null
func drop_item():
- var item_to_drop = data.inventory.pop_item()
- if item_to_drop:
- terrain.drop_item(item_to_drop, global_position)
- AudioManager.play_sfx("Drop")
+ var item_to_drop = data.inventory.pop_item()
+ if item_to_drop:
+ terrain.drop_item(item_to_drop, global_position)
+ AudioManager.play_sfx("Drop")
func delete_item(item: Item):
- data.inventory.remove_item(item)
+ data.inventory.remove_item(item)
func try_use_item(item : Item, use_position : Vector2):
- setup_action_zone(use_position, item)
- instruction = ItemActionInstruction.new(
- use_position,
- item
- )
+ await setup_action_zone(use_position, item)
+ instruction = ItemActionInstruction.new(
+ use_position,
+ item
+ )
func preview_could_use_item(item : Item) -> bool:
- return could_use_item_on_zone(item, preview_zone)
+ return could_use_item_on_zone(item, preview_zone)
func could_use_item_on_zone(item : Item, zone: ActionZone) -> bool:
- return (
- data.inventory.has_item(item)
- and item.can_use(self, zone)
- )
+ return (
+ data.inventory.has_item(item)
+ and item.can_use(self, zone)
+ )
func can_use_item_on_zone(item : Item, zone: ActionZone) -> bool:
- return (
- could_use_item_on_zone(item, zone)
- and has_energy_to_use_item(item)
- )
+ return (
+ could_use_item_on_zone(item, zone)
+ and has_energy_to_use_item(item)
+ )
func has_energy_to_use_item(item : Item):
- return (data.energy - item.energy_usage) >= 0
+ return (data.energy - item.energy_usage) >= 0
func use_item(item : Item):
- if can_use_item_on_zone(item, action_zone):
- var is_item_used = await item.use(self, action_zone)
- if is_item_used:
- data.energy -= item.energy_usage
- if item.is_one_time_use():
- data.inventory.remove_item(item)
+ if can_use_item_on_zone(item, action_zone):
+ var is_item_used = await item.use(self, action_zone)
+ if is_item_used:
+ data.energy -= item.energy_usage
+ if item.is_one_time_use():
+ data.inventory.remove_item(item)
func upgrade_max_energy(amount = 1):
- data.max_energy += amount
- upgraded.emit()
- player_updated.emit(self)
+ data.max_energy += amount
+ upgraded.emit()
+ player_updated.emit(self)
func upgrade_inventory_size(amount = 1):
- data.inventory.size += 1
- upgraded.emit()
- player_updated.emit(self)
+ data.inventory.size += amount
+ upgraded.emit()
+ player_updated.emit(self)
func recharge(amount : int = data.max_energy):
- data.energy += + amount
- upgraded.emit()
+ data.energy += + amount
+ upgraded.emit()
func full_recharge():
- data.energy = max(data.energy, data.max_energy)
+ data.energy = max(data.energy, data.max_energy)
func generate_action_zone(item : Item) -> ActionZone:
- var zone = ActionZone.new(item)
+ var zone = ActionZone.new(item)
- if zone.area:
- get_parent().add_child(zone.area)
+ if not get_parent().is_node_ready():
+ await get_parent().ready
+ get_parent().add_child(zone.area)
- return zone
+ return zone
-func setup_preview_zone(item : Item) -> ActionZone:
- if preview_zone and preview_zone.item == item:
- return preview_zone
- elif preview_zone:
- preview_zone.destroy()
-
- if item:
- preview_zone = generate_action_zone(item)
- else:
- preview_zone = null
-
- return preview_zone
+func setup_preview_zone(item : Item):
+ if preview_zone and preview_zone.item == item:
+ return preview_zone
+ elif preview_zone:
+ preview_zone.destroy()
+
+ if item:
+ preview_zone = await generate_action_zone(item)
+ else:
+ preview_zone = null
func setup_action_zone(zone_position : Vector2, item: Item) -> ActionZone:
- if action_zone:
- action_zone.destroy()
- action_zone = generate_action_zone(item)
- action_zone.move_to_position(zone_position)
- last_action_area_movement_timer = 0.
- return action_zone
+ if action_zone:
+ action_zone.destroy()
+ action_zone = await generate_action_zone(item)
+ action_zone.move_to_position(zone_position)
+ last_action_area_movement_timer = 0.
+ return action_zone
func move_preview_zone(zone_position : Vector2):
- if preview_zone:
- preview_zone.move_to_position(zone_position)
+ if preview_zone:
+ preview_zone.move_to_position(zone_position)
class Instruction:
- var position : Vector2
+ var position : Vector2
- func _init(_pos : Vector2):
- position = _pos
+ func _init(_pos : Vector2):
+ position = _pos
- func can_be_done(player : Player):
- return player.global_position.distance_to(position) < player.MAX_REACH
+ func can_be_done(player : Player):
+ return player.global_position.distance_to(position) < player.MAX_REACH
- func do(_player : Player):
- pass
-
+ func do(_player : Player):
+ pass
+
class MoveInstruction extends Instruction:
- pass
+ func can_be_done(player : Player):
+ return player.global_position.distance_to(position) < 10.
+
class ItemActionInstruction extends Instruction:
- var item = Item
+ var item = Item
- func _init(_pos : Vector2, _item : Item):
- position = _pos
- item = _item
-
- func can_be_done(player : Player):
- return (
- player.global_position.distance_to(position) < player.MAX_REACH
- )
-
- func do(player : Player):
- player.use_item(item)
+ func _init(_pos : Vector2, _item : Item):
+ position = _pos
+ item = _item
+
+ func can_be_done(player : Player):
+ return (
+ player.global_position.distance_to(position) < player.MAX_REACH
+ )
+
+ func do(player : Player):
+ player.use_item(item)
class InteractableInstruction extends Instruction:
- var interactable = Interactable
+ var interactable = Interactable
- func _init(_interactable : Interactable):
- interactable = _interactable
- position = interactable.global_position
-
- func can_be_done(player : Player):
- return player.global_position.distance_to(position) < player.MAX_REACH
-
- func do(player : Player):
- interactable.interact(player)
+ func _init(_interactable : Interactable):
+ interactable = _interactable
+ position = interactable.global_position
+
+ func can_be_done(player : Player):
+ return player.global_position.distance_to(position) < player.MAX_REACH
+
+ func do(player : Player):
+ interactable.interact(player)
class ActionZone:
- var item : Item = null
- var area : Area2D
- var affected_areas : Array[InspectableEntity]= []
+ var item : Item = null
+ var area : Area2D
+ var affected_areas : Array[InspectableEntity]= []
- func _init(_i : Item):
- item = _i
- if item and item.get_usage_zone_radius() > 0:
- area = Area2D.new()
- var collision_shape = CollisionShape2D.new()
- var circle_shape = CircleShape2D.new()
+ func _init(_i : Item):
+ item = _i
+ if item and item.get_usage_zone_radius() > 0:
+ area = Area2D.new()
+ var collision_shape = CollisionShape2D.new()
+ var circle_shape = CircleShape2D.new()
- circle_shape.radius = item.get_usage_zone_radius()
- collision_shape.shape = circle_shape
- area.add_child(collision_shape)
+ circle_shape.radius = item.get_usage_zone_radius()
+ collision_shape.shape = circle_shape
+ area.add_child(collision_shape)
- func clear_preview_on_affected_area():
- for a in affected_areas:
- if a:
- a.affect_preview(false)
+ func clear_preview_on_affected_area():
+ for a in affected_areas:
+ if a:
+ a.affect_preview(false)
- func update_preview_on_affected_area():
- var detected_areas = get_affected_areas()
- clear_preview_on_affected_area()
- var new_affected_areas : Array[InspectableEntity] = []
- for a in detected_areas:
- if a is InspectableEntity and item.get_usage_object_affected(a):
- a.affect_preview(true)
- new_affected_areas.append(a)
- affected_areas = new_affected_areas
+ func update_preview_on_affected_area():
+ var detected_areas = get_affected_areas()
+ clear_preview_on_affected_area()
+ var new_affected_areas : Array[InspectableEntity] = []
+ for a in detected_areas:
+ if a is InspectableEntity and item.get_usage_object_affected(a):
+ a.affect_preview(true)
+ new_affected_areas.append(a)
+ affected_areas = new_affected_areas
- func get_affected_areas() -> Array[Area2D]:
- var empty_array : Array[Area2D] = []
- return empty_array if area == null else area.get_overlapping_areas()
+ func get_affected_areas() -> Array[Area2D]:
+ var empty_array : Array[Area2D] = []
+ return empty_array if area == null else area.get_overlapping_areas()
- func destroy():
- clear_preview_on_affected_area()
- if area:
- area.queue_free()
-
- func get_global_position() -> Vector2:
- return Vector2.ZERO if area == null else area.global_position
+ func destroy():
+ clear_preview_on_affected_area()
+ if area:
+ area.queue_free()
+
+ func get_global_position() -> Vector2:
+ return Vector2.ZERO if area == null else area.global_position
- func move_to_position(pos : Vector2):
- if area:
- update_preview_on_affected_area()
- area.global_position = pos
+ func move_to_position(pos : Vector2):
+ if area:
+ update_preview_on_affected_area()
+ area.global_position = pos
- func get_points_in_zone(point_factor = 10) -> Array[Vector2]:
- var points : Array[Vector2] = []
- var radius = item.get_usage_zone_radius()
- for x in range(-radius, radius, point_factor):
- for y in range(-radius, radius, point_factor):
- if Vector2(x, y).length() <= radius:
- points.append(area.global_position + Vector2(x, y))
-
- return points
+ func get_tiles() -> Array[Vector2i]:
+ return Math.get_tiles_in_circle(
+ get_global_position(),
+ item.get_usage_zone_radius()
+ )
\ No newline at end of file
diff --git a/entities/player/scripts/player_data.gd b/entities/player/scripts/player_data.gd
index ad53d40..cc2ddcc 100644
--- a/entities/player/scripts/player_data.gd
+++ b/entities/player/scripts/player_data.gd
@@ -3,7 +3,7 @@ class_name PlayerData
signal updated(player_data : PlayerData)
-const DEFAULT_MAX_ENERGY = 2
+const DEFAULT_MAX_ENERGY = 3
const DEFAULT_INVENTORY_SIZE = 3
@export var max_energy : int = DEFAULT_MAX_ENERGY :
diff --git a/entities/underground_loot/assets/sprites/underground_loot.svg b/entities/underground_loot/assets/sprites/underground_loot.svg
deleted file mode 100644
index 0be5a5e..0000000
--- a/entities/underground_loot/assets/sprites/underground_loot.svg
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
diff --git a/entities/underground_loot/scripts/underground_loot.gd b/entities/underground_loot/scripts/underground_loot.gd
deleted file mode 100644
index 3a045cf..0000000
--- a/entities/underground_loot/scripts/underground_loot.gd
+++ /dev/null
@@ -1,39 +0,0 @@
-extends InspectableEntity
-class_name UndergroundLoot
-
-const AREA_WIDTH = 20
-const LOOTED_ITEM_RANDOM_RANGE = 50
-
-@export var item_number : int = 1
-
-func pointer_text() -> String:
- return tr("BURIED_SEEDS")
-
-func generate_collision_shape() -> CollisionShape2D:
- var collision = CollisionShape2D.new()
- var shape = CircleShape2D.new()
- shape.radius = AREA_WIDTH
-
- collision.shape = shape
- add_child(collision)
-
- return collision
-
-func generate_loot() -> Array[Item]:
- var seeds : Array[Item] = []
- if len(GameInfo.game_data.unlocked_plant_types):
- seeds.append(
- Seed.new(
- GameInfo.game_data.unlocked_plant_types.pick_random()
- )
- )
- return seeds
-
-
-func dig():
- for item in generate_loot():
- planet.drop_item(item, global_position, LOOTED_ITEM_RANDOM_RANGE)
- queue_free()
-
-func save() -> UndergroundLootData:
- return UndergroundLootData.new(self)
\ No newline at end of file
diff --git a/entities/underground_loot/scripts/underground_loot.gd.uid b/entities/underground_loot/scripts/underground_loot.gd.uid
deleted file mode 100644
index b566683..0000000
--- a/entities/underground_loot/scripts/underground_loot.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://dfd2hh12155lo
diff --git a/entities/underground_loot/scripts/underground_loot_data.gd b/entities/underground_loot/scripts/underground_loot_data.gd
deleted file mode 100644
index b75234b..0000000
--- a/entities/underground_loot/scripts/underground_loot_data.gd
+++ /dev/null
@@ -1,15 +0,0 @@
-extends EntityData
-class_name UndergroundLootData
-
-const SCENE = preload("res://entities/underground_loot/underground_loot.tscn")
-
-@export var item_number : int
-
-func _init(e : UndergroundLoot):
- position = e.global_position
- item_number = e.item_number
-
-func load() -> Entity:
- var loot : UndergroundLoot = (SCENE.instantiate() as UndergroundLoot)
- loot.item_number = item_number
- return loot
diff --git a/entities/underground_loot/scripts/underground_loot_data.gd.uid b/entities/underground_loot/scripts/underground_loot_data.gd.uid
deleted file mode 100644
index 865d70e..0000000
--- a/entities/underground_loot/scripts/underground_loot_data.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://68plwch6h4f7
diff --git a/entities/underground_loot/underground_loot.tscn b/entities/underground_loot/underground_loot.tscn
deleted file mode 100644
index 5b79e09..0000000
--- a/entities/underground_loot/underground_loot.tscn
+++ /dev/null
@@ -1,21 +0,0 @@
-[gd_scene load_steps=4 format=3 uid="uid://dxjud7bti0na0"]
-
-[ext_resource type="Script" uid="uid://dfd2hh12155lo" path="res://entities/underground_loot/scripts/underground_loot.gd" id="1_knus5"]
-[ext_resource type="Texture2D" uid="uid://bu26h0iqutnky" path="res://entities/underground_loot/assets/sprites/underground_loot.svg" id="2_jfggo"]
-
-[sub_resource type="CircleShape2D" id="CircleShape2D_knus5"]
-radius = 20.09975
-
-[node name="UndergroundLootSprites" type="Area2D"]
-script = ExtResource("1_knus5")
-default_info_title = "BURIED_SEEDS"
-default_info_desc = "BURIED_SEEDS_DESC_TEXT"
-metadata/_custom_type_script = "uid://d3bk52402ylvl"
-
-[node name="Sprite2D" type="Sprite2D" parent="."]
-modulate = Color(0.286275, 0.219608, 0.313726, 1)
-scale = Vector2(0.0806452, 0.0806452)
-texture = ExtResource("2_jfggo")
-
-[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-shape = SubResource("CircleShape2D_knus5")
diff --git a/gui/game/tutorial/scripts/tutorial.gd b/gui/game/tutorial/scripts/tutorial.gd
index 1c610ff..2f74da1 100644
--- a/gui/game/tutorial/scripts/tutorial.gd
+++ b/gui/game/tutorial/scripts/tutorial.gd
@@ -8,177 +8,204 @@ var indicators : Array[InGameIndicator]
@export var planet : Planet
@onready var steps : Array[Step] = [
- TakeShovelStep.new(),
- DigLootStep.new(),
- TakeSeedStep.new(),
- PlantSeedStep.new(),
- RechargeStep.new(),
- # WaitMaturePlant.new(),
- # HarvestMaturePlant.new(),
+ TakeShovelStep.new(),
+ DigSeedStep.new(),
+ TakeSeedStep.new(),
+ PlantSeedStep.new(),
+ RechargeStep.new(),
+ # WaitMaturePlant.new(),
+ # HarvestMaturePlant.new(),
]
var actual_step : Step = null : set = pass_to_step
func _process(_d):
- if not GameInfo.game_data.tutorial_done:
- if not actual_step and planet.data.tutorial_step < len(steps):
- destroy_indicators()
- pass_to_step(steps[planet.data.tutorial_step])
+ if not GameInfo.game_data.tutorial_done:
+ if not actual_step and planet.data.tutorial_step < len(steps):
+ destroy_indicators()
+ pass_to_step(steps[planet.data.tutorial_step])
- if player and actual_step and actual_step.is_step_over(player, planet):
- destroy_indicators()
- planet.data.tutorial_step += 1
- if planet.data.tutorial_step < len(steps):
- pass_to_step(steps[planet.data.tutorial_step])
- else :
- GameInfo.game_data.tutorial_done = true
+ if player and actual_step and actual_step.is_step_over(player, planet):
+ destroy_indicators()
+ planet.data.tutorial_step += 1
+ if planet.data.tutorial_step < len(steps):
+ pass_to_step(steps[planet.data.tutorial_step])
+ else :
+ GameInfo.game_data.tutorial_done = true
func destroy_indicators():
- for i in indicators:
- i.queue_free()
- indicators = []
+ for i in indicators:
+ i.queue_free()
+ indicators = []
func pass_to_step(new_step : Step):
- actual_step = new_step
- indicators = new_step.generate_indicators(player, planet)
- for i in indicators:
- add_child(i)
+ actual_step = new_step
+ indicators = new_step.generate_indicators(player, planet)
+ for i in indicators:
+ add_child(i)
class Step:
- func generate_indicator(text : String) -> InGameIndicator:
- var new_indicator : InGameIndicator = INDICATOR_SCENE.instantiate()
- new_indicator.setup(
- text
- )
- return new_indicator
+ func generate_indicator(text : String) -> InGameIndicator:
+ var new_indicator : InGameIndicator = INDICATOR_SCENE.instantiate()
+ new_indicator.setup(
+ text
+ )
+ return new_indicator
- func generate_indicators(_player : Player, _planet : Planet) -> Array[InGameIndicator]:
- return []
-
- func is_step_over(_p : Player, _planet : Planet) -> bool:
- return true
-
+ func generate_indicators(_player : Player, _planet : Planet) -> Array[InGameIndicator]:
+ return []
+
+ func is_step_over(_p : Player, _planet : Planet) -> bool:
+ return true
+
class TakeShovelStep extends Step:
- func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
- for entity in planet.entity_container.get_children():
- if entity is ItemObject and entity.item is Shovel:
- var indicator = generate_indicator(tr("TAKE_THE_SHOVEL"))
- indicator.follow_entity(entity)
- return [
- indicator
- ]
- printerr("No Shovel found...")
- return []
-
- func is_step_over(p : Player, _planet : Planet) -> bool:
- for item in p.data.inventory.items:
- if item is Shovel:
- return true
- return false
+ func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
+ for entity in planet.entity_container.get_children():
+ if entity is ItemObject and entity.item is Shovel:
+ var indicator = generate_indicator(tr("TAKE_THE_SHOVEL"))
+ indicator.follow_entity(entity)
+ return [
+ indicator
+ ]
+ printerr("No Shovel found...")
+ return []
+
+ func is_step_over(p : Player, _planet : Planet) -> bool:
+ for item in p.data.inventory.items:
+ if item is Shovel:
+ return true
+ return false
-class DigLootStep extends Step:
- func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
- var closest_loot : UndergroundLoot
- var closest_distance = 10000000
+class DigSeedStep extends Step:
+ func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
+ var closest_seed = null
+ var limit_distance = 1000
- for entity in planet.entity_container.get_children():
- if entity is UndergroundLoot:
- var distance = entity.global_position.distance_to(p.global_position)
- if distance < closest_distance:
- closest_distance = distance
- closest_loot = entity
-
- if closest_loot:
- var indicator = generate_indicator(tr("DIG_UNDERGROUND_LOOT"))
- indicator.follow_entity(closest_loot)
- return [indicator]
- return []
-
- func is_step_over(_p : Player, planet : Planet) -> bool:
- for entity in planet.entity_container.get_children():
- if entity is ItemObject and entity.item is Seed:
- return true
- return false
+ var actual_distance = 100
+ var player_tile = Math.get_tile_from_pos(p.global_position)
+
+ while closest_seed == null and actual_distance < limit_distance:
+ print(player_tile)
+ for x in range(actual_distance):
+ for y in range(actual_distance):
+ var coord = Vector2i(x,y) - Vector2i.ONE * floori(actual_distance/2.) + player_tile
+ if planet.rock_layer.get_tile_type(coord) == RockLayer.TileType.CRISTAL:
+ if closest_seed == null or player_tile.distance_to(coord) < player_tile.distance_to(closest_seed):
+ closest_seed = coord
+
+ actual_distance += 100
+
+ if closest_seed:
+ var indicator = generate_indicator(tr("DIG_UNDERGROUND_LOOT"))
+ indicator.follow_game_position(closest_seed * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.))
+ return [indicator]
+ return []
+
+ func is_step_over(_p : Player, planet : Planet) -> bool:
+ for entity in planet.entity_container.get_children():
+ if entity is ItemObject and entity.item is Seed:
+ return true
+ return false
class TakeSeedStep extends Step:
- func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
- var indicators : Array[InGameIndicator] = []
- for entity in planet.entity_container.get_children():
- if entity is ItemObject and entity.item is Seed:
- var indicator = generate_indicator(tr("TAKE_A_SEED"))
- indicator.follow_entity(entity)
- indicators.append(
- indicator
- )
- return indicators
-
- func is_step_over(p : Player, _planet : Planet) -> bool:
- for item in p.data.inventory.items:
- if item is Seed:
- return true
- return false
+ func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
+ var indicators : Array[InGameIndicator] = []
+ for entity in planet.entity_container.get_children():
+ if entity is ItemObject and entity.item is Seed:
+ var indicator = generate_indicator(tr("TAKE_A_SEED"))
+ indicator.follow_entity(entity)
+ indicators.append(
+ indicator
+ )
+ return indicators
+
+ func is_step_over(p : Player, _planet : Planet) -> bool:
+ for item in p.data.inventory.items:
+ if item is Seed:
+ return true
+ return false
class PlantSeedStep extends Step:
- func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
- var indicator = generate_indicator(tr("PLANT_THE_SEED_IN_DECONTAMINED_ZONE"))
- indicator.follow_game_position(Vector2(0,0) + planet.entity_container.global_position)
- return [indicator]
-
- func is_step_over(_p : Player, planet : Planet) -> bool:
- for entity in planet.entity_container.get_children():
- if entity is Plant:
- return true
- return false
+ func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
+
+ var closest_decontamination = null
+ var limit_distance = 1000
+
+ var actual_distance = 100
+ var player_tile = Math.get_tile_from_pos(p.global_position)
+
+ while closest_decontamination == null and actual_distance < limit_distance:
+ print(player_tile)
+ for x in range(actual_distance):
+ for y in range(actual_distance):
+ var coord = Vector2i(x,y) - Vector2i.ONE * floori(actual_distance/2.) + player_tile
+ if planet.decontamination_layer.is_decontamined(coord):
+ if closest_decontamination == null or player_tile.distance_to(coord) < player_tile.distance_to(closest_decontamination):
+ closest_decontamination = coord
+
+ actual_distance += 100
+
+ if closest_decontamination:
+ var indicator = generate_indicator(tr("PLANT_THE_SEED_IN_DECONTAMINED_ZONE"))
+ indicator.follow_game_position(closest_decontamination * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.))
+ return [indicator]
+ return []
+
+ func is_step_over(_p : Player, planet : Planet) -> bool:
+ for entity in planet.entity_container.get_children():
+ if entity is Plant:
+ return true
+ return false
class RechargeStep extends Step:
- func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
- for entity in planet.entity_container.get_children():
- var indicator = generate_indicator(tr("RECHARGE_TO_PASS_DAYS"))
- indicator.follow_entity(entity)
- if entity is TruckRecharge:
- return [
- indicator
- ]
- printerr("No Recharge Station found...")
- return []
-
- func is_step_over(_p : Player, planet : Planet) -> bool:
- if planet == null :
- return false
- return planet.data.day > 1
+ func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
+ for entity in planet.entity_container.get_children():
+ var indicator = generate_indicator(tr("RECHARGE_TO_PASS_DAYS"))
+ indicator.follow_entity(entity)
+ if entity is TruckRecharge:
+ return [
+ indicator
+ ]
+ printerr("No Recharge Station found...")
+ return []
+
+ func is_step_over(_p : Player, planet : Planet) -> bool:
+ if planet == null :
+ return false
+ return planet.data.day > 1
class WaitMaturePlant extends Step:
- func generate_indicators(_p: Player, _planet : Planet) -> Array[InGameIndicator]:
- return []
-
- func is_step_over(_p : Player, planet : Planet) -> bool:
- if planet == null :
- return false
- for entity in planet.entity_container.get_children():
- if entity is Plant and entity.state == Plant.State.MATURE:
- return true
- return false
+ func generate_indicators(_p: Player, _planet : Planet) -> Array[InGameIndicator]:
+ return []
+
+ func is_step_over(_p : Player, planet : Planet) -> bool:
+ if planet == null :
+ return false
+ for entity in planet.entity_container.get_children():
+ if entity is Plant and entity.state == Plant.State.MATURE:
+ return true
+ return false
class HarvestMaturePlant extends Step:
- var mature_plant_number : int = 0
+ var mature_plant_number : int = 0
- func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
- var indicators : Array[InGameIndicator] = []
- for entity in planet.entity_container.get_children():
- if entity is Plant and entity.state == Plant.State.MATURE:
- var indicator = generate_indicator(tr("HARVEST_MATURE_PLANTS_WITH_SHOVEL"))
- indicator.follow_entity(entity)
- indicators.append(
- indicator
- )
- mature_plant_number += 1
- return indicators
-
- func is_step_over(_p : Player, planet : Planet) -> bool:
- if planet == null :
- return false
- var actual_mature_plant_number = 0
- for entity in planet.entity_container.get_children():
- if entity is Plant and entity.state == Plant.State.MATURE:
- actual_mature_plant_number += 1
- return mature_plant_number != actual_mature_plant_number
+ func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
+ var indicators : Array[InGameIndicator] = []
+ for entity in planet.entity_container.get_children():
+ if entity is Plant and entity.state == Plant.State.MATURE:
+ var indicator = generate_indicator(tr("HARVEST_MATURE_PLANTS_WITH_SHOVEL"))
+ indicator.follow_entity(entity)
+ indicators.append(
+ indicator
+ )
+ mature_plant_number += 1
+ return indicators
+
+ func is_step_over(_p : Player, planet : Planet) -> bool:
+ if planet == null :
+ return false
+ var actual_mature_plant_number = 0
+ for entity in planet.entity_container.get_children():
+ if entity is Plant and entity.state == Plant.State.MATURE:
+ actual_mature_plant_number += 1
+ return mature_plant_number != actual_mature_plant_number
diff --git a/readme.md b/readme.md
index 03f825f..047cb59 100644
--- a/readme.md
+++ b/readme.md
@@ -85,9 +85,9 @@ Pour ajouter un ou plusieurs fichiers ou modifier du code dans le projet, suivez
4. Créer une demande de modification dans Gitea en suivant [ce lien](https://git.zacharie-guet.fr/zacharie/seeding-planets/pulls), cliquez sur Demande d'ajout et renseignez comme suit
- Fusionner dans `main`
- Tirer les modification depuis votre branche
- - Cliquez sur "Nouvelle Demande d'ajout"
+ - Cliquez sur "Nouvelle Demande d'ajout"
- Editer le titre de la demande d'ajout ou laissez comme telle
- - Cliquez sur sur "Créer une demande d'ajout"
+ - Cliquez sur sur "Créer une demande d'ajout"
5. Communiquez avec l'équipe sur cette demande d'ajout, et appliquer la si vous avez l'aval de tous le monde (ou du moins des concernés du changement), en cliquant sur "Rebaser et avancer rapidement"
> Pour actualiser votre dépôt local, replacez vous sur `main` et récupérer les nouvelles modifications
diff --git a/stages/planet_run/planet_run.tscn b/stages/planet_run/planet_run.tscn
index 5fde303..9fc577d 100644
--- a/stages/planet_run/planet_run.tscn
+++ b/stages/planet_run/planet_run.tscn
@@ -27,7 +27,7 @@ metadata/_edit_use_anchors_ = true
visible = false
[node name="Tutorial" parent="CanvasLayer" node_paths=PackedStringArray("player", "planet") instance=ExtResource("5_orelw")]
-player = NodePath("../../Entities/Player")
+player = NodePath("../../Planet/Entities/Player")
planet = NodePath("../../Planet")
[node name="BaseIndicator" parent="CanvasLayer" node_paths=PackedStringArray("player") instance=ExtResource("5_gisiu")]
@@ -36,28 +36,28 @@ offset_bottom = 91.0
size_flags_horizontal = 4
size_flags_vertical = 4
script = ExtResource("6_cnjsq")
-player = NodePath("../../Entities/Player")
+player = NodePath("../../Planet/Entities/Player")
-[node name="Entities" type="Node2D" parent="."]
-y_sort_enabled = true
-
-[node name="Player" parent="Entities" instance=ExtResource("4_g33f4")]
-position = Vector2(33, -75)
-
-[node name="TruckLadder" parent="Entities" instance=ExtResource("9_gisiu")]
-position = Vector2(50, -135)
-
-[node name="TruckRecharge" parent="Entities" instance=ExtResource("10_cnjsq")]
-position = Vector2(-46, -152)
-
-[node name="Planet" parent="." node_paths=PackedStringArray("quota_reward", "import_entities_from_node") instance=ExtResource("8_t31p7")]
+[node name="Planet" parent="." node_paths=PackedStringArray("quota_reward", "entity_container") instance=ExtResource("8_t31p7")]
loot_item_number = Array[int]([1])
quota_reward = NodePath("../Reward")
-import_entities_from_node = NodePath("../Entities")
+entity_container = NodePath("Entities")
+
+[node name="Entities" type="Node2D" parent="Planet"]
+y_sort_enabled = true
+
+[node name="Player" parent="Planet/Entities" instance=ExtResource("4_g33f4")]
+position = Vector2(2, 0)
+
+[node name="TruckLadder" parent="Planet/Entities" instance=ExtResource("9_gisiu")]
+position = Vector2(50, -135)
+
+[node name="TruckRecharge" parent="Planet/Entities" instance=ExtResource("10_cnjsq")]
+position = Vector2(-46, -152)
[node name="Camera" parent="." node_paths=PackedStringArray("following") instance=ExtResource("16_m18ms")]
position = Vector2(2.22, 0)
-following = NodePath("../Entities/Player")
+following = NodePath("../Planet/Entities/Player")
[connection signal="day_limit_exceed" from="Planet" to="CanvasLayer/Win" method="_on_planet_day_limit_exceed"]
[connection signal="pass_day_ended" from="Planet" to="RootGui" method="_on_planet_pass_day_ended"]
diff --git a/stages/terrain/planet/assets/textures/blue_rect.png b/stages/terrain/planet/assets/textures/blue_rect.png
new file mode 100644
index 0000000..1f4b9f1
Binary files /dev/null and b/stages/terrain/planet/assets/textures/blue_rect.png differ
diff --git a/stages/terrain/planet/assets/textures/blue_rect.png.import b/stages/terrain/planet/assets/textures/blue_rect.png.import
new file mode 100644
index 0000000..7baf2d6
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/blue_rect.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cd62k5urdpw3i"
+path="res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/blue_rect.png"
+dest_files=["res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/assets/textures/green_rect.png b/stages/terrain/planet/assets/textures/green_rect.png
new file mode 100644
index 0000000..212e668
Binary files /dev/null and b/stages/terrain/planet/assets/textures/green_rect.png differ
diff --git a/stages/terrain/planet/assets/textures/green_rect.png.import b/stages/terrain/planet/assets/textures/green_rect.png.import
new file mode 100644
index 0000000..0a8f4f1
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/green_rect.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bvangyp301tsp"
+path="res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/green_rect.png"
+dest_files=["res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/assets/textures/green_tiles.png b/stages/terrain/planet/assets/textures/green_tiles.png
new file mode 100644
index 0000000..490fe57
Binary files /dev/null and b/stages/terrain/planet/assets/textures/green_tiles.png differ
diff --git a/stages/terrain/planet/assets/textures/green_tiles.png.import b/stages/terrain/planet/assets/textures/green_tiles.png.import
new file mode 100644
index 0000000..2c4c1c0
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/green_tiles.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://yl4dg6gerykb"
+path="res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/green_tiles.png"
+dest_files=["res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/assets/textures/red_rect.png b/stages/terrain/planet/assets/textures/red_rect.png
new file mode 100644
index 0000000..ab11b0f
Binary files /dev/null and b/stages/terrain/planet/assets/textures/red_rect.png differ
diff --git a/stages/terrain/planet/assets/textures/red_rect.png.import b/stages/terrain/planet/assets/textures/red_rect.png.import
new file mode 100644
index 0000000..84486f5
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/red_rect.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bi08trir23od2"
+path="res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/red_rect.png"
+dest_files=["res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/assets/textures/red_tiles.png b/stages/terrain/planet/assets/textures/red_tiles.png
new file mode 100644
index 0000000..adce628
Binary files /dev/null and b/stages/terrain/planet/assets/textures/red_tiles.png differ
diff --git a/stages/terrain/planet/assets/textures/red_tiles.png.import b/stages/terrain/planet/assets/textures/red_tiles.png.import
new file mode 100644
index 0000000..c67c3f0
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/red_tiles.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ddecvei4l62gn"
+path="res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/red_tiles.png"
+dest_files=["res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=false
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=0
diff --git a/stages/terrain/planet/assets/textures/rock_cristal_texture.png b/stages/terrain/planet/assets/textures/rock_cristal_texture.png
new file mode 100644
index 0000000..aa42e88
Binary files /dev/null and b/stages/terrain/planet/assets/textures/rock_cristal_texture.png differ
diff --git a/stages/terrain/planet/assets/textures/rock_cristal_texture.png.import b/stages/terrain/planet/assets/textures/rock_cristal_texture.png.import
new file mode 100644
index 0000000..1289aa3
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/rock_cristal_texture.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://02nuoqleo4yu"
+path="res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png"
+dest_files=["res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/assets/textures/round_red_tiles.png b/stages/terrain/planet/assets/textures/round_red_tiles.png
new file mode 100644
index 0000000..8986d1a
Binary files /dev/null and b/stages/terrain/planet/assets/textures/round_red_tiles.png differ
diff --git a/stages/terrain/planet/assets/textures/round_red_tiles.png.import b/stages/terrain/planet/assets/textures/round_red_tiles.png.import
new file mode 100644
index 0000000..cd33a85
--- /dev/null
+++ b/stages/terrain/planet/assets/textures/round_red_tiles.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bmdb63witojeg"
+path="res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://stages/terrain/planet/assets/textures/round_red_tiles.png"
+dest_files=["res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/stages/terrain/planet/planet.tscn b/stages/terrain/planet/planet.tscn
index 16effc2..a92f881 100644
--- a/stages/terrain/planet/planet.tscn
+++ b/stages/terrain/planet/planet.tscn
@@ -1,48 +1,6 @@
-[gd_scene load_steps=10 format=3 uid="uid://tsi5j1uxppa4"]
+[gd_scene load_steps=2 format=3 uid="uid://tsi5j1uxppa4"]
[ext_resource type="Script" uid="uid://d1mp5sguc0b6u" path="res://stages/terrain/planet/scripts/planet.gd" id="1_y7d8a"]
-[ext_resource type="Shader" uid="uid://bglep64ppn74p" path="res://common/vfx/materials/shaders/textures_data_filter.gdshader" id="3_6qoee"]
-
-[sub_resource type="FastNoiseLite" id="FastNoiseLite_3v4ta"]
-frequency = 0.04
-offset = Vector3(0, 10, 0)
-fractal_weighted_strength = 1.0
-
-[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7jtco"]
-width = 50
-height = 50
-noise = SubResource("FastNoiseLite_3v4ta")
-seamless_blend_skirt = 0.0
-
-[sub_resource type="Gradient" id="Gradient_ydx6d"]
-colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1)
-
-[sub_resource type="GradientTexture1D" id="GradientTexture1D_6cs2h"]
-gradient = SubResource("Gradient_ydx6d")
-width = 1
-
-[sub_resource type="Gradient" id="Gradient_qxify"]
-offsets = PackedFloat32Array(0)
-colors = PackedColorArray(0, 0, 0, 1)
-
-[sub_resource type="GradientTexture1D" id="GradientTexture1D_sd6ll"]
-gradient = SubResource("Gradient_qxify")
-width = 1
-
-[sub_resource type="ShaderMaterial" id="ShaderMaterial_hyapw"]
-shader = ExtResource("3_6qoee")
-shader_parameter/data_texture = SubResource("NoiseTexture2D_7jtco")
-shader_parameter/data_texture_size = Vector2(120, 120)
-shader_parameter/data_texture_threshold = 0.5
-shader_parameter/texture_0 = SubResource("GradientTexture1D_6cs2h")
-shader_parameter/texture_1 = SubResource("GradientTexture1D_sd6ll")
-shader_parameter/texture_scale = 5.0
[node name="Planet" type="Node2D"]
script = ExtResource("1_y7d8a")
-
-[node name="Polygon2D2" type="Polygon2D" parent="."]
-visible = false
-material = SubResource("ShaderMaterial_hyapw")
-position = Vector2(-10, -10)
-polygon = PackedVector2Array(10, 10, 10, 110, 110, 110, 110, 10)
diff --git a/stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres b/stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres
new file mode 100644
index 0000000..81cd832
--- /dev/null
+++ b/stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres
@@ -0,0 +1,9 @@
+[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://b3vnia5tb6pil"]
+
+[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_4m73r"]
+[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_4m73r"]
+
+[resource]
+shader = ExtResource("1_4m73r")
+shader_parameter/red_overlay_tex = ExtResource("2_4m73r")
+shader_parameter/scale = 0.006944444
diff --git a/stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres b/stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres
new file mode 100644
index 0000000..b06aae2
--- /dev/null
+++ b/stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres
@@ -0,0 +1,9 @@
+[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://85ap1buim1ha"]
+
+[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_v8wor"]
+[ext_resource type="Texture2D" uid="uid://c3t26nlbnkxg7" path="res://stages/terrain/planet/assets/textures/garden_decontamined_background_texture.png" id="2_v8wor"]
+
+[resource]
+shader = ExtResource("1_v8wor")
+shader_parameter/red_overlay_tex = ExtResource("2_v8wor")
+shader_parameter/scale = 0.006944444
diff --git a/stages/terrain/planet/resources/materials/ground_planet_tilemap.tres b/stages/terrain/planet/resources/materials/ground_planet_tilemap.tres
new file mode 100644
index 0000000..ef138ce
--- /dev/null
+++ b/stages/terrain/planet/resources/materials/ground_planet_tilemap.tres
@@ -0,0 +1,9 @@
+[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://dpxu8yeee4qi1"]
+
+[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_6vcas"]
+[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_x0w2y"]
+
+[resource]
+shader = ExtResource("1_6vcas")
+shader_parameter/red_overlay_tex = ExtResource("2_x0w2y")
+shader_parameter/scale = 0.006944444
diff --git a/stages/terrain/planet/resources/materials/rock_planet_tilemap.tres b/stages/terrain/planet/resources/materials/rock_planet_tilemap.tres
new file mode 100644
index 0000000..ce8a0ab
--- /dev/null
+++ b/stages/terrain/planet/resources/materials/rock_planet_tilemap.tres
@@ -0,0 +1,11 @@
+[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://d365ovfmi3d0s"]
+
+[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_xr5ia"]
+[ext_resource type="Texture2D" uid="uid://beqx4rmgthkql" path="res://stages/terrain/planet/assets/textures/rock_background_texture.png" id="2_ieaec"]
+[ext_resource type="Texture2D" uid="uid://02nuoqleo4yu" path="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png" id="2_sc014"]
+
+[resource]
+shader = ExtResource("1_xr5ia")
+shader_parameter/red_overlay_tex = ExtResource("2_ieaec")
+shader_parameter/green_overlay_tex = ExtResource("2_sc014")
+shader_parameter/scale = 0.006944444
diff --git a/stages/terrain/planet/resources/planet_tileset.tres b/stages/terrain/planet/resources/planet_tileset.tres
new file mode 100644
index 0000000..5b5d74e
--- /dev/null
+++ b/stages/terrain/planet/resources/planet_tileset.tres
@@ -0,0 +1,1213 @@
+[gd_resource type="TileSet" load_steps=10 format=3 uid="uid://b3m7ve0adlxi1"]
+
+[ext_resource type="Texture2D" uid="uid://yl4dg6gerykb" path="res://stages/terrain/planet/assets/textures/green_tiles.png" id="1_gjijh"]
+[ext_resource type="Texture2D" uid="uid://bi08trir23od2" path="res://stages/terrain/planet/assets/textures/red_rect.png" id="1_hqeut"]
+[ext_resource type="Texture2D" uid="uid://ddecvei4l62gn" path="res://stages/terrain/planet/assets/textures/red_tiles.png" id="1_uvbas"]
+[ext_resource type="Texture2D" uid="uid://bmdb63witojeg" path="res://stages/terrain/planet/assets/textures/round_red_tiles.png" id="5_skkk4"]
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_f4n6l"]
+texture = ExtResource("1_hqeut")
+texture_region_size = Vector2i(64, 64)
+0:0/0 = 0
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_rklv6"]
+resource_name = "GreenPhysic"
+texture = ExtResource("1_gjijh")
+texture_region_size = Vector2i(64, 64)
+0:0/0 = 0
+0:0/0/terrain_set = 0
+0:0/0/terrain = 1
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 32, -16, 32)
+0:0/0/terrains_peering_bit/bottom_side = 1
+1:0/0 = 0
+1:0/0/terrain_set = 0
+1:0/0/terrain = 1
+1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 32, -16, 32, 16, 16, 32, -16, 32)
+1:0/0/terrains_peering_bit/right_side = 1
+1:0/0/terrains_peering_bit/bottom_side = 1
+2:0/0 = 0
+2:0/0/terrain_set = 0
+2:0/0/terrain = 1
+2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, 16, 32, -16, 32, -32, 16)
+2:0/0/terrains_peering_bit/right_side = 1
+2:0/0/terrains_peering_bit/bottom_side = 1
+2:0/0/terrains_peering_bit/left_side = 1
+3:0/0 = 0
+3:0/0/terrain_set = 0
+3:0/0/terrain = 1
+3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 16, -16, 16, 32, -16, 32, -32, 16.369743)
+3:0/0/terrains_peering_bit/bottom_side = 1
+3:0/0/terrains_peering_bit/left_side = 1
+4:0/0 = 0
+4:0/0/terrain_set = 0
+4:0/0/terrain = 1
+4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 15.240791, 16, 32, -16, 32, -32, 19.192108)
+4:0/0/terrains_peering_bit/right_side = 1
+4:0/0/terrains_peering_bit/bottom_side = 1
+4:0/0/terrains_peering_bit/left_side = 1
+4:0/0/terrains_peering_bit/top_left_corner = 1
+4:0/0/terrains_peering_bit/top_side = 1
+5:0/0 = 0
+5:0/0/terrain_set = 0
+5:0/0/terrain = 1
+5:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 32, -16, 32, -32, 16)
+5:0/0/terrains_peering_bit/right_side = 1
+5:0/0/terrains_peering_bit/bottom_right_corner = 1
+5:0/0/terrains_peering_bit/bottom_side = 1
+5:0/0/terrains_peering_bit/left_side = 1
+6:0/0 = 0
+6:0/0/terrain_set = 0
+6:0/0/terrain = 1
+6:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, 16, 32, -32, 32)
+6:0/0/terrains_peering_bit/right_side = 1
+6:0/0/terrains_peering_bit/bottom_side = 1
+6:0/0/terrains_peering_bit/bottom_left_corner = 1
+6:0/0/terrains_peering_bit/left_side = 1
+7:0/0 = 0
+7:0/0/terrain_set = 0
+7:0/0/terrain = 1
+7:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 32, -32, 32, 16, 16, 32, -16, 32, -32, 16)
+7:0/0/terrains_peering_bit/right_side = 1
+7:0/0/terrains_peering_bit/bottom_side = 1
+7:0/0/terrains_peering_bit/left_side = 1
+7:0/0/terrains_peering_bit/top_side = 1
+7:0/0/terrains_peering_bit/top_right_corner = 1
+8:0/0 = 0
+8:0/0/terrain_set = 0
+8:0/0/terrain = 1
+8:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 32, -16, 32, 32, -16, 32)
+8:0/0/terrains_peering_bit/right_side = 1
+8:0/0/terrains_peering_bit/bottom_right_corner = 1
+8:0/0/terrains_peering_bit/bottom_side = 1
+9:0/0 = 0
+9:0/0/terrain_set = 0
+9:0/0/terrain = 1
+9:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 32, -16, 32, 32, -32, 32)
+9:0/0/terrains_peering_bit/right_side = 1
+9:0/0/terrains_peering_bit/bottom_right_corner = 1
+9:0/0/terrains_peering_bit/bottom_side = 1
+9:0/0/terrains_peering_bit/bottom_left_corner = 1
+9:0/0/terrains_peering_bit/left_side = 1
+9:0/0/terrains_peering_bit/top_side = 1
+10:0/0 = 0
+10:0/0/terrain_set = 0
+10:0/0/terrain = 1
+10:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 32, -32, 32)
+10:0/0/terrains_peering_bit/right_side = 1
+10:0/0/terrains_peering_bit/bottom_right_corner = 1
+10:0/0/terrains_peering_bit/bottom_side = 1
+10:0/0/terrains_peering_bit/bottom_left_corner = 1
+10:0/0/terrains_peering_bit/left_side = 1
+11:0/0 = 0
+11:0/0/terrain_set = 0
+11:0/0/terrain = 1
+11:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 16, -16, 16, 32, -32, 32)
+11:0/0/terrains_peering_bit/bottom_side = 1
+11:0/0/terrains_peering_bit/bottom_left_corner = 1
+11:0/0/terrains_peering_bit/left_side = 1
+0:1/0 = 0
+0:1/0/terrain_set = 0
+0:1/0/terrain = 1
+0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 16, 32, -16, 32)
+0:1/0/terrains_peering_bit/bottom_side = 1
+0:1/0/terrains_peering_bit/top_side = 1
+1:1/0 = 0
+1:1/0/terrain_set = 0
+1:1/0/terrain = 1
+1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 14.111847, 16, 32, -16, 32)
+1:1/0/terrains_peering_bit/right_side = 1
+1:1/0/terrains_peering_bit/bottom_side = 1
+1:1/0/terrains_peering_bit/top_side = 1
+2:1/0 = 0
+2:1/0/terrain_set = 0
+2:1/0/terrain = 1
+2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16.369743, -32, 32, -16, 32, 16.369743, 16, 32, -16, 32, -32, 18.62764)
+2:1/0/terrains_peering_bit/right_side = 1
+2:1/0/terrains_peering_bit/bottom_side = 1
+2:1/0/terrains_peering_bit/left_side = 1
+2:1/0/terrains_peering_bit/top_side = 1
+3:1/0 = 0
+3:1/0/terrain_set = 0
+3:1/0/terrain = 1
+3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 16, 32, -16, 32, -32, 16, -32, -16)
+3:1/0/terrains_peering_bit/bottom_side = 1
+3:1/0/terrains_peering_bit/left_side = 1
+3:1/0/terrains_peering_bit/top_side = 1
+4:1/0 = 0
+4:1/0/terrain_set = 0
+4:1/0/terrain = 1
+4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 32, -16, 32)
+4:1/0/terrains_peering_bit/right_side = 1
+4:1/0/terrains_peering_bit/bottom_right_corner = 1
+4:1/0/terrains_peering_bit/bottom_side = 1
+4:1/0/terrains_peering_bit/top_side = 1
+5:1/0 = 0
+5:1/0/terrain_set = 0
+5:1/0/terrain = 1
+5:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -15.240795, -32, 32, -32, 32, 32, -32, 32)
+5:1/0/terrains_peering_bit/right_side = 1
+5:1/0/terrains_peering_bit/bottom_right_corner = 1
+5:1/0/terrains_peering_bit/bottom_side = 1
+5:1/0/terrains_peering_bit/bottom_left_corner = 1
+5:1/0/terrains_peering_bit/left_side = 1
+5:1/0/terrains_peering_bit/top_side = 1
+5:1/0/terrains_peering_bit/top_right_corner = 1
+6:1/0 = 0
+6:1/0/terrain_set = 0
+6:1/0/terrain = 1
+6:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 32, -32, 32)
+6:1/0/terrains_peering_bit/right_side = 1
+6:1/0/terrains_peering_bit/bottom_right_corner = 1
+6:1/0/terrains_peering_bit/bottom_side = 1
+6:1/0/terrains_peering_bit/bottom_left_corner = 1
+6:1/0/terrains_peering_bit/left_side = 1
+6:1/0/terrains_peering_bit/top_left_corner = 1
+6:1/0/terrains_peering_bit/top_side = 1
+7:1/0 = 0
+7:1/0/terrain_set = 0
+7:1/0/terrain = 1
+7:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 16, 32, -32, 32)
+7:1/0/terrains_peering_bit/bottom_side = 1
+7:1/0/terrains_peering_bit/bottom_left_corner = 1
+7:1/0/terrains_peering_bit/left_side = 1
+7:1/0/terrains_peering_bit/top_side = 1
+8:1/0 = 0
+8:1/0/terrain_set = 0
+8:1/0/terrain = 1
+8:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 32, -16, 32)
+8:1/0/terrains_peering_bit/right_side = 1
+8:1/0/terrains_peering_bit/bottom_right_corner = 1
+8:1/0/terrains_peering_bit/bottom_side = 1
+8:1/0/terrains_peering_bit/top_side = 1
+8:1/0/terrains_peering_bit/top_right_corner = 1
+9:1/0 = 0
+9:1/0/terrain_set = 0
+9:1/0/terrain = 1
+9:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 32, -32, 32, 16, 16, 32, -32, 32)
+9:1/0/terrains_peering_bit/right_side = 1
+9:1/0/terrains_peering_bit/bottom_side = 1
+9:1/0/terrains_peering_bit/bottom_left_corner = 1
+9:1/0/terrains_peering_bit/left_side = 1
+9:1/0/terrains_peering_bit/top_side = 1
+9:1/0/terrains_peering_bit/top_right_corner = 1
+10:1/0 = 0
+10:1/0/terrain_set = 0
+11:1/0 = 0
+11:1/0/terrain_set = 0
+11:1/0/terrain = 1
+11:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 16, 16, 32, -32, 32)
+11:1/0/terrains_peering_bit/right_side = 1
+11:1/0/terrains_peering_bit/bottom_side = 1
+11:1/0/terrains_peering_bit/bottom_left_corner = 1
+11:1/0/terrains_peering_bit/left_side = 1
+11:1/0/terrains_peering_bit/top_left_corner = 1
+11:1/0/terrains_peering_bit/top_side = 1
+0:2/0 = 0
+0:2/0/terrain_set = 0
+0:2/0/terrain = 1
+0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 16, 16, -16, 16)
+0:2/0/terrains_peering_bit/top_side = 1
+1:2/0 = 0
+1:2/0/terrain_set = 0
+1:2/0/terrain = 1
+1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16.934216, 32, 16, -16, 16)
+1:2/0/terrains_peering_bit/right_side = 1
+1:2/0/terrains_peering_bit/top_side = 1
+2:2/0 = 0
+2:2/0/terrain_set = 0
+2:2/0/terrain = 1
+2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -17.498692, 32, 16, -32, 16, -32, -16.369743)
+2:2/0/terrains_peering_bit/right_side = 1
+2:2/0/terrains_peering_bit/left_side = 1
+2:2/0/terrains_peering_bit/top_side = 1
+3:2/0 = 0
+3:2/0/terrain_set = 0
+3:2/0/terrain = 1
+3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 16, 16, -32, 16)
+3:2/0/terrains_peering_bit/left_side = 1
+3:2/0/terrains_peering_bit/top_side = 1
+4:2/0 = 0
+4:2/0/terrain_set = 0
+4:2/0/terrain = 1
+4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 16, 16, 32, -16, 32)
+4:2/0/terrains_peering_bit/right_side = 1
+4:2/0/terrains_peering_bit/bottom_side = 1
+4:2/0/terrains_peering_bit/top_side = 1
+4:2/0/terrains_peering_bit/top_right_corner = 1
+5:2/0 = 0
+5:2/0/terrain_set = 0
+5:2/0/terrain = 1
+5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 32, -16.369743, 32, -32, 16)
+5:2/0/terrains_peering_bit/right_side = 1
+5:2/0/terrains_peering_bit/bottom_right_corner = 1
+5:2/0/terrains_peering_bit/bottom_side = 1
+5:2/0/terrains_peering_bit/left_side = 1
+5:2/0/terrains_peering_bit/top_left_corner = 1
+5:2/0/terrains_peering_bit/top_side = 1
+5:2/0/terrains_peering_bit/top_right_corner = 1
+6:2/0 = 0
+6:2/0/terrain_set = 0
+6:2/0/terrain = 1
+6:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 16, 17.498688, 32, -32, 32)
+6:2/0/terrains_peering_bit/right_side = 1
+6:2/0/terrains_peering_bit/bottom_side = 1
+6:2/0/terrains_peering_bit/bottom_left_corner = 1
+6:2/0/terrains_peering_bit/left_side = 1
+6:2/0/terrains_peering_bit/top_left_corner = 1
+6:2/0/terrains_peering_bit/top_side = 1
+6:2/0/terrains_peering_bit/top_right_corner = 1
+7:2/0 = 0
+7:2/0/terrain_set = 0
+7:2/0/terrain = 1
+7:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 16, 32, -16, 32, -32, 16)
+7:2/0/terrains_peering_bit/bottom_side = 1
+7:2/0/terrains_peering_bit/left_side = 1
+7:2/0/terrains_peering_bit/top_left_corner = 1
+7:2/0/terrains_peering_bit/top_side = 1
+8:2/0 = 0
+8:2/0/terrain_set = 0
+8:2/0/terrain = 1
+8:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 32, -32, 32, 32, -16, 32, -32, 16)
+8:2/0/terrains_peering_bit/right_side = 1
+8:2/0/terrains_peering_bit/bottom_right_corner = 1
+8:2/0/terrains_peering_bit/bottom_side = 1
+8:2/0/terrains_peering_bit/left_side = 1
+8:2/0/terrains_peering_bit/top_side = 1
+8:2/0/terrains_peering_bit/top_right_corner = 1
+9:2/0 = 0
+9:2/0/terrain_set = 0
+9:2/0/terrain = 1
+9:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 32, -32, 32)
+9:2/0/terrains_peering_bit/right_side = 1
+9:2/0/terrains_peering_bit/bottom_right_corner = 1
+9:2/0/terrains_peering_bit/bottom_side = 1
+9:2/0/terrains_peering_bit/bottom_left_corner = 1
+9:2/0/terrains_peering_bit/left_side = 1
+9:2/0/terrains_peering_bit/top_left_corner = 1
+9:2/0/terrains_peering_bit/top_side = 1
+9:2/0/terrains_peering_bit/top_right_corner = 1
+10:2/0 = 0
+10:2/0/terrain_set = 0
+10:2/0/terrain = 1
+10:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 32, -16, 32, -32, 16)
+10:2/0/terrains_peering_bit/right_side = 1
+10:2/0/terrains_peering_bit/bottom_right_corner = 1
+10:2/0/terrains_peering_bit/bottom_side = 1
+10:2/0/terrains_peering_bit/left_side = 1
+10:2/0/terrains_peering_bit/top_left_corner = 1
+10:2/0/terrains_peering_bit/top_side = 1
+11:2/0 = 0
+11:2/0/terrain_set = 0
+11:2/0/terrain = 1
+11:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 16, 32, -32, 32)
+11:2/0/terrains_peering_bit/bottom_side = 1
+11:2/0/terrains_peering_bit/bottom_left_corner = 1
+11:2/0/terrains_peering_bit/left_side = 1
+11:2/0/terrains_peering_bit/top_left_corner = 1
+11:2/0/terrains_peering_bit/top_side = 1
+0:3/0 = 0
+0:3/0/terrain_set = 0
+0:3/0/terrain = 1
+0:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 0, 0, -16, 16, 0, 0, 16)
+1:3/0 = 0
+1:3/0/terrain_set = 0
+1:3/0/terrain = 1
+1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 32, -16, 32, 16, -16, 16)
+1:3/0/terrains_peering_bit/right_side = 1
+2:3/0 = 0
+2:3/0/terrain_set = 0
+2:3/0/terrain = 1
+2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, -32, 16)
+2:3/0/terrains_peering_bit/right_side = 1
+2:3/0/terrains_peering_bit/left_side = 1
+3:3/0 = 0
+3:3/0/terrain_set = 0
+3:3/0/terrain = 1
+3:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 16, -16, 16, 16, -32, 16)
+3:3/0/terrains_peering_bit/left_side = 1
+4:3/0 = 0
+4:3/0/terrain_set = 0
+4:3/0/terrain = 1
+4:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 16, 16, 32, -32, 32, -32, -16)
+4:3/0/terrains_peering_bit/right_side = 1
+4:3/0/terrains_peering_bit/bottom_side = 1
+4:3/0/terrains_peering_bit/bottom_left_corner = 1
+4:3/0/terrains_peering_bit/left_side = 1
+4:3/0/terrains_peering_bit/top_side = 1
+5:3/0 = 0
+5:3/0/terrain_set = 0
+5:3/0/terrain = 1
+5:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 32, -32, 32, 16, -32, 16)
+5:3/0/terrains_peering_bit/right_side = 1
+5:3/0/terrains_peering_bit/left_side = 1
+5:3/0/terrains_peering_bit/top_side = 1
+5:3/0/terrains_peering_bit/top_right_corner = 1
+6:3/0 = 0
+6:3/0/terrain_set = 0
+6:3/0/terrain = 1
+6:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -15.805267, 32, 16, -32, 16)
+6:3/0/terrains_peering_bit/right_side = 1
+6:3/0/terrains_peering_bit/left_side = 1
+6:3/0/terrains_peering_bit/top_left_corner = 1
+6:3/0/terrains_peering_bit/top_side = 1
+7:3/0 = 0
+7:3/0/terrain_set = 0
+7:3/0/terrain = 1
+7:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -15.240795, -32, 16, -32, 32, -16, 32, 32, -16, 32, -32, 16)
+7:3/0/terrains_peering_bit/right_side = 1
+7:3/0/terrains_peering_bit/bottom_right_corner = 1
+7:3/0/terrains_peering_bit/bottom_side = 1
+7:3/0/terrains_peering_bit/left_side = 1
+7:3/0/terrains_peering_bit/top_side = 1
+8:3/0 = 0
+8:3/0/terrain_set = 0
+8:3/0/terrain = 1
+8:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 16, -16, 16)
+8:3/0/terrains_peering_bit/right_side = 1
+8:3/0/terrains_peering_bit/top_side = 1
+8:3/0/terrains_peering_bit/top_right_corner = 1
+9:3/0 = 0
+9:3/0/terrain_set = 0
+9:3/0/terrain = 1
+9:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 16, -32, 16)
+9:3/0/terrains_peering_bit/right_side = 1
+9:3/0/terrains_peering_bit/left_side = 1
+9:3/0/terrains_peering_bit/top_left_corner = 1
+9:3/0/terrains_peering_bit/top_side = 1
+9:3/0/terrains_peering_bit/top_right_corner = 1
+10:3/0 = 0
+10:3/0/terrain_set = 0
+10:3/0/terrain = 1
+10:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 16, 16, 32, -16, 32, -32, 16)
+10:3/0/terrains_peering_bit/right_side = 1
+10:3/0/terrains_peering_bit/bottom_side = 1
+10:3/0/terrains_peering_bit/left_side = 1
+10:3/0/terrains_peering_bit/top_left_corner = 1
+10:3/0/terrains_peering_bit/top_side = 1
+10:3/0/terrains_peering_bit/top_right_corner = 1
+11:3/0 = 0
+11:3/0/terrain_set = 0
+11:3/0/terrain = 1
+11:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 16, 16, -32, 16)
+11:3/0/terrains_peering_bit/left_side = 1
+11:3/0/terrains_peering_bit/top_left_corner = 1
+11:3/0/terrains_peering_bit/top_side = 1
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_aw22q"]
+resource_name = "RedNoPhysic"
+texture = ExtResource("1_uvbas")
+texture_region_size = Vector2i(64, 64)
+0:0/0 = 0
+0:0/0/terrain_set = 0
+0:0/0/terrain = 2
+0:0/0/terrains_peering_bit/bottom_side = 2
+1:0/0 = 0
+1:0/0/terrain_set = 0
+1:0/0/terrain = 2
+1:0/0/terrains_peering_bit/right_side = 2
+1:0/0/terrains_peering_bit/bottom_side = 2
+2:0/0 = 0
+2:0/0/terrain_set = 0
+2:0/0/terrain = 2
+2:0/0/terrains_peering_bit/right_side = 2
+2:0/0/terrains_peering_bit/bottom_side = 2
+2:0/0/terrains_peering_bit/left_side = 2
+3:0/0 = 0
+3:0/0/terrain_set = 0
+3:0/0/terrain = 2
+3:0/0/terrains_peering_bit/bottom_side = 2
+3:0/0/terrains_peering_bit/left_side = 2
+4:0/0 = 0
+4:0/0/terrain_set = 0
+4:0/0/terrain = 2
+4:0/0/terrains_peering_bit/right_side = 2
+4:0/0/terrains_peering_bit/bottom_side = 2
+4:0/0/terrains_peering_bit/left_side = 2
+4:0/0/terrains_peering_bit/top_left_corner = 2
+4:0/0/terrains_peering_bit/top_side = 2
+5:0/0 = 0
+5:0/0/terrain_set = 0
+5:0/0/terrain = 2
+5:0/0/terrains_peering_bit/right_side = 2
+5:0/0/terrains_peering_bit/bottom_right_corner = 2
+5:0/0/terrains_peering_bit/bottom_side = 2
+5:0/0/terrains_peering_bit/left_side = 2
+6:0/0 = 0
+6:0/0/terrain_set = 0
+6:0/0/terrain = 2
+6:0/0/terrains_peering_bit/right_side = 2
+6:0/0/terrains_peering_bit/bottom_side = 2
+6:0/0/terrains_peering_bit/bottom_left_corner = 2
+6:0/0/terrains_peering_bit/left_side = 2
+7:0/0 = 0
+7:0/0/terrain_set = 0
+7:0/0/terrain = 2
+7:0/0/terrains_peering_bit/right_side = 2
+7:0/0/terrains_peering_bit/bottom_side = 2
+7:0/0/terrains_peering_bit/left_side = 2
+7:0/0/terrains_peering_bit/top_side = 2
+7:0/0/terrains_peering_bit/top_right_corner = 2
+8:0/0 = 0
+8:0/0/terrain_set = 0
+8:0/0/terrain = 2
+8:0/0/terrains_peering_bit/right_side = 2
+8:0/0/terrains_peering_bit/bottom_right_corner = 2
+8:0/0/terrains_peering_bit/bottom_side = 2
+9:0/0 = 0
+9:0/0/terrain_set = 0
+9:0/0/terrain = 2
+9:0/0/terrains_peering_bit/right_side = 2
+9:0/0/terrains_peering_bit/bottom_right_corner = 2
+9:0/0/terrains_peering_bit/bottom_side = 2
+9:0/0/terrains_peering_bit/bottom_left_corner = 2
+9:0/0/terrains_peering_bit/left_side = 2
+9:0/0/terrains_peering_bit/top_side = 2
+10:0/0 = 0
+10:0/0/terrain_set = 0
+10:0/0/terrain = 2
+10:0/0/terrains_peering_bit/right_side = 2
+10:0/0/terrains_peering_bit/bottom_right_corner = 2
+10:0/0/terrains_peering_bit/bottom_side = 2
+10:0/0/terrains_peering_bit/bottom_left_corner = 2
+10:0/0/terrains_peering_bit/left_side = 2
+11:0/0 = 0
+11:0/0/terrain_set = 0
+11:0/0/terrain = 2
+11:0/0/terrains_peering_bit/bottom_side = 2
+11:0/0/terrains_peering_bit/bottom_left_corner = 2
+11:0/0/terrains_peering_bit/left_side = 2
+0:1/0 = 0
+0:1/0/terrain_set = 0
+0:1/0/terrain = 2
+0:1/0/terrains_peering_bit/bottom_side = 2
+0:1/0/terrains_peering_bit/top_side = 2
+1:1/0 = 0
+1:1/0/terrain_set = 0
+1:1/0/terrain = 2
+1:1/0/terrains_peering_bit/right_side = 2
+1:1/0/terrains_peering_bit/bottom_side = 2
+1:1/0/terrains_peering_bit/top_side = 2
+2:1/0 = 0
+2:1/0/terrain_set = 0
+2:1/0/terrain = 2
+2:1/0/terrains_peering_bit/right_side = 2
+2:1/0/terrains_peering_bit/bottom_side = 2
+2:1/0/terrains_peering_bit/left_side = 2
+2:1/0/terrains_peering_bit/top_side = 2
+3:1/0 = 0
+3:1/0/terrain_set = 0
+3:1/0/terrain = 2
+3:1/0/terrains_peering_bit/bottom_side = 2
+3:1/0/terrains_peering_bit/left_side = 2
+3:1/0/terrains_peering_bit/top_side = 2
+4:1/0 = 0
+4:1/0/terrain_set = 0
+4:1/0/terrain = 2
+4:1/0/terrains_peering_bit/right_side = 2
+4:1/0/terrains_peering_bit/bottom_right_corner = 2
+4:1/0/terrains_peering_bit/bottom_side = 2
+4:1/0/terrains_peering_bit/top_side = 2
+5:1/0 = 0
+5:1/0/terrain_set = 0
+5:1/0/terrain = 2
+5:1/0/terrains_peering_bit/right_side = 2
+5:1/0/terrains_peering_bit/bottom_right_corner = 2
+5:1/0/terrains_peering_bit/bottom_side = 2
+5:1/0/terrains_peering_bit/bottom_left_corner = 2
+5:1/0/terrains_peering_bit/left_side = 2
+5:1/0/terrains_peering_bit/top_side = 2
+5:1/0/terrains_peering_bit/top_right_corner = 2
+6:1/0 = 0
+6:1/0/terrain_set = 0
+6:1/0/terrain = 2
+6:1/0/terrains_peering_bit/right_side = 2
+6:1/0/terrains_peering_bit/bottom_right_corner = 2
+6:1/0/terrains_peering_bit/bottom_side = 2
+6:1/0/terrains_peering_bit/bottom_left_corner = 2
+6:1/0/terrains_peering_bit/left_side = 2
+6:1/0/terrains_peering_bit/top_left_corner = 2
+6:1/0/terrains_peering_bit/top_side = 2
+7:1/0 = 0
+7:1/0/terrain_set = 0
+7:1/0/terrain = 2
+7:1/0/terrains_peering_bit/bottom_side = 2
+7:1/0/terrains_peering_bit/bottom_left_corner = 2
+7:1/0/terrains_peering_bit/left_side = 2
+7:1/0/terrains_peering_bit/top_side = 2
+8:1/0 = 0
+8:1/0/terrain_set = 0
+8:1/0/terrain = 2
+8:1/0/terrains_peering_bit/right_side = 2
+8:1/0/terrains_peering_bit/bottom_right_corner = 2
+8:1/0/terrains_peering_bit/bottom_side = 2
+8:1/0/terrains_peering_bit/top_side = 2
+8:1/0/terrains_peering_bit/top_right_corner = 2
+9:1/0 = 0
+9:1/0/terrain_set = 0
+9:1/0/terrain = 2
+9:1/0/terrains_peering_bit/right_side = 2
+9:1/0/terrains_peering_bit/bottom_side = 2
+9:1/0/terrains_peering_bit/bottom_left_corner = 2
+9:1/0/terrains_peering_bit/left_side = 2
+9:1/0/terrains_peering_bit/top_side = 2
+9:1/0/terrains_peering_bit/top_right_corner = 2
+10:1/0 = 0
+11:1/0 = 0
+11:1/0/terrain_set = 0
+11:1/0/terrain = 2
+11:1/0/terrains_peering_bit/right_side = 2
+11:1/0/terrains_peering_bit/bottom_side = 2
+11:1/0/terrains_peering_bit/bottom_left_corner = 2
+11:1/0/terrains_peering_bit/left_side = 2
+11:1/0/terrains_peering_bit/top_left_corner = 2
+11:1/0/terrains_peering_bit/top_side = 2
+0:2/0 = 0
+0:2/0/terrain_set = 0
+0:2/0/terrain = 2
+0:2/0/terrains_peering_bit/top_side = 2
+1:2/0 = 0
+1:2/0/terrain_set = 0
+1:2/0/terrain = 2
+1:2/0/terrains_peering_bit/right_side = 2
+1:2/0/terrains_peering_bit/top_side = 2
+2:2/0 = 0
+2:2/0/terrain_set = 0
+2:2/0/terrain = 2
+2:2/0/terrains_peering_bit/right_side = 2
+2:2/0/terrains_peering_bit/left_side = 2
+2:2/0/terrains_peering_bit/top_side = 2
+3:2/0 = 0
+3:2/0/terrain_set = 0
+3:2/0/terrain = 2
+3:2/0/terrains_peering_bit/left_side = 2
+3:2/0/terrains_peering_bit/top_side = 2
+4:2/0 = 0
+4:2/0/terrain_set = 0
+4:2/0/terrain = 2
+4:2/0/terrains_peering_bit/right_side = 2
+4:2/0/terrains_peering_bit/bottom_side = 2
+4:2/0/terrains_peering_bit/top_side = 2
+4:2/0/terrains_peering_bit/top_right_corner = 2
+5:2/0 = 0
+5:2/0/terrain_set = 0
+5:2/0/terrain = 2
+5:2/0/terrains_peering_bit/right_side = 2
+5:2/0/terrains_peering_bit/bottom_right_corner = 2
+5:2/0/terrains_peering_bit/bottom_side = 2
+5:2/0/terrains_peering_bit/left_side = 2
+5:2/0/terrains_peering_bit/top_left_corner = 2
+5:2/0/terrains_peering_bit/top_side = 2
+5:2/0/terrains_peering_bit/top_right_corner = 2
+6:2/0 = 0
+6:2/0/terrain_set = 0
+6:2/0/terrain = 2
+6:2/0/terrains_peering_bit/right_side = 2
+6:2/0/terrains_peering_bit/bottom_side = 2
+6:2/0/terrains_peering_bit/bottom_left_corner = 2
+6:2/0/terrains_peering_bit/left_side = 2
+6:2/0/terrains_peering_bit/top_left_corner = 2
+6:2/0/terrains_peering_bit/top_side = 2
+6:2/0/terrains_peering_bit/top_right_corner = 2
+7:2/0 = 0
+7:2/0/terrain_set = 0
+7:2/0/terrain = 2
+7:2/0/terrains_peering_bit/bottom_side = 2
+7:2/0/terrains_peering_bit/left_side = 2
+7:2/0/terrains_peering_bit/top_left_corner = 2
+7:2/0/terrains_peering_bit/top_side = 2
+8:2/0 = 0
+8:2/0/terrain_set = 0
+8:2/0/terrain = 2
+8:2/0/terrains_peering_bit/right_side = 2
+8:2/0/terrains_peering_bit/bottom_right_corner = 2
+8:2/0/terrains_peering_bit/bottom_side = 2
+8:2/0/terrains_peering_bit/left_side = 2
+8:2/0/terrains_peering_bit/top_side = 2
+8:2/0/terrains_peering_bit/top_right_corner = 2
+9:2/0 = 0
+9:2/0/terrain_set = 0
+9:2/0/terrain = 2
+9:2/0/terrains_peering_bit/right_side = 2
+9:2/0/terrains_peering_bit/bottom_right_corner = 2
+9:2/0/terrains_peering_bit/bottom_side = 2
+9:2/0/terrains_peering_bit/bottom_left_corner = 2
+9:2/0/terrains_peering_bit/left_side = 2
+9:2/0/terrains_peering_bit/top_left_corner = 2
+9:2/0/terrains_peering_bit/top_side = 2
+9:2/0/terrains_peering_bit/top_right_corner = 2
+10:2/0 = 0
+10:2/0/terrain_set = 0
+10:2/0/terrain = 2
+10:2/0/terrains_peering_bit/right_side = 2
+10:2/0/terrains_peering_bit/bottom_right_corner = 2
+10:2/0/terrains_peering_bit/bottom_side = 2
+10:2/0/terrains_peering_bit/left_side = 2
+10:2/0/terrains_peering_bit/top_left_corner = 2
+10:2/0/terrains_peering_bit/top_side = 2
+11:2/0 = 0
+11:2/0/terrain_set = 0
+11:2/0/terrain = 2
+11:2/0/terrains_peering_bit/bottom_side = 2
+11:2/0/terrains_peering_bit/bottom_left_corner = 2
+11:2/0/terrains_peering_bit/left_side = 2
+11:2/0/terrains_peering_bit/top_left_corner = 2
+11:2/0/terrains_peering_bit/top_side = 2
+0:3/0 = 0
+0:3/0/terrain_set = 0
+0:3/0/terrain = 2
+1:3/0 = 0
+1:3/0/terrain_set = 0
+1:3/0/terrain = 2
+1:3/0/terrains_peering_bit/right_side = 2
+2:3/0 = 0
+2:3/0/terrain_set = 0
+2:3/0/terrain = 2
+2:3/0/terrains_peering_bit/right_side = 2
+2:3/0/terrains_peering_bit/left_side = 2
+3:3/0 = 0
+3:3/0/terrain_set = 0
+3:3/0/terrain = 2
+3:3/0/terrains_peering_bit/left_side = 2
+4:3/0 = 0
+4:3/0/terrain_set = 0
+4:3/0/terrain = 2
+4:3/0/terrains_peering_bit/right_side = 2
+4:3/0/terrains_peering_bit/bottom_side = 2
+4:3/0/terrains_peering_bit/bottom_left_corner = 2
+4:3/0/terrains_peering_bit/left_side = 2
+4:3/0/terrains_peering_bit/top_side = 2
+5:3/0 = 0
+5:3/0/terrain_set = 0
+5:3/0/terrain = 2
+5:3/0/terrains_peering_bit/right_side = 2
+5:3/0/terrains_peering_bit/left_side = 2
+5:3/0/terrains_peering_bit/top_side = 2
+5:3/0/terrains_peering_bit/top_right_corner = 2
+6:3/0 = 0
+6:3/0/terrain_set = 0
+6:3/0/terrain = 2
+6:3/0/terrains_peering_bit/right_side = 2
+6:3/0/terrains_peering_bit/left_side = 2
+6:3/0/terrains_peering_bit/top_left_corner = 2
+6:3/0/terrains_peering_bit/top_side = 2
+7:3/0 = 0
+7:3/0/terrain_set = 0
+7:3/0/terrain = 2
+7:3/0/terrains_peering_bit/right_side = 2
+7:3/0/terrains_peering_bit/bottom_right_corner = 2
+7:3/0/terrains_peering_bit/bottom_side = 2
+7:3/0/terrains_peering_bit/left_side = 2
+7:3/0/terrains_peering_bit/top_side = 2
+8:3/0 = 0
+8:3/0/terrain_set = 0
+8:3/0/terrain = 2
+8:3/0/terrains_peering_bit/right_side = 2
+8:3/0/terrains_peering_bit/top_side = 2
+8:3/0/terrains_peering_bit/top_right_corner = 2
+9:3/0 = 0
+9:3/0/terrain_set = 0
+9:3/0/terrain = 2
+9:3/0/terrains_peering_bit/right_side = 2
+9:3/0/terrains_peering_bit/left_side = 2
+9:3/0/terrains_peering_bit/top_left_corner = 2
+9:3/0/terrains_peering_bit/top_side = 2
+9:3/0/terrains_peering_bit/top_right_corner = 2
+10:3/0 = 0
+10:3/0/terrain_set = 0
+10:3/0/terrain = 2
+10:3/0/terrains_peering_bit/right_side = 2
+10:3/0/terrains_peering_bit/bottom_side = 2
+10:3/0/terrains_peering_bit/left_side = 2
+10:3/0/terrains_peering_bit/top_left_corner = 2
+10:3/0/terrains_peering_bit/top_side = 2
+10:3/0/terrains_peering_bit/top_right_corner = 2
+11:3/0 = 0
+11:3/0/terrain_set = 0
+11:3/0/terrain = 2
+11:3/0/terrains_peering_bit/left_side = 2
+11:3/0/terrains_peering_bit/top_left_corner = 2
+11:3/0/terrains_peering_bit/top_side = 2
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_4i8c6"]
+resource_name = "RedPhysic"
+texture = ExtResource("1_uvbas")
+texture_region_size = Vector2i(64, 64)
+0:0/0 = 0
+0:0/0/terrain_set = 0
+0:0/0/terrain = 0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 0, 0, -16, 16, 0, 16, 32, -16, 32)
+0:0/0/terrains_peering_bit/bottom_side = 0
+1:0/0 = 0
+1:0/0/terrain_set = 0
+1:0/0/terrain = 0
+1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(32, -16, 32, 16, 16, 32, -16, 32)
+1:0/0/terrains_peering_bit/right_side = 0
+1:0/0/terrains_peering_bit/bottom_side = 0
+2:0/0 = 0
+2:0/0/terrain_set = 0
+2:0/0/terrain = 0
+2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, 16, 32, -16, 32, -32, 16)
+2:0/0/terrains_peering_bit/right_side = 0
+2:0/0/terrains_peering_bit/bottom_side = 0
+2:0/0/terrains_peering_bit/left_side = 0
+3:0/0 = 0
+3:0/0/terrain_set = 0
+3:0/0/terrain = 0
+3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 16, 32, -16, 32, -32, 16)
+3:0/0/terrains_peering_bit/bottom_side = 0
+3:0/0/terrains_peering_bit/left_side = 0
+4:0/0 = 0
+4:0/0/terrain_set = 0
+4:0/0/terrain = 0
+4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 16, 16, 32, -16, 32, -32, 16)
+4:0/0/terrains_peering_bit/right_side = 0
+4:0/0/terrains_peering_bit/bottom_side = 0
+4:0/0/terrains_peering_bit/left_side = 0
+4:0/0/terrains_peering_bit/top_left_corner = 0
+4:0/0/terrains_peering_bit/top_side = 0
+5:0/0 = 0
+5:0/0/terrain_set = 0
+5:0/0/terrain = 0
+5:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, 16, -32, -16, 32, -16, 32, 32, -16, 32)
+5:0/0/terrains_peering_bit/right_side = 0
+5:0/0/terrains_peering_bit/bottom_right_corner = 0
+5:0/0/terrains_peering_bit/bottom_side = 0
+5:0/0/terrains_peering_bit/left_side = 0
+6:0/0 = 0
+6:0/0/terrain_set = 0
+6:0/0/terrain = 0
+6:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, 16, 32, -32, 32)
+6:0/0/terrains_peering_bit/right_side = 0
+6:0/0/terrains_peering_bit/bottom_side = 0
+6:0/0/terrains_peering_bit/bottom_left_corner = 0
+6:0/0/terrains_peering_bit/left_side = 0
+7:0/0 = 0
+7:0/0/terrain_set = 0
+7:0/0/terrain = 0
+7:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 32, -32, 16, -32, -16, -16, -32, 32, -32, 32, 16, 16, 32)
+7:0/0/terrains_peering_bit/right_side = 0
+7:0/0/terrains_peering_bit/bottom_side = 0
+7:0/0/terrains_peering_bit/left_side = 0
+7:0/0/terrains_peering_bit/top_side = 0
+7:0/0/terrains_peering_bit/top_right_corner = 0
+8:0/0 = 0
+8:0/0/terrain_set = 0
+8:0/0/terrain = 0
+8:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(32, -16, 32, 32, -16, 32)
+8:0/0/terrains_peering_bit/right_side = 0
+8:0/0/terrains_peering_bit/bottom_right_corner = 0
+8:0/0/terrains_peering_bit/bottom_side = 0
+9:0/0 = 0
+9:0/0/terrain_set = 0
+9:0/0/terrain = 0
+9:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 32, -32, 32, -32, -16)
+9:0/0/terrains_peering_bit/right_side = 0
+9:0/0/terrains_peering_bit/bottom_right_corner = 0
+9:0/0/terrains_peering_bit/bottom_side = 0
+9:0/0/terrains_peering_bit/bottom_left_corner = 0
+9:0/0/terrains_peering_bit/left_side = 0
+9:0/0/terrains_peering_bit/top_side = 0
+10:0/0 = 0
+10:0/0/terrain_set = 0
+10:0/0/terrain = 0
+10:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 32, -32, 32)
+10:0/0/terrains_peering_bit/right_side = 0
+10:0/0/terrains_peering_bit/bottom_right_corner = 0
+10:0/0/terrains_peering_bit/bottom_side = 0
+10:0/0/terrains_peering_bit/bottom_left_corner = 0
+10:0/0/terrains_peering_bit/left_side = 0
+11:0/0 = 0
+11:0/0/terrain_set = 0
+11:0/0/terrain = 0
+11:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 16, 32, -32, 32)
+11:0/0/terrains_peering_bit/bottom_side = 0
+11:0/0/terrains_peering_bit/bottom_left_corner = 0
+11:0/0/terrains_peering_bit/left_side = 0
+0:1/0 = 0
+0:1/0/terrain_set = 0
+0:1/0/terrain = 0
+0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 16, 32, -16, 32)
+0:1/0/terrains_peering_bit/bottom_side = 0
+0:1/0/terrains_peering_bit/top_side = 0
+1:1/0 = 0
+1:1/0/terrain_set = 0
+1:1/0/terrain = 0
+1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 16, 16, 32, -16, 32)
+1:1/0/terrains_peering_bit/right_side = 0
+1:1/0/terrains_peering_bit/bottom_side = 0
+1:1/0/terrains_peering_bit/top_side = 0
+2:1/0 = 0
+2:1/0/terrain_set = 0
+2:1/0/terrain = 0
+2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 16, 16, 32, -16, 32, -32, 16, -32, -16)
+2:1/0/terrains_peering_bit/right_side = 0
+2:1/0/terrains_peering_bit/bottom_side = 0
+2:1/0/terrains_peering_bit/left_side = 0
+2:1/0/terrains_peering_bit/top_side = 0
+3:1/0 = 0
+3:1/0/terrain_set = 0
+3:1/0/terrain = 0
+3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 16, 32, -16, 32, -32, 16)
+3:1/0/terrains_peering_bit/bottom_side = 0
+3:1/0/terrains_peering_bit/left_side = 0
+3:1/0/terrains_peering_bit/top_side = 0
+4:1/0 = 0
+4:1/0/terrain_set = 0
+4:1/0/terrain = 0
+4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(16, -32, 32, -16, 32, 32, -16, 32, -16, -32)
+4:1/0/terrains_peering_bit/right_side = 0
+4:1/0/terrains_peering_bit/bottom_right_corner = 0
+4:1/0/terrains_peering_bit/bottom_side = 0
+4:1/0/terrains_peering_bit/top_side = 0
+5:1/0 = 0
+5:1/0/terrain_set = 0
+5:1/0/terrain = 0
+5:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 32, -32, 32, -32, -16)
+5:1/0/terrains_peering_bit/right_side = 0
+5:1/0/terrains_peering_bit/bottom_right_corner = 0
+5:1/0/terrains_peering_bit/bottom_side = 0
+5:1/0/terrains_peering_bit/bottom_left_corner = 0
+5:1/0/terrains_peering_bit/left_side = 0
+5:1/0/terrains_peering_bit/top_side = 0
+5:1/0/terrains_peering_bit/top_right_corner = 0
+6:1/0 = 0
+6:1/0/terrain_set = 0
+6:1/0/terrain = 0
+6:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 32, -32, 32)
+6:1/0/terrains_peering_bit/right_side = 0
+6:1/0/terrains_peering_bit/bottom_right_corner = 0
+6:1/0/terrains_peering_bit/bottom_side = 0
+6:1/0/terrains_peering_bit/bottom_left_corner = 0
+6:1/0/terrains_peering_bit/left_side = 0
+6:1/0/terrains_peering_bit/top_left_corner = 0
+6:1/0/terrains_peering_bit/top_side = 0
+7:1/0 = 0
+7:1/0/terrain_set = 0
+7:1/0/terrain = 0
+7:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 16, 32, -32, 32)
+7:1/0/terrains_peering_bit/bottom_side = 0
+7:1/0/terrains_peering_bit/bottom_left_corner = 0
+7:1/0/terrains_peering_bit/left_side = 0
+7:1/0/terrains_peering_bit/top_side = 0
+8:1/0 = 0
+8:1/0/terrain_set = 0
+8:1/0/terrain = 0
+8:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 32, -16, 32)
+8:1/0/terrains_peering_bit/right_side = 0
+8:1/0/terrains_peering_bit/bottom_right_corner = 0
+8:1/0/terrains_peering_bit/bottom_side = 0
+8:1/0/terrains_peering_bit/top_side = 0
+8:1/0/terrains_peering_bit/top_right_corner = 0
+9:1/0 = 0
+9:1/0/terrain_set = 0
+9:1/0/terrain = 0
+9:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, 32, -32, -16, -16, -32, 32, -32, 32, 16, 16, 32)
+9:1/0/terrains_peering_bit/right_side = 0
+9:1/0/terrains_peering_bit/bottom_side = 0
+9:1/0/terrains_peering_bit/bottom_left_corner = 0
+9:1/0/terrains_peering_bit/left_side = 0
+9:1/0/terrains_peering_bit/top_side = 0
+9:1/0/terrains_peering_bit/top_right_corner = 0
+11:1/0 = 0
+11:1/0/terrain_set = 0
+11:1/0/terrain = 0
+11:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 16, 16, 32, -32, 32)
+11:1/0/terrains_peering_bit/right_side = 0
+11:1/0/terrains_peering_bit/bottom_side = 0
+11:1/0/terrains_peering_bit/bottom_left_corner = 0
+11:1/0/terrains_peering_bit/left_side = 0
+11:1/0/terrains_peering_bit/top_left_corner = 0
+11:1/0/terrains_peering_bit/top_side = 0
+0:2/0 = 0
+0:2/0/terrain_set = 0
+0:2/0/terrain = 0
+0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 16, 0, -0.564476, 16, -16, 0)
+0:2/0/terrains_peering_bit/top_side = 0
+1:2/0 = 0
+1:2/0/terrain_set = 0
+1:2/0/terrain = 0
+1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 16)
+1:2/0/terrains_peering_bit/right_side = 0
+1:2/0/terrains_peering_bit/top_side = 0
+2:2/0 = 0
+2:2/0/terrain_set = 0
+2:2/0/terrain = 0
+2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, 32, -16, 32, 16, -32, 16, -32, -16)
+2:2/0/terrains_peering_bit/right_side = 0
+2:2/0/terrains_peering_bit/left_side = 0
+2:2/0/terrains_peering_bit/top_side = 0
+3:2/0 = 0
+3:2/0/terrain_set = 0
+3:2/0/terrain = 0
+3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 16, -32, -32, 16, -32, -16)
+3:2/0/terrains_peering_bit/left_side = 0
+3:2/0/terrains_peering_bit/top_side = 0
+4:2/0 = 0
+4:2/0/terrain_set = 0
+4:2/0/terrain = 0
+4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 16, 16, 32, -16, 32)
+4:2/0/terrains_peering_bit/right_side = 0
+4:2/0/terrains_peering_bit/bottom_side = 0
+4:2/0/terrains_peering_bit/top_side = 0
+4:2/0/terrains_peering_bit/top_right_corner = 0
+5:2/0 = 0
+5:2/0/terrain_set = 0
+5:2/0/terrain = 0
+5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 32, -16, 32, -32, 16)
+5:2/0/terrains_peering_bit/right_side = 0
+5:2/0/terrains_peering_bit/bottom_right_corner = 0
+5:2/0/terrains_peering_bit/bottom_side = 0
+5:2/0/terrains_peering_bit/left_side = 0
+5:2/0/terrains_peering_bit/top_left_corner = 0
+5:2/0/terrains_peering_bit/top_side = 0
+5:2/0/terrains_peering_bit/top_right_corner = 0
+6:2/0 = 0
+6:2/0/terrain_set = 0
+6:2/0/terrain = 0
+6:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 16, 16, 32, -32, 32)
+6:2/0/terrains_peering_bit/right_side = 0
+6:2/0/terrains_peering_bit/bottom_side = 0
+6:2/0/terrains_peering_bit/bottom_left_corner = 0
+6:2/0/terrains_peering_bit/left_side = 0
+6:2/0/terrains_peering_bit/top_left_corner = 0
+6:2/0/terrains_peering_bit/top_side = 0
+6:2/0/terrains_peering_bit/top_right_corner = 0
+7:2/0 = 0
+7:2/0/terrain_set = 0
+7:2/0/terrain = 0
+7:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 16, 32, -16, 32, -32, 16)
+7:2/0/terrains_peering_bit/bottom_side = 0
+7:2/0/terrains_peering_bit/left_side = 0
+7:2/0/terrains_peering_bit/top_left_corner = 0
+7:2/0/terrains_peering_bit/top_side = 0
+8:2/0 = 0
+8:2/0/terrain_set = 0
+8:2/0/terrain = 0
+8:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 32, -16, 32, -32, 16, -32, -16)
+8:2/0/terrains_peering_bit/right_side = 0
+8:2/0/terrains_peering_bit/bottom_right_corner = 0
+8:2/0/terrains_peering_bit/bottom_side = 0
+8:2/0/terrains_peering_bit/left_side = 0
+8:2/0/terrains_peering_bit/top_side = 0
+8:2/0/terrains_peering_bit/top_right_corner = 0
+9:2/0 = 0
+9:2/0/terrain_set = 0
+9:2/0/terrain = 0
+9:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 32, -32, 32)
+9:2/0/terrains_peering_bit/right_side = 0
+9:2/0/terrains_peering_bit/bottom_right_corner = 0
+9:2/0/terrains_peering_bit/bottom_side = 0
+9:2/0/terrains_peering_bit/bottom_left_corner = 0
+9:2/0/terrains_peering_bit/left_side = 0
+9:2/0/terrains_peering_bit/top_left_corner = 0
+9:2/0/terrains_peering_bit/top_side = 0
+9:2/0/terrains_peering_bit/top_right_corner = 0
+10:2/0 = 0
+10:2/0/terrain_set = 0
+10:2/0/terrain = 0
+10:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 32, -32, 16, -32, -32, 16, -32, 32, -16, 32, 32)
+10:2/0/terrains_peering_bit/right_side = 0
+10:2/0/terrains_peering_bit/bottom_right_corner = 0
+10:2/0/terrains_peering_bit/bottom_side = 0
+10:2/0/terrains_peering_bit/left_side = 0
+10:2/0/terrains_peering_bit/top_left_corner = 0
+10:2/0/terrains_peering_bit/top_side = 0
+11:2/0 = 0
+11:2/0/terrain_set = 0
+11:2/0/terrain = 0
+11:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 16, 32, -32, 32)
+11:2/0/terrains_peering_bit/bottom_side = 0
+11:2/0/terrains_peering_bit/bottom_left_corner = 0
+11:2/0/terrains_peering_bit/left_side = 0
+11:2/0/terrains_peering_bit/top_left_corner = 0
+11:2/0/terrains_peering_bit/top_side = 0
+0:3/0 = 0
+0:3/0/terrain_set = 0
+0:3/0/terrain = 0
+0:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 0, 0, -16, 16, 0, 0, 16)
+1:3/0 = 0
+1:3/0/terrain_set = 0
+1:3/0/terrain = 0
+1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(0, -16, 32, -16, 32, 16, 0, 16, -16, 0)
+1:3/0/terrains_peering_bit/right_side = 0
+2:3/0 = 0
+2:3/0/terrain_set = 0
+2:3/0/terrain = 0
+2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 32, -16, 32, 16, -32, 16)
+2:3/0/terrains_peering_bit/right_side = 0
+2:3/0/terrains_peering_bit/left_side = 0
+3:3/0 = 0
+3:3/0/terrain_set = 0
+3:3/0/terrain = 0
+3:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, 0, -16, 16, 0, 0, 16, -32, 16)
+3:3/0/terrains_peering_bit/left_side = 0
+4:3/0 = 0
+4:3/0/terrain_set = 0
+4:3/0/terrain = 0
+4:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 32, -16, 32, 16, 16, 32, -32, 32)
+4:3/0/terrains_peering_bit/right_side = 0
+4:3/0/terrains_peering_bit/bottom_side = 0
+4:3/0/terrains_peering_bit/bottom_left_corner = 0
+4:3/0/terrains_peering_bit/left_side = 0
+4:3/0/terrains_peering_bit/top_side = 0
+5:3/0 = 0
+5:3/0/terrain_set = 0
+5:3/0/terrain = 0
+5:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 16, -32, 16, -32, -16)
+5:3/0/terrains_peering_bit/right_side = 0
+5:3/0/terrains_peering_bit/left_side = 0
+5:3/0/terrains_peering_bit/top_side = 0
+5:3/0/terrains_peering_bit/top_right_corner = 0
+6:3/0 = 0
+6:3/0/terrain_set = 0
+6:3/0/terrain = 0
+6:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 16, -32, 32, -16, 32, 16, -32, 16)
+6:3/0/terrains_peering_bit/right_side = 0
+6:3/0/terrains_peering_bit/left_side = 0
+6:3/0/terrains_peering_bit/top_left_corner = 0
+6:3/0/terrains_peering_bit/top_side = 0
+7:3/0 = 0
+7:3/0/terrain_set = 0
+7:3/0/terrain = 0
+7:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -16, -16, -32, 16, -32, 32, -16, 32, 32, -32, 32)
+7:3/0/terrains_peering_bit/right_side = 0
+7:3/0/terrains_peering_bit/bottom_right_corner = 0
+7:3/0/terrains_peering_bit/bottom_side = 0
+7:3/0/terrains_peering_bit/left_side = 0
+7:3/0/terrains_peering_bit/top_side = 0
+8:3/0 = 0
+8:3/0/terrain_set = 0
+8:3/0/terrain = 0
+8:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -32, 32, -32, 32, 16)
+8:3/0/terrains_peering_bit/right_side = 0
+8:3/0/terrains_peering_bit/top_side = 0
+8:3/0/terrains_peering_bit/top_right_corner = 0
+9:3/0 = 0
+9:3/0/terrain_set = 0
+9:3/0/terrain = 0
+9:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, -32, 32, -32, 32, 16, -32, 16)
+9:3/0/terrains_peering_bit/right_side = 0
+9:3/0/terrains_peering_bit/left_side = 0
+9:3/0/terrains_peering_bit/top_left_corner = 0
+9:3/0/terrains_peering_bit/top_side = 0
+9:3/0/terrains_peering_bit/top_right_corner = 0
+10:3/0 = 0
+10:3/0/terrain_set = 0
+10:3/0/terrain = 0
+10:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-32, 16, -32, -32, 32, -32, 32, 16, 16, 32, -16, 32)
+10:3/0/terrains_peering_bit/right_side = 0
+10:3/0/terrains_peering_bit/bottom_side = 0
+10:3/0/terrains_peering_bit/left_side = 0
+10:3/0/terrains_peering_bit/top_left_corner = 0
+10:3/0/terrains_peering_bit/top_side = 0
+10:3/0/terrains_peering_bit/top_right_corner = 0
+11:3/0 = 0
+11:3/0/terrain_set = 0
+11:3/0/terrain = 0
+11:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(16, -32, -32, 16, -32, -32)
+11:3/0/terrains_peering_bit/left_side = 0
+11:3/0/terrains_peering_bit/top_left_corner = 0
+11:3/0/terrains_peering_bit/top_side = 0
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_2x7bf"]
+texture = ExtResource("5_skkk4")
+texture_region_size = Vector2i(64, 64)
+0:0/0 = 0
+0:0/0/terrain_set = 1
+0:0/0/terrain = 0
+0:0/0/terrains_peering_bit/bottom_side = 0
+1:0/0 = 0
+1:0/0/terrain_set = 1
+1:0/0/terrain = 0
+1:0/0/terrains_peering_bit/right_side = 0
+1:0/0/terrains_peering_bit/bottom_side = 0
+2:0/0 = 0
+2:0/0/terrain_set = 1
+2:0/0/terrain = 0
+2:0/0/terrains_peering_bit/right_side = 0
+2:0/0/terrains_peering_bit/bottom_side = 0
+2:0/0/terrains_peering_bit/left_side = 0
+3:0/0 = 0
+3:0/0/terrain_set = 1
+3:0/0/terrain = 0
+3:0/0/terrains_peering_bit/bottom_side = 0
+3:0/0/terrains_peering_bit/left_side = 0
+0:1/0 = 0
+0:1/0/terrain_set = 1
+0:1/0/terrain = 0
+0:1/0/terrains_peering_bit/bottom_side = 0
+0:1/0/terrains_peering_bit/top_side = 0
+1:1/0 = 0
+1:1/0/terrain_set = 1
+1:1/0/terrain = 0
+1:1/0/terrains_peering_bit/right_side = 0
+1:1/0/terrains_peering_bit/bottom_side = 0
+1:1/0/terrains_peering_bit/top_side = 0
+2:1/0 = 0
+2:1/0/terrain_set = 1
+2:1/0/terrain = 0
+2:1/0/terrains_peering_bit/right_side = 0
+2:1/0/terrains_peering_bit/bottom_side = 0
+2:1/0/terrains_peering_bit/left_side = 0
+2:1/0/terrains_peering_bit/top_side = 0
+3:1/0 = 0
+3:1/0/terrain_set = 1
+3:1/0/terrain = 0
+3:1/0/terrains_peering_bit/bottom_side = 0
+3:1/0/terrains_peering_bit/left_side = 0
+3:1/0/terrains_peering_bit/top_side = 0
+0:2/0 = 0
+0:2/0/terrain_set = 1
+0:2/0/terrain = 0
+0:2/0/terrains_peering_bit/top_side = 0
+1:2/0 = 0
+1:2/0/terrain_set = 1
+1:2/0/terrain = 0
+1:2/0/terrains_peering_bit/right_side = 0
+1:2/0/terrains_peering_bit/top_side = 0
+2:2/0 = 0
+2:2/0/terrain_set = 1
+2:2/0/terrain = 0
+2:2/0/terrains_peering_bit/right_side = 0
+2:2/0/terrains_peering_bit/left_side = 0
+2:2/0/terrains_peering_bit/top_side = 0
+3:2/0 = 0
+3:2/0/terrain_set = 1
+3:2/0/terrain = 0
+3:2/0/terrains_peering_bit/left_side = 0
+3:2/0/terrains_peering_bit/top_side = 0
+0:3/0 = 0
+0:3/0/terrain_set = 1
+0:3/0/terrain = 0
+1:3/0 = 0
+1:3/0/terrain_set = 1
+1:3/0/terrain = 0
+1:3/0/terrains_peering_bit/right_side = 0
+2:3/0 = 0
+2:3/0/terrain_set = 1
+2:3/0/terrain = 0
+2:3/0/terrains_peering_bit/right_side = 0
+2:3/0/terrains_peering_bit/left_side = 0
+3:3/0 = 0
+3:3/0/terrain_set = 1
+3:3/0/terrain = 0
+3:3/0/terrains_peering_bit/left_side = 0
+
+[resource]
+tile_size = Vector2i(64, 64)
+physics_layer_0/collision_layer = 1
+terrain_set_0/mode = 0
+terrain_set_0/terrain_0/name = "RedColl"
+terrain_set_0/terrain_0/color = Color(0.60520345, 0.269086, 0.20414418, 1)
+terrain_set_0/terrain_1/name = "GreenColl"
+terrain_set_0/terrain_1/color = Color(0.5019608, 0.80784315, 0, 1)
+terrain_set_0/terrain_2/name = "RedNoColl"
+terrain_set_0/terrain_2/color = Color(1, 1, 1, 1)
+terrain_set_1/mode = 2
+terrain_set_1/terrain_0/name = "Sides"
+terrain_set_1/terrain_0/color = Color(0.5, 0.34375, 0.25, 1)
+sources/3 = SubResource("TileSetAtlasSource_4i8c6")
+sources/6 = SubResource("TileSetAtlasSource_2x7bf")
+sources/1 = SubResource("TileSetAtlasSource_rklv6")
+sources/0 = SubResource("TileSetAtlasSource_f4n6l")
+sources/2 = SubResource("TileSetAtlasSource_aw22q")
diff --git a/stages/terrain/planet/scripts/chunk.gd b/stages/terrain/planet/scripts/chunk.gd
index f1466d3..2d04ae4 100644
--- a/stages/terrain/planet/scripts/chunk.gd
+++ b/stages/terrain/planet/scripts/chunk.gd
@@ -1,137 +1,164 @@
+@tool
extends Node2D
class_name Chunk
-const UNIT_PER_PIXEL = 30
-
-var coord : Vector2i
-var size : Vector2i
var planet : Planet
-var wall_threshold = 0.4
-var noise_image : Image
-var entity_generated : bool
+var planet_seed : int
+var wall_threshold = 0.6
+var decontamination_threshold = 0.15
+var cristal_threshold = 0.08
+var rock_noise_image : Noise = null
+var decontamination_noise_image : Noise = null
-const CHUNK_TEXTURE_SCALE : float = 3.0
-const DEFAULT_CHUNK_BACKGROUND_MATERIAL : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/default_chunk_material.tres")
+const NOISE_IMAGE_SIZE := 150
const LOOT_NUMBER : Array[int] = [2,3,4]
const LOOT_ITEM_NUMBER : Array[int] = [1,2]
-var chunk_background_material
+const ROCK_NOISE_FREQUENCY := 0.01
+const DECONTAMINATION_NOISE_FREQUENCY := 0.01
+
+var generation_thread: Thread
+
+@export_tool_button("Update", "Callable") var update_action = func():
+ planet_seed = randi()
+ setup()
+
+var data : ChunkData
func _init(
- _coord : Vector2i,
- _size : Vector2i,
- _planet : Planet,
- _entity_generated = false
+ _data : ChunkData,
+ _planet : Planet = null,
):
- coord = _coord
- size = _size
- planet = _planet
- entity_generated = _entity_generated
+ planet = _planet
+ if planet:
+ planet_seed = planet.data.planet_seed
+ data = _data
func _ready():
- noise_image = generate_noise()
- generate_background_sprite()
- global_position = coord * size
- generate_walls()
- if not entity_generated:
- generate_loot()
+ setup()
-func generate_noise() -> Image:
- var image_size = Vector2i(
- roundi(float(size.x) / UNIT_PER_PIXEL),
- roundi(float(size.y) / UNIT_PER_PIXEL)
- )
- var noise: FastNoiseLite = FastNoiseLite.new()
- noise.seed = planet.data.planet_seed
- noise.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
- noise.frequency = 0.05
- noise.fractal_weighted_strength = 1.0
- noise.offset = Vector3(
- image_size.x * coord.x,
- image_size.y * coord.y,
- 1
- )
+func setup():
+ rock_noise_image = generate_noise(planet_seed + 1, ROCK_NOISE_FREQUENCY)
+ decontamination_noise_image = generate_noise(planet_seed + 2, DECONTAMINATION_NOISE_FREQUENCY)
- var image = noise.get_image(
- image_size.x,
- image_size.y,
- 1.0,
- )
+ generation_thread = Thread.new()
+ generation_thread.start(
+ func ():
+ generate_rocks()
+ generate_ground()
+ generate_decontamination()
+ )
- return image
+ global_position = data.chunk_coord * (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE)
+ queue_redraw()
-func generate_background_sprite() -> Polygon2D:
- var sprite :Polygon2D = generate_polygon_sprite()
+func unload():
+ for x in range(Planet.CHUNK_TILE_SIZE):
+ for y in range(Planet.CHUNK_TILE_SIZE):
+ var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
+ planet.rock_layer.erase_cell(global_coord)
+ planet.ground_layer.erase_cell(global_coord)
+ planet.decontamination_layer.erase_cell(global_coord)
- sprite.texture = ImageTexture.create_from_image(noise_image)
+# Debug
+# func _draw():
+# draw_rect(
+# Rect2(Vector2.ZERO, Vector2.ONE * Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE),
+# Color.WHITE,
+# false,
+# 3
+# )
- var background_material = DEFAULT_CHUNK_BACKGROUND_MATERIAL.duplicate_deep()
+ # for x in range(NOISE_IMAGE_SIZE):
+ # for y in range(NOISE_IMAGE_SIZE):
+ # var noise_value = rock_noise_image.get_noise_2d(
+ # x,
+ # y
+ # )
+ # draw_rect(
+ # Rect2(Vector2i(x,y) * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE, Vector2i.ONE * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE),
+ # Color.WHITE * ((noise_value+1)/2),
+ # true,
+ # )
- background_material.set_shader_parameter("data_texture", ImageTexture.create_from_image(noise_image))
- background_material.set_shader_parameter("data_texture_size", size)
- background_material.set_shader_parameter("data_texture_threshold", wall_threshold)
- background_material.set_shader_parameter("texture_scale", CHUNK_TEXTURE_SCALE)
+func generate_noise(
+ noise_seed : int,
+ frequency := 0.01
+) -> Noise:
+ var noise_image_size := NOISE_IMAGE_SIZE * Vector2i.ONE
+ var noise: FastNoiseLite = FastNoiseLite.new()
+ noise.seed = noise_seed
+ noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
+ noise.frequency = 0.01
+ noise.fractal_type = FastNoiseLite.FRACTAL_NONE
+ noise.fractal_weighted_strength = 1.0
+ noise.offset = Vector3(
+ noise_image_size.x * data.chunk_coord.x,
+ noise_image_size.y * data.chunk_coord.y,
+ 1
+ )
- sprite.material = background_material
+ return noise
- return sprite
+func get_tile_value_from_noise(tile_position : Vector2i, noise : Noise) -> float:
+ var val = noise.get_noise_2d(
+ floori(float(tile_position.x * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE),
+ floori(float(tile_position.y * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE)
+ )
+ return (val + 1)/2
-func generate_polygon_sprite() -> Polygon2D:
- var sprite = Polygon2D.new()
- sprite.polygon = PackedVector2Array([
- Vector2(0,0),
- Vector2(size.x, 0),
- Vector2(size.x, size.y),
- Vector2(0, size.y),
- ])
+func generate_rocks():
+ var cristals : Array[Vector2i] = []
+ var rocks : Array[Vector2i] = []
+ for x in range(Planet.CHUNK_TILE_SIZE):
+ for y in range(Planet.CHUNK_TILE_SIZE):
+ var tile_type := get_generated_rock_type(Vector2i(x, y))
+ var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
+ if tile_type == RockLayer.TileType.CRISTAL:
+ cristals.append(global_coord)
+ elif tile_type == RockLayer.TileType.ROCK:
+ rocks.append(global_coord)
+
+ planet.rock_layer.mutex.lock()
+ planet.rock_layer.place_rocks(cristals, RockLayer.TileType.CRISTAL)
+ planet.rock_layer.place_rocks(rocks, RockLayer.TileType.ROCK)
+ planet.rock_layer.mutex.unlock()
+
+func get_generated_rock_type(coord : Vector2i) -> RockLayer.TileType:
+ var tile_value : float = get_tile_value_from_noise(coord, rock_noise_image)
+ var saved_diff := data.get_rock_tile_diff(coord)
- sprite.z_index = -100
+ if (
+ (saved_diff == ChunkData.TileDiff.PRESENT or tile_value < wall_threshold)
+ and saved_diff != ChunkData.TileDiff.ABSENT
+ ):
+ return RockLayer.TileType.CRISTAL if tile_value < cristal_threshold else RockLayer.TileType.ROCK
+ return RockLayer.TileType.EMPTY
- add_child(sprite)
+func generate_ground():
+ planet.ground_layer.mutex.lock()
+ for x in range(Planet.CHUNK_TILE_SIZE):
+ for y in range(Planet.CHUNK_TILE_SIZE):
+ planet.ground_layer.place_ground(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
+ planet.ground_layer.mutex.unlock()
- return sprite
+func generate_decontamination():
+ var decontamination_tiles : Array[Vector2i] = []
+ for x in range(Planet.CHUNK_TILE_SIZE):
+ for y in range(Planet.CHUNK_TILE_SIZE):
+ var coord = Vector2i(x,y)
+ var tile_value : float = get_tile_value_from_noise(coord, decontamination_noise_image)
+ var saved_diff := data.get_decontamination_tile_diff(coord)
+ if (
+ (saved_diff == ChunkData.TileDiff.PRESENT or tile_value < decontamination_threshold)
+ and saved_diff != ChunkData.TileDiff.ABSENT
+ ):
+ decontamination_tiles.append(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
+
+ planet.decontamination_layer.mutex.lock()
+ planet.decontamination_layer.place_decontaminations(decontamination_tiles)
+ planet.decontamination_layer.mutex.unlock()
-func generate_walls():
- var static_body = StaticBody2D.new()
- add_child(static_body)
- var wall_resolution_factor = 25
-
- for x in range(1, size.x, wall_resolution_factor):
- for y in range(1, size.y, wall_resolution_factor):
- if is_wall(Vector2(x, y)):
- var new_collision_shape = CollisionShape2D.new()
- new_collision_shape.shape = CircleShape2D.new()
- new_collision_shape.shape.radius = wall_resolution_factor / 2.
- static_body.add_child(new_collision_shape)
- new_collision_shape.global_position = Vector2i(x, y) + coord * size + Vector2i.ONE * 5
-
-func generate_loot(number : int = LOOT_NUMBER.pick_random()):
- for i in range(number):
- var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
- loot.item_number = LOOT_ITEM_NUMBER.pick_random()
-
- var max_placement_try = 10
- var valid_coord = false
- while max_placement_try > 0 and not valid_coord:
- var random_position = Vector2(
- randf_range(0, size.x),
- randf_range(0, size.y)
- )
- if not is_wall(random_position):
- planet.add_entity(loot, random_position + Vector2(coord * size))
- valid_coord = true
- else :
- max_placement_try -= 1
-
-func get_pixel_point(point : Vector2) -> Vector2i:
- var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
- return Vector2i(
- roundi(vec.x + 0.5),
- roundi(vec.y + 0.5)
- )
-
-
-func is_wall(game_point : Vector2) -> bool:
- var pixel_point = get_pixel_point(game_point)
- return noise_image.get_pixel(pixel_point.x, pixel_point.y).r < wall_threshold
\ No newline at end of file
+func _exit_tree():
+ generation_thread.wait_to_finish()
diff --git a/stages/terrain/planet/scripts/chunk_data.gd b/stages/terrain/planet/scripts/chunk_data.gd
new file mode 100644
index 0000000..f6cb6e5
--- /dev/null
+++ b/stages/terrain/planet/scripts/chunk_data.gd
@@ -0,0 +1,62 @@
+extends Resource
+class_name ChunkData
+
+enum TileDiff { NO_DIFF,PRESENT,ABSENT }
+
+@export var chunk_coord : Vector2i
+@export var rock_tiles_diff : Dictionary[String, TileDiff]
+@export var decontamination_tiles_diff : Dictionary[String, TileDiff]
+
+func _init(
+ _chunk_coord : Vector2i
+):
+ chunk_coord = _chunk_coord
+
+#region ------------------ Generic Tile ------------------
+
+func get_coord_key(coord : Vector2i) -> String:
+ return "%d:%d" % [coord.x, coord.y]
+
+func get_tile_diff(
+ coord : Vector2i,
+ tiles_diff : Dictionary[String, TileDiff]
+) -> TileDiff:
+ if not has_diff(coord, tiles_diff):
+ return TileDiff.NO_DIFF
+ return tiles_diff[get_coord_key(coord)]
+
+func update_tile_diff(
+ coord : Vector2i,
+ diff : TileDiff,
+ tiles_diff : Dictionary[String, TileDiff]
+):
+ tiles_diff[get_coord_key(coord)] = diff
+
+func has_diff(
+ coord : Vector2i,
+ tiles_diff : Dictionary[String, TileDiff]
+):
+ return tiles_diff.has(get_coord_key(coord))
+
+#region ------------------ Rock ------------------
+
+func get_rock_tile_diff(coord : Vector2i) -> TileDiff:
+ return get_tile_diff(coord, rock_tiles_diff)
+
+func update_rock_tile_diff(coord : Vector2i, diff : TileDiff):
+ update_tile_diff(coord, diff, rock_tiles_diff)
+
+func has_rock_tile_diff(coord : Vector2i):
+ return has_diff(coord, rock_tiles_diff)
+
+
+#region ------------------ Decontamination ------------------
+
+func get_decontamination_tile_diff(coord : Vector2i) -> TileDiff:
+ return get_tile_diff(coord, decontamination_tiles_diff)
+
+func update_decontamination_tile_diff(coord : Vector2i, diff : TileDiff):
+ update_tile_diff(coord, diff, decontamination_tiles_diff)
+
+func has_decontamination_tile_diff(coord : Vector2i):
+ return has_diff(coord, decontamination_tiles_diff)
\ No newline at end of file
diff --git a/stages/terrain/planet/scripts/chunk_data.gd.uid b/stages/terrain/planet/scripts/chunk_data.gd.uid
new file mode 100644
index 0000000..1367907
--- /dev/null
+++ b/stages/terrain/planet/scripts/chunk_data.gd.uid
@@ -0,0 +1 @@
+uid://clqa88okc325t
diff --git a/stages/terrain/planet/scripts/garden.gd b/stages/terrain/planet/scripts/garden.gd
index b215325..fc6869b 100644
--- a/stages/terrain/planet/scripts/garden.gd
+++ b/stages/terrain/planet/scripts/garden.gd
@@ -1,48 +1,18 @@
extends Node2D
class_name Garden
-const GARDEN_TEXTURE_SCALE : float = 3.0
-
-var contamination_material : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/ground_contamination.tres")
-
-var contamination_sprite : Polygon2D
-var contamination_texture : Texture2D
-var decontamination_surface : float
-
var plants : Array[Plant]
var planet_data : PlanetData
-var size = PlanetData.DEFAULT_GARDEN_SIZE
-
func _init(_planet_data : PlanetData, _initial_plants : Array[Plant] = []):
planet_data = _planet_data
plants = _initial_plants
# update_garden_score()
func _ready():
- contamination_sprite = generate_contamination_terrain_sprite()
- decontamination_surface = planet_data.get_decontamination_surface()
-
for p in plants:
p.harvested.connect(_on_plant_harvested)
p.state_changed.connect(_on_plant_state_changed)
- # update_garden_score()
-
-func generate_contamination_terrain_sprite() -> Polygon2D:
- if not planet_data.garden_contamination:
- planet_data.generate_default_contamination()
-
- var sprite :Polygon2D = generate_polygon_sprite(size, 1)
-
- contamination_texture = ImageTexture.create_from_image(planet_data.garden_contamination.image)
-
- contamination_material.set_shader_parameter("data_texture", contamination_texture)
- contamination_material.set_shader_parameter("data_texture_size", size)
- contamination_material.set_shader_parameter("texture_scale", GARDEN_TEXTURE_SCALE)
-
- sprite.material = contamination_material
-
- return sprite
func get_score():
var score = 0
@@ -88,30 +58,3 @@ func remove_plant(p: Plant):
func update_garden_score():
planet_data.garden_score = get_score()
-
-func impact_contamination(impact_position : Vector2, impact_radius : int, contamination : bool = false):
- planet_data.impact_contamination(impact_position, impact_radius, 0. if contamination else 1.)
- if contamination_texture:
- contamination_texture.update(planet_data.garden_contamination.image)
-
-func generate_polygon_sprite(s : Vector2 = size, order : int = 0) -> Polygon2D:
- var sprite = Polygon2D.new()
- sprite.polygon = PackedVector2Array([
- Vector2(0,0),
- Vector2(s.x, 0),
- Vector2(s.x, s.y),
- Vector2(0, s.y),
- ])
-
- sprite.z_index = -100 + order
-
- add_child(sprite)
-
- return sprite
-
-
-func is_in_garden(point : Vector2) -> bool:
- return planet_data.is_in_garden(point)
-
-func is_there_contamination(point : Vector2) -> bool:
- return planet_data.get_contamination(point) < 0.5
diff --git a/stages/terrain/planet/scripts/planet.gd b/stages/terrain/planet/scripts/planet.gd
index 6e5fa93..80de363 100644
--- a/stages/terrain/planet/scripts/planet.gd
+++ b/stages/terrain/planet/scripts/planet.gd
@@ -8,7 +8,17 @@ signal pass_day_ended(planet : Planet)
const PASS_DAY_ANIMATION_TIME : float = 1.5
const DEFAULT_DAY_LIMIT : int = 7
-const PLANET_TEXTURE_SCALE : float = 5.0
+
+const TILE_SET : TileSet = preload("res://stages/terrain/planet/resources/planet_tileset.tres")
+const TILE_SCALE = 1
+const TILE_SIZE : int = roundi(TILE_SET.tile_size.x * TILE_SCALE)
+const GROUND_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
+const CONTAMINATION_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres")
+const ORIGIN_CHUNK_HOLE_RADIUS = 5
+const CHUNK_TILE_SIZE : int = 20
+const CHUNK_SIZE = CHUNK_TILE_SIZE * TILE_SIZE
+const CHUNK_LOAD_DISTANCE : int = 1
+const CHUNK_UNLOAD_DISTANCE : int = 2
@export_group("Loot")
@export var first_loot_number : int = 3
@@ -19,157 +29,178 @@ var data : PlanetData
var contamination_texture : ImageTexture
var day_limit = DEFAULT_DAY_LIMIT
+var rock_layer : RockLayer
+var ground_layer : GroundLayer
+var decontamination_layer : DecontaminationLayer
var garden : Garden = null
-var generated_chunks_objects : Array[Vector2i] = []
+var generated_chunks : Dictionary[String,Chunk] = {}
+
+func _init():
+ data = GameInfo.game_data.current_planet_data
func _ready():
- data = GameInfo.game_data.current_planet_data
-
- entity_container.position = PlanetData.DEFAULT_GARDEN_SIZE/2
- load_entities(data.entities_saved_data)
+ entity_container.position = TILE_SIZE * CHUNK_TILE_SIZE * Vector2.ONE / 2
+ load_entities(data.entities_saved_data)
- var plants : Array[Plant] = []
- for e in entity_container.get_children():
- if e is Plant:
- plants.append(e)
+ var plants : Array[Plant] = []
+ for e in entity_container.get_children():
+ if e is Plant:
+ plants.append(e)
- garden = Garden.new(data, plants)
- add_child(garden)
+ garden = Garden.new(data, plants)
+ add_child(garden)
- if len(GameInfo.game_data.unlocked_plant_types) == 0:
- quota_reward.trigger_reward()
+ if len(GameInfo.game_data.unlocked_plant_types) == 0:
+ quota_reward.trigger_reward()
- generate_first_entities()
+ generate_first_entities()
- AudioManager.enter_planet()
+ AudioManager.enter_planet()
- if player:
- generate_near_chunks(player)
+ ground_layer = GroundLayer.new(self)
+ add_child(ground_layer)
+ rock_layer = RockLayer.new(self)
+ add_child(rock_layer)
+ decontamination_layer = DecontaminationLayer.new(self)
+ add_child(decontamination_layer)
+
+ if player:
+ generate_near_chunks(player)
func _process(_d):
- if player:
- generate_near_chunks(player)
+ if player:
+ generate_near_chunks(player)
+ remove_far_chunks(player)
-# queue_redraw()
+# queue_redraw()
# func _draw():
-# var factor = 20
-# for x in range(terrain_size.x / factor):
-# for y in range(terrain_size.y / factor):
-# var point = Vector2(x, y) * factor
+# var factor = 20
+# for x in range(terrain_size.x / factor):
+# for y in range(terrain_size.y / factor):
+# var point = Vector2(x, y) * factor
-# draw_circle(
-# point,
-# factor/10,
-# Color.BLUE if garden.is_there_contamination(point) else Color.RED,
-# true
-# )
+# draw_circle(
+# point,
+# factor/10,
+# Color.BLUE if garden.is_there_contamination(point) else Color.RED,
+# true
+# )
#region ------------------ Generation ------------------
func generate_first_entities():
- if not (Vector2i.ZERO in data.generated_chunk_entities):
- # Generate shovel
- drop_item(Shovel.new(), PlanetData.DEFAULT_GARDEN_SIZE/2 + Vector2(0, 100))
+ if not (Vector2i.ZERO in data.generated_chunk_entities):
+ # Generate shovel
+ drop_item(Shovel.new(), entity_container.global_position + Vector2(0, 100))
- # Generate first loots
- generate_loot(first_loot_number)
- data.generated_chunk_entities.append(Vector2i.ZERO)
+func get_chunk_key(coord) -> String:
+ return "%d:%d" % [coord.x, coord.y]
func generate_near_chunks(p : Player):
- var player_chunk_coord = Vector2i(
- floor(p.global_position.x / PlanetData.DEFAULT_GARDEN_SIZE.x),
- floor(p.global_position.y / PlanetData.DEFAULT_GARDEN_SIZE.y)
- )
- for x in [-1, 0, 1]:
- for y in [-1, 0, 1]:
- var coord = Vector2i(x,y) + player_chunk_coord
- if coord != Vector2i.ZERO and generated_chunks_objects.find(coord) == -1:
- generate_chunk(coord)
+ var player_chunk_coord = Math.get_chunk_from_pos(p.global_position)
+
+ for x in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
+ for y in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
+ var coord : Vector2i = Vector2i(x,y) + player_chunk_coord
+ if not generated_chunks.has(get_chunk_key(coord)):
+ generate_chunk(coord)
+
+func remove_far_chunks(p : Player):
+ var player_chunk_coord = Vector2i(
+ floor(p.global_position.x / (CHUNK_TILE_SIZE * TILE_SIZE)),
+ floor(p.global_position.y / (CHUNK_TILE_SIZE * TILE_SIZE))
+ )
+
+ for chunk in generated_chunks.values():
+ var chunk_coord = chunk.data.chunk_coord
+ if player_chunk_coord.distance_to(chunk_coord) > CHUNK_UNLOAD_DISTANCE:
+ remove_chunk(chunk)
func generate_chunk(coord : Vector2i):
- if generated_chunks_objects.find(coord) == -1:
- generated_chunks_objects.append(coord)
- var new_chunk = Chunk.new(
- coord,
- PlanetData.DEFAULT_GARDEN_SIZE,
- self,
- (data.generated_chunk_entities.find(coord) != -1)
- )
- add_child(new_chunk)
- data.generated_chunk_entities.append(coord)
+ var chunk_data := data.get_or_create_chunk_data(coord)
+ if coord == Vector2i(0,0):
+ create_hole_in_chunk(chunk_data, ORIGIN_CHUNK_HOLE_RADIUS)
+ var chunk_key = get_chunk_key(coord)
+ if not generated_chunks.has(chunk_key):
+ var new_chunk = Chunk.new(
+ chunk_data,
+ self
+ )
+ generated_chunks[chunk_key] = new_chunk
+ add_child(new_chunk)
+ data.generated_chunk_entities.append(coord)
+
+func create_hole_in_chunk(chunk_data : ChunkData, hole_radius : int):
+ var hole_center = Vector2i.ONE * floori(CHUNK_TILE_SIZE/2.)
+ for x in range(CHUNK_TILE_SIZE):
+ for y in range(CHUNK_TILE_SIZE):
+ var coord = Vector2i(x,y)
+ if coord.distance_to(hole_center) < hole_radius:
+ chunk_data.update_rock_tile_diff(
+ coord,
+ ChunkData.TileDiff.ABSENT
+ )
+
+func remove_chunk(chunk : Chunk):
+ generated_chunks.erase(get_chunk_key(chunk.data.chunk_coord))
+ chunk.unload()
+ chunk.queue_free()
func save():
- data.entities_saved_data = save_entities()
+ data.entities_saved_data = save_entities()
#endregion
#region ------------------ Usage ------------------
func plant(
- type : PlantType,
- plant_position : Vector2,
- plant_mutations : Array[PlantMutation] = []
+ type : PlantType,
+ plant_position : Vector2,
+ plant_mutations : Array[PlantMutation] = []
) -> bool:
- if garden.is_in_garden(plant_position):
- var new_plant = garden.plant(type, plant_mutations)
- add_entity(new_plant, plant_position)
- return true
- return false
+ var new_plant = garden.plant(type, plant_mutations)
+ add_entity(new_plant, plant_position)
+ return true
func pass_day():
- for e : Node2D in entity_container.get_children():
- if e.has_method("_start_pass_day"):
- e._start_pass_day()
- pass_day_started.emit(self)
- await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
+ for e : Node2D in entity_container.get_children():
+ if e.has_method("_start_pass_day"):
+ e._start_pass_day()
+ pass_day_started.emit(self)
+ await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
- pass_day_proceeded.emit(self)
- data.day += 1
- data.quota_days -= 1
- for e : Node2D in entity_container.get_children():
- if e.has_method("_pass_day"):
- e._pass_day()
-
- pass_day_ended.emit(self)
- await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
- for e : Node2D in entity_container.get_children():
- if e.has_method("_end_pass_day"):
- e._end_pass_day()
+ pass_day_proceeded.emit(self)
+ data.day += 1
+ data.quota_days -= 1
+ for e : Node2D in entity_container.get_children():
+ if e.has_method("_pass_day"):
+ e._pass_day()
+
+ pass_day_ended.emit(self)
+ await get_tree().create_timer(PASS_DAY_ANIMATION_TIME/2.).timeout
+ for e : Node2D in entity_container.get_children():
+ if e.has_method("_end_pass_day"):
+ e._end_pass_day()
- garden.update_garden_score()
+ garden.update_garden_score()
- if data.garden_score >= data.get_quota_score():
- reach_quota()
- elif data.quota_days <= 0:
- day_limit_exceed.emit(self)
+ if data.garden_score >= data.get_quota_score():
+ reach_quota()
+ elif data.quota_days <= 0:
+ day_limit_exceed.emit(self)
- save()
-
-func generate_loot(number : int):
- for i in range(number):
- var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
- loot.item_number = loot_item_number.pick_random()
-
- var loot_random_range = UndergroundLoot.LOOTED_ITEM_RANDOM_RANGE
-
- add_entity(
- loot,
- Vector2(
- randf_range(loot_random_range, garden.size.x),
- randf_range(loot_random_range, garden.size.y)
- )
- )
+ save()
func reach_quota():
- data.quota += 1
- quota_reward.trigger_reward()
- await quota_reward.reward_chosen
- garden.update_garden_score()
- if data.garden_score >= data.get_quota_score():
- reach_quota()
- data.quota_days = data.get_quota_duration()
+ data.quota += 1
+ quota_reward.trigger_reward()
+ await quota_reward.reward_chosen
+ garden.update_garden_score()
+ if data.garden_score >= data.get_quota_score():
+ reach_quota()
+ data.quota_days = data.get_quota_duration()
#endregion
diff --git a/stages/terrain/planet/scripts/planet_data.gd b/stages/terrain/planet/scripts/planet_data.gd
index 444e115..7cdb40d 100644
--- a/stages/terrain/planet/scripts/planet_data.gd
+++ b/stages/terrain/planet/scripts/planet_data.gd
@@ -3,97 +3,85 @@ class_name PlanetData
signal new_quota_started(planet_data : PlanetData)
signal plant_gaining_score(p : Plant, amount : int)
-signal contamination_updated(decontamination_surface : float)
signal updated(planet_data : PlanetData)
const MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE = 3000
const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
@export var garden_size : Vector2 = Vector2(2000,2000)
-@export var garden_contamination : TerrainData
+@export var planet_seed : int
@export var quota : int = 0 :
- set(v):
- quota = v
- is_quota_announced = false
- new_quota_started.emit(self)
+ set(v):
+ quota = v
+ is_quota_announced = false
+ new_quota_started.emit(self)
@export var is_quota_announced : bool = false
@export var garden_score : int = 0 :
- set(v):
- garden_score = v
- updated.emit(self)
+ set(v):
+ garden_score = v
+ updated.emit(self)
@export var day : int = 1
-@export var planet_seed : int
@export var quota_days : int = get_quota_duration() :
- set(v):
- quota_days = v
- updated.emit(self)
+ set(v):
+ quota_days = v
+ updated.emit(self)
@export var entities_saved_data : Array[EntityData] = []
@export var score_by_plant : Array[int] = []
@export var generated_chunk_entities : Array[Vector2i]
@export var tutorial_step : int = 0
+@export var chunks_data : Dictionary[String, ChunkData]
+
func _init(_base_size : Vector2 = DEFAULT_GARDEN_SIZE):
- planet_seed = randi()
- garden_size = _base_size
- garden_contamination = TerrainData.new(garden_size)
- garden_contamination.draw_random_zone(
- MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE,
- garden_size/2,
- planet_seed
- )
- contamination_updated.emit(get_decontamination_surface())
+ planet_seed = randi()
+ garden_size = _base_size
-#region ------------------ Contamination ------------------
-func impact_contamination(position : Vector2, impact_radius : float, to_value : float = 1.):
- garden_contamination.draw_circle(
- position,
- impact_radius,
- to_value
- )
- contamination_updated.emit(get_decontamination_surface())
+#region ------------------ Chunks ------------------
-func is_in_garden(point):
- return (
- point.x > 0
- and point.y > 0
- and point.x < garden_size.x
- and point.y < garden_size.y)
+func get_coord_id(coord):
+ return "%d:%d" % [coord.x, coord.y]
-func get_contamination(point : Vector2) -> float:
- return garden_contamination.get_value(point)
+func has_chunk_data(coord : Vector2i) -> bool:
+ return chunks_data.has(get_coord_id(coord))
-func get_decontamination_coverage() -> float:
- return garden_contamination.get_value_coverage()
+func add_chunk_data(coord : Vector2i, data : ChunkData):
+ chunks_data[get_coord_id(coord)] = data
-func get_decontamination_surface() -> float:
- return garden_contamination.get_value_surface()
+func get_chunk_data(coord : Vector2i) -> ChunkData:
+ return chunks_data[get_coord_id(coord)]
-#endregion
+func get_or_create_chunk_data(coord : Vector2i) -> ChunkData:
+ if has_chunk_data(coord):
+ return get_chunk_data(coord)
+ else:
+ var new_chunk_data = ChunkData.new(coord)
+ add_chunk_data(coord, new_chunk_data)
+ return new_chunk_data
#region ------------------ Quotas ------------------
func get_quota_score(q : int = quota) -> int:
- var first_quotas = [
- 4,
- 10,
- 20,
- 40,
- 80,
- ]
+ var first_quotas = [
+ 4,
+ 10,
+ 20,
+ 40,
+ 80,
+ ]
- if quota >= len(first_quotas):
- return pow(q, 3)
- else:
- return first_quotas[q]
+ if quota >= len(first_quotas):
+ return pow(q, 3)
+ else:
+ return first_quotas[q]
func get_quota_duration(_q = quota) -> int:
- return 7
+ return 7
#endregion
#region ------------------ Score ------------------
func plant_has_gained_score(plant : Plant, amount : int):
- plant_gaining_score.emit(plant, amount)
+ plant_gaining_score.emit(plant, amount)
#endregion
-
+
diff --git a/stages/terrain/planet/scripts/terrain_data.gd b/stages/terrain/planet/scripts/terrain_data.gd
deleted file mode 100644
index f8c50fa..0000000
--- a/stages/terrain/planet/scripts/terrain_data.gd
+++ /dev/null
@@ -1,105 +0,0 @@
-extends Resource
-class_name TerrainData
-
-const UNIT_PER_PIXEL = 30
-
-@export var image : Image
-@export var image_size : Vector2i
-
-func _init(terrain_size : Vector2):
- image_size = terrain_size / UNIT_PER_PIXEL
- image = Image.create(
- image_size.x,
- image_size.y,
- false,
- Image.Format.FORMAT_L8
- )
-
-func draw_random_zone(
- zone_max_surface : float,
- zone_position : Vector2i,
- random_seed : int,
-):
- var noise: Noise = FastNoiseLite.new()
- noise.seed = random_seed
- noise.noise_type = FastNoiseLite.TYPE_CELLULAR
- noise.frequency = 0.1
-
- var noise_image_size : Vector2i = Vector2i.ONE * (image_size)
- var noise_image_center = noise_image_size / 2
-
- var noise_image = noise.get_image(
- noise_image_size.x,
- noise_image_size.y,
- 1.0,
- )
-
- ImageTools.flatten(noise_image, 0.5)
-
- ImageTools.draw_circle(
- noise_image,
- noise_image_center,
- int(round(80./float(UNIT_PER_PIXEL))),
- Color.WHITE,
- )
-
- var random_step = 1
- var zone_radius = noise_image_size.x - random_step
- while get_value_surface(noise_image) > zone_max_surface:
- zone_radius -= random_step
- ImageTools.draw_circle(
- noise_image,
- noise_image_center,
- zone_radius,
- Color.BLACK,
- true
- )
-
- image.blit_rect(
- noise_image,
- Rect2i(
- Vector2i.ZERO,
- noise_image_size
- ),
- Vector2i(zone_position / UNIT_PER_PIXEL) - noise_image_size/2
- )
-
-func draw_circle(position : Vector2, impact_radius : float, to_value : float = 1.):
- ImageTools.draw_circle(
- image,
- position / UNIT_PER_PIXEL,
- roundi(impact_radius / UNIT_PER_PIXEL),
- Color(1., 1., 1., to_value)
- )
-
-func is_in_image(pixel_point : Vector2i):
- return (
- pixel_point.x > 0
- and pixel_point.y > 0
- and pixel_point.x < image.get_width()
- and pixel_point.y < image.get_height())
-
-func is_in_terrain(point : Vector2):
- return is_in_image(get_pixel_point(point))
-
-func get_value(point : Vector2) -> float:
- var pixel_point : Vector2i = get_pixel_point(point)
- if (is_in_image(pixel_point)):
- return image.get_pixel(
- pixel_point.x,
- pixel_point.y
- ).r
- return 0
-
-func get_value_coverage(i : Image = image) -> float:
- return ImageTools.get_color_coverage(i)
-
-func get_value_surface(i : Image = image) -> float:
- return float(ImageTools.get_color_pixel_count(i)) * UNIT_PER_PIXEL
-
-func get_pixel_point(point : Vector2) -> Vector2i:
- var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
- return Vector2i(
- roundi(vec.x + 0.5),
- roundi(vec.y + 0.5)
- )
diff --git a/stages/terrain/planet/scripts/terrain_data.gd.uid b/stages/terrain/planet/scripts/terrain_data.gd.uid
deleted file mode 100644
index fd8489a..0000000
--- a/stages/terrain/planet/scripts/terrain_data.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://we5pyyr1n06v
diff --git a/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd b/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd
new file mode 100644
index 0000000..e1f44b6
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd
@@ -0,0 +1,33 @@
+@tool
+extends PlanetLayer
+class_name DecontaminationLayer
+
+const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres")
+const DECONTAMINATION_TILE_TERRAIN_SET : int = 0
+const DECONTAMINATION_TILE_TERRAIN : int = 2
+
+func setup():
+ material = MATERIAL
+ z_index = -99
+
+func place_decontamination(coord : Vector2i, save = false):
+ place_decontaminations([coord], save)
+
+func place_decontaminations(coords : Array[Vector2i], save = false):
+ set_cells_terrain_connect(
+ coords,
+ DECONTAMINATION_TILE_TERRAIN_SET,
+ DECONTAMINATION_TILE_TERRAIN
+ )
+ if save:
+ for coord in coords:
+ var chunk_coord = Vector2i(
+ floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
+ floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
+ )
+ (planet.data
+ .get_chunk_data(chunk_coord)
+ .update_decontamination_tile_diff(coord, ChunkData.TileDiff.PRESENT))
+
+func is_decontamined(coord : Vector2i) -> bool:
+ return has_cell(coord)
diff --git a/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd.uid b/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd.uid
new file mode 100644
index 0000000..3a1e743
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/decontamination_layer.gd.uid
@@ -0,0 +1 @@
+uid://2p41t6efxudd
diff --git a/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd b/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd
new file mode 100644
index 0000000..4100882
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd
@@ -0,0 +1,18 @@
+@tool
+extends PlanetLayer
+class_name GroundLayer
+
+const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
+const GROUND_TILE_SOURCE_ID : int = 0
+const GROUND_TILE_ATLAS_COORD : Vector2i = Vector2i.ZERO
+
+func setup():
+ material = MATERIAL
+ z_index = -100
+
+func place_ground(tile_position : Vector2i):
+ set_cell(
+ tile_position,
+ GROUND_TILE_SOURCE_ID,
+ GROUND_TILE_ATLAS_COORD,
+ )
\ No newline at end of file
diff --git a/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd.uid b/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd.uid
new file mode 100644
index 0000000..07bce75
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/ground_layer.gd.uid
@@ -0,0 +1 @@
+uid://cui423qbula4a
diff --git a/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd b/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd
new file mode 100644
index 0000000..0bc4d6a
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd
@@ -0,0 +1,36 @@
+@abstract
+extends TileMapLayer
+class_name PlanetLayer
+
+var planet : Planet
+@onready var mutex : Mutex = Mutex.new()
+
+
+func _init(
+ _planet : Planet = null
+):
+ planet = _planet
+
+func _ready():
+ tile_set = Planet.TILE_SET
+ scale = Vector2.ONE * Planet.TILE_SCALE
+ navigation_enabled = false
+ setup()
+
+func setup():
+ pass
+
+func get_all_neighbors_cell(coord : Vector2i) -> Array[Vector2i]:
+ var neighbors : Array[Vector2i] = []
+ for x in [-1, 0, 1]:
+ for y in [-1, 0, 1]:
+ var neighbor = Vector2i(
+ coord.x + x,
+ coord.y + y
+ )
+ if coord != neighbor:
+ neighbors.append(neighbor)
+ return neighbors
+
+func has_cell(tile_position : Vector2i) -> bool:
+ return get_cell_source_id(tile_position) != -1
\ No newline at end of file
diff --git a/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd.uid b/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd.uid
new file mode 100644
index 0000000..cad9cfe
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/planet_layer.gd.uid
@@ -0,0 +1 @@
+uid://cyqmcmgeb76cp
diff --git a/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd b/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd
new file mode 100644
index 0000000..04d1fa5
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd
@@ -0,0 +1,87 @@
+@tool
+extends PlanetLayer
+class_name RockLayer
+
+const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/rock_planet_tilemap.tres")
+const ROCK_TILE_TERRAIN_SET : int = 0
+const ROCK_TILE_TERRAIN : int = 0
+const CRISTAL_TILE_TERRAIN : int = 1
+
+const CRISTAL_LOOT_CHANCE : float = 1
+
+enum TileType { EMPTY,ROCK,CRISTAL }
+
+func setup():
+ material = MATERIAL
+ z_index = 2
+
+func place_rock(coord : Vector2i, type := TileType.ROCK):
+ if type != TileType.EMPTY:
+ set_cells_terrain_connect(
+ [coord],
+ ROCK_TILE_TERRAIN_SET,
+ ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
+ )
+
+func place_rocks(coords : Array[Vector2i], type := TileType.ROCK):
+ if type != TileType.EMPTY:
+ set_cells_terrain_connect(
+ coords,
+ ROCK_TILE_TERRAIN_SET,
+ ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
+ )
+
+func remove_rocks(coords : Array[Vector2i], save = false):
+ set_cells_terrain_connect(
+ coords,
+ ROCK_TILE_TERRAIN_SET,
+ -1
+ )
+ if save:
+ for coord in coords:
+ var chunk_coord = Vector2i(
+ floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
+ floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
+ )
+ var chunk_tile_coord : Vector2i = coord - chunk_coord * Planet.CHUNK_TILE_SIZE
+ (planet.data
+ .get_chunk_data(chunk_coord)
+ .update_rock_tile_diff(chunk_tile_coord, ChunkData.TileDiff.ABSENT))
+
+func dig_rocks(coords : Array[Vector2i]) -> bool:
+ var has_rock = false
+
+ for coord in coords:
+ if has_tile(coord):
+ has_rock = true
+ loot_rock(coord)
+
+ if has_rock:
+ remove_rocks(coords, true)
+
+ return has_rock
+
+func loot_rock(coord : Vector2i):
+ if get_tile_type(coord) == TileType.CRISTAL and randf() < CRISTAL_LOOT_CHANCE:
+ if len(GameInfo.game_data.unlocked_plant_types):
+ var loot = Seed.new(
+ GameInfo.game_data.unlocked_plant_types.pick_random()
+ )
+ planet.drop_item(
+ loot,
+ coord * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.),
+ floor(Planet.TILE_SIZE/2.)
+ )
+
+func update_cells(coords : Array[Vector2i]):
+ for coord in coords:
+ if has_tile(coord):
+ place_rock(coord)
+
+func has_tile(coord : Vector2i) -> bool:
+ return has_cell(coord)
+
+func get_tile_type(coord : Vector2i) -> TileType:
+ if has_tile(coord):
+ return TileType.CRISTAL if get_cell_tile_data(coord).terrain == CRISTAL_TILE_TERRAIN else TileType.ROCK
+ return TileType.EMPTY
diff --git a/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd.uid b/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd.uid
new file mode 100644
index 0000000..46df1e4
--- /dev/null
+++ b/stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd.uid
@@ -0,0 +1 @@
+uid://cjys51dllryqk
diff --git a/stages/terrain/scripts/terrain.gd b/stages/terrain/scripts/terrain.gd
index 7835c9a..f3bdac4 100644
--- a/stages/terrain/scripts/terrain.gd
+++ b/stages/terrain/scripts/terrain.gd
@@ -5,9 +5,8 @@ const BORDER_WIDTH = 100
var player : Player
-@export var import_entities_from_node : Node2D = null
+@export var entity_container : Node2D
-@onready var entity_container : Node2D = create_entity_container()
func instantiate_entity(s: PackedScene, entity_position : Vector2):
var entity = s.instantiate() as Node2D
@@ -23,15 +22,18 @@ func add_entity(entity : Node2D, entity_global_position : Vector2 = Vector2.ZERO
else:
entity.get_parent().remove_child(entity)
+ enroll_entity(entity)
+
+ container.add_child(entity)
+ entity.global_position = entity_global_position
+
+func enroll_entity(entity : Node2D):
if "terrain" in entity:
entity.terrain = self
if entity is Player:
player = entity
- container.add_child(entity)
- entity.global_position = entity_global_position
-
func save_entities() -> Array[EntityData]:
var saved_entities_data : Array[EntityData] = []
for e in entity_container.get_children():
@@ -42,6 +44,9 @@ func save_entities() -> Array[EntityData]:
return saved_entities_data
func load_entities(saved_entities_data : Array[EntityData]):
+ for static_entity in entity_container.get_children():
+ enroll_entity(static_entity)
+
for save_data in saved_entities_data:
var entity = save_data.load()
if entity:
@@ -57,14 +62,6 @@ func create_entity_container() -> Node2D:
add_child(container)
- if import_entities_from_node:
- for child in import_entities_from_node.get_children():
- add_entity(
- child,
- child.global_position + (container.global_position - import_entities_from_node.global_position),
- container
- )
-
return container
func drop_item(item: Item, item_position : Vector2, random_displacement_factor = 0) -> ItemObject:
diff --git a/stages/terrain/truck/truck.tscn b/stages/terrain/truck/truck.tscn
index bea6a47..4d44a06 100644
--- a/stages/terrain/truck/truck.tscn
+++ b/stages/terrain/truck/truck.tscn
@@ -11,16 +11,17 @@
[node name="GameGui" parent="CanvasLayer" instance=ExtResource("2_dw1sv")]
-[node name="TruckInterior" parent="." node_paths=PackedStringArray("import_entities_from_node") instance=ExtResource("1_ycq4y")]
+[node name="TruckInterior" parent="." node_paths=PackedStringArray("entity_container") instance=ExtResource("1_ycq4y")]
position = Vector2(0, 0)
-import_entities_from_node = NodePath("../Entities")
+entity_container = NodePath("Entities")
+
+[node name="Entities" type="Node2D" parent="TruckInterior"]
+y_sort_enabled = true
+
+[node name="Player" parent="TruckInterior/Entities" instance=ExtResource("5_dw1sv")]
+position = Vector2(51, 492)
[node name="Camera" type="Camera2D" parent="."]
position = Vector2(385, 343)
script = ExtResource("2_063c3")
metadata/_custom_type_script = "uid://d1nsr56bh1a1y"
-
-[node name="Entities" type="Node2D" parent="."]
-
-[node name="Player" parent="Entities" instance=ExtResource("5_dw1sv")]
-position = Vector2(51, 492)