Extend opening battle pacing

This commit is contained in:
2026-06-19 17:06:14 +09:00
parent e70a4da0a6
commit 3b7f198044
3 changed files with 96 additions and 13 deletions

View File

@@ -9,7 +9,7 @@
"victory": {
"type": "all",
"conditions": [
{ "type": "all_units_defeated", "team": "enemy", "after_event": "turn_9_western_reserve" },
{ "type": "all_units_defeated", "team": "enemy", "after_event": "turn_11_last_rally" },
{
"type": "unit_reaches_tile",
"label": "성채 장악",
@@ -393,7 +393,7 @@
},
{
"type": "set_objective",
"victory": "성채를 장악한 채 마지막 황건대까지 모두 격파하라."
"victory": "성채를 장악하고 서쪽 숲 마지막 잔당이 드러날 때까지 전열을 유지하라."
},
{
"type": "spawn_deployments",
@@ -435,6 +435,64 @@
}
]
},
{
"id": "turn_11_last_rally",
"once": true,
"when": { "type": "turn_start", "team": "enemy", "turn": 11 },
"actions": [
{ "type": "log", "text": "흩어진 황건 잔당이 서쪽 둔덕에서 마지막 반격을 시도한다." },
{
"type": "dialogue",
"lines": [
{ "speaker": "Scout", "display_speaker": "척후", "side": "right", "text": "서쪽 둔덕에 남은 깃발이 있습니다. 성채를 보고 마지막으로 모여듭니다!" },
{ "speaker": "Xiahou Dun", "display_speaker": "하후돈", "side": "right", "text": "제 뒤를 물려는 놈들입니다. 성채 앞줄은 그대로 두고, 돌아드는 길만 끊겠습니다." },
{ "speaker": "Cao Cao", "display_speaker": "조조", "side": "left", "text": "좋다. 이제 도망길도, 기대어 설 깃발도 없다. 성채를 붙들고 남은 황건대를 모두 거두어라." }
]
},
{
"type": "set_objective",
"victory": "성채를 장악한 채 마지막 황건 잔당까지 모두 격파하라."
},
{
"type": "spawn_deployments",
"deployments": [
{
"unit_id": "yellow_turban_last_rally_1",
"name": "황건 잔당",
"class_id": "infantry",
"team": "enemy",
"level": 1,
"pos": [1, 8],
"base": { "hp": 34, "atk": 10, "def": 6 }
},
{
"unit_id": "yellow_turban_last_rally_2",
"name": "황건 궁수",
"class_id": "archer",
"team": "enemy",
"level": 1,
"pos": [2, 8],
"base": { "hp": 26, "atk": 9, "def": 4 }
},
{
"unit_id": "yellow_turban_last_rally_3",
"name": "황건 유격병",
"class_id": "bandit",
"team": "enemy",
"level": 1,
"pos": [4, 9],
"base": { "hp": 32, "atk": 11, "def": 5 }
}
]
},
{
"type": "set_ai_target_priority",
"unit_ids": ["cao_cao", "xiahou_dun"],
"priority": 13,
"text": "마지막 황건 잔당이 조조와 하후돈의 후미를 노린다."
}
]
},
{
"id": "zhang_mancheng_falls",
"once": true,

View File

@@ -299,6 +299,7 @@ func _check_opening_battle_event_dialogue_structure(failures: Array[String]) ->
"turn_4_eastern_reserve",
"turn_7_southern_raiders",
"turn_9_western_reserve",
"turn_11_last_rally",
"zhang_mancheng_falls"
]:
var event := _event_by_id(state, event_id)
@@ -732,14 +733,15 @@ func _check_opening_battle_story_beats(failures: Array[String]) -> void:
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 4)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 7)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 9)
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 11)
if dialogue_batches.size() < 4:
if dialogue_batches.size() < 5:
failures.append("opening battle should add dialogue beats for each major reinforcement phase")
var victory_text := str(state.objectives.get("victory", ""))
if not victory_text.contains("마지막 황건"):
failures.append("opening battle turn 9 event should update the victory objective after the final reserve arrives")
if not state._condition_gate_open({"after_event": "turn_9_western_reserve"}):
failures.append("opening battle final objective gate should open after the turn 9 story beat")
if not victory_text.contains("마지막 황건 잔당"):
failures.append("opening battle turn 11 event should update the victory objective after the final rally arrives")
if not state._condition_gate_open({"after_event": "turn_11_last_rally"}):
failures.append("opening battle final objective gate should open after the turn 11 story beat")
func _check_sishui_gate_story_beats(failures: Array[String]) -> void:

