Add tactic seal action lock

This commit is contained in:
2026-06-18 09:55:54 +09:00
parent a20c099301
commit 23642a14e1
10 changed files with 181 additions and 28 deletions

View File

@@ -1039,6 +1039,8 @@ func _unit_status_marker_kinds(unit: Dictionary) -> Array[String]:
func _unit_status_marker_kind(effect: Dictionary) -> String:
var effect_type := str(effect.get("type", "stat_bonus"))
if effect_type == "action_lock" and str(effect.get("action", "skill")) == "skill":
return str(effect.get("status", "seal"))
if effect_type == "damage_over_time" and int(effect.get("amount", 0)) > 0:
return str(effect.get("status", "poison"))
if effect_type == "stat_bonus":
@@ -1057,6 +1059,8 @@ func _unit_status_marker_color(marker_kind: String) -> Color:
return Color(0.78, 0.55, 1.0)
if marker_kind == "poison":
return Color(0.54, 0.95, 0.36)
if marker_kind == "seal":
return Color(0.44, 0.86, 1.0)
return Color(0.72, 0.86, 1.0)
@@ -1113,6 +1117,8 @@ func _floating_text_color(kind: String) -> Color:
return Color(0.80, 0.52, 1.0)
if kind == "poison":
return Color(0.54, 0.95, 0.36)
if kind == "seal":
return Color(0.44, 0.86, 1.0)
if kind == "miss" or kind == "fade":
return Color(0.82, 0.84, 0.90)
if kind == "defeat":
@@ -1182,9 +1188,13 @@ func _attack_target_preview_badge(selected: Dictionary, target: Dictionary) -> D
func _skill_target_preview_badge(selected: Dictionary, target: Dictionary) -> Dictionary:
var preview := state.get_skill_preview(selected["id"], selected_skill_id, hover_cell)
if preview.is_empty() or target.is_empty():
if preview.is_empty():
return {}
if bool(preview.get("skill_locked", false)):
return _make_target_preview_badge("SEALED", "seal")
if target.is_empty():
return {}
if not bool(preview.get("valid_target", false)):
return _make_target_preview_badge("INVALID", "invalid")
if not bool(preview.get("in_range", false)):
@@ -1200,7 +1210,7 @@ func _skill_target_preview_badge(selected: Dictionary, target: Dictionary) -> Di
return _make_target_preview_badge("+%d HP" % heal, "heal")
if kind == "support":
var effect_text := str(preview.get("effect_text", "Support"))
var badge_kind := "poison" if effect_text.contains("Poison") else ("debuff" if effect_text.contains("-") else "support")
var badge_kind := "seal" if effect_text.contains("Seal") else ("poison" if effect_text.contains("Poison") else ("debuff" if effect_text.contains("-") else "support"))
return _make_target_preview_badge(_compact_support_preview_text(effect_text), badge_kind)
var result_text := "KO" if bool(preview.get("would_defeat", false)) else "-%d" % int(preview.get("damage", 0))
@@ -1275,6 +1285,8 @@ func _target_preview_badge_color(kind: String) -> Color:
return Color(0.78, 0.55, 1.0)
if kind == "poison":
return Color(0.54, 0.95, 0.36)
if kind == "seal":
return Color(0.44, 0.86, 1.0)
return Color(0.78, 0.80, 0.86)
@@ -1475,6 +1487,12 @@ func _update_skill_forecast(selected: Dictionary) -> void:
var target := state.get_unit_at(hover_cell)
var range_text := "ready" if preview["in_range"] else "out of range"
var mp_text := "" if preview["has_mp"] else " Not enough MP."
if bool(preview.get("skill_locked", false)):
forecast_label.text = "%s: sealed, %d MP.\nCannot use tactics." % [
preview["skill_name"],
preview["mp_cost"]
]
return
if target.is_empty() or not preview["valid_target"]:
forecast_label.text = "%s: %s, %d MP.%s\nNo valid target." % [
preview["skill_name"],
@@ -1867,6 +1885,14 @@ func _on_tactic_pressed() -> void:
var selected := state.get_selected_unit()
if selected.is_empty():
return
if state.is_unit_skill_sealed(selected["id"]):
_play_ui_cancel()
selected_skill_id = ""
_hide_tactic_menu()
_refresh_ranges()
_update_hud()
queue_redraw()
return
_play_ui_click()
if tactic_menu != null and tactic_menu.visible:
_hide_tactic_menu()
@@ -3244,6 +3270,10 @@ func _update_tactic_button(selected: Dictionary) -> void:
tactic_button.text = "Tactic"
tactic_button.disabled = true
return
if state.is_unit_skill_sealed(selected["id"]):
tactic_button.text = "Tactic - Sealed"
tactic_button.disabled = true
return
if not selected_skill_id.is_empty():
var skill := state.get_skill_def(selected_skill_id)
@@ -3280,12 +3310,17 @@ func _rebuild_tactic_menu(selected: Dictionary) -> void:
empty_label.text = "No tactics"
tactic_list.add_child(empty_label)
return
var skill_sealed := state.is_unit_skill_sealed(selected["id"])
if skill_sealed:
var sealed_label := Label.new()
sealed_label.text = "Tactics sealed"
tactic_list.add_child(sealed_label)
for skill_id in skill_ids:
var skill := state.get_skill_def(str(skill_id))
var skill_button := Button.new()
skill_button.text = _format_tactic_button_text(str(skill_id), skill, selected)
skill_button.disabled = selected.get("acted", false) or _is_input_locked() or int(selected.get("mp", 0)) < int(skill.get("mp_cost", 0))
skill_button.disabled = skill_sealed or selected.get("acted", false) or _is_input_locked() or int(selected.get("mp", 0)) < int(skill.get("mp_cost", 0))
skill_button.pressed.connect(_on_tactic_skill_pressed.bind(str(skill_id)))
tactic_list.add_child(skill_button)
@@ -3308,7 +3343,11 @@ func _format_tactic_button_text(skill_id: String, skill: Dictionary, selected: D
var kind := str(skill.get("kind", "skill")).capitalize()
var range_text := _format_tactic_range_text(skill)
var effect_text := _format_tactic_effect_text(skill)
var disabled_text := " - MP" if int(selected.get("mp", 0)) < mp_cost else ""
var disabled_text := ""
if state.is_unit_skill_sealed(selected["id"]):
disabled_text = " - Sealed"
elif int(selected.get("mp", 0)) < mp_cost:
disabled_text = " - MP"
return "%s%s %dMP %s R%s %s%s" % [marker, skill_name, mp_cost, kind, range_text, effect_text, disabled_text]
@@ -3328,6 +3367,8 @@ func _format_tactic_effect_text(skill: Dictionary) -> String:
elif effect_type == "damage_over_time" and amount > 0:
var status_name := str(effect.get("status", "status")).replace("_", " ").capitalize()
parts.append("%s -%d" % [status_name, amount])
elif effect_type == "action_lock" and str(effect.get("action", "skill")) == "skill":
parts.append("%s tactics" % str(effect.get("status", "seal")).replace("_", " ").capitalize())
if not parts.is_empty():
return _join_strings(parts, ", ")
return "P%d" % int(skill.get("power", 0))