Improve Xian emperor escort battle pacing
This commit is contained in:
@@ -2,20 +2,28 @@
|
||||
"id": "007_xian_emperor_escort",
|
||||
"name": "헌제 호송전",
|
||||
"objectives": {
|
||||
"victory": "조조를 동쪽 행로 표식까지 이동시켜라.",
|
||||
"defeat": "조조 또는 천자 사자가 퇴각하거나 제11군령에 이르면 패한다."
|
||||
"victory": "동도 호송로를 장악한 뒤 잔당을 격파하라.",
|
||||
"defeat": "조조나 천자 사자가 퇴각하거나 제18군령이 시작되면 패한다."
|
||||
},
|
||||
"conditions": {
|
||||
"victory": {
|
||||
"type": "unit_reaches_tile",
|
||||
"team": "player",
|
||||
"officer_ids": ["cao_cao"],
|
||||
"pos": [13, 4]
|
||||
"type": "all",
|
||||
"conditions": [
|
||||
{ "type": "all_units_defeated", "team": "enemy", "after_event": "turn_9_final_escort_pressure" },
|
||||
{
|
||||
"type": "unit_reaches_tile",
|
||||
"label": "동도 호송로",
|
||||
"team": "player",
|
||||
"unit_ids": ["cao_cao_ch7"],
|
||||
"officer_ids": ["cao_cao"],
|
||||
"cells": [[12, 4], [13, 4]]
|
||||
}
|
||||
]
|
||||
},
|
||||
"defeat": [
|
||||
{ "type": "any_officer_defeated", "team": "player", "officer_ids": ["cao_cao"] },
|
||||
{ "type": "any_unit_defeated", "unit_ids": ["imperial_envoy_ch7"] },
|
||||
{ "type": "turn_reached", "turn": 11, "team": "player" }
|
||||
{ "type": "turn_reached", "turn": 18, "team": "player" }
|
||||
]
|
||||
},
|
||||
"briefing": {
|
||||
@@ -23,7 +31,8 @@
|
||||
"location": "낙양 동도, 건안 원년",
|
||||
"lines": [
|
||||
"폐허가 된 낙양에서 천자의 거가가 제후들의 압박을 피해 동쪽 길로 나섰다.",
|
||||
"잔당이 길목을 죄기 전에 조조를 동도 표식까지 이끌어 호송로를 장악하라."
|
||||
"잔당이 길목을 죄기 전에 조조를 동도 표식까지 이끌어 호송로를 장악하라.",
|
||||
"후미의 사자를 지키며 제9군령의 마지막 압박까지 견디면, 조정의 행렬이 안전하게 빠져나갈 수 있다."
|
||||
],
|
||||
"conditional_lines": [
|
||||
{
|
||||
@@ -140,11 +149,11 @@
|
||||
"GGGGGGGGGGGGGGG",
|
||||
"GGGFFGGGHHGGGGG",
|
||||
"GGGFFRRRHHGGGGG",
|
||||
"GGGGGRRRGGFFFGG",
|
||||
"GGGGGRRRGGCCFGG",
|
||||
"RRRRRRRRRRRRRRR",
|
||||
"GGGGGRRRGGFFFGG",
|
||||
"GGHHGFFFGGGRRGG",
|
||||
"GGHHGFFFGGGWWGG",
|
||||
"GGGGGRRRGGCCFGG",
|
||||
"GGHHTTFFGGGRRGG",
|
||||
"GGHHTTFFGGGWWGG",
|
||||
"GGGGGGFFGGGWWGG",
|
||||
"GGGGGGGGGGGGGGG"
|
||||
]
|
||||
@@ -239,6 +248,33 @@
|
||||
"level": 7,
|
||||
"pos": [12, 6],
|
||||
"base": { "hp": 36, "mp": 20, "atk": 7, "def": 6, "int": 13 }
|
||||
},
|
||||
{
|
||||
"unit_id": "escort_gate_spearman",
|
||||
"name": "동도 창병",
|
||||
"class_id": "infantry",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [10, 3],
|
||||
"base": { "hp": 44, "atk": 15, "def": 9 }
|
||||
},
|
||||
{
|
||||
"unit_id": "escort_south_guard",
|
||||
"name": "남쪽 방패병",
|
||||
"class_id": "infantry",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [11, 5],
|
||||
"base": { "hp": 44, "atk": 14, "def": 10 }
|
||||
},
|
||||
{
|
||||
"unit_id": "escort_woods_rider",
|
||||
"name": "숲길 기병",
|
||||
"class_id": "cavalry",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [9, 6],
|
||||
"base": { "hp": 42, "atk": 16, "def": 8, "agi": 11 }
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
@@ -305,7 +341,7 @@
|
||||
{
|
||||
"id": "midroad_ambush",
|
||||
"once": true,
|
||||
"when": { "type": "unit_reaches_tile", "team": "player", "pos": [7, 4] },
|
||||
"when": { "type": "unit_reaches_tile", "team": "player", "unit_ids": ["cao_cao_ch7"], "officer_ids": ["cao_cao"], "pos": [7, 4] },
|
||||
"actions": [
|
||||
{
|
||||
"type": "dialogue",
|
||||
@@ -352,6 +388,117 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "turn_6_envoy_pincher",
|
||||
"once": true,
|
||||
"when": { "type": "turn_start", "team": "enemy", "turn": 6 },
|
||||
"actions": [
|
||||
{ "type": "log", "text": "잔당이 후미 사자를 노리고 숲길 양쪽에서 밀려든다." },
|
||||
{
|
||||
"type": "dialogue",
|
||||
"lines": [
|
||||
{ "speaker": "Scout", "text": "남쪽 숲과 북쪽 언덕에서 동시에 움직임이 있습니다!" },
|
||||
{ "speaker": "Dian Wei", "text": "사자 곁을 비우지 마십시오. 적이 찾는 것은 조조가 아니라 행렬의 약한 고리입니다." }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "spawn_deployments",
|
||||
"deployments": [
|
||||
{
|
||||
"unit_id": "envoy_pincher_archer",
|
||||
"name": "북쪽 궁병",
|
||||
"class_id": "archer",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [6, 1],
|
||||
"base": { "hp": 34, "atk": 13, "def": 6 }
|
||||
},
|
||||
{
|
||||
"unit_id": "envoy_pincher_bandit",
|
||||
"name": "남쪽 도적",
|
||||
"class_id": "bandit",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [6, 8],
|
||||
"base": { "hp": 42, "atk": 14, "def": 7 }
|
||||
},
|
||||
{
|
||||
"unit_id": "envoy_pincher_rider",
|
||||
"name": "숲길 추격기",
|
||||
"class_id": "cavalry",
|
||||
"team": "enemy",
|
||||
"level": 7,
|
||||
"pos": [9, 8],
|
||||
"base": { "hp": 42, "atk": 16, "def": 8, "agi": 11 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "set_ai_target_priority",
|
||||
"unit_id": "imperial_envoy_ch7",
|
||||
"priority": 10,
|
||||
"text": "후미 압박대가 천자 사자를 노린다."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "turn_9_final_escort_pressure",
|
||||
"once": true,
|
||||
"when": { "type": "turn_start", "team": "enemy", "turn": 9 },
|
||||
"actions": [
|
||||
{
|
||||
"type": "set_objective",
|
||||
"victory": "동도 호송로를 지키며 마지막 잔당을 격파하라.",
|
||||
"defeat": "조조나 천자 사자가 퇴각하거나 제18군령이 시작되면 패한다."
|
||||
},
|
||||
{ "type": "log", "text": "이각과 곽사의 잔당이 마지막 길목을 막아선다." },
|
||||
{
|
||||
"type": "dialogue",
|
||||
"lines": [
|
||||
{ "speaker": "Li Jue", "display_speaker": "이각", "text": "천자의 행렬이 여기까지 온다 해도, 동쪽 길은 아직 우리 창끝 아래 있다." },
|
||||
{ "speaker": "Cao Cao", "display_speaker": "조조", "text": "길은 황제가 지나가면 길이 되고, 막는 자는 잔당이 된다. 동도 호송로를 열어라." }
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "spawn_deployments",
|
||||
"deployments": [
|
||||
{
|
||||
"unit_id": "final_escort_rider",
|
||||
"name": "마지막 추격기",
|
||||
"class_id": "cavalry",
|
||||
"team": "enemy",
|
||||
"level": 8,
|
||||
"pos": [13, 3],
|
||||
"base": { "hp": 48, "atk": 17, "def": 8, "agi": 12 }
|
||||
},
|
||||
{
|
||||
"unit_id": "final_escort_guard",
|
||||
"name": "마지막 방패병",
|
||||
"class_id": "infantry",
|
||||
"team": "enemy",
|
||||
"level": 8,
|
||||
"pos": [13, 5],
|
||||
"base": { "hp": 48, "atk": 15, "def": 10 }
|
||||
},
|
||||
{
|
||||
"unit_id": "final_escort_archer",
|
||||
"name": "마지막 궁병",
|
||||
"class_id": "archer",
|
||||
"team": "enemy",
|
||||
"level": 8,
|
||||
"pos": [12, 2],
|
||||
"base": { "hp": 36, "atk": 14, "def": 6 }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "set_ai_target_priority",
|
||||
"unit_ids": ["cao_cao_ch7", "imperial_envoy_ch7"],
|
||||
"priority": 12,
|
||||
"text": "마지막 잔당이 조조와 천자 사자를 함께 노린다."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"rewards": {
|
||||
|
||||
@@ -1515,8 +1515,8 @@ func _create_hud() -> void:
|
||||
briefing_objective_header.add_child(_make_section_caption("승리와 패배", 548))
|
||||
|
||||
briefing_objective_toggle_button = Button.new()
|
||||
briefing_objective_toggle_button.text = "조건 접기"
|
||||
briefing_objective_toggle_button.tooltip_text = "승리와 패배 조건을 접거나 펼칩니다."
|
||||
briefing_objective_toggle_button.text = "닫기"
|
||||
briefing_objective_toggle_button.tooltip_text = "승리와 패배 조건을 닫거나 펼칩니다."
|
||||
briefing_objective_toggle_button.custom_minimum_size = Vector2(124, 28)
|
||||
briefing_objective_toggle_button.pressed.connect(_on_briefing_objective_toggle_pressed)
|
||||
briefing_objective_header.add_child(briefing_objective_toggle_button)
|
||||
@@ -5798,7 +5798,7 @@ func _update_briefing_objective_visibility() -> void:
|
||||
briefing_objective_panel.visible = has_text and not briefing_objective_collapsed
|
||||
if briefing_objective_toggle_button != null:
|
||||
briefing_objective_toggle_button.visible = has_text
|
||||
briefing_objective_toggle_button.text = "조건 보기" if briefing_objective_collapsed else "조건 접기"
|
||||
briefing_objective_toggle_button.text = "펼치기" if briefing_objective_collapsed else "닫기"
|
||||
|
||||
|
||||
func _on_begin_battle_pressed() -> void:
|
||||
|
||||
@@ -103,11 +103,17 @@ func _init() -> void:
|
||||
_progress_text("res://data/scenarios/006_dingtao_counterattack.json", false),
|
||||
"중앙 방진"
|
||||
)
|
||||
_check_contains(
|
||||
failures,
|
||||
"007 gated victory progress",
|
||||
_progress_text("res://data/scenarios/007_xian_emperor_escort.json", false),
|
||||
"제9군령에 전공 갱신"
|
||||
)
|
||||
_check_contains(
|
||||
failures,
|
||||
"007 destination progress",
|
||||
_progress_text("res://data/scenarios/007_xian_emperor_escort.json", false),
|
||||
"전장 표식 (14, 5) · 미도달"
|
||||
"동도 호송로 (13, 5), (14, 5) · 미도달"
|
||||
)
|
||||
_check_contains(
|
||||
failures,
|
||||
@@ -130,6 +136,7 @@ func _init() -> void:
|
||||
_check_qingzhou_campaign_extended_pressure(failures)
|
||||
_check_puyang_raid_extended_pressure(failures)
|
||||
_check_dingtao_counterattack_extended_pressure(failures)
|
||||
_check_xian_emperor_escort_extended_pressure(failures)
|
||||
_check_objective_update(failures)
|
||||
_check_objective_notice(failures)
|
||||
_check_terrain_recovery(failures)
|
||||
@@ -667,6 +674,83 @@ func _check_dingtao_counterattack_extended_pressure(failures: Array[String]) ->
|
||||
scene.free()
|
||||
|
||||
|
||||
func _check_xian_emperor_escort_extended_pressure(failures: Array[String]) -> void:
|
||||
var state = BattleStateScript.new()
|
||||
if not state.load_battle("res://data/scenarios/007_xian_emperor_escort.json"):
|
||||
failures.append("Xian Emperor Escort pressure smoke could not load scenario")
|
||||
return
|
||||
if state.get_turn_limit() != 17:
|
||||
failures.append("Xian Emperor Escort should allow play through turn 17, got limit %d" % state.get_turn_limit())
|
||||
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 8:
|
||||
failures.append("Xian Emperor Escort should start with 8 enemies, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
|
||||
if state._condition_gate_open({"after_event": "turn_9_final_escort_pressure"}):
|
||||
failures.append("Xian Emperor Escort final defeat-all condition should be gated until turn 9 final pressure")
|
||||
var marker_cells := state.get_objective_cells()
|
||||
for road_cell in [Vector2i(12, 4), Vector2i(13, 4)]:
|
||||
if not marker_cells.has(road_cell):
|
||||
failures.append("Xian Emperor Escort should mark east road cell %s: %s" % [str(road_cell), str(marker_cells)])
|
||||
if state.get_objective_cell_label(road_cell) != "동도 호송로":
|
||||
failures.append("Xian Emperor Escort road marker should expose label at %s" % str(road_cell))
|
||||
var recovery_summaries := state.get_recovery_terrain_summaries()
|
||||
var has_road_recovery := false
|
||||
var has_village_recovery := false
|
||||
for summary in recovery_summaries:
|
||||
if str(summary.get("name", "")) == "성채" and int(summary.get("count", 0)) == 4 and int(summary.get("heal", 0)) == 8:
|
||||
has_road_recovery = true
|
||||
if str(summary.get("name", "")) == "마을" and int(summary.get("count", 0)) == 4 and int(summary.get("heal", 0)) == 6:
|
||||
has_village_recovery = true
|
||||
if not has_road_recovery:
|
||||
failures.append("Xian Emperor Escort should expose road recovery terrain: %s" % str(recovery_summaries))
|
||||
if not has_village_recovery:
|
||||
failures.append("Xian Emperor Escort should expose village recovery terrain: %s" % str(recovery_summaries))
|
||||
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 3)
|
||||
var cao_cao: Dictionary = state.get_unit("cao_cao_ch7")
|
||||
cao_cao["pos"] = Vector2i(7, 4)
|
||||
state._run_events("unit_reaches_tile", BattleStateScript.TEAM_PLAYER, 1, cao_cao)
|
||||
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 6)
|
||||
if int(state.get_unit("imperial_envoy_ch7").get("ai_target_priority", 0)) != 10:
|
||||
failures.append("Xian Emperor Escort turn 6 pressure should target the imperial envoy")
|
||||
state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 9)
|
||||
if not state._condition_gate_open({"after_event": "turn_9_final_escort_pressure"}):
|
||||
failures.append("Xian Emperor Escort final gate should open after turn 9 pressure event")
|
||||
if state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 18:
|
||||
failures.append("Xian Emperor Escort should field 18 enemies after ambush and final pressure, got %d" % state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
|
||||
if int(state.get_unit("cao_cao_ch7").get("ai_target_priority", 0)) != 12:
|
||||
failures.append("Xian Emperor Escort turn 9 final pressure should target Cao Cao")
|
||||
if int(state.get_unit("imperial_envoy_ch7").get("ai_target_priority", 0)) != 12:
|
||||
failures.append("Xian Emperor Escort turn 9 final pressure should keep targeting the imperial envoy")
|
||||
for enemy in state.get_living_units(BattleStateScript.TEAM_ENEMY):
|
||||
enemy["alive"] = false
|
||||
cao_cao["pos"] = Vector2i(11, 4)
|
||||
state._check_battle_status()
|
||||
if str(state.battle_status) != BattleStateScript.STATUS_ACTIVE:
|
||||
failures.append("Xian Emperor Escort should not end before the east road is secured, got %s" % str(state.battle_status))
|
||||
cao_cao["pos"] = Vector2i(12, 4)
|
||||
state._check_battle_status()
|
||||
if str(state.battle_status) != BattleStateScript.STATUS_VICTORY:
|
||||
failures.append("Xian Emperor Escort should end after final pressure falls and the east road is secured, got %s" % str(state.battle_status))
|
||||
var no_ambush_state = BattleStateScript.new()
|
||||
if not no_ambush_state.load_battle("res://data/scenarios/007_xian_emperor_escort.json"):
|
||||
failures.append("Xian Emperor Escort no-ambush smoke could not load scenario")
|
||||
return
|
||||
no_ambush_state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 3)
|
||||
no_ambush_state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 6)
|
||||
no_ambush_state._run_events("turn_start", BattleStateScript.TEAM_ENEMY, 9)
|
||||
if no_ambush_state.get_living_units(BattleStateScript.TEAM_ENEMY).size() != 16:
|
||||
failures.append("Xian Emperor Escort should field 16 enemies without the road ambush, got %d" % no_ambush_state.get_living_units(BattleStateScript.TEAM_ENEMY).size())
|
||||
var scene = BattleSceneScript.new()
|
||||
if not scene.state.load_battle("res://data/scenarios/007_xian_emperor_escort.json"):
|
||||
failures.append("Xian Emperor Escort briefing smoke could not load scenario")
|
||||
scene.free()
|
||||
return
|
||||
var overview := scene._format_briefing_battlefield_overview_text()
|
||||
_check_contains(failures, "007 briefing map size", overview, "15칸 x 10칸")
|
||||
_check_contains(failures, "007 briefing enemy count", overview, "적세 8명")
|
||||
_check_contains(failures, "007 briefing village recovery", overview, "마을 4칸 +6")
|
||||
_check_contains(failures, "007 briefing road recovery", overview, "성채 4칸 +8")
|
||||
scene.free()
|
||||
|
||||
|
||||
func _check_opening_board_avoids_side_panel(failures: Array[String]) -> void:
|
||||
var state = BattleStateScript.new()
|
||||
if not state.load_battle("res://data/scenarios/001_yellow_turbans.json"):
|
||||
|
||||
@@ -3199,14 +3199,14 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void:
|
||||
failures.append("mission objective panel should reopen cleanly")
|
||||
if scene.briefing_start_button == null or scene.briefing_start_button.text != "전투 시작":
|
||||
failures.append("briefing start button should clearly start after briefing")
|
||||
if scene.briefing_objective_toggle_button == null or scene.briefing_objective_toggle_button.text != "조건 접기":
|
||||
failures.append("briefing objective panel should expose a collapse button")
|
||||
if scene.briefing_objective_toggle_button == null or scene.briefing_objective_toggle_button.text != "닫기":
|
||||
failures.append("briefing objective panel should expose a close button")
|
||||
else:
|
||||
scene._set_briefing_objective_collapsed(true)
|
||||
if scene.briefing_objective_panel == null or scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "조건 보기":
|
||||
if scene.briefing_objective_panel == null or scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "펼치기":
|
||||
failures.append("briefing objective panel should collapse cleanly")
|
||||
scene._set_briefing_objective_collapsed(false)
|
||||
if scene.briefing_objective_panel == null or not scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "조건 접기":
|
||||
if scene.briefing_objective_panel == null or not scene.briefing_objective_panel.visible or scene.briefing_objective_toggle_button.text != "닫기":
|
||||
failures.append("briefing objective panel should reopen cleanly")
|
||||
scene.briefing_panel.visible = true
|
||||
scene.battle_started = false
|
||||
|
||||
Reference in New Issue
Block a user