43 lines
1.4 KiB
GDScript
43 lines
1.4 KiB
GDScript
## Fighter.gd
|
|
## AI-controlled unit that attacks creeps during combat phase.
|
|
class_name Fighter
|
|
extends CharacterBody2D
|
|
|
|
var _data: Dictionary = {}
|
|
var _target: Node = null
|
|
var _attack_cooldown: float = 0.0
|
|
|
|
func setup(tower_data: Dictionary) -> void:
|
|
_data = tower_data
|
|
|
|
func _process(delta: float) -> void:
|
|
if GameState.current_phase != GameState.Phase.COMBAT:
|
|
return
|
|
_attack_cooldown -= delta
|
|
_find_target()
|
|
if _target and _attack_cooldown <= 0.0:
|
|
_attack()
|
|
|
|
func _find_target() -> void:
|
|
if _target and is_instance_valid(_target) and not _target.is_queued_for_deletion():
|
|
return # keep current target
|
|
# Find nearest creep in range
|
|
var range_px: float = _data.get("range", 150.0) * 32.0 # tiles to pixels
|
|
var nearest: Node = null
|
|
var nearest_dist: float = INF
|
|
for creep in get_tree().get_nodes_in_group("creeps"):
|
|
var d = global_position.distance_to(creep.global_position)
|
|
if d <= range_px and d < nearest_dist:
|
|
nearest = creep
|
|
nearest_dist = d
|
|
_target = nearest
|
|
|
|
func _attack() -> void:
|
|
if not _target or not is_instance_valid(_target):
|
|
return
|
|
var atk_type = _data.get("attack_type", DamageCalc.AttackType.NORMAL)
|
|
var arm_type = _target.get_armor_type() if _target.has_method("get_armor_type") else DamageCalc.ArmorType.LIGHT
|
|
var damage = DamageCalc.calculate(_data.get("damage", 10), atk_type, arm_type)
|
|
_target.take_damage(damage)
|
|
var speed: float = _data.get("attack_speed", 1.0)
|
|
_attack_cooldown = 1.0 / speed
|