View File

@@ -35,7 +35,7 @@ func _init() -> void:
failures,
"001 late reserve gate",
_progress_text("res://data/scenarios/001_yellow_turbans.json", false),
"9군령에 전공 갱신"
"11군령에 전공 갱신"
)
_check_contains(
failures,
@@ -351,8 +351,14 @@ func _check_opening_battle_requires_castle_capture(failures: Array[String]) -> v
for enemy in state.get_living_units(BattleStateScript.TEAM_ENEMY):
enemy["alive"] = false
state._check_battle_status()
if str(state.battle_status) != BattleStateScript.STATUS_ACTIVE:
failures.append("opening battle should wait for the turn 11 last rally before victory, got %s" % str(state.battle_status))
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 11)
for enemy in state.get_living_units(BattleStateScript.TEAM_ENEMY):
enemy["alive"] = false
state._check_battle_status()
if str(state.battle_status) != BattleStateScript.STATUS_VICTORY:
failures.append("opening battle should end after late reserve falls and castle is captured, got %s" % str(state.battle_status))
failures.append("opening battle should end after the turn 11 last rally falls and castle is captured, got %s" % str(state.battle_status))
func _check_log_contains(failures: Array[String], logs: Array, expected: String) -> void:
@@ -404,15 +410,32 @@ func _check_opening_battle_extended_pressure(failures: Array[String]) -> void:
failures.append("opening battle should allow play through turn 17, got limit %d" % state.get_turn_limit())
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 12:
failures.append("opening battle should start with 12 enemies, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
if state._condition_gate_open({"after_event": "turn_9_western_reserve"}):
failures.append("opening battle final defeat-all condition should be gated until turn 9 reserve")
if state._condition_gate_open({"after_event": "turn_11_last_rally"}):
failures.append("opening battle final defeat-all condition should be gated until turn 11 last rally")
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 4)
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 14:
failures.append("opening battle should field 14 enemies after turn 4 reserve, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
if int(state.get_unit("xiahou_dun").get("ai_target_priority", 0)) < 9:
failures.append("opening battle turn 4 reserve should pressure Xiahou Dun's vanguard")
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 7)
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 16:
failures.append("opening battle should field 16 enemies after turn 7 raiders, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
if int(state.get_unit("cao_cao").get("ai_target_priority", 0)) < 11:
failures.append("opening battle turn 7 raiders should pressure Cao Cao")
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 9)
if not state._condition_gate_open({"after_event": "turn_9_western_reserve"}):
failures.append("opening battle final gate should open after turn 9 reserve event")
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 19:
failures.append("opening battle should field 19 enemies after late reserve, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
if int(state.get_unit("cao_cao").get("ai_target_priority", 0)) < 12:
failures.append("opening battle turn 9 reserve should keep pressure on Cao Cao")
if state._condition_gate_open({"after_event": "turn_11_last_rally"}):
failures.append("opening battle should stay open-ended until the turn 11 last rally arrives")
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 11)
if not state._condition_gate_open({"after_event": "turn_11_last_rally"}):
failures.append("opening battle final gate should open after turn 11 last rally event")
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 22:
failures.append("opening battle should field 22 enemies after final rally, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
if int(state.get_unit("cao_cao").get("ai_target_priority", 0)) < 13 or int(state.get_unit("xiahou_dun").get("ai_target_priority", 0)) < 13:
failures.append("opening battle turn 11 last rally should pressure both Cao Cao and Xiahou Dun")
func _check_sishui_gate_extended_pressure(failures: Array[String]) -> void: