Add story beats to Sishui Gate

This commit is contained in:
2026-06-19 15:44:16 +09:00
parent ffbe61a28e
commit c380a4a95f
3 changed files with 118 additions and 4 deletions

View File

@@ -24,7 +24,9 @@ func _init() -> void:
_check_dialogue_localization_and_side(failures)
_check_event_dialogue_side_passthrough(failures)
_check_opening_battle_event_dialogue_structure(failures)
_check_sishui_gate_event_dialogue_structure(failures)
_check_opening_battle_story_beats(failures)
_check_sishui_gate_story_beats(failures)
_check_pixel_unit_helpers(failures)
if failures.is_empty():
@@ -109,9 +111,10 @@ func _check_dialogue_localization_and_side(failures: Array[String]) -> void:
{"speaker": "Cao Cao", "text": "전열을 세워라."},
{"speaker": "Lu Bu", "text": "조조를 짓밟아라."},
{"speaker": "Qingzhou Chief", "text": "마을 곡식을 내놓아라."},
{"speaker": "Camp Merchant", "text": "군막에 물자가 남았습니다."}
{"speaker": "Camp Merchant", "text": "군막에 물자가 남았습니다."},
{"speaker": "Hua Xiong", "text": "사수관을 지켜라."}
])
if lines.size() != 4:
if lines.size() != 5:
failures.append("dialogue normalization should keep all valid chapter one lines")
scene.free()
return
@@ -123,6 +126,8 @@ func _check_dialogue_localization_and_side(failures: Array[String]) -> void:
failures.append("chapter one named enemy dialogue should be localized and right-sided")
if lines[3].get("speaker", "") != "군막 상인" or lines[3].get("side", "") != "right":
failures.append("camp merchant dialogue should be localized and right-sided by default")
if lines[4].get("speaker", "") != "화웅" or lines[4].get("side", "") != "right":
failures.append("Sishui Gate enemy commander dialogue should localize to Korean on the right")
scene.free()
@@ -178,6 +183,34 @@ func _check_opening_battle_event_dialogue_structure(failures: Array[String]) ->
failures.append("Zhang Mancheng defeat event should watch yellow_turban_1")
func _check_sishui_gate_event_dialogue_structure(failures: Array[String]) -> void:
var state = BattleStateScript.new()
if not state.load_battle("res://data/scenarios/002_sishui_gate.json"):
failures.append("could not load Sishui Gate for event dialogue structure")
return
for event_id in [
"opening_dialogue",
"turn_2_warning",
"turn_5_ridge_patrol",
"turn_8_gate_reserve",
"hua_xiong_vanguard_falls"
]:
var event := _event_by_id(state, event_id)
if event.is_empty():
failures.append("Sishui Gate missing event: %s" % event_id)
continue
if not _event_has_dialogue_action(event):
failures.append("Sishui Gate event should include contextual dialogue: %s" % event_id)
var vanguard_event := _event_by_id(state, "hua_xiong_vanguard_falls")
if not vanguard_event.is_empty():
var when: Dictionary = vanguard_event.get("when", {})
var unit_ids: Array = when.get("unit_ids", [])
if not unit_ids.has("hua_xiong_vanguard"):
failures.append("Hua Xiong vanguard defeat event should watch hua_xiong_vanguard")
if not _event_has_set_objective_action(vanguard_event):
failures.append("Hua Xiong vanguard defeat event should clarify the next objective")
func _check_opening_battle_story_beats(failures: Array[String]) -> void:
var state = BattleStateScript.new()
if not state.load_battle("res://data/scenarios/001_yellow_turbans.json"):
@@ -203,6 +236,30 @@ func _check_opening_battle_story_beats(failures: Array[String]) -> void:
failures.append("opening battle final objective gate should open after the turn 9 story beat")
func _check_sishui_gate_story_beats(failures: Array[String]) -> void:
var state = BattleStateScript.new()
if not state.load_battle("res://data/scenarios/002_sishui_gate.json"):
failures.append("could not load Sishui Gate for story beat checks")
return
var dialogue_batches := []
state.dialogue_requested.connect(func(lines: Array) -> void:
dialogue_batches.append(lines)
)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 2)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 5)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 8)
if dialogue_batches.size() < 3:
failures.append("Sishui Gate should add dialogue beats for each major reserve phase")
var victory_text := str(state.objectives.get("victory", ""))
if not victory_text.contains("마지막 예비대"):
failures.append("Sishui Gate turn 8 event should update the victory objective after the final reserve arrives")
if not state._condition_gate_open({"after_event": "turn_8_gate_reserve"}):
failures.append("Sishui Gate final objective gate should open after the turn 8 story beat")
func _event_by_id(state, event_id: String) -> Dictionary:
for event in state.battle_events:
if typeof(event) == TYPE_DICTIONARY and str(event.get("id", "")) == event_id:
@@ -218,6 +275,14 @@ func _event_has_dialogue_action(event: Dictionary) -> bool:
return false
func _event_has_set_objective_action(event: Dictionary) -> bool:
var actions: Array = event.get("actions", [])
for action in actions:
if typeof(action) == TYPE_DICTIONARY and str(action.get("type", "")) == "set_objective":
return true
return false
func _check_pixel_unit_helpers(failures: Array[String]) -> void:
var scene = BattleSceneScript.new()
for method_name in [