TowerDefense/Towers/Tower.gd

148 lines
3.6 KiB
GDScript3
Raw Normal View History

@tool
2025-03-26 18:55:43 +01:00
extends StaticBody3D
class_name Tower
2025-08-29 12:11:51 +02:00
# 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")
2025-08-31 23:07:55 +02:00
@export var tower_name : String = "None"
@export var type : TYPE
@export_group("Base data")
2025-08-25 23:42:09 +02:00
@export var icone : Texture2D
@export var bio : String
@export var price : int = 100
2025-06-18 12:19:43 +02:00
@export_group("Attack")
2025-08-31 23:07:55 +02:00
@export var projectileRessource : ProjectileResource
@export var towerRange : Shape3D
2025-06-18 12:19:43 +02:00
@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 :
set(value):
max_energy = value
towerChange.call_deferred()
@export var energy_regen : float = 10.0
@export var energy_cost : float = 50.0
2025-08-29 20:07:36 +02:00
@export_group("Button")
@export var buttonTooltip : String
2025-09-04 02:54:37 +02:00
@onready var energyBar : ProgressBar = $EnergyBar3D/SubViewport/EnergyBar2D
2025-08-27 13:27:32 +02:00
@onready var sprite : Sprite3D = $Sprite3D
2025-09-04 02:54:37 +02:00
@onready var energyRecoveryCooldown : Timer = $EnergyRecoveryCooldown
var energy : float = max_energy:
set(value):
2025-09-04 02:54:37 +02:00
energyBar.value = value
energy = clampf(value, 0.0, max_energy)
2025-08-30 15:46:36 +02:00
is_exhausted = energy < energy_cost
EventBus.tower_changed.emit(self)
2025-09-04 02:54:37 +02:00
var availableTargets : Array[Enemy]
var target : Enemy
var is_exhausted : bool = false
2025-09-04 02:54:37 +02:00
var is_rest : bool :
get(): return not energyRecoveryCooldown.is_stopped()
2025-08-29 12:11:51 +02:00
var builded : bool = false
2025-09-03 18:39:58 +02:00
2025-08-25 23:23:03 +02:00
@export_category("Upgrades")
2025-09-03 18:39:58 +02:00
@export var upgrades : Array[TowerUpgrade]
2025-08-25 23:23:03 +02:00
2025-06-18 12:19:43 +02:00
func _ready() -> void:
2025-09-03 18:39:58 +02:00
EventBus.tower_upgraded.connect(apply_upgrade)
2025-09-04 02:54:37 +02:00
energyRecoveryCooldown.timeout.connect(func(): energy += energy_regen)
# WARNING : Prevent .tscn file to be modified by the load of the scene in editor
if not Engine.is_editor_hint():
2025-09-04 02:54:37 +02:00
collision_layer = 0
collision_mask = 0
2025-09-04 02:54:37 +02:00
$PriceTag.text = str(price) + ""
$Range/Range.shape = towerRange
func _process(_delta: float) -> void:
2025-09-04 02:54:37 +02:00
if visible && $AttackCooldown.is_stopped() && builded && is_instance_valid(target):
shoot()
2025-08-25 23:23:03 +02:00
func get_available_upgrades() -> Array[TowerUpgrade]:
2025-09-03 18:39:58 +02:00
return upgrades.filter(func(u: TowerUpgrade): u.isLevelMax)
2025-08-25 23:23:03 +02:00
2025-09-03 18:39:58 +02:00
func apply_upgrade(towerType : Tower.TYPE, upgrade : TowerUpgrade):
if towerType == type && upgrade.canUpgrade():
2025-09-03 18:39:58 +02:00
upgrade.upgrade(self)
2025-06-18 12:19:43 +02:00
2025-03-26 18:55:43 +01:00
func shoot() -> void:
energy -= energy_cost
2025-08-31 23:07:55 +02:00
var projectile : Projectile = projectileScene.instantiate()
2025-09-04 02:54:37 +02:00
projectile.loadProjectile(projectileRessource, target)
EventBus.projectile_shooted.emit(projectile, $Aim.global_position)
2025-09-04 02:54:37 +02:00
$AttackCooldown.start(action_cooldown)
2025-03-26 18:55:43 +01:00
func resting() -> void:
visible = false
2025-09-04 02:54:37 +02:00
collision_layer = 0
collision_mask = 0
if builded:
energyRecoveryCooldown.start()
func in_action() -> void:
visible = true
if builded:
collision_layer = 0b100
collision_mask = 0b100
energyRecoveryCooldown.stop()
2025-09-04 02:54:37 +02:00
func choose_target() -> void:
target = null
for enemy in availableTargets:
if not target || enemy.progress > target.progress:
target = enemy
2025-03-26 18:55:43 +01:00
2025-09-04 02:54:37 +02:00
func build() -> bool:
if builded || not Game.spendMoney(price):
2025-09-04 02:54:37 +02:00
return false
sprite.modulate = "ffffffff"
energyBar.value = energy
energyBar.max_value = max_energy
$EnergyBar3D.visible = true
builded = true
$PriceTag.visible = false
EventBus.tower_changed.emit(self)
2025-09-04 02:54:37 +02:00
return true
2025-08-27 13:27:32 +02:00
func towerChange() -> void:
energyBar.max_value = max_energy
EventBus.tower_changed.emit(self)
2025-03-26 18:55:43 +01:00
func _on_range_body_entered(body: Node3D) -> void:
if body is Enemy:
2025-09-04 02:54:37 +02:00
availableTargets.append(body)
choose_target()
2025-03-26 18:55:43 +01:00
func _on_range_body_exited(body: Node3D) -> void:
if body is Enemy:
2025-09-04 02:54:37 +02:00
availableTargets.erase(body)
choose_target()