class_name CombatUI extends CanvasLayer signal fight_confirmed(proposal: CombatProposal) signal fight_cancelled @onready var unit_panel: PanelContainer = %UnitPanel @onready var name_label: Label = %NameLabel @onready var hp_bar: ProgressBar = %HPBar @onready var background_tint: ColorRect = %BackgroundTint @onready var proposal_panel: PanelContainer = %CombatProposalPanel @onready var atk_name_label: Label = %AttackerNameLabel @onready var atk_hp_bar: ProgressBar = %AttackerHPBar @onready var atk_atk_label: Label = %AttackerATKLabel @onready var atk_def_label: Label = %AttackerDEFLabel @onready var atk_hit_label: Label = %AttackerHITLabel @onready var atk_spd_label: Label = %AttackerSPDLabel @onready var def_name_label: Label = %DefenderNameLabel @onready var def_hp_bar: ProgressBar = %DefenderHPBar @onready var def_atk_label: Label = %DefenderATKLabel @onready var def_def_label: Label = %DefenderDEFLabel @onready var def_hit_label: Label = %DefenderHITLabel @onready var def_spd_label: Label = %DefenderSPDLabel @onready var fight_button: Button = %FightButton @onready var cancel_button: Button = %CancelButton @onready var atk_tactic_select: OptionButton = %AttackerTacticSelect @onready var def_tactic_select: OptionButton = %DefenderTacticSelect var _selected_unit: DeployedUnit var _current_proposal: CombatProposal var combat_system: CombatSystem func _ready() -> void: unit_panel.visible = false proposal_panel.visible = false fight_button.pressed.connect(_on_fight_pressed) cancel_button.pressed.connect(_on_cancel_pressed) atk_tactic_select.item_selected.connect(_on_atk_tactic_selected) def_tactic_select.item_selected.connect(_on_def_tactic_selected) for deployed: DeployedUnit in get_tree().get_nodes_in_group("deployed_units"): deployed.unit_selected_changed.connect(_on_unit_selected_changed) deployed.unit_died.connect(_on_unit_died) get_tree().node_added.connect(_on_node_added) func _on_node_added(node: Node) -> void: if node is DeployedUnit and node.is_in_group("deployed_units"): 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(deployed: DeployedUnit) -> void: if _selected_unit == deployed: _selected_unit = null unit_panel.visible = false if _current_proposal: if _current_proposal.attacker.deployed == deployed or _current_proposal.defender.deployed == deployed: _hide_proposal() func _process(_delta: float) -> void: 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 func _unhandled_input(event: InputEvent) -> void: if proposal_panel.visible and event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_RIGHT: _hide_proposal() fight_cancelled.emit() get_viewport().set_input_as_handled() func _on_unit_selected_changed(deployed: DeployedUnit, selected: bool) -> void: if selected: _selected_unit = deployed name_label.text = deployed.unit.info.name hp_bar.max_value = deployed.current_stats.max_hp hp_bar.value = deployed.current_stats.current_hp unit_panel.visible = true else: _selected_unit = null unit_panel.visible = false func show_proposal(proposal: CombatProposal) -> void: _current_proposal = proposal _populate_tactic_select(atk_tactic_select, proposal.attacker) _populate_tactic_select(def_tactic_select, proposal.defender) _refresh_stats() background_tint.visible = true proposal_panel.visible = true func _hide_proposal() -> void: background_tint.visible = false proposal_panel.visible = false _current_proposal = null func _on_fight_pressed() -> void: if _current_proposal: var proposal := _current_proposal _hide_proposal() fight_confirmed.emit(proposal) func _on_cancel_pressed() -> void: _hide_proposal() fight_cancelled.emit() func _populate_tactic_select(button: OptionButton, combatant: CombatProposal.CombatantStats) -> void: button.clear() var selected_idx := 0 for i in combatant.available_tactics.size(): var tactic := combatant.available_tactics[i] button.add_item(tactic.tactic_name) if tactic == combatant.selected_tactic: selected_idx = i button.selected = selected_idx var is_player := combatant.deployed.unit.allegiance.type == UnitAllegiance.AllegianceType.PLAYER button.disabled = not is_player func _refresh_stats() -> void: var atk := _current_proposal.attacker var def := _current_proposal.defender atk_name_label.text = atk.deployed.unit.info.name atk_hp_bar.max_value = atk.max_hp atk_hp_bar.value = atk.hp atk_atk_label.text = "ATK: %d" % atk.atk atk_def_label.text = "DEF: %d" % atk.def atk_hit_label.text = "HIT: %d%%" % atk.hit atk_spd_label.text = "SPD: %d" % atk.spd def_name_label.text = def.deployed.unit.info.name def_hp_bar.max_value = def.max_hp def_hp_bar.value = def.hp def_atk_label.text = "ATK: %d" % def.atk def_def_label.text = "DEF: %d" % def.def def_hit_label.text = "HIT: %d%%" % def.hit def_spd_label.text = "SPD: %d" % def.spd func _on_atk_tactic_selected(index: int) -> void: if not _current_proposal or not combat_system: return var tactic := _current_proposal.attacker.available_tactics[index] combat_system.update_tactic(_current_proposal, true, tactic) _refresh_stats() func _on_def_tactic_selected(index: int) -> void: if not _current_proposal or not combat_system: return var tactic := _current_proposal.defender.available_tactics[index] combat_system.update_tactic(_current_proposal, false, tactic) _refresh_stats()