gros dev pre proto

* Changement de l'UI, ajouts de l'inspecteur par carte et changement de police
* Ajout d'un semblant d'exploration
* Ajout de la sauvegarde des entités
* Restructuration mineure de l'arborescence
* Fix divers et réécriture des textes
This commit is contained in:
2025-10-31 13:52:45 +01:00
parent ceae7af589
commit ed7a8bcb6e
167 changed files with 2665 additions and 1201 deletions

View File

@@ -4,48 +4,67 @@ class_name GameData
signal current_planet_data_updated(p : PlanetData)
func _init():
set_default_unlocked()
set_default_unlocked()
@export var tutorial_done = false
@export var current_planet_data : PlanetData :
set(v):
current_planet_data = v
current_planet_data_updated.emit(v)
@export var current_planet_data : PlanetData = PlanetData.new() :
set(v):
current_planet_data = v
current_planet_data_updated.emit(v)
@export var player_data : PlayerData = PlayerData.new()
@export var unlocked_plant_types : Array[PlantType] = []
@export var unlocked_plant_mutations : Array[PlantMutation] = []
@export var unlocked_machines : Array[MachineType] = []
@export var truck_data : TruckData = TruckData.new()
func set_default_unlocked():
unlocked_plant_types = all_plant_types()
unlocked_plant_mutations = all_plant_mutations()
unlocked_machines = all_machines()
unlocked_plant_types = all_plant_types()
unlocked_plant_mutations = all_plant_mutations()
unlocked_machines = all_machines()
func reset_planet():
current_planet_data = PlanetData.new()
func reset_player():
player_data = PlayerData.new()
func reset_truck():
truck_data = TruckData.new()
func reset_all():
reset_planet()
reset_player()
reset_truck()
func all_plant_types() -> Array[PlantType]:
return [
preload("res://entities/plants/resources/plant_types/champ.tres"),
preload("res://entities/plants/resources/plant_types/chardi.tres"),
preload("res://entities/plants/resources/plant_types/ferno.tres"),
preload("res://entities/plants/resources/plant_types/maias.tres"),
preload("res://entities/plants/resources/plant_types/philea.tres"),
preload("res://entities/plants/resources/plant_types/pili.tres"),
preload("res://entities/plants/resources/plant_types/solita.tres"),
]
return [
preload("res://entities/plants/resources/plant_types/champ.tres"),
preload("res://entities/plants/resources/plant_types/chardi.tres"),
preload("res://entities/plants/resources/plant_types/ferno.tres"),
preload("res://entities/plants/resources/plant_types/maias.tres"),
preload("res://entities/plants/resources/plant_types/philea.tres"),
preload("res://entities/plants/resources/plant_types/pili.tres"),
preload("res://entities/plants/resources/plant_types/solita.tres"),
]
func all_machines() -> Array[MachineType]:
return [
preload("res://entities/interactables/machines/solar_pannel/solar_pannel.tres"),
]
return [
preload("res://entities/interactables/machines/solar_pannel/solar_pannel.tres"),
]
func all_plant_mutations() -> Array[PlantMutation]:
return [
preload("res://entities/plants/resources/plant_mutations/ancient_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/elitist_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/ermit_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/precocious_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/quality_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/quick_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/sociable_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/strong_mutation.tres"),
]
return [
preload("res://entities/plants/resources/plant_mutations/ancient_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/elitist_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/ermit_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/precocious_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/quality_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/quick_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/sociable_mutation.tres"),
preload("res://entities/plants/resources/plant_mutations/strong_mutation.tres"),
]

View File

