diff --git a/art/backgrounds/white_horse_relief.png b/art/backgrounds/white_horse_relief.png new file mode 100644 index 0000000..df8c60d Binary files /dev/null and b/art/backgrounds/white_horse_relief.png differ diff --git a/data/campaign/campaign.json b/data/campaign/campaign.json index e9ba5bc..acc8ea2 100644 --- a/data/campaign/campaign.json +++ b/data/campaign/campaign.json @@ -101,7 +101,7 @@ }, { "id": "010_white_horse_relief", - "title": "White Horse Relief", + "title": "백마 구원전", "path": "res://data/scenarios/010_white_horse_relief.json" }, { diff --git a/data/scenarios/010_white_horse_relief.json b/data/scenarios/010_white_horse_relief.json index 22292c9..a73f008 100644 --- a/data/scenarios/010_white_horse_relief.json +++ b/data/scenarios/010_white_horse_relief.json @@ -1,9 +1,9 @@ { "id": "010_white_horse_relief", - "name": "White Horse Relief", + "name": "백마 구원전", "objectives": { - "victory": "Defeat Yan Liang's vanguard after the decoy line is sprung.", - "defeat": "Cao Cao is defeated or the battle reaches Turn 12." + "victory": "유인 진형이 펼쳐진 뒤 안량 선봉을 격파하라.", + "defeat": "조조가 퇴각하거나 제12군령에 이르면 패한다." }, "conditions": { "victory": { "type": "all_units_defeated", "team": "enemy", "after_event": "turn_3_decoy_line" }, @@ -13,23 +13,23 @@ ] }, "briefing": { - "title": "White Horse Relief", - "location": "White Horse, 200 CE", + "title": "백마 구원전", + "location": "백마, 건안 오년", "lines": [ - "Yuan Shao's forward army presses toward White Horse with Yan Liang at its point.", - "Guo Jia proposes a decoy line: draw the vanguard down the road, then strike once its wings stretch too far." + "원소의 전군이 안량을 앞세워 백마 나루를 짓누르고 있다.", + "곽가는 거짓 퇴각을 청하였다. 선봉을 길 한복판으로 끌어낸 뒤 양익이 길게 벌어진 틈을 칠 계책이다." ], "conditional_lines": [ { "campaign_flags": { "integrated_xu_province": true }, "lines": [ - "Officials left in Xu Province keep the rear quiet, letting Cao Cao commit steadier reserves to the northern front." + "서주에 남긴 관리들이 후방을 안정시켜, 북방 전선으로 보낼 예비 군량이 흔들리지 않는다." ] }, { "campaign_flags": { "pressed_northern_campaign": true }, "lines": [ - "The army marches quickly from Xiapi, hoping speed can strike Yuan Shao's vanguard before it settles." + "하비에서 곧장 북상한 군세가 원소의 선봉이 자리를 굳히기 전에 칼끝을 들이댄다." ] } ], @@ -38,19 +38,19 @@ "id": "white_horse_decoy_council", "group": "officer", "officer_id": "guo_jia", - "label": "Guo Jia - Decoy Line", + "label": "곽가 - 유인 진형", "speaker": "Guo Jia", - "summary": "Set the false retreat that will pull Yan Liang away from his supports.", + "summary": "안량을 엄호대에서 떼어낼 거짓 퇴각의 박자를 정한다.", "lines": [ { "speaker": "Guo Jia", "side": "right", - "text": "Yan Liang will read a bending line as weakness. Let him see exactly enough of what he wants." + "text": "안량은 휘어지는 전열을 약함으로 읽을 것입니다. 그가 보고 싶은 만큼만 보여 주면 됩니다." }, { "speaker": "Cao Cao", "side": "left", - "text": "A trap that looks too clever warns the prey. This one must look like fear." + "text": "너무 교묘한 덫은 먹잇감에게 먼저 알려진다. 이번 덫은 두려움처럼 보여야 한다." } ] }, @@ -58,19 +58,19 @@ "id": "white_horse_xiahou_dun_false_retreat", "group": "officer", "officer_id": "xiahou_dun", - "label": "Xiahou Dun - False Retreat", + "label": "하후돈 - 거짓 퇴각", "speaker": "Xiahou Dun", - "summary": "Prepare the center line to yield without breaking.", + "summary": "중군이 무너지지 않고 물러서는 법을 다잡는다.", "lines": [ { "speaker": "Xiahou Dun", "side": "left", - "text": "Men can pretend to retreat, but their backs still know the feeling. I will keep the center from turning real." + "text": "거짓으로 물러난다 해도 병사의 등은 그 맛을 압니다. 제가 중군의 물러섬이 참패가 되지 않게 붙들겠습니다." }, { "speaker": "Guo Jia", "side": "right", - "text": "Good. Bend the line by measure, not panic. Yan Liang must think he chose the road himself." + "text": "좋습니다. 공포가 아니라 자로 잰 만큼만 휘게 하십시오. 안량은 스스로 그 길을 골랐다고 믿어야 합니다." } ] }, @@ -78,18 +78,18 @@ "id": "white_horse_xu_reserve_medicine", "campaign_flags": { "integrated_xu_province": true }, "group": "topic", - "label": "Xu Reserve Medicine", - "summary": "Draw field medicine from the quiet rear roads secured after Xiapi.", + "label": "서주 예비 약상", + "summary": "하비 뒤 안정된 후방로에서 전장 약재를 끌어온다.", "lines": [ { "speaker": "Cao Ren", "side": "left", - "text": "Xu Province is quiet behind us. The reserve carts arrived with dry medicine and no arrows in the canvas." + "text": "서주는 뒤에서 조용합니다. 예비 수레가 젖지 않은 약재를 싣고, 천막에 화살 하나 맞지 않은 채 도착했습니다." }, { "speaker": "Cao Cao", "side": "right", - "text": "Then send it to the men who must look beaten without becoming so." + "text": "그렇다면 패한 척하되 패해서는 안 될 자들에게 먼저 보내라." } ], "effects": [ @@ -97,7 +97,7 @@ "type": "grant_item", "item_id": "panacea", "count": 1, - "text": "The Xu reserve medicine adds a Panacea to the field supplies." + "text": "서주 예비 약상에서 만능약 한 꾸러미를 군수에 보탰다." } ] }, @@ -105,18 +105,18 @@ "id": "white_horse_fast_march_beans", "campaign_flags": { "pressed_northern_campaign": true }, "group": "topic", - "label": "Fast March Beans", - "summary": "Issue portable food to troops who reached White Horse ahead of the heavy carts.", + "label": "급행군 콩자루", + "summary": "큰 수레보다 먼저 백마에 닿은 병사들에게 휴대 군량을 나눈다.", "lines": [ { "speaker": "Xiahou Yuan", "side": "right", - "text": "The army came north fast from Xiapi. The riders are fresh enough, but the footmen ate while walking." + "text": "하비에서 북상한 길이 빨랐습니다. 기병은 아직 숨이 남았으나, 보병은 걸으며 먹었습니다." }, { "speaker": "Guo Jia", "side": "left", - "text": "Give the center beans before it yields. A false retreat is easier on a full breath." + "text": "중군이 물러서기 전에 콩을 나누십시오. 배 속이 비지 않아야 거짓 퇴각도 흐트러지지 않습니다." } ], "effects": [ @@ -124,7 +124,7 @@ "type": "grant_item", "item_id": "bean", "count": 1, - "text": "The fast march beans add a Bean to the field supplies." + "text": "급행군 콩자루에서 콩 한 꾸러미를 군수에 보탰다." } ] } @@ -153,10 +153,10 @@ } ], "merchant": { - "name": "White Horse Road Sutler", + "name": "백마 야상", "lines": [ - "Buy before the banners start pretending to run. Once the decoy begins, every cart follows its assigned fear.", - "Beans for the center line, medicine for mistakes, and no heavy baggage where Yan Liang can see it." + "깃발이 달아나는 척하기 전에 사 두십시오. 유인책이 시작되면 수레마다 맡은 두려움이 따로 있습니다.", + "중군에는 콩을, 실수에는 약을. 안량의 눈에 띌 무거운 짐은 뒤에 묻어 두었습니다." ] } }, @@ -168,6 +168,7 @@ "cells": [[1, 3], [1, 4], [1, 5], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [3, 3], [3, 4]] }, "map": { + "background": "res://art/backgrounds/white_horse_relief.png", "width": 15, "height": 10, "terrain": [ @@ -226,7 +227,7 @@ }, { "unit_id": "yan_liang_vanguard", - "name": "Yan Liang Vanguard", + "name": "안량 선봉", "class_id": "elite_cavalry", "team": "enemy", "level": 10, @@ -235,7 +236,7 @@ }, { "unit_id": "yuan_shao_spear_line", - "name": "Yuan Spear Line", + "name": "원소 창병대", "class_id": "infantry", "team": "enemy", "level": 9, @@ -244,7 +245,7 @@ }, { "unit_id": "yuan_shao_guard", - "name": "Yuan Guard", + "name": "원소 수비대", "class_id": "infantry", "team": "enemy", "level": 9, @@ -253,7 +254,7 @@ }, { "unit_id": "white_horse_archer_north", - "name": "White Horse Archer", + "name": "백마 궁병", "class_id": "archer", "team": "enemy", "level": 9, @@ -262,7 +263,7 @@ }, { "unit_id": "white_horse_archer_south", - "name": "White Horse Archer", + "name": "백마 궁병", "class_id": "archer", "team": "enemy", "level": 9, @@ -271,7 +272,7 @@ }, { "unit_id": "yuan_shao_advisor", - "name": "Yuan Advisor", + "name": "원소 책사", "class_id": "strategist", "team": "enemy", "level": 9, @@ -286,7 +287,7 @@ "once": true, "when": { "type": "battle_start" }, "actions": [ - { "type": "log", "text": "Yuan Shao's vanguard advances toward White Horse." } + { "type": "log", "text": "원소의 선봉이 백마 나루로 밀고 들어온다." } ] }, { @@ -297,9 +298,9 @@ { "type": "dialogue", "lines": [ - { "speaker": "Guo Jia", "text": "Yan Liang is brave enough to follow a retreating banner. That is the door we open." }, - { "speaker": "Cao Cao", "text": "Then the center yields just enough. When his wings stretch, we cut them." }, - { "speaker": "Xiahou Dun", "text": "A false retreat still needs men willing to look beaten." } + { "speaker": "Guo Jia", "text": "안량은 물러나는 깃발을 따라올 만큼 용맹합니다. 그 문을 우리가 열어 주는 것입니다." }, + { "speaker": "Cao Cao", "text": "그렇다면 중군은 딱 필요한 만큼만 물러난다. 그의 양익이 벌어지면 그때 베어 낸다." }, + { "speaker": "Xiahou Dun", "text": "거짓 퇴각이라 해도 패한 얼굴을 할 병사가 필요합니다." } ] } ] @@ -312,8 +313,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Yan Liang", "text": "Cao Cao's line bends already. Drive straight down the road!" }, - { "speaker": "Guo Jia", "text": "He takes the bait. Hold until the second signal." } + { "speaker": "Yan Liang", "text": "조조의 전열이 벌써 휘어진다. 길 한복판으로 그대로 밀어붙여라!" }, + { "speaker": "Guo Jia", "text": "미끼를 물었습니다. 두 번째 신호가 오기까지 붙드십시오." } ] }, { @@ -321,7 +322,7 @@ "deployments": [ { "unit_id": "yan_liang_rider_north", - "name": "Yan Liang Rider", + "name": "안량 기병", "class_id": "cavalry", "team": "enemy", "level": 9, @@ -330,7 +331,7 @@ }, { "unit_id": "yan_liang_rider_south", - "name": "Yan Liang Rider", + "name": "안량 기병", "class_id": "cavalry", "team": "enemy", "level": 9, @@ -349,21 +350,21 @@ { "type": "dialogue", "lines": [ - { "speaker": "Cao Cao", "text": "Signal the counterstroke. Yan Liang has outrun his supports." }, - { "speaker": "Guo Jia", "text": "The vanguard is isolated. Strike the horse first, then the spears." } + { "speaker": "Cao Cao", "text": "반격 신호를 올려라. 안량이 엄호보다 앞서 달렸다." }, + { "speaker": "Guo Jia", "text": "선봉이 고립되었습니다. 먼저 말을 치고, 그다음 창진을 꺾으십시오." } ] }, { "type": "set_objective", - "victory": "Defeat Yan Liang and every isolated vanguard unit.", - "defeat": "Cao Cao is defeated or the battle reaches Turn 12." + "victory": "안량과 고립된 선봉 전부를 격파하라.", + "defeat": "조조가 퇴각하거나 제12군령에 이르면 패한다." }, { "type": "spawn_deployments", "deployments": [ { "unit_id": "decoy_cutoff_guard", - "name": "Cutoff Guard", + "name": "차단 보병", "class_id": "infantry", "team": "enemy", "level": 9, @@ -372,7 +373,7 @@ }, { "unit_id": "decoy_cutoff_archer", - "name": "Cutoff Archer", + "name": "차단 궁병", "class_id": "archer", "team": "enemy", "level": 9, @@ -391,8 +392,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Guo Jia", "text": "Yan Liang's banner is down. His riders will feel that before Yuan Shao can answer." }, - { "speaker": "Cao Cao", "text": "Press the isolated vanguard and make White Horse breathe again." } + { "speaker": "Guo Jia", "text": "안량의 깃발이 내려갔습니다. 원소가 답하기 전에 그의 기병들이 먼저 흔들릴 것입니다." }, + { "speaker": "Cao Cao", "text": "고립된 선봉을 밀어붙여 백마가 다시 숨 쉬게 하라." } ] } ] @@ -405,8 +406,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Cao Ren", "text": "Xu Province's roads are quiet. The reserve wagons have arrived on time." }, - { "speaker": "Cao Cao", "text": "Order and grain win battles before blades touch." } + { "speaker": "Cao Ren", "text": "서주의 길은 조용합니다. 예비 수레가 때맞춰 들어왔습니다." }, + { "speaker": "Cao Cao", "text": "질서와 군량은 칼이 닿기 전에 이미 승패를 가른다." } ] } ] @@ -419,15 +420,15 @@ { "type": "dialogue", "lines": [ - { "speaker": "Yuan Scout", "text": "Cao Cao came quickly. Send the rear riders before his men settle!" }, - { "speaker": "Xiahou Yuan", "text": "More riders from the east. They are trying to punish our speed." } + { "speaker": "Yuan Scout", "text": "조조가 너무 빨리 왔다. 저들이 진을 굳히기 전에 후방 기병을 보내라!" }, + { "speaker": "Xiahou Yuan", "text": "동쪽에서 기병이 더 옵니다. 우리의 빠른 행군을 벌하려는 셈입니다." } ] }, { "type": "spawn_deployment", "deployment": { "unit_id": "yuan_rear_rider", - "name": "Yuan Rear Rider", + "name": "원소 후방 기병", "class_id": "cavalry", "team": "enemy", "level": 9, @@ -445,8 +446,8 @@ { "type": "dialogue", "lines": [ - { "speaker": "Guo Jia", "text": "Yan Liang's formation is no longer an army. It is a collection of frightened men." }, - { "speaker": "Cao Cao", "text": "Then finish this cleanly. White Horse must not remain under threat." } + { "speaker": "Guo Jia", "text": "안량의 진형은 더는 군대가 아닙니다. 놀란 병사들이 흩어진 모양일 뿐입니다." }, + { "speaker": "Cao Cao", "text": "그렇다면 깨끗이 끝내라. 백마를 위협 아래 남겨 둘 수 없다." } ] } ] @@ -457,23 +458,23 @@ "items": ["bean", "wine", "iron_armor"] }, "post_battle_dialogue": [ - { "speaker": "Xiahou Dun", "text": "Yan Liang's charge broke exactly where Guo Jia said it would." }, - { "speaker": "Guo Jia", "text": "Bravery is useful. Predictable bravery is a road sign." }, - { "speaker": "Cao Cao", "text": "White Horse is relieved. Now Yuan Shao must answer us with more than numbers." } + { "speaker": "Xiahou Dun", "text": "안량의 돌격은 곽가가 말한 바로 그 자리에서 꺾였습니다." }, + { "speaker": "Guo Jia", "text": "용맹은 쓸모가 있습니다. 다만 읽히는 용맹은 길 표식과 다르지 않습니다." }, + { "speaker": "Cao Cao", "text": "백마는 풀렸다. 이제 원소는 숫자만으로 답할 수 없을 것이다." } ], "post_battle_choices": [ { "id": "fortify_white_horse", - "label": "Fortify White Horse", - "description": "Cao Cao strengthens the crossing before the main Guandu confrontation.", + "label": "백마 요새화", + "description": "조조가 관도 대전에 앞서 백마 나루의 방비를 굳힌다.", "set_flags": { "fortified_white_horse": true, "raided_yuan_supplies": false }, "gold": 150, "items": ["iron_armor"] }, { "id": "raid_yuan_supplies", - "label": "Raid Supplies", - "description": "The army uses the vanguard's collapse to harass Yuan Shao's supply train.", + "label": "원소 군량 기습", + "description": "무너진 선봉의 빈틈을 타 원소의 보급 수레를 괴롭힌다.", "set_flags": { "fortified_white_horse": false, "raided_yuan_supplies": true }, "gold": 100, "items": ["wine", "training_spear"] diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index ac48e2e..8d98e41 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -119,14 +119,17 @@ const SPEAKER_DISPLAY_NAMES := { "Chen Gong": "진궁", "Gao Shun": "고순", "Lu Bu": "여포", + "Yan Liang": "안량", "Puyang Night Trader": "복양 야상", "Dingtao Field Sutler": "정도 야상", "Escort Road Sutler": "호송 야상", "Wan Castle Sutler": "완성 야상", "Xiapi Flood-Gate Sutler": "하비 수문 야상", + "White Horse Road Sutler": "백마 야상", "Imperial Envoy": "천자 사자", "Imperial Guard": "천자 금위", "Wan Scout": "완성 척후", + "Yuan Scout": "원소 척후", "Coalition Merchant": "군막 상인", "Coalition Quartermaster": "연합 군수관", "Camp Merchant": "군막 상인", @@ -147,6 +150,8 @@ const SPEAKER_CANONICAL_NAMES := { "진궁": "Chen Gong", "고순": "Gao Shun", "여포": "Lu Bu", + "안량": "Yan Liang", + "원소 척후": "Yuan Scout", "천자 금위": "Imperial Guard", "완성 척후": "Wan Scout" } diff --git a/tools/smoke_camp_conversation_rewards.gd b/tools/smoke_camp_conversation_rewards.gd index 5ef96c6..9e8032e 100644 --- a/tools/smoke_camp_conversation_rewards.gd +++ b/tools/smoke_camp_conversation_rewards.gd @@ -746,7 +746,7 @@ func _check_white_horse_branch_camp_conversations(failures: Array[String]) -> vo if not base_scene._camp_conversation_by_id(WHITE_HORSE_PRESSED_CONVERSATION_ID).is_empty(): failures.append("White Horse fast march beans should be hidden without pressed north flag") var merchant: Dictionary = base_scene.state.get_shop_merchant() - if str(merchant.get("name", "")) != "White Horse Road Sutler": + if str(merchant.get("name", "")) != "백마 야상": failures.append("White Horse 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 553407a..930efa4 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -50,6 +50,11 @@ const SCENARIO_BACKGROUNDS := [ "background_path": "res://art/backgrounds/xiapi_flooded_siege.png", "label": "009 Xiapi flooded siege background" }, + { + "scenario_path": "res://data/scenarios/010_white_horse_relief.json", + "background_path": "res://art/backgrounds/white_horse_relief.png", + "label": "010 White Horse relief background" + }, { "scenario_path": "res://data/scenarios/012_guandu_showdown.json", "background_path": "res://art/backgrounds/guandu_defensive_camps.png", @@ -512,7 +517,7 @@ func _check_battle_visual_data(failures: Array[String]) -> void: _check_camp_conversation(failures, white_horse_conversations[0], "white_horse_decoy_council", "officer", "guo_jia") _check_camp_conversation(failures, white_horse_conversations[1], "white_horse_xiahou_dun_false_retreat", "officer", "xiahou_dun") var white_horse_merchant := white_horse_state.get_shop_merchant() - if str(white_horse_merchant.get("name", "")) != "White Horse Road Sutler": + if str(white_horse_merchant.get("name", "")) != "백마 야상": failures.append("010 shop should expose White Horse merchant name") if (white_horse_merchant.get("lines", []) as Array).size() < 2: failures.append("010 shop should expose merchant flavor lines")