Add Sishui Gate camp content

This commit is contained in:
2026-06-18 23:15:02 +09:00
parent b4f3b28ef3
commit 28053dc8c9
4 changed files with 87 additions and 0 deletions

View File

@@ -18,9 +18,55 @@
"lines": [
"The coalition gathers to challenge Dong Zhuo.",
"Cao Cao leads a small vanguard to test Hua Xiong's defenses."
],
"camp_conversations": [
{
"id": "sishui_coalition_reading",
"group": "officer",
"officer_id": "cao_cao",
"label": "Cao Cao - Coalition Nerve",
"speaker": "Cao Cao",
"summary": "Measure the coalition before challenging Hua Xiong.",
"lines": [
{ "speaker": "Cao Cao", "side": "left", "text": "The coalition has banners enough to shade the pass, yet every lord waits for another to move first." },
{ "speaker": "Xiahou Dun", "side": "right", "text": "Then let them watch us move. Hua Xiong will learn which banner has teeth." }
]
},
{
"id": "sishui_xiahou_yuan_ridge",
"group": "officer",
"officer_id": "xiahou_yuan",
"label": "Xiahou Yuan - Ridge Line",
"speaker": "Xiahou Yuan",
"summary": "Discuss the archers watching the road.",
"lines": [
{ "speaker": "Xiahou Yuan", "side": "right", "text": "Their archers favor the ridge above the road. If we let them settle, the vanguard will bleed before touching Hua Xiong." },
{ "speaker": "Cao Cao", "side": "left", "text": "Keep their eyes busy. A single opened flank will make the pass feel wider than it is." }
]
},
{
"id": "sishui_quartermaster_antidote",
"group": "topic",
"label": "Quartermaster's Bundle",
"summary": "Check the last useful supplies before the gate.",
"lines": [
{ "speaker": "Coalition Quartermaster", "side": "left", "text": "My lord, the western stores are crowded with borrowed seals and empty promises. I found one antidote bundle that is actually useful." },
{ "speaker": "Cao Ren", "side": "right", "text": "Take it. A single clean cure can keep a line from folding." }
],
"effects": [
{ "type": "grant_item", "item_id": "antidote", "count": 1, "text": "The quartermaster adds an Antidote to the field supplies." }
]
}
]
},
"shop": {
"merchant": {
"name": "Coalition Merchant",
"lines": [
"Every lord at Sishui wants credit, but only the first vanguard buys enough bandages.",
"I have robes, armor, bows, and spears. If Hua Xiong breaks through, nobody will ask where they came from."
]
},
"items": [
"bean",
"antidote",

View File

@@ -6,6 +6,9 @@ const CAMPAIGN_PATH := "res://data/campaign/campaign.json"
const SCENARIO_ID := "001_yellow_turbans"
const SCENARIO_PATH := "res://data/scenarios/001_yellow_turbans.json"
const CONVERSATION_ID := "northern_woods_cache"
const SISHUI_SCENARIO_ID := "002_sishui_gate"
const SISHUI_SCENARIO_PATH := "res://data/scenarios/002_sishui_gate.json"
const SISHUI_CONVERSATION_ID := "sishui_quartermaster_antidote"
const BRANCH_SCENARIO_ID := "003_xingyang_ambush"
const BRANCH_SCENARIO_PATH := "res://data/scenarios/003_xingyang_ambush.json"
const WUCHAO_SCENARIO_ID := "013_wuchao_raid"
@@ -21,6 +24,7 @@ func _init() -> void:
_check_claim_updates_campaign_and_battle(failures)
_check_shop_and_armory_preserve_claim(failures)
_check_sishui_gate_camp_supplies(failures)
_check_manual_checkpoint_reverts_claim(failures)
_check_completed_replay_cannot_claim(failures)
_check_conditional_camp_conversations(failures)
@@ -107,6 +111,28 @@ func _check_shop_and_armory_preserve_claim(failures: Array[String]) -> void:
scene.free()
func _check_sishui_gate_camp_supplies(failures: Array[String]) -> void:
var scene = _new_prebattle_scene_for(failures, "Sishui camp supplies", SISHUI_SCENARIO_ID, SISHUI_SCENARIO_PATH)
if scene == null:
return
var conversation: Dictionary = scene._camp_conversation_by_id(SISHUI_CONVERSATION_ID)
if conversation.is_empty():
failures.append("Sishui should expose quartermaster antidote conversation")
scene.free()
return
if not scene._format_camp_conversation_button_text(conversation).contains("Supply Antidote"):
failures.append("Sishui quartermaster button should preview Antidote supply")
var before_antidote := int(scene.campaign_state.get_inventory_snapshot().get("antidote", 0))
scene._apply_camp_conversation_effects(conversation)
if int(scene.campaign_state.get_inventory_snapshot().get("antidote", 0)) != before_antidote + 1:
failures.append("Sishui quartermaster should add Antidote to campaign inventory")
if int(scene.state.get_inventory_snapshot().get("antidote", 0)) != before_antidote + 1:
failures.append("Sishui quartermaster should refresh battle Antidote inventory")
if not scene.campaign_state.has_claimed_camp_conversation_effects(SISHUI_SCENARIO_ID, SISHUI_CONVERSATION_ID):
failures.append("Sishui quartermaster claim should be saved")
scene.free()
func _check_manual_checkpoint_reverts_claim(failures: Array[String]) -> void:
var scene = _new_prebattle_scene(failures, "manual checkpoint")
if scene == null:

View File

@@ -43,6 +43,7 @@ func _init() -> void:
_check_contains(failures, "campaign section", result_text, "Next: Sishui Gate")
_check_contains(failures, "next camp section", result_text, "Next Camp")
_check_contains(failures, "next camp location", result_text, "Sishui Gate, 190 CE")
_check_contains(failures, "next camp talk", result_text, "Talk 3")
_check_contains(failures, "next camp shop", result_text, "Shop 6 goods")
_check_contains(failures, "next camp deploy", result_text, "Deploy 2/3")
_check_contains(failures, "next camp formation", result_text, "Formation 6 tiles")

View File

@@ -122,6 +122,20 @@ func _check_battle_visual_data(failures: Array[String]) -> void:
failures.append("could not load Sishui Gate for enemy cavalry sprite")
else:
_check_unit_sprite_resolution(failures, gate_state, "hua_xiong_vanguard", "res://art/units/enemies/enemy_cavalry.png", true)
var gate_briefing := gate_state.get_briefing()
var gate_conversations: Array = gate_briefing.get("camp_conversations", [])
if gate_conversations.size() < 3:
failures.append("002 briefing should expose at least three camp conversations")
else:
_check_camp_conversation(failures, gate_conversations[0], "sishui_coalition_reading", "officer", "cao_cao")
_check_camp_conversation(failures, gate_conversations[1], "sishui_xiahou_yuan_ridge", "officer", "xiahou_yuan")
_check_camp_conversation(failures, gate_conversations[2], "sishui_quartermaster_antidote", "topic", "")
_check_camp_conversation_effect(failures, gate_conversations[2], "antidote", 1)
var gate_merchant := gate_state.get_shop_merchant()
if str(gate_merchant.get("name", "")) != "Coalition Merchant":
failures.append("002 shop should expose coalition merchant name")
if (gate_merchant.get("lines", []) as Array).size() < 2:
failures.append("002 shop should expose merchant flavor lines")
for item_id in ["bronze_sword", "training_spear", "short_bow", "hand_axe", "iron_armor", "panacea"]:
var item := state.get_item_def(item_id)