Add post-move action menu flow
This commit is contained in:
@@ -639,7 +639,7 @@ func clear_selection() -> void:
|
||||
_notify_changed()
|
||||
|
||||
|
||||
func try_move_selected(cell: Vector2i) -> bool:
|
||||
func try_move_selected(cell: Vector2i, defer_reach_events := false) -> bool:
|
||||
var unit := get_selected_unit()
|
||||
if unit.is_empty() or battle_status != STATUS_ACTIVE:
|
||||
return false
|
||||
@@ -660,9 +660,40 @@ func try_move_selected(cell: Vector2i) -> bool:
|
||||
unit["moved"] = true
|
||||
unit_motion_requested.emit(str(unit.get("id", "")), from_cell, cell)
|
||||
_emit_log("%s moved to %s." % [unit["name"], _format_cell(cell)])
|
||||
if not defer_reach_events:
|
||||
_run_events("unit_reaches_tile", str(unit.get("team", "")), turn_number, unit)
|
||||
_check_battle_status()
|
||||
_notify_changed()
|
||||
return true
|
||||
|
||||
|
||||
func commit_pending_move_events(unit_id: String) -> bool:
|
||||
var unit := get_unit(unit_id)
|
||||
if unit.is_empty() or battle_status != STATUS_ACTIVE:
|
||||
return false
|
||||
_run_events("unit_reaches_tile", str(unit.get("team", "")), turn_number, unit)
|
||||
_check_battle_status()
|
||||
_notify_changed()
|
||||
return battle_status == STATUS_ACTIVE
|
||||
|
||||
|
||||
func cancel_pending_move(unit_id: String, from_cell: Vector2i, to_cell: Vector2i) -> bool:
|
||||
var unit := get_unit(unit_id)
|
||||
if unit.is_empty() or battle_status != STATUS_ACTIVE:
|
||||
return false
|
||||
if bool(unit.get("acted", false)) or not bool(unit.get("moved", false)):
|
||||
return false
|
||||
if unit.get("pos", Vector2i(-1, -1)) != to_cell:
|
||||
return false
|
||||
var blocker := get_unit_at(from_cell)
|
||||
if not blocker.is_empty() and str(blocker.get("id", "")) != unit_id:
|
||||
return false
|
||||
|
||||
unit["pos"] = from_cell
|
||||
unit["moved"] = false
|
||||
unit_motion_requested.emit(unit_id, to_cell, from_cell)
|
||||
_emit_log("%s cancels movement." % unit["name"])
|
||||
_notify_changed()
|
||||
return true
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ const DIALOGUE_COLUMN_SIZE := Vector2(820, 186)
|
||||
const DIALOGUE_TEXT_SIZE := Vector2(800, 104)
|
||||
const HUD_UNIT_PORTRAIT_SIZE := Vector2(92, 104)
|
||||
const HUD_UNIT_PORTRAIT_STACK_SIZE := Vector2(88, 100)
|
||||
const POST_MOVE_MENU_SIZE := Vector2(228, 120)
|
||||
const POST_MOVE_MENU_OFFSET := Vector2(20, -34)
|
||||
|
||||
var state: BattleState = BattleStateScript.new()
|
||||
var campaign_state: CampaignState = CampaignStateScript.new()
|
||||
@@ -70,6 +72,10 @@ var item_cells: Array[Vector2i] = []
|
||||
var threat_cells: Array[Vector2i] = []
|
||||
var selected_skill_id := ""
|
||||
var selected_item_id := ""
|
||||
var basic_attack_targeting := false
|
||||
var pending_move_unit_id := ""
|
||||
var pending_move_from_cell := Vector2i(-1, -1)
|
||||
var pending_move_to_cell := Vector2i(-1, -1)
|
||||
var show_threat_overlay := false
|
||||
var active_scenario_id := ""
|
||||
var battle_started := false
|
||||
@@ -158,6 +164,13 @@ var item_list: VBoxContainer
|
||||
var equip_button: Button
|
||||
var equip_menu: VBoxContainer
|
||||
var equip_list: VBoxContainer
|
||||
var post_move_menu: PanelContainer
|
||||
var post_move_title_label: Label
|
||||
var post_move_attack_button: Button
|
||||
var post_move_tactic_button: Button
|
||||
var post_move_item_button: Button
|
||||
var post_move_wait_button: Button
|
||||
var post_move_cancel_button: Button
|
||||
var threat_button: Button
|
||||
var restart_button: Button
|
||||
var new_campaign_button: Button
|
||||
@@ -220,6 +233,8 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
queue_redraw()
|
||||
elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
||||
_handle_board_click(event.position)
|
||||
elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
|
||||
_handle_cancel_input()
|
||||
elif event is InputEventKey and event.pressed and not event.echo:
|
||||
_handle_key(event)
|
||||
|
||||
@@ -429,6 +444,58 @@ func _create_hud() -> void:
|
||||
equip_list.add_theme_constant_override("separation", 4)
|
||||
equip_menu.add_child(equip_list)
|
||||
|
||||
post_move_menu = PanelContainer.new()
|
||||
post_move_menu.visible = false
|
||||
post_move_menu.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
post_move_menu.custom_minimum_size = POST_MOVE_MENU_SIZE
|
||||
post_move_menu.size = POST_MOVE_MENU_SIZE
|
||||
root.add_child(post_move_menu)
|
||||
|
||||
var post_move_column := VBoxContainer.new()
|
||||
post_move_column.add_theme_constant_override("separation", 4)
|
||||
post_move_menu.add_child(post_move_column)
|
||||
|
||||
post_move_title_label = Label.new()
|
||||
post_move_title_label.text = "Choose Action"
|
||||
post_move_title_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
post_move_column.add_child(post_move_title_label)
|
||||
|
||||
var post_move_grid := GridContainer.new()
|
||||
post_move_grid.columns = 2
|
||||
post_move_grid.add_theme_constant_override("h_separation", 6)
|
||||
post_move_grid.add_theme_constant_override("v_separation", 4)
|
||||
post_move_column.add_child(post_move_grid)
|
||||
|
||||
post_move_attack_button = Button.new()
|
||||
post_move_attack_button.text = "Attack"
|
||||
post_move_attack_button.tooltip_text = "Choose an enemy target from this unit's current position."
|
||||
post_move_attack_button.pressed.connect(_on_post_move_attack_pressed)
|
||||
post_move_grid.add_child(post_move_attack_button)
|
||||
|
||||
post_move_tactic_button = Button.new()
|
||||
post_move_tactic_button.text = "Tactic"
|
||||
post_move_tactic_button.tooltip_text = "Open tactics after this move."
|
||||
post_move_tactic_button.pressed.connect(_on_post_move_tactic_pressed)
|
||||
post_move_grid.add_child(post_move_tactic_button)
|
||||
|
||||
post_move_item_button = Button.new()
|
||||
post_move_item_button.text = "Item"
|
||||
post_move_item_button.tooltip_text = "Open consumable items after this move."
|
||||
post_move_item_button.pressed.connect(_on_post_move_item_pressed)
|
||||
post_move_grid.add_child(post_move_item_button)
|
||||
|
||||
post_move_wait_button = Button.new()
|
||||
post_move_wait_button.text = "Wait"
|
||||
post_move_wait_button.tooltip_text = "Commit this move and end the unit's action."
|
||||
post_move_wait_button.pressed.connect(_on_post_move_wait_pressed)
|
||||
post_move_grid.add_child(post_move_wait_button)
|
||||
|
||||
post_move_cancel_button = Button.new()
|
||||
post_move_cancel_button.text = "Cancel Move"
|
||||
post_move_cancel_button.tooltip_text = "Return to the starting cell."
|
||||
post_move_cancel_button.pressed.connect(_on_post_move_cancel_pressed)
|
||||
post_move_column.add_child(post_move_cancel_button)
|
||||
|
||||
log_box = RichTextLabel.new()
|
||||
log_box.custom_minimum_size = Vector2(420, 70)
|
||||
log_box.fit_content = false
|
||||
@@ -938,50 +1005,173 @@ func _handle_board_click(screen_position: Vector2) -> void:
|
||||
if _can_select(clicked_unit):
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
state.select_unit(clicked_unit["id"])
|
||||
return
|
||||
|
||||
if not selected_item_id.is_empty():
|
||||
if state.try_use_selected_item_on_cell(selected_item_id, cell):
|
||||
if item_cells.has(cell) and _commit_pending_move_before_action() and state.try_use_selected_item_on_cell(selected_item_id, cell):
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
return
|
||||
if _has_pending_move():
|
||||
return
|
||||
if not clicked_unit.is_empty() and clicked_unit.get("team", "") == selected_unit.get("team", "") and _can_select(clicked_unit):
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
state.select_unit(clicked_unit["id"])
|
||||
return
|
||||
|
||||
if not selected_skill_id.is_empty():
|
||||
if state.try_cast_selected_skill(selected_skill_id, cell):
|
||||
if skill_cells.has(cell) and _commit_pending_move_before_action() and state.try_cast_selected_skill(selected_skill_id, cell):
|
||||
selected_skill_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
return
|
||||
if _has_pending_move():
|
||||
return
|
||||
if not clicked_unit.is_empty() and clicked_unit.get("team", "") == selected_unit.get("team", "") and _can_select(clicked_unit):
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
state.select_unit(clicked_unit["id"])
|
||||
return
|
||||
|
||||
if not clicked_unit.is_empty() and clicked_unit.get("team", "") != selected_unit.get("team", ""):
|
||||
if state.try_attack_selected(clicked_unit["id"]):
|
||||
if _has_pending_move() and not basic_attack_targeting:
|
||||
return
|
||||
var target_cell: Vector2i = clicked_unit.get("pos", cell)
|
||||
if attack_cells.has(target_cell) and _commit_pending_move_before_action() and state.try_attack_selected(clicked_unit["id"]):
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
return
|
||||
|
||||
if not clicked_unit.is_empty() and clicked_unit.get("team", "") == selected_unit.get("team", ""):
|
||||
if _has_pending_move():
|
||||
return
|
||||
if _can_select(clicked_unit):
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
state.select_unit(clicked_unit["id"])
|
||||
return
|
||||
|
||||
if state.try_move_selected(cell):
|
||||
var selected_start_cell: Vector2i = selected_unit.get("pos", Vector2i(-1, -1))
|
||||
if not _has_pending_move() and state.try_move_selected(cell, true):
|
||||
pending_move_unit_id = str(selected_unit.get("id", ""))
|
||||
pending_move_from_cell = selected_start_cell
|
||||
pending_move_to_cell = cell
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_refresh_ranges()
|
||||
_show_post_move_menu()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return
|
||||
|
||||
if _can_select(clicked_unit):
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_clear_pending_move_state()
|
||||
state.select_unit(clicked_unit["id"])
|
||||
|
||||
|
||||
func _has_pending_move() -> bool:
|
||||
return (
|
||||
not pending_move_unit_id.is_empty()
|
||||
and pending_move_from_cell != Vector2i(-1, -1)
|
||||
and pending_move_to_cell != Vector2i(-1, -1)
|
||||
)
|
||||
|
||||
|
||||
func _clear_pending_move_state(hide_menu := true) -> void:
|
||||
pending_move_unit_id = ""
|
||||
pending_move_from_cell = Vector2i(-1, -1)
|
||||
pending_move_to_cell = Vector2i(-1, -1)
|
||||
basic_attack_targeting = false
|
||||
if hide_menu:
|
||||
_hide_post_move_menu()
|
||||
|
||||
|
||||
func _commit_pending_move_before_action() -> bool:
|
||||
if not _has_pending_move():
|
||||
return true
|
||||
var unit_id := pending_move_unit_id
|
||||
_clear_pending_move_state()
|
||||
var still_active := state.commit_pending_move_events(unit_id)
|
||||
return still_active and state.can_player_act() and not state.get_selected_unit().is_empty() and not _is_input_locked()
|
||||
|
||||
|
||||
func _cancel_pending_move() -> bool:
|
||||
if not _has_pending_move():
|
||||
return false
|
||||
var unit_id := pending_move_unit_id
|
||||
var from_cell := pending_move_from_cell
|
||||
var to_cell := pending_move_to_cell
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_hide_post_move_menu()
|
||||
if state.cancel_pending_move(unit_id, from_cell, to_cell):
|
||||
_clear_pending_move_state()
|
||||
_play_ui_cancel()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _handle_cancel_input() -> bool:
|
||||
if _has_pending_move():
|
||||
return _cancel_pending_move()
|
||||
if tactic_menu != null and tactic_menu.visible:
|
||||
_play_ui_cancel()
|
||||
_hide_tactic_menu()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return true
|
||||
if item_menu != null and item_menu.visible:
|
||||
_play_ui_cancel()
|
||||
_hide_item_menu()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return true
|
||||
if equip_menu != null and equip_menu.visible:
|
||||
_play_ui_cancel()
|
||||
_hide_equip_menu()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return true
|
||||
if not selected_skill_id.is_empty() or not selected_item_id.is_empty() or basic_attack_targeting:
|
||||
_play_ui_cancel()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
return true
|
||||
if not state.get_selected_unit().is_empty():
|
||||
_play_ui_cancel()
|
||||
state.clear_selection()
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _handle_key(event: InputEventKey) -> void:
|
||||
if event.keycode == KEY_ENTER and briefing_panel != null and briefing_panel.visible:
|
||||
if _is_prep_menu_visible():
|
||||
@@ -1006,21 +1196,10 @@ func _handle_key(event: InputEventKey) -> void:
|
||||
_hide_item_menu()
|
||||
elif equip_menu != null and equip_menu.visible:
|
||||
_hide_equip_menu()
|
||||
elif selected_skill_id.is_empty() and selected_item_id.is_empty():
|
||||
state.clear_selection()
|
||||
else:
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
_handle_cancel_input()
|
||||
elif event.keycode == KEY_SPACE and not _is_input_locked():
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
state.end_player_turn()
|
||||
_on_end_turn_pressed()
|
||||
elif event.keycode == KEY_R and not _is_prep_menu_visible():
|
||||
_on_restart_pressed()
|
||||
elif event.keycode == KEY_T and not _is_input_locked():
|
||||
@@ -1346,6 +1525,11 @@ func _draw_overlays() -> void:
|
||||
for cell in move_cells:
|
||||
draw_rect(_rect_for_cell(cell), Color(0.16, 0.55, 0.95, 0.28))
|
||||
|
||||
if _has_pending_move() and state.is_inside(pending_move_to_cell):
|
||||
var pending_rect := _rect_for_cell(pending_move_to_cell)
|
||||
draw_rect(pending_rect.grow(-4.0), Color(1.0, 0.82, 0.28, 0.32))
|
||||
draw_rect(pending_rect.grow(-7.0), Color(1.0, 0.88, 0.36, 0.86), false, 2.0)
|
||||
|
||||
for cell in attack_cells:
|
||||
draw_rect(_rect_for_cell(cell), Color(0.95, 0.22, 0.18, 0.24))
|
||||
|
||||
@@ -1847,6 +2031,8 @@ func _target_preview_badge() -> Dictionary:
|
||||
return _skill_target_preview_badge(selected, target)
|
||||
if not selected_item_id.is_empty():
|
||||
return _item_target_preview_badge(selected, target)
|
||||
if _has_pending_move() and not basic_attack_targeting:
|
||||
return {}
|
||||
var attack_badge := _attack_target_preview_badge(selected, target)
|
||||
if not attack_badge.is_empty():
|
||||
return attack_badge
|
||||
@@ -1942,6 +2128,8 @@ func _item_target_preview_badge(selected: Dictionary, target: Dictionary) -> Dic
|
||||
func _hover_intent_preview_badge(selected: Dictionary, target: Dictionary) -> Dictionary:
|
||||
if selected.is_empty():
|
||||
return {}
|
||||
if _has_pending_move():
|
||||
return {}
|
||||
if not state.can_player_act():
|
||||
return {}
|
||||
if not bool(selected.get("controllable", true)) or bool(selected.get("acted", false)):
|
||||
@@ -2039,20 +2227,24 @@ func _refresh_ranges() -> void:
|
||||
if selected.is_empty():
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
return
|
||||
move_cells = state.get_movement_range(selected["id"])
|
||||
if not selected_skill_id.is_empty():
|
||||
skill_cells = state.get_skill_cells(selected["id"], selected_skill_id)
|
||||
if skill_cells.is_empty():
|
||||
selected_skill_id = ""
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
if not _has_pending_move() or basic_attack_targeting:
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
elif not selected_item_id.is_empty():
|
||||
item_cells = state.get_item_target_cells(selected["id"], selected_item_id)
|
||||
if item_cells.is_empty():
|
||||
selected_item_id = ""
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
if not _has_pending_move() or basic_attack_targeting:
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
else:
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
if not _has_pending_move() or basic_attack_targeting:
|
||||
attack_cells = state.get_attack_cells(selected["id"])
|
||||
|
||||
|
||||
func _update_hud() -> void:
|
||||
@@ -2098,6 +2290,7 @@ func _update_hud() -> void:
|
||||
_update_end_turn_button()
|
||||
restart_button.disabled = campaign_complete_screen
|
||||
_update_threat_button()
|
||||
_update_post_move_menu()
|
||||
|
||||
|
||||
func _format_objective_hud_text() -> String:
|
||||
@@ -2666,6 +2859,7 @@ func _on_state_changed() -> void:
|
||||
if state.get_selected_unit().is_empty():
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
@@ -2914,9 +3108,11 @@ func _show_next_dialogue() -> void:
|
||||
return
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_hide_post_move_menu()
|
||||
_refresh_ranges()
|
||||
active_dialogue_lines = dialogue_queue.pop_front()
|
||||
active_dialogue_index = 0
|
||||
@@ -3066,18 +3262,29 @@ func _is_dialogue_visible() -> bool:
|
||||
func _on_wait_pressed() -> void:
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
if state.try_wait_selected():
|
||||
if _commit_pending_move_before_action() and state.try_wait_selected():
|
||||
_play_ui_confirm()
|
||||
|
||||
|
||||
func _on_end_turn_pressed() -> void:
|
||||
if state.can_player_act():
|
||||
_play_ui_confirm()
|
||||
if _has_pending_move():
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
if not (_commit_pending_move_before_action() and state.try_wait_selected()):
|
||||
return
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
@@ -3091,6 +3298,7 @@ func _on_tactic_pressed() -> void:
|
||||
if state.is_unit_skill_sealed(selected["id"]):
|
||||
_play_ui_cancel()
|
||||
selected_skill_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
@@ -3099,8 +3307,12 @@ func _on_tactic_pressed() -> void:
|
||||
_play_ui_click()
|
||||
if tactic_menu != null and tactic_menu.visible:
|
||||
_hide_tactic_menu()
|
||||
if _has_pending_move():
|
||||
_show_post_move_menu()
|
||||
else:
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_post_move_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_show_tactic_menu(selected)
|
||||
@@ -3116,8 +3328,12 @@ func _on_item_pressed() -> void:
|
||||
_play_ui_click()
|
||||
if item_menu != null and item_menu.visible:
|
||||
_hide_item_menu()
|
||||
if _has_pending_move():
|
||||
_show_post_move_menu()
|
||||
else:
|
||||
selected_skill_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_post_move_menu()
|
||||
_hide_tactic_menu()
|
||||
_hide_equip_menu()
|
||||
_show_item_menu(selected)
|
||||
@@ -3138,8 +3354,10 @@ func _on_equip_pressed() -> void:
|
||||
else:
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_post_move_menu()
|
||||
_show_equip_menu(selected)
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
@@ -3172,6 +3390,7 @@ func _on_restart_pressed() -> void:
|
||||
shop_sell_mode = false
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
armory_unit_id = ""
|
||||
formation_unit_id = ""
|
||||
_hide_tactic_menu()
|
||||
@@ -3216,6 +3435,7 @@ func _load_scenario(scenario_id: String) -> void:
|
||||
unit_motion_by_unit.clear()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
@@ -3358,6 +3578,7 @@ func _show_briefing() -> void:
|
||||
_hide_roster_menu()
|
||||
_hide_formation_menu()
|
||||
_hide_save_menu()
|
||||
_clear_pending_move_state()
|
||||
var prep_locked := _is_prebattle_prep_locked()
|
||||
if chapter_button != null:
|
||||
chapter_button.disabled = campaign_state.get_chapter_progress_entries().is_empty()
|
||||
@@ -3392,6 +3613,7 @@ func _start_battle_from_briefing() -> void:
|
||||
_hide_roster_menu()
|
||||
_hide_formation_menu()
|
||||
_hide_save_menu()
|
||||
_clear_pending_move_state()
|
||||
state.run_battle_begin_events()
|
||||
_show_next_dialogue()
|
||||
_update_hud()
|
||||
@@ -3914,6 +4136,7 @@ func _reload_from_campaign_state() -> void:
|
||||
unit_motion_by_unit.clear()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
armory_unit_id = ""
|
||||
formation_unit_id = ""
|
||||
_hide_tactic_menu()
|
||||
@@ -4497,6 +4720,7 @@ func _try_show_post_battle_dialogue() -> bool:
|
||||
dialogue_queue.clear()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
@@ -4834,6 +5058,7 @@ func _show_campaign_complete() -> void:
|
||||
item_cells.clear()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
@@ -4870,6 +5095,7 @@ func _on_new_campaign_pressed() -> void:
|
||||
post_battle_dialogue_started = false
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
_clear_pending_move_state()
|
||||
formation_unit_id = ""
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
@@ -4885,6 +5111,119 @@ func _on_new_campaign_pressed() -> void:
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _show_post_move_menu() -> void:
|
||||
if post_move_menu == null or not _has_pending_move():
|
||||
return
|
||||
_update_post_move_menu()
|
||||
post_move_menu.visible = true
|
||||
post_move_menu.move_to_front()
|
||||
|
||||
|
||||
func _hide_post_move_menu() -> void:
|
||||
if post_move_menu == null:
|
||||
return
|
||||
post_move_menu.visible = false
|
||||
|
||||
|
||||
func _update_post_move_menu() -> void:
|
||||
if post_move_menu == null:
|
||||
return
|
||||
if not _has_pending_move():
|
||||
_hide_post_move_menu()
|
||||
return
|
||||
var selected := state.get_selected_unit()
|
||||
if selected.is_empty() or str(selected.get("id", "")) != pending_move_unit_id or bool(selected.get("acted", false)):
|
||||
_hide_post_move_menu()
|
||||
return
|
||||
_position_post_move_menu()
|
||||
if post_move_title_label != null:
|
||||
post_move_title_label.text = "%s: choose action" % str(selected.get("name", "Unit"))
|
||||
if post_move_attack_button != null:
|
||||
var attack_blocked := state.get_attack_cells(pending_move_unit_id).is_empty()
|
||||
post_move_attack_button.disabled = attack_blocked
|
||||
post_move_attack_button.tooltip_text = "No enemy is in range after this move." if attack_blocked else "Choose an enemy target from this unit's current position."
|
||||
if post_move_tactic_button != null:
|
||||
var skill_ids := state.get_skill_ids(pending_move_unit_id)
|
||||
var skill_blocked := skill_ids.is_empty() or state.is_unit_skill_sealed(pending_move_unit_id) or state.get_first_usable_skill_id(pending_move_unit_id).is_empty()
|
||||
post_move_tactic_button.disabled = skill_blocked
|
||||
post_move_tactic_button.tooltip_text = "No usable tactic is available after this move." if skill_blocked else "Open tactics after this move."
|
||||
if post_move_item_button != null:
|
||||
var item_blocked := not _unit_has_usable_item_target(pending_move_unit_id)
|
||||
post_move_item_button.disabled = item_blocked
|
||||
post_move_item_button.tooltip_text = "No usable item target is in range." if item_blocked else "Open consumable items after this move."
|
||||
if post_move_wait_button != null:
|
||||
post_move_wait_button.disabled = false
|
||||
post_move_wait_button.tooltip_text = "Commit this move and end the unit's action."
|
||||
if post_move_cancel_button != null:
|
||||
post_move_cancel_button.disabled = false
|
||||
post_move_cancel_button.tooltip_text = "Right-click also returns to the starting cell."
|
||||
|
||||
|
||||
func _position_post_move_menu() -> void:
|
||||
if post_move_menu == null:
|
||||
return
|
||||
var cell_rect := _rect_for_cell(pending_move_to_cell)
|
||||
var next_position := cell_rect.position + Vector2(TILE_SIZE, 0.0) + POST_MOVE_MENU_OFFSET
|
||||
var board_size := Vector2(state.map_size.x, state.map_size.y) * TILE_SIZE
|
||||
var board_min := BOARD_OFFSET + Vector2(4.0, 4.0)
|
||||
var board_max := BOARD_OFFSET + board_size - POST_MOVE_MENU_SIZE - Vector2(4.0, 4.0)
|
||||
board_max.x = maxf(board_min.x, board_max.x)
|
||||
board_max.y = maxf(board_min.y, board_max.y)
|
||||
next_position.x = clampf(next_position.x, board_min.x, board_max.x)
|
||||
next_position.y = clampf(next_position.y, board_min.y, board_max.y)
|
||||
post_move_menu.position = next_position
|
||||
|
||||
|
||||
func _on_post_move_attack_pressed() -> void:
|
||||
if not _has_pending_move():
|
||||
return
|
||||
if state.get_attack_cells(pending_move_unit_id).is_empty():
|
||||
_play_ui_cancel()
|
||||
return
|
||||
_play_ui_click()
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = true
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_hide_post_move_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _on_post_move_tactic_pressed() -> void:
|
||||
if not _has_pending_move():
|
||||
return
|
||||
_hide_post_move_menu()
|
||||
basic_attack_targeting = false
|
||||
_on_tactic_pressed()
|
||||
|
||||
|
||||
func _on_post_move_item_pressed() -> void:
|
||||
if not _has_pending_move():
|
||||
return
|
||||
_hide_post_move_menu()
|
||||
basic_attack_targeting = false
|
||||
_on_item_pressed()
|
||||
|
||||
|
||||
func _on_post_move_wait_pressed() -> void:
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
if _commit_pending_move_before_action() and state.try_wait_selected():
|
||||
_play_ui_confirm()
|
||||
|
||||
|
||||
func _on_post_move_cancel_pressed() -> void:
|
||||
_cancel_pending_move()
|
||||
|
||||
|
||||
func _set_action_button_state(button: Button, label: String, disabled: bool, tooltip := "") -> void:
|
||||
if button == null:
|
||||
return
|
||||
@@ -5129,9 +5468,11 @@ func _on_tactic_skill_pressed(skill_id: String) -> void:
|
||||
_play_ui_confirm()
|
||||
selected_skill_id = skill_id
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
_hide_item_menu()
|
||||
_hide_equip_menu()
|
||||
_hide_post_move_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
@@ -5140,7 +5481,10 @@ func _on_tactic_skill_pressed(skill_id: String) -> void:
|
||||
func _on_tactic_cancel_pressed() -> void:
|
||||
_play_ui_cancel()
|
||||
selected_skill_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_tactic_menu()
|
||||
if _has_pending_move():
|
||||
_show_post_move_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
@@ -5252,9 +5596,11 @@ func _on_item_selected_pressed(item_id: String) -> void:
|
||||
_play_ui_confirm()
|
||||
selected_item_id = item_id
|
||||
selected_skill_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_item_menu()
|
||||
_hide_tactic_menu()
|
||||
_hide_equip_menu()
|
||||
_hide_post_move_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
@@ -5263,7 +5609,10 @@ func _on_item_selected_pressed(item_id: String) -> void:
|
||||
func _on_item_cancel_pressed() -> void:
|
||||
_play_ui_cancel()
|
||||
selected_item_id = ""
|
||||
basic_attack_targeting = false
|
||||
_hide_item_menu()
|
||||
if _has_pending_move():
|
||||
_show_post_move_menu()
|
||||
_refresh_ranges()
|
||||
_update_hud()
|
||||
queue_redraw()
|
||||
|
||||
Reference in New Issue
Block a user