Unit death

This commit is contained in:
gamer147
2026-04-02 09:01:10 -04:00
parent ce92c6e435
commit 528cb50e58
5 changed files with 67 additions and 9 deletions

View File

@@ -74,6 +74,11 @@ func _apply_deploy(unit: Unit, coords: Vector2i) -> void:
func is_wall(coords: Vector2i) -> bool:
return tile_map.get_cell_atlas_coords(coords) == tile_set.wall_tile_coords
func remove_unit(unit: Unit) -> void:
if unit.get_parent() == self:
remove_child(unit)
func target_tile(coords: Vector2i) -> void:
highlight_map.target_tile(coords)
tile_hovered.emit(coords)

View File

@@ -20,6 +20,8 @@ func _snapshot(unit: Unit, opponent: Unit) -> CombatProposal.CombatantStats:
return stats
func process_combat(attacker: Unit, defender: Unit) -> void:
if not attacker.is_alive() or not defender.is_alive():
return
var proposal := create_proposal(attacker, defender)
var atk_name := attacker.current_info.name
var def_name := defender.current_info.name
@@ -27,7 +29,9 @@ func process_combat(attacker: Unit, defender: Unit) -> void:
print(" %s — HP:%d ATK:%d DEF:%d HIT:%d" % [atk_name, proposal.attacker.hp, proposal.attacker.atk, proposal.attacker.def, proposal.attacker.hit])
print(" %s — HP:%d ATK:%d DEF:%d HIT:%d" % [def_name, proposal.defender.hp, proposal.defender.atk, proposal.defender.def, proposal.defender.hit])
apply_proposal(proposal)
print(" Result: %s HP=%d, %s HP=%d" % [atk_name, attacker.current_stats.current_hp, def_name, defender.current_stats.current_hp])
var atk_hp := attacker.current_stats.current_hp if is_instance_valid(attacker) else 0
var def_hp := defender.current_stats.current_hp if is_instance_valid(defender) else 0
print(" Result: %s HP=%d, %s HP=%d" % [atk_name, atk_hp, def_name, def_hp])
func apply_proposal(proposal: CombatProposal) -> void:
@@ -40,11 +44,11 @@ func apply_proposal(proposal: CombatProposal) -> void:
var atk_roll := randi_range(1, 100)
if atk_roll <= atk_stats.hit:
var damage := maxi(atk_stats.atk - def_stats.def, 0)
def_unit.current_stats.current_hp -= damage
def_unit.take_damage(damage)
# Counterattack if defender survives
if def_unit.current_stats.current_hp > 0:
if def_unit.is_alive():
var def_roll := randi_range(1, 100)
if def_roll <= def_stats.hit:
var damage := maxi(def_stats.atk - atk_stats.def, 0)
atk_unit.current_stats.current_hp -= damage
atk_unit.take_damage(damage)

View File

@@ -12,13 +12,31 @@ var _goal_pos: Vector2
var _moving := false
func _ready() -> void:
for unit: Unit in get_tree().get_nodes_in_group("units"):
unit.unit_died.connect(_on_unit_died)
get_tree().node_added.connect(_on_node_added)
func _on_node_added(node: Node) -> void:
if node is Unit and node.is_in_group("units"):
if not node.unit_died.is_connected(_on_unit_died):
node.unit_died.connect(_on_unit_died)
func _on_unit_died(unit: Unit) -> void:
if _selected_unit == unit:
_selected_unit = null
_moving = false
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton and not event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
var world_pos: Vector2 = get_viewport().get_canvas_transform().affine_inverse() * event.position
var clicked_unit := _get_unit_at(world_pos)
if clicked_unit:
if _selected_unit and clicked_unit != _selected_unit:
if _selected_unit and clicked_unit != _selected_unit and _selected_unit.is_alive() and clicked_unit.is_alive():
combat_requested.emit(_selected_unit, clicked_unit)
else:
_select_unit(clicked_unit)
@@ -33,7 +51,7 @@ func _unhandled_input(event: InputEvent) -> void:
func _physics_process(delta: float) -> void:
if not _selected_unit:
if not _selected_unit or not _selected_unit.is_alive():
return
if _moving:
@@ -78,6 +96,8 @@ func _select_unit(unit: Unit) -> void:
func _get_unit_at(world_pos: Vector2) -> Unit:
var snapped := dl_map.snap_to_grid(world_pos)
for unit: Unit in get_tree().get_nodes_in_group("units"):
if not unit.is_alive():
continue
var unit_snapped := dl_map.snap_to_grid(unit.global_position)
if unit_snapped == snapped:
return unit

View File

@@ -1,5 +1,7 @@
class_name Unit extends Node2D
enum UnitState { ALIVE, DEAD }
#region Templates
@export var stat_template: UnitStats
@export var info_template: UnitInfo
@@ -9,15 +11,33 @@ class_name Unit extends Node2D
var current_stats: UnitStats
var current_info: UnitInfo
var current_allegiance: UnitAllegiance
var state: UnitState = UnitState.ALIVE
signal unit_selected_changed(unit: Unit, selected: bool)
signal unit_allegiance_changed(unit: Unit, allegiance: UnitAllegiance)
signal unit_died(unit: Unit)
func _ready() -> void:
current_stats = stat_template.duplicate(true)
current_info = info_template.duplicate(true)
current_allegiance = allegiance_template.duplicate(true)
unit_allegiance_changed.emit(self, current_allegiance)
func set_selected(selected: bool) -> void:
unit_selected_changed.emit(self, selected)
func is_alive() -> bool:
return state == UnitState.ALIVE
func take_damage(amount: int) -> void:
if state != UnitState.ALIVE:
return
current_stats.current_hp -= amount
if current_stats.current_hp <= 0:
current_stats.current_hp = 0
_die()
func _die() -> void:
state = UnitState.DEAD
unit_died.emit(self)
queue_free()

View File

@@ -10,14 +10,23 @@ func _ready() -> void:
unit_panel.visible = false
for unit: Unit in get_tree().get_nodes_in_group("units"):
unit.unit_selected_changed.connect(_on_unit_selected_changed)
unit.unit_died.connect(_on_unit_died)
get_tree().node_added.connect(_on_node_added)
func _on_node_added(node: Node) -> void:
if node is Unit and node.is_in_group("units"):
node.unit_selected_changed.connect(_on_unit_selected_changed)
if not node.unit_selected_changed.is_connected(_on_unit_selected_changed):
node.unit_selected_changed.connect(_on_unit_selected_changed)
if not node.unit_died.is_connected(_on_unit_died):
node.unit_died.connect(_on_unit_died)
func _on_unit_died(unit: Unit) -> void:
if _selected_unit == unit:
_selected_unit = null
unit_panel.visible = false
func _process(_delta: float) -> void:
if _selected_unit:
if _selected_unit and is_instance_valid(_selected_unit):
hp_bar.max_value = _selected_unit.current_stats.max_hp
hp_bar.value = _selected_unit.current_stats.current_hp