From f883dc43665b1a0dad029d9a7fbdf38ebcc3eba4 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Fri, 19 Jun 2026 07:52:48 +0900 Subject: [PATCH] Antique Xiapi siege scenario --- data/campaign/campaign.json | 2 +- data/scenarios/009_xiapi_siege.json | 134 +++++++++++------------ scripts/scenes/battle_scene.gd | 3 + tools/smoke_camp_conversation_rewards.gd | 2 +- tools/smoke_visual_assets.gd | 2 +- 5 files changed, 73 insertions(+), 70 deletions(-) diff --git a/data/campaign/campaign.json b/data/campaign/campaign.json index d81071e..e9ba5bc 100644 --- a/data/campaign/campaign.json +++ b/data/campaign/campaign.json @@ -96,7 +96,7 @@ }, { "id": "009_xiapi_siege", - "title": "Xiapi Siege", + "title": "하비 수공전", "path": "res://data/scenarios/009_xiapi_siege.json" }, { diff --git a/data/scenarios/009_xiapi_siege.json b/data/scenarios/009_xiapi_siege.json index 74531b3..e6b251c 100644 --- a/data/scenarios/009_xiapi_siege.json +++ b/data/scenarios/009_xiapi_siege.json @@ -1,9 +1,9 @@ { "id": "009_xiapi_siege", - "name": "Xiapi Siege", + "name": "하비 수공전", "objectives": { - "victory": "Hold through the flood-gate operation, then defeat Lu Bu's army.", - "defeat": "Cao Cao is defeated or the battle reaches Turn 13." + "victory": "수문 작전이 끝날 때까지 버틴 뒤 여포군을 격파하라.", + "defeat": "조조가 퇴각하거나 제13군령에 이르면 패한다." }, "conditions": { "victory": { "type": "all_units_defeated", "team": "enemy", "after_event": "turn_3_flood_gates" }, @@ -13,23 +13,23 @@ ] }, "briefing": { - "title": "Xiapi Siege", - "location": "Xiapi, 198 CE", + "title": "하비 수공전", + "location": "하비, 건안 삼년", "lines": [ - "Lu Bu has withdrawn behind Xiapi's wet walls, trusting his cavalry and Chen Gong's counsel to break the siege.", - "Cao Cao orders the river channels opened. Survive the countercharge until the flood-gate signals confirm that Lu Bu's army has been forced into the open." + "여포는 하비의 젖은 성벽 뒤로 물러나 기병과 진궁의 계책으로 포위를 깨려 한다.", + "조조는 물길을 열라 명한다. 수문 신호가 올라 여포군을 낮은 길로 끌어낼 때까지 첫 반격을 버텨라." ], "conditional_lines": [ { "campaign_flags": { "held_wan_gate": true }, "lines": [ - "The baggage recovered at Wan Castle keeps the siege line supplied with heavier shields and dry bowstrings." + "완성에서 되찾은 짐수레 덕에 포위선에는 두꺼운 방패와 마른 활시위가 넉넉하다." ] }, { "campaign_flags": { "swift_wan_escape": true }, "lines": [ - "The army reached Xiapi quickly after leaving Wan Castle behind, but some siege stores are still catching up." + "완성의 짐을 버리고 빠르게 하비에 닿았으나, 무거운 공성 물자는 아직 뒤따르는 중이다." ] } ], @@ -38,19 +38,19 @@ "id": "xiapi_floodgate_council", "group": "officer", "officer_id": "cao_cao", - "label": "Cao Cao - Flood Gates", + "label": "조조 - 수문 계책", "speaker": "Cao Cao", - "summary": "Set the siege rhythm around the sluice-gate signal.", + "summary": "수문 신호에 맞춰 포위전의 박자를 정한다.", "lines": [ { "speaker": "Cao Cao", "side": "left", - "text": "Lu Bu wants speed to decide this siege. Water is slower than cavalry, but it remembers every low road." + "text": "여포는 속도로 이 포위를 가르려 한다. 물은 기병보다 느리나, 낮은 길을 하나도 잊지 않는다." }, { "speaker": "Xiahou Dun", "side": "right", - "text": "Then we hold until the channels answer. Once the mud rises, his riders lose the field they trust." + "text": "그렇다면 물길이 대답할 때까지 버티겠습니다. 진흙이 오르면 저들의 기병은 믿던 들판을 잃습니다." } ] }, @@ -58,19 +58,19 @@ "id": "xiapi_dian_wei_siege_road", "group": "officer", "officer_id": "dian_wei", - "label": "Dian Wei - Siege Road", + "label": "전위 - 포위로", "speaker": "Dian Wei", - "summary": "Place Dian Wei where Lu Bu's first countercharge must break.", + "summary": "여포의 첫 반격이 부딪힐 길목에 전위를 세운다.", "lines": [ { "speaker": "Dian Wei", "side": "right", - "text": "Give me the road before the water reaches it. Horsemen hate a man who refuses to step aside." + "text": "물이 닿기 전의 길목을 제게 주십시오. 비켜서지 않는 사람을 기병은 싫어합니다." }, { "speaker": "Cao Cao", "side": "left", - "text": "Stand where the line can see you. A siege holds better when courage has a face." + "text": "전열이 너를 볼 수 있는 곳에 서라. 용기가 얼굴을 가지면 포위선은 더 오래 버틴다." } ] }, @@ -78,18 +78,18 @@ "id": "xiapi_wan_baggage_dressings", "campaign_flags": { "held_wan_gate": true }, "group": "topic", - "label": "Wan Baggage Dressings", - "summary": "Open the recovered baggage for antidotes and field medicine.", + "label": "완성 짐수레 약상", + "summary": "되찾은 짐수레에서 해독약과 야전 약상을 연다.", "lines": [ { "speaker": "Cao Ren", "side": "left", - "text": "The baggage saved at Wan still has dry medicine. The river air is already turning wounds sour." + "text": "완성에서 건진 짐수레에 아직 마른 약이 남아 있습니다. 강가의 습기가 벌써 상처를 곪게 합니다." }, { "speaker": "Cao Cao", "side": "right", - "text": "Issue it before the gates open. A steady siege line is built from small mercies." + "text": "수문을 열기 전에 나누어라. 흔들리지 않는 포위선은 작은 구휼에서 세워진다." } ], "effects": [ @@ -97,7 +97,7 @@ "type": "grant_item", "item_id": "panacea", "count": 1, - "text": "The Wan baggage dressings add a Panacea to the field supplies." + "text": "완성 짐수레 약상에서 만능약 한 꾸러미를 군수에 보탰다." } ] }, @@ -105,18 +105,18 @@ "id": "xiapi_forced_march_rations", "campaign_flags": { "swift_wan_escape": true }, "group": "topic", - "label": "Forced March Rations", - "summary": "Ration portable food to soldiers who reached Xiapi before the heavy stores.", + "label": "강행군 군량", + "summary": "무거운 군수보다 먼저 하비에 닿은 병사에게 휴대 군량을 나눈다.", "lines": [ { "speaker": "Xiahou Yuan", "side": "right", - "text": "We reached Xiapi ahead of the slow wagons. The men can fight light, but the night work has emptied their canteens." + "text": "느린 수레보다 먼저 하비에 닿았습니다. 가볍게 싸울 수는 있으나 밤일로 물통이 비었습니다." }, { "speaker": "Dian Wei", "side": "left", - "text": "Give them beans, then point them at Lu Bu's road. Light packs still hit hard." + "text": "콩을 먹이고 여포의 길목을 가리켜라. 짐이 가벼운 병사도 부딪히면 세다." } ], "effects": [ @@ -124,7 +124,7 @@ "type": "grant_item", "item_id": "bean", "count": 1, - "text": "The forced march rations add a Bean to the field supplies." + "text": "강행군 군량에서 콩 한 꾸러미를 군수에 보탰다." } ] } @@ -153,10 +153,10 @@ } ], "merchant": { - "name": "Xiapi Flood-Gate Sutler", + "name": "하비 수문 야상", "lines": [ - "Keep the sacks off the low road. Once the channels open, every dry bean becomes expensive.", - "Buy before the signal rises. After the water moves, I sell only to men who can still reach the wagons." + "자루를 낮은 길에 두지 마십시오. 물길이 열리면 마른 콩 하나도 값이 오릅니다.", + "신호가 오르기 전에 사 두십시오. 물이 움직인 뒤에는 수레까지 걸어올 수 있는 사람에게만 팝니다." ] } }, @@ -220,7 +220,7 @@ }, { "unit_id": "lu_bu_xiapi", - "name": "Lu Bu", + "name": "여포", "class_id": "elite_cavalry", "team": "enemy", "level": 9, @@ -229,7 +229,7 @@ }, { "unit_id": "chen_gong_strategist", - "name": "Chen Gong", + "name": "진궁", "class_id": "strategist", "team": "enemy", "level": 9, @@ -239,7 +239,7 @@ }, { "unit_id": "gao_shun_trap_line", - "name": "Gao Shun Line", + "name": "고순 방진", "class_id": "infantry", "team": "enemy", "level": 9, @@ -248,7 +248,7 @@ }, { "unit_id": "xiapi_rider_north", - "name": "Xiapi Rider", + "name": "하비 기병", "class_id": "cavalry", "team": "enemy", "level": 8, @@ -257,7 +257,7 @@ }, { "unit_id": "xiapi_rider_south", - "name": "Xiapi Rider", + "name": "하비 기병", "class_id": "cavalry", "team": "enemy", "level": 8, @@ -266,7 +266,7 @@ }, { "unit_id": "xiapi_wall_archer", - "name": "Wall Archer", + "name": "성벽 궁병", "class_id": "archer", "team": "enemy", "level": 8, @@ -275,7 +275,7 @@ }, { "unit_id": "xiapi_gate_guard", - "name": "Gate Guard", + "name": "수문 수비병", "class_id": "infantry", "team": "enemy", "level": 8, @@ -289,7 +289,7 @@ "once": true, "when": { "type": "battle_start" }, "actions": [ - { "type": "log", "text": "The siege lines tighten around Xiapi." } + { "type": "log", "text": "하비를 둘러싼 포위선이 조여 든다." } ] }, { @@ -300,9 +300,9 @@ { "type": "dialogue", "lines": [ - { "speaker": "Cao Cao", "text": "Lu Bu trusts his speed even behind walls. We will make the ground choose against him." }, - { "speaker": "Xiahou Dun", "text": "The channels are ready. We only need to hold the line until the signal rises." }, - { "speaker": "Dian Wei", "text": "Then I hold the road. Let the horsemen find me first." } + { "speaker": "Cao Cao", "text": "여포는 성벽 뒤에서도 속도를 믿는다. 이번에는 땅이 그를 배반하게 만들 것이다." }, + { "speaker": "Xiahou Dun", "text": "수로는 준비되었습니다. 신호가 오를 때까지 전열만 붙들면 됩니다." }, + { "speaker": "Dian Wei", "text": "그렇다면 제가 길을 붙들겠습니다. 기병들이 먼저 저를 찾게 두십시오." } ] } ] @@ -315,8 +315,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Lu Bu", "text": "Cao Cao hides behind ditches and mud. Riders, break the siege line before the water rises!" }, - { "speaker": "Chen Gong", "text": "Strike the commander if the line bends. The flood plan dies with him." } + { "speaker": "Lu Bu", "text": "조조가 도랑과 진흙 뒤에 숨었구나. 물이 차기 전에 포위선을 짓밟아라!" }, + { "speaker": "Chen Gong", "text": "전열이 휘면 장수를 치십시오. 수공의 계책도 그와 함께 죽습니다." } ] }, { @@ -324,7 +324,7 @@ "deployments": [ { "unit_id": "lu_bu_flank_rider_north", - "name": "Flank Rider", + "name": "측익 기병", "class_id": "cavalry", "team": "enemy", "level": 8, @@ -333,7 +333,7 @@ }, { "unit_id": "lu_bu_flank_rider_south", - "name": "Flank Rider", + "name": "측익 기병", "class_id": "cavalry", "team": "enemy", "level": 8, @@ -349,18 +349,18 @@ "once": true, "when": { "type": "turn_start", "team": "player", "turn": 3 }, "actions": [ - { "type": "log", "text": "The flood-gate signal rises around Xiapi." }, + { "type": "log", "text": "하비 둘레에 수문 개방 신호가 오른다." }, { "type": "dialogue", "lines": [ - { "speaker": "Scout", "text": "The water is moving. Xiapi's outer detachments are falling back from the low roads!" }, - { "speaker": "Cao Cao", "text": "Good. Now Lu Bu must fight where we can reach him." } + { "speaker": "Scout", "text": "물이 움직입니다. 하비 외곽 부대가 낮은 길에서 물러납니다!" }, + { "speaker": "Cao Cao", "text": "좋다. 이제 여포는 우리가 닿을 수 있는 곳에서 싸워야 한다." } ] }, { "type": "set_objective", - "victory": "Defeat Lu Bu, Chen Gong, and the remaining Xiapi defenders.", - "defeat": "Cao Cao is defeated or the battle reaches Turn 13." + "victory": "여포, 진궁, 남은 하비 수비대를 격파하라.", + "defeat": "조조가 퇴각하거나 제13군령에 이르면 패한다." }, { "type": "withdraw_units", @@ -371,7 +371,7 @@ "deployments": [ { "unit_id": "flooded_gate_guard", - "name": "Sluice Gate Guard", + "name": "수문 수비병", "class_id": "infantry", "team": "enemy", "level": 8, @@ -380,7 +380,7 @@ }, { "unit_id": "flooded_wall_archer", - "name": "Sluice Wall Archer", + "name": "수문 성벽 궁병", "class_id": "archer", "team": "enemy", "level": 8, @@ -399,8 +399,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Cao Ren", "text": "The baggage wagons from Wan have reached the siege line. The reserves are steady." }, - { "speaker": "Cao Cao", "text": "Then press forward carefully. We can afford patience." } + { "speaker": "Cao Ren", "text": "완성에서 온 짐수레가 포위선에 닿았습니다. 예비대가 안정되었습니다." }, + { "speaker": "Cao Cao", "text": "그렇다면 조심스럽게 밀어붙여라. 이제는 인내를 쓸 여유가 있다." } ] } ] @@ -413,15 +413,15 @@ { "type": "dialogue", "lines": [ - { "speaker": "Chen Gong", "text": "Cao Cao came quickly, but speed thins a siege line. Strike the loose wagons." }, - { "speaker": "Xiahou Yuan", "text": "Their raiders found the supply road. I will cut them off." } + { "speaker": "Chen Gong", "text": "조조가 빨리 왔으나, 빠른 행군은 포위선을 얇게 만듭니다. 느슨한 수레를 치십시오." }, + { "speaker": "Xiahou Yuan", "text": "저들의 기습대가 보급로를 찾았습니다. 제가 끊어 내겠습니다." } ] }, { "type": "spawn_deployment", "deployment": { "unit_id": "supply_road_raider", - "name": "Supply Road Raider", + "name": "보급로 습격병", "class_id": "bandit", "team": "enemy", "level": 8, @@ -439,8 +439,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Cao Cao", "text": "His cavalry has nowhere clean to run. Close the ring and do not let Chen Gong buy another hour." }, - { "speaker": "Dian Wei", "text": "Then the road ends here." } + { "speaker": "Cao Cao", "text": "저 기병이 달릴 마른 길은 이제 없다. 포위망을 닫고 진궁에게 한 시각도 더 주지 마라." }, + { "speaker": "Dian Wei", "text": "그렇다면 길은 여기서 끝입니다." } ] } ] @@ -452,24 +452,24 @@ "join_officers": ["guo_jia"] }, "post_battle_dialogue": [ - { "speaker": "Xiahou Dun", "text": "Xiapi is broken. Lu Bu's riders will not trouble Yan Province again." }, - { "speaker": "Dian Wei", "text": "Fast horses drown the same as slow ones." }, - { "speaker": "Guo Jia", "text": "Lu Bu's fall leaves Yuan Shao as the real measure of the north." }, - { "speaker": "Cao Cao", "text": "Speed without judgment is only a longer fall. We turn now from survival to rule." } + { "speaker": "Xiahou Dun", "text": "하비가 무너졌습니다. 여포의 기병은 다시 연주를 어지럽히지 못할 것입니다." }, + { "speaker": "Dian Wei", "text": "빠른 말도 느린 말과 똑같이 물에 잠깁니다." }, + { "speaker": "Guo Jia", "text": "여포가 쓰러졌으니, 북방의 진짜 저울은 원소가 되었습니다." }, + { "speaker": "Cao Cao", "text": "판단 없는 속도는 더 긴 추락일 뿐이다. 이제 우리는 생존이 아니라 통치를 향해 돈다." } ], "post_battle_choices": [ { "id": "integrate_xu_province", - "label": "Integrate Xu Province", - "description": "Cao Cao places officials to secure the newly won territory.", + "label": "서주 편입", + "description": "조조가 새로 얻은 땅에 관리를 두어 서주를 안정시킨다.", "set_flags": { "integrated_xu_province": true, "pressed_northern_campaign": false }, "gold": 200, "items": ["iron_armor"] }, { "id": "press_northern_campaign", - "label": "Press North", - "description": "The army prepares to turn its momentum toward the northern rivals.", + "label": "북방 압박", + "description": "군세가 승세를 몰아 북방의 제후들을 겨눌 준비를 한다.", "set_flags": { "integrated_xu_province": false, "pressed_northern_campaign": true }, "gold": 100, "items": ["wine", "war_drum"] diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index d2c6e79..5fbbbe7 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -116,12 +116,14 @@ const SPEAKER_DISPLAY_NAMES := { "Zhang Xiu": "장수", "Jia Xu": "가후", "Cao Ang": "조앙", + "Chen Gong": "진궁", "Gao Shun": "고순", "Lu Bu": "여포", "Puyang Night Trader": "복양 야상", "Dingtao Field Sutler": "정도 야상", "Escort Road Sutler": "호송 야상", "Wan Castle Sutler": "완성 야상", + "Xiapi Flood-Gate Sutler": "하비 수문 야상", "Imperial Envoy": "천자 사자", "Imperial Guard": "천자 금위", "Wan Scout": "완성 척후", @@ -142,6 +144,7 @@ const SPEAKER_CANONICAL_NAMES := { "장수": "Zhang Xiu", "가후": "Jia Xu", "조앙": "Cao Ang", + "진궁": "Chen Gong", "고순": "Gao Shun", "여포": "Lu Bu", "천자 금위": "Imperial Guard", diff --git a/tools/smoke_camp_conversation_rewards.gd b/tools/smoke_camp_conversation_rewards.gd index 3a95685..5ef96c6 100644 --- a/tools/smoke_camp_conversation_rewards.gd +++ b/tools/smoke_camp_conversation_rewards.gd @@ -664,7 +664,7 @@ func _check_xiapi_branch_camp_conversations(failures: Array[String]) -> void: if not base_scene._camp_conversation_by_id(XIAPI_SWIFT_CONVERSATION_ID).is_empty(): failures.append("Xiapi forced march rations should be hidden without swift Wan escape flag") var merchant: Dictionary = base_scene.state.get_shop_merchant() - if str(merchant.get("name", "")) != "Xiapi Flood-Gate Sutler": + if str(merchant.get("name", "")) != "하비 수문 야상": failures.append("Xiapi shop merchant name should be present") var merchant_lines: Array = merchant.get("lines", []) if merchant_lines.size() < 2: diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index a4381cf..f0dc0cc 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -454,7 +454,7 @@ func _check_battle_visual_data(failures: Array[String]) -> void: _check_camp_conversation(failures, xiapi_conversations[0], "xiapi_floodgate_council", "officer", "cao_cao") _check_camp_conversation(failures, xiapi_conversations[1], "xiapi_dian_wei_siege_road", "officer", "dian_wei") var xiapi_merchant := xiapi_state.get_shop_merchant() - if str(xiapi_merchant.get("name", "")) != "Xiapi Flood-Gate Sutler": + if str(xiapi_merchant.get("name", "")) != "하비 수문 야상": failures.append("009 shop should expose Xiapi merchant name") if (xiapi_merchant.get("lines", []) as Array).size() < 2: failures.append("009 shop should expose merchant flavor lines")