@tool extends StaticBody3D class_name Tower # DANGER "NONE" Should always be first enum TYPE { NONE, PIERRE, ALINE, MAXENCE, VICTORIA, EVAN, ALEX, GERALDINE } var projectileScene : PackedScene = preload("res://Towers/Projectiles/projectile.tscn") @export var tower_name : String = "None" @export var tower_type : TYPE @export_group("Base data") @export var icone : Texture2D @export var bio : String @export var price : int = 100 @export_group("Attack") @export var projectileRessource : ProjectileResource @export var towerRange : Shape3D @export var action_cooldown : float = 1.5: set(value): action_cooldown = clamp(value, 0.3, 999) @export_group("Energy") @export var max_energy : float = 100.0 @export var energy_regen : float = 10.0 @export var energy_cost : float = 50.0 @export_group("Button") @export var buttonTooltip : String @onready var energy_bar : ProgressBar = $EnergyBar3D/SubViewport/EnergyBar2D @onready var sprite : Sprite3D = $Sprite3D var energy : float = 0: set(value): energy_bar.value = value energy = clampf(value, 0.0, max_energy) is_exhausted = energy < energy_cost EventBus.energy_has_changed.emit(self) var current_targets : Array = [] var current : CharacterBody3D var can_shoot : bool = false var is_exhausted : bool = false var builded : bool = false var is_rest : bool = true: set(value): is_rest = value if value: resting() else: in_action() @export_category("Upgrades") @export var upgrades : Array[TowerUpgrade] func _ready() -> void: EventBus.tower_upgraded.connect(apply_upgrade) EventBus.energy_has_changed.emit(self) # WARNING : Prevent .tscn file to be modified by the load of the scene in editor if not Engine.is_editor_hint(): $PriceTag.text = str(price) +" €" energy = max_energy $Range/Range.shape = towerRange energy_bar.value = energy energy_bar.max_value = max_energy $Cooldown.wait_time = action_cooldown func _process(_delta: float) -> void: if is_rest: return if is_instance_valid(current): if can_shoot && not is_exhausted: shoot() can_shoot = false $Cooldown.start() func get_available_upgrades() -> Array[TowerUpgrade]: return upgrades.filter(func(u: TowerUpgrade): u.isLevelMax) func apply_upgrade(towerType : Tower.TYPE, upgrade : TowerUpgrade): ## TODO DANGER connect cube money if towerType == tower_type && upgrade.canUpgrade(100): upgrade.upgrade(self) func shoot() -> void: energy -= energy_cost var projectile : Projectile = projectileScene.instantiate() projectile.loadProjectile(projectileRessource, current) EventBus.projectile_shooted.emit(projectile, $Aim.global_position) func resting() -> void: energy += energy_regen visible = false set_collision_layer_value(3,false) set_collision_mask_value(3, false) $EnergyCooldown.start() func in_action() -> void: visible = true set_collision_layer_value(3, true) set_collision_mask_value(3, true) $EnergyCooldown.stop() func choose_target(_current_targets : Array) -> void: var temp_array : Array = _current_targets var current_target : CharacterBody3D = null for i in temp_array: if current_target == null : current_target = i else: if i.get_parent().get_progress() > current_target.get_parent().get_progress(): current_target = i current = current_target func build() -> void: EventBus.money_spent.emit(price) can_shoot = true collision_layer = 3 sprite.modulate = "ffffffff" builded = true $PriceTag.visible = false EventBus.tower_builded.emit(self) func _on_range_body_entered(body: Node3D) -> void: if body is Enemy: current_targets.append(body) choose_target(current_targets) func _on_range_body_exited(body: Node3D) -> void: if body is Enemy: current_targets.erase(body) choose_target(current_targets) func _on_cooldown_timeout() -> void: can_shoot = true func _on_energy_cooldown_timeout() -> void: resting()