@@ -1,88 +0,0 @@
extends Resource
class_name PlanetData
signal quota_number_updated(quota : int)
signal contamination_updated(decontamination_surface : float)
const MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE = 3000
const DEFAULT_BASE_SIZE = Vector2(1500,1500)
@export var base_size : Vector2 = Vector2(2000,2000)
@export var contamination : TerrainData
@export var quota_number : int = 0 :
set(v):
quota_number = v
quota_number_updated.emit(v)
func _init(_base_size : Vector2 = DEFAULT_BASE_SIZE):
base_size = _base_size
contamination = TerrainData.new(base_size)
contamination.draw_random_zone(
MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE,
base_size/2
)
contamination_updated.emit(get_decontamination_surface())
func impact_contamination(position : Vector2, impact_radius : float, to_value : float = 1.):
contamination.draw_circle(
position,
impact_radius,
to_value
)
contamination_updated.emit(get_decontamination_surface())
func is_in_base(point):
return (
point.x > 0
and point.y > 0
and point.x < base_size.x
and point.y < base_size.y)
func get_contamination(point : Vector2) -> float:
return contamination.get_value(point)
func get_decontamination_coverage() -> float:
return contamination.get_value_coverage()
func get_decontamination_surface() -> float:
return contamination.get_value_surface()
#endregion
#region ------------------ Objectives ------------------
func generate_objective_rewards(level = 0) -> Array[ObjectiveReward]:
var amount = level + 1
var possible_objective_rewards_path : Array[ObjectiveReward] = [
LootRandomSeedsReward.new(randi_range(4+level, 6+level))
]
var objectives_reward : Array[ObjectiveReward] = []
var i = 0
while i < amount and len(possible_objective_rewards_path) > 0:
var r = possible_objective_rewards_path.pick_random()
possible_objective_rewards_path.erase(r)
objectives_reward.append(r)
i += 1
return objectives_reward
#endregion
#region ------------------ Quotas ------------------
func get_quota(n = 0) -> int:
var first_quotas = [
5,
10,
20,
50,
]
if n >= len(first_quotas):
return pow(n, 3)
else:
return first_quotas[n]
#endregion

View File

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

View File

@@ -1,104 +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
):
var noise: Noise = FastNoiseLite.new()
noise.seed = randi()
noise.noise_type = FastNoiseLite.TYPE_CELLULAR
noise.frequency = 0.01
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,
80/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)
)

View File

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

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-align-right"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 6l16 0" /><path d="M10 12l10 0" /><path d="M6 18l14 0" /></svg>

After

Width:  |  Height:  |  Size: 372 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dth2mj0nh2q70"
path="res://.godot/imported/align-right.svg-00a2b5131e77dace169169767ed900d3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://common/icons/align-right.svg"
dest_files=["res://.godot/imported/align-right.svg-00a2b5131e77dace169169767ed900d3.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
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#ffffff" class="icon icon-tabler icons-tabler-filled icon-tabler-caret-down"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 9c.852 0 1.297 .986 .783 1.623l-.076 .084l-6 6a1 1 0 0 1 -1.32 .083l-.094 -.083l-6 -6l-.083 -.094l-.054 -.077l-.054 -.096l-.017 -.036l-.027 -.067l-.032 -.108l-.01 -.053l-.01 -.06l-.004 -.057v-.118l.005 -.058l.009 -.06l.01 -.052l.032 -.108l.027 -.067l.07 -.132l.065 -.09l.073 -.081l.094 -.083l.077 -.054l.096 -.054l.036 -.017l.067 -.027l.108 -.032l.053 -.01l.06 -.01l.057 -.004l12.059 -.002z" /></svg>

After

Width:  |  Height:  |  Size: 630 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://deywxmh76nu5w"
path="res://.godot/imported/caret-down.svg-5e12f7a0e24150592bca8fbef87f9420.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://common/icons/caret-down.svg"
dest_files=["res://.godot/imported/caret-down.svg-5e12f7a0e24150592bca8fbef87f9420.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
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#ffffff" class="icon icon-tabler icons-tabler-filled icon-tabler-circle-number-1"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10 -10 10s-10 -4.477 -10 -10s4.477 -10 10 -10zm.994 5.886c-.083 -.777 -1.008 -1.16 -1.617 -.67l-.084 .077l-2 2l-.083 .094a1 1 0 0 0 0 1.226l.083 .094l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l.293 -.293v5.586l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-8l-.006 -.114z" /></svg>

After

Width:  |  Height:  |  Size: 537 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b5it82pe130mw"
path="res://.godot/imported/circle-number-1.svg-9130748c35c52e7585b27d380ce0d1a2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://common/icons/circle-number-1.svg"
dest_files=["res://.godot/imported/circle-number-1.svg-9130748c35c52e7585b27d380ce0d1a2.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
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#ffffff" class="icon icon-tabler icons-tabler-filled icon-tabler-swipe-down"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 3a5 5 0 0 1 1.001 9.9l-.001 4.684l1.293 -1.291a1 1 0 0 1 1.32 -.083l.094 .083a1 1 0 0 1 0 1.414l-3 3a1 1 0 0 1 -.112 .097l-.11 .071l-.114 .054l-.105 .035l-.149 .03l-.117 .006l-.075 -.003l-.126 -.017l-.111 -.03l-.111 -.044l-.098 -.052l-.096 -.067l-.09 -.08l-3 -3a1 1 0 0 1 1.414 -1.414l1.293 1.292v-4.685a5.002 5.002 0 0 1 1 -9.9" /></svg>

After

Width:  |  Height:  |  Size: 568 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dqhqcplref0hc"
path="res://.godot/imported/swipe-down.svg-65a44f5fb7f727b34db8ef80248316a5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://common/icons/swipe-down.svg"
dest_files=["res://.godot/imported/swipe-down.svg-65a44f5fb7f727b34db8ef80248316a5.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
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -1,92 +0,0 @@
extends Resource
class_name Inventory
signal inventory_changed(inventory: Inventory)
@export var items: Array[Item] = []
var current_item_ind: int = 0
func _init(inventory_size: int = 1):
items.resize(inventory_size)
func get_best_available_slot_ind():
if items[current_item_ind] == null:
return current_item_ind
for i in items.size():
if items[i] == null:
return i
return current_item_ind
func set_current_item(new_ind: int):
if new_ind >= items.size():
return
if new_ind != current_item_ind:
current_item_ind = new_ind
emit_signal("inventory_changed", self)
func change_current_item(ind_mod: int):
if items.size() == 0:
current_item_ind = 0
return
var new_ind: int = current_item_ind + ind_mod
new_ind = new_ind % items.size()
if new_ind < 0:
new_ind += items.size()
set_current_item(new_ind)
func add_item(item: Item):
var best_ind = get_best_available_slot_ind()
if best_ind != current_item_ind:
set_item(item, best_ind)
return true
else:
return false
func set_item(item: Item, ind: int = 0) -> bool:
if ind < 0 || ind >= items.size():
return false
while len(items) <= ind:
items.append(null)
items[ind] = item
emit_signal("inventory_changed", self)
return true
func get_item(ind: int = current_item_ind) -> Item:
if ind < 0 || items.size() <= ind:
return null
return items[ind]
func has_item(item: Item) -> bool:
return item in items
func remove_item(item: Item):
var ind = items.find(item)
if ind >= 0:
items[ind] = null
emit_signal("inventory_changed", self)
func remove_item_at(ind: int = current_item_ind):
if items.size() <= ind:
return
items[ind] = null
emit_signal("inventory_changed", self)
func remove_current_item():
remove_item_at()
func pop_item(ind: int = current_item_ind) -> Item:
if items.size() == 0:
return
var item_removed: Item = items[ind]
items[ind] = null
emit_signal("inventory_changed", self)
return item_removed
func is_full():
for i in items:
if i == null : return false
return true

View File

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

View File

@@ -1,48 +0,0 @@
extends Resource
class_name Item
var name: String : get = get_item_name
var description: String : get = get_description
var icon: Texture2D : get = get_icon
var usage_zone_radius: int = 5 : get = get_usage_zone_radius
var energy_usage : int = 1 : get = get_energy_used
func get_item_name() -> String:
return name
func get_description() -> String:
return description
func get_icon() -> Texture2D:
return icon
func get_energy_used() -> int:
return energy_usage
func get_usage_zone_radius() -> int:
return usage_zone_radius
func get_usage_object_affected(_i : InspectableEntity) -> bool:
return false
func is_one_time_use():
return false
func can_use(_player : Player, zone: Player.ActionZone) -> bool:
return false
func use_text() -> String:
return ""
func use(_player : Player, zone: Player.ActionZone):
return false
func inspector_info() -> Inspector.Info:
return Inspector.Info.new(
get_item_name(),
get_description(),
get_icon()
)
func get_particles() -> Array[Particles.Parameters]:
return []

View File

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

View File

@@ -1,39 +0,0 @@
extends Item
class_name Blueprint
@export var machine_type: MachineType
@export var machine_level: int = 1
func _init(_machine_type : MachineType = null, _machine_level : int = 1):
machine_type = _machine_type
machine_level = _machine_level
func get_item_name() -> String:
if machine_type:
return machine_type.name
return ""
func get_description() -> String:
if machine_type:
return machine_type.description
return ""
func get_icon() -> Texture2D:
return preload("res://common/icons/cube-3d-sphere.svg")
func use_text() -> String:
if machine_type:
return "Build " + machine_type.name
return ""
func is_one_time_use():
return true
func can_use(player : Player, zone : Player.ActionZone) -> bool:
return player.planet && player.planet.is_in_base(zone.get_global_position())
func use(player : Player, zone : Player.ActionZone) -> bool:
if machine_type and machine_level and player.planet:
player.planet.instantiate_machine(machine_type, machine_level, zone.get_global_position())
return true
return false

View File

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

View File

@@ -1,46 +0,0 @@
extends Item
class_name Fork
const USE_INTERVAL = 0.15
func get_item_name() -> String:
return "Fork"
func get_description() -> String:
return "Use it to harvest mature plants."
func get_icon() -> Texture2D:
return preload("res://common/icons/fork.svg")
func get_energy_used() -> int:
return 1
func get_usage_zone_radius() -> int:
return 50
func get_usage_object_affected(i : InspectableEntity) -> bool:
return i is Plant
func use_text() -> String:
return "Harvest"
func can_use(_player : Player, zone : Player.ActionZone) -> bool:
var areas = zone.get_affected_areas()
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
return true
func harvest(p : Plant, player: Player):
player.play_sfx("harvest")
p.harvest()
if player.planet:
player.planet.update_garden_score()

View File

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

View File

@@ -1,19 +0,0 @@
extends Fork
class_name Knife
const KNIFE_ZONE_RADIUS = 10
func get_item_name() -> String:
return "Knife"
func get_description() -> String:
return "Use it to harvest mature plants. Do not cost energy."
func get_energy_used() -> int:
return 0
func get_icon() -> Texture2D:
return preload("res://common/icons/slice.svg")
func get_usage_zone_radius() -> int:
return KNIFE_ZONE_RADIUS

View File

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

View File

@@ -1,32 +0,0 @@
extends Item
class_name Package
@export var scene: PackedScene
@export var package_name : String
@export_multiline var package_description : String
func _init(_scene : PackedScene = null):
scene = _scene
func get_item_name() -> String:
return package_name
func get_description() -> String:
return package_description
func get_icon() -> Texture2D:
return preload("res://common/icons/package.svg")
func use_text() -> String:
return "Open"
func is_one_time_use():
return true
func can_use(player : Player, zone : Player.ActionZone) -> bool:
return player.planet != null
func use(player : Player, zone : Player.ActionZone) -> bool:
player.planet.instantiate_entity(scene, zone.get_global_position())
return true

View File

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

View File

@@ -1,180 +0,0 @@
extends Item
class_name Seed
const MUTATION_PROBABILITY = 0.3
const SHOVEL_ICON = preload("res://common/icons/shovel.svg")
const GROWING_ICON = preload("res://common/icons/chevrons-up.svg")
const SCORE_ICON = preload("res://common/icons/growth.svg")
@export var plant_type: PlantType
@export var plant_mutations: Array[PlantMutation]
func get_item_name() -> String:
return plant_type.name
func get_description() -> String:
return ""
func get_icon() -> Texture2D:
return plant_type.seed_texture
func get_energy_used() -> int:
return 1
func get_usage_zone_radius() -> int:
return 30
func get_usage_object_affected(i : InspectableEntity) -> bool:
return i is Plant
func _init(
_plant_type : PlantType = null,
_parent_mutation : Array[PlantMutation] = []
):
plant_type = _plant_type
plant_mutations = Seed.mutate(_parent_mutation)
func use_text() -> String:
return "Plant " + plant_type.name
func is_one_time_use():
return true
func can_use(player : Player, zone : Player.ActionZone) -> bool:
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.is_there_contamination(point):
is_there_contamination_in_zone = true
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
player.play_sfx("dig")
return player.planet.plant(
plant_type,
zone.get_global_position(),
plant_mutations
)
func inspector_info() -> Inspector.Info:
var info = Inspector.Info.new(
get_item_name(),
get_description(),
get_icon()
)
for m in plant_mutations:
info.framed_infos.append(
PlantMutation.get_framed_info_from_mutation(m)
)
info.framed_infos.append_array(
PlantEffect.get_framed_info_from_all_trigger_effects(
plant_type.default_mature_effects,
plant_type.default_harvest_effects,
plant_type.default_cyclic_effects
)
)
info.stat_infos = [
Inspector.StatInfo.new(
"[b]%d[/b] points when mature" % plant_type.default_plant_score,
SCORE_ICON
),
Inspector.StatInfo.new(
"Grow in [b]%d[/b] days" % plant_type.default_growing_time,
GROWING_ICON
)
]
return info
func get_particles() -> 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)
)
)
return param
static func mutate(parent_mutation : Array[PlantMutation] = []) -> Array[PlantMutation]:
if randf() > MUTATION_PROBABILITY:
return parent_mutation
var possible_mutations : Array[MutationPossibility] = [
AddMutation.new()
]
if len(parent_mutation):
possible_mutations.append_array( [
UpgradeMutation.new(),
RemoveMutation.new(),
])
var chosen_mutation = possible_mutations.pick_random()
return chosen_mutation.mutate(parent_mutation)
class MutationPossibility:
func mutate(_parent_mutation : Array[PlantMutation] = [])-> Array[PlantMutation]:
return []
class DontMutate extends MutationPossibility:
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()
if mut:
var existing_mut_id = new_mutations.find_custom(func(m:PlantMutation): 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
class UpgradeMutation extends MutationPossibility:
func mutate(
parent_mutation : Array[PlantMutation] = []
) -> Array[PlantMutation]:
var new_mutations = parent_mutation.duplicate_deep()
new_mutations.pick_random().level += 1
return new_mutations
class RemoveMutation extends MutationPossibility:
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))
return new_mutations

View File

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

View File

@@ -1,44 +0,0 @@
extends Fork
class_name Shovel
const SHOVEL_ZONE_RADIUS = 50
func get_item_name() -> String:
return "Shovel"
func get_description() -> String:
return "Can dig up buried seeds and can be used to harvest mature plants."
func get_icon() -> Texture2D:
return preload("res://common/icons/shovel.svg")
func get_usage_zone_radius() -> int:
return SHOVEL_ZONE_RADIUS
func get_usage_object_affected(i : InspectableEntity) -> bool:
return i is Plant or i is UndergroundLoot
func use_text() -> String:
return "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
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
func dig(u: UndergroundLoot, player: Player):
player.play_sfx("dig")
u.dig()

View File

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

View File

@@ -1,21 +0,0 @@
extends Fork
class_name Trowel
const TROWEL_ZONE_RADIUS = 50
func get_item_name() -> String:
return "Trowel"
func get_description() -> String:
return "Use it to harvest mature plants, can get a [b]bonus seed[/b] from each plant."
func get_icon() -> Texture2D:
return preload("res://common/icons/trowel.svg")
func get_usage_zone_radius() -> int:
return TROWEL_ZONE_RADIUS
func harvest(p : Plant, player: Player):
ProduceSeedsEffect.new(1).effect(p)
player.play_sfx("harvest")
p.harvest()

View File

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

View File

@@ -5,11 +5,11 @@
[ext_resource type="AudioStream" uid="uid://bqwiaek5b5q00" path="res://common/music/assets/forest_phase_2.ogg" id="2_ji160"]
[ext_resource type="AudioStream" uid="uid://d1fyd5o331360" path="res://common/music/assets/vent.ogg" id="2_n52pk"]
[node name="Music" type="Node" node_paths=PackedStringArray("decontamination_musics")]
[node name="Music" type="Node" node_paths=PackedStringArray("garden_musics")]
process_mode = 3
script = ExtResource("1_ji160")
decontamination_musics = [NodePath("ForestPhase1"), NodePath("ForestPhase2")]
decontamination_musics_levels = Array[float]([0.0, 100.0])
garden_musics = [NodePath("ForestPhase1"), NodePath("ForestPhase2")]
garden_score_musics_levels = Array[float]([0.0, 10.0])
[node name="ForestPhase1" type="AudioStreamPlayer" parent="."]
stream = ExtResource("1_stre8")

View File

@@ -2,8 +2,8 @@ extends Node
@export var default_fade_time = 1.0
@export var decontamination_musics : Array[AudioStreamPlayer]
@export var decontamination_musics_levels : Array[float]
@export var garden_musics : Array[AudioStreamPlayer]
@export var garden_score_musics_levels : Array[float]
@onready var playing_music = null : set = play_music
@@ -13,18 +13,18 @@ func _ready():
func _on_current_planet_data_updated(planet_data : PlanetData):
if planet_data:
planet_data.contamination_updated.connect(_on_contamination_updated)
if len(decontamination_musics):
play_music(decontamination_musics[0])
if len(garden_musics):
play_music(garden_musics[0])
func _on_contamination_updated(decontamination_surface : float):
func _on_contamination_updated(garden_score : float):
var actual_level = 0
if len(decontamination_musics_levels) and len(decontamination_musics):
for level in range(1, len(decontamination_musics_levels)):
if decontamination_surface > decontamination_musics_levels[level]:
if len(garden_score_musics_levels) and len(garden_musics):
for level in range(1, len(garden_score_musics_levels)):
if garden_score > garden_score_musics_levels[level]:
actual_level = level
if len(decontamination_musics) > actual_level:
play_music(decontamination_musics[actual_level])
if len(garden_musics) > actual_level:
play_music(garden_musics[actual_level])
func stop_music():
play_music(null)

View File

@@ -0,0 +1,35 @@
shader_type canvas_item;
#define pow2(x) (x * x)
#define iResolution 1.0/SCREEN_PIXEL_SIZE
uniform sampler2D data_texture;
uniform vec2 data_texture_size;
uniform float data_texture_threshold = 0.5;
uniform sampler2D texture_0 : filter_nearest, repeat_enable;
uniform sampler2D texture_1 : filter_nearest, repeat_enable;
uniform float texture_scale = 10.;
//uniform float smooth_change_range = 0.15;
varying vec2 vert;
void vertex() {
vert = VERTEX;
}
void fragment() {
vec4 pixel_color = texture(data_texture, vert/data_texture_size);
float value = pixel_color.x;
vec2 texture_0_size = vec2(float(textureSize(texture_0, 0).x), float(textureSize(texture_0, 0).y)) / texture_scale;
vec2 texture_1_size = vec2(float(textureSize(texture_1, 0).x), float(textureSize(texture_1, 0).y)) / texture_scale;
vec4 color = texture(texture_0, vert/texture_0_size);
if (value > data_texture_threshold)
color = texture(texture_1, vert / texture_1_size);
COLOR = color;
}

View File

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