Add fourth Meng Huo capture battle
This commit is contained in:
@@ -75,15 +75,16 @@ Build a small complete tactical RPG loop that can grow into a longer Romance of
|
||||
- Forty-eighth battle Meng Huo main-force route, where Zhuge Liang leads a seven-officer pacification sortie across a 96x78 southern mountain battlefield, captures Meng Huo through a dedicated pacify-leader objective, and opens post-battle release, captive-ledger, and market-reassurance camp events
|
||||
- Forty-ninth battle Meng Huo second-capture route, turning the first release into a repeated Seven Captures arc with a 98x80 marsh-jungle battlefield, renewed pacify-leader objective, second-release camp dialogues, and village/captive reassurance visits
|
||||
- Fiftieth battle Meng Huo third-capture route, making the growing recruited roster matter through a Zhuge Liang-led seven-officer sortie choice, a 100x82 clan-and-marsh battlefield, named southern clan officers, and post-battle clan-persuasion camp events
|
||||
- Fifty-first battle Meng Huo fourth-capture route, where prior clan-persuasion camp choices become battlefield goals through an amnesty-route objective, fire-fort suppression, a 102x84 poison-river battlefield, and Ma Chao/Ma Dai pursuit-control sortie recommendations
|
||||
- Camp progress timeline tab that summarizes Liu Bei's long campaign arc, completed battles, current chapter, latest battle, and next major chapter
|
||||
- Tactical sortie preparation panel with battle-specific sortie limits, recommended officers with reasons, class role, named equipment, core stats, bond partner, next-map terrain suitability, focused officer analysis, deployment preview, formation roles, active bond count, recruited-officer count, reserve roster summary, and readiness advice for each deployable officer
|
||||
- Officer collection support in camp, including full roster status, selected/reserve/recommended markers, selectable reserve drill focus, and post-battle reserve training growth for benched officers
|
||||
- Treasure equipment effects wired into battle previews and resolution, including named weapon damage bonuses, defensive treasure mitigation, support recovery bonuses, turn-start charm recovery, and equipment-specific growth bonuses
|
||||
- Flow verification script from title through the third Meng Huo capture camp, King of Hanzhong council milestone, Shu-Han foundation milestone, recruit sortie selection, Liu Biao visit rewards, Zhuge Liang recruitment, Bowang/Changban/Jiangdong/Red Cliffs/Jing Province/Guiyang/Wuling/Changsha/Yi Province/Fu Pass/Luo Castle/Luofeng/Luo main gate/Mianzhu/Chengdu/Jiameng/Yangping/Dingjun/Hanzhong/Jing defense/Fan Castle/Han River/Fan siege/Jing rear/Gongan collapse/Maicheng isolation/Yiling vanguard/Yiling fire/Baidi entrustment/Nanzhong stabilization/Meng Huo pacification camp states, campaign timeline state, and camp save state
|
||||
- Flow verification script from title through the fourth Meng Huo capture camp, King of Hanzhong council milestone, Shu-Han foundation milestone, recruit sortie selection, Liu Biao visit rewards, Zhuge Liang recruitment, Bowang/Changban/Jiangdong/Red Cliffs/Jing Province/Guiyang/Wuling/Changsha/Yi Province/Fu Pass/Luo Castle/Luofeng/Luo main gate/Mianzhu/Chengdu/Jiameng/Yangping/Dingjun/Hanzhong/Jing defense/Fan Castle/Han River/Fan siege/Jing rear/Gongan collapse/Maicheng isolation/Yiling vanguard/Yiling fire/Baidi entrustment/Nanzhong stabilization/Meng Huo pacification camp states, campaign timeline state, and camp save state
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Build the fourth Seven Captures Nanman battle so the previous clan persuasion choices begin changing objectives, enemy morale, and recommended sortie officers
|
||||
1. Build the fifth Seven Captures Nanman battle so hardline clan separation and repeated amnesty routes begin changing enemy morale, optional objectives, and post-battle persuasion outcomes
|
||||
2. Expand post-Baidi and post-Nanzhong camp consequences with grief checks, recovery policy choices, village reassurance, captive handling, and regency decisions that affect sortie recommendations
|
||||
3. Expand reserve planning into individual officer assignments, including targeted class practice, paired bond training, and camp task slots
|
||||
4. Add a dedicated treasure/equipment management view so players can compare special effects and growth
|
||||
|
||||
@@ -1739,7 +1739,7 @@ try {
|
||||
if (
|
||||
progressTabState?.activeTab !== 'progress' ||
|
||||
progressTabState.campaignProgress?.completedKnown !== 17 ||
|
||||
progressTabState.campaignProgress?.totalKnown !== 50 ||
|
||||
progressTabState.campaignProgress?.totalKnown !== 51 ||
|
||||
progressTabState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
|
||||
progressTabState.campaignProgress?.latestBattleTitle !== '융중 방문로' ||
|
||||
progressTabState.campaignProgress?.nextBattleTitle !== '박망파 매복전'
|
||||
@@ -1891,7 +1891,7 @@ try {
|
||||
if (
|
||||
postBowangProgressState?.activeTab !== 'progress' ||
|
||||
postBowangProgressState.campaignProgress?.completedKnown !== 18 ||
|
||||
postBowangProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postBowangProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postBowangProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
|
||||
postBowangProgressState.campaignProgress?.latestBattleTitle !== '박망파 매복전' ||
|
||||
postBowangProgressState.campaignProgress?.nextBattleTitle !== '장판파 피난로'
|
||||
@@ -2029,7 +2029,7 @@ try {
|
||||
if (
|
||||
postChangbanProgressState?.activeTab !== 'progress' ||
|
||||
postChangbanProgressState.campaignProgress?.completedKnown !== 19 ||
|
||||
postChangbanProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postChangbanProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postChangbanProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
|
||||
postChangbanProgressState.campaignProgress?.latestBattleTitle !== '장판파 피난로' ||
|
||||
postChangbanProgressState.campaignProgress?.nextBattleTitle !== '강동 사절로'
|
||||
@@ -2167,7 +2167,7 @@ try {
|
||||
if (
|
||||
postJiangdongProgressState?.activeTab !== 'progress' ||
|
||||
postJiangdongProgressState.campaignProgress?.completedKnown !== 20 ||
|
||||
postJiangdongProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postJiangdongProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postJiangdongProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
|
||||
postJiangdongProgressState.campaignProgress?.latestBattleTitle !== '강동 사절로' ||
|
||||
postJiangdongProgressState.campaignProgress?.nextBattleTitle !== '적벽 전초전'
|
||||
@@ -2307,7 +2307,7 @@ try {
|
||||
if (
|
||||
postRedCliffsProgressState?.activeTab !== 'progress' ||
|
||||
postRedCliffsProgressState.campaignProgress?.completedKnown !== 21 ||
|
||||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postRedCliffsProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postRedCliffsProgressState.campaignProgress?.activeChapter?.title !== '적벽대전' ||
|
||||
postRedCliffsProgressState.campaignProgress?.latestBattleTitle !== '적벽 전초전' ||
|
||||
postRedCliffsProgressState.campaignProgress?.nextBattleTitle !== '적벽 화공전'
|
||||
@@ -2447,7 +2447,7 @@ try {
|
||||
if (
|
||||
postFireAttackProgressState?.activeTab !== 'progress' ||
|
||||
postFireAttackProgressState.campaignProgress?.completedKnown !== 22 ||
|
||||
postFireAttackProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postFireAttackProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFireAttackProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postFireAttackProgressState.campaignProgress?.latestBattleTitle !== '적벽 화공전' ||
|
||||
postFireAttackProgressState.campaignProgress?.nextBattleTitle !== '형주 남부 진입전'
|
||||
@@ -2590,7 +2590,7 @@ try {
|
||||
if (
|
||||
postJingzhouProgressState?.activeTab !== 'progress' ||
|
||||
postJingzhouProgressState.campaignProgress?.completedKnown !== 23 ||
|
||||
postJingzhouProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postJingzhouProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postJingzhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postJingzhouProgressState.campaignProgress?.latestBattleTitle !== '형주 남부 진입전' ||
|
||||
postJingzhouProgressState.campaignProgress?.nextBattleTitle !== '계양 설득전'
|
||||
@@ -2732,7 +2732,7 @@ try {
|
||||
if (
|
||||
postGuiyangProgressState?.activeTab !== 'progress' ||
|
||||
postGuiyangProgressState.campaignProgress?.completedKnown !== 24 ||
|
||||
postGuiyangProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postGuiyangProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postGuiyangProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postGuiyangProgressState.campaignProgress?.latestBattleTitle !== '계양 설득전' ||
|
||||
postGuiyangProgressState.campaignProgress?.nextBattleTitle !== '무릉 산길 확보전'
|
||||
@@ -2875,7 +2875,7 @@ try {
|
||||
if (
|
||||
postWulingProgressState?.activeTab !== 'progress' ||
|
||||
postWulingProgressState.campaignProgress?.completedKnown !== 25 ||
|
||||
postWulingProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postWulingProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postWulingProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postWulingProgressState.campaignProgress?.latestBattleTitle !== '무릉 산길 확보전' ||
|
||||
postWulingProgressState.campaignProgress?.nextBattleTitle !== '장사 노장 대면전'
|
||||
@@ -3024,7 +3024,7 @@ try {
|
||||
if (
|
||||
postChangshaProgressState?.activeTab !== 'progress' ||
|
||||
postChangshaProgressState.campaignProgress?.completedKnown !== 26 ||
|
||||
postChangshaProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postChangshaProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postChangshaProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postChangshaProgressState.campaignProgress?.latestBattleTitle !== '장사 노장 대면전' ||
|
||||
postChangshaProgressState.campaignProgress?.nextBattleTitle !== '익주 원군로'
|
||||
@@ -3169,7 +3169,7 @@ try {
|
||||
if (
|
||||
postYizhouProgressState?.activeTab !== 'progress' ||
|
||||
postYizhouProgressState.campaignProgress?.completedKnown !== 27 ||
|
||||
postYizhouProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postYizhouProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postYizhouProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postYizhouProgressState.campaignProgress?.latestBattleTitle !== '익주 원군로' ||
|
||||
postYizhouProgressState.campaignProgress?.nextBattleTitle !== '부수관 진입전'
|
||||
@@ -3316,7 +3316,7 @@ try {
|
||||
if (
|
||||
postFuPassProgressState?.activeTab !== 'progress' ||
|
||||
postFuPassProgressState.campaignProgress?.completedKnown !== 28 ||
|
||||
postFuPassProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postFuPassProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFuPassProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postFuPassProgressState.campaignProgress?.latestBattleTitle !== '부수관 진입전' ||
|
||||
postFuPassProgressState.campaignProgress?.nextBattleTitle !== '낙성 외곽전'
|
||||
@@ -3465,7 +3465,7 @@ try {
|
||||
if (
|
||||
postLuoProgressState?.activeTab !== 'progress' ||
|
||||
postLuoProgressState.campaignProgress?.completedKnown !== 29 ||
|
||||
postLuoProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postLuoProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postLuoProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postLuoProgressState.campaignProgress?.latestBattleTitle !== '낙성 외곽전' ||
|
||||
postLuoProgressState.campaignProgress?.nextBattleTitle !== '낙봉파 매복전'
|
||||
@@ -3611,7 +3611,7 @@ try {
|
||||
if (
|
||||
postLuofengProgressState?.activeTab !== 'progress' ||
|
||||
postLuofengProgressState.campaignProgress?.completedKnown !== 30 ||
|
||||
postLuofengProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postLuofengProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postLuofengProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postLuofengProgressState.campaignProgress?.latestBattleTitle !== '낙봉파 매복전' ||
|
||||
postLuofengProgressState.campaignProgress?.nextBattleTitle !== '낙성 본성 공략'
|
||||
@@ -3763,7 +3763,7 @@ try {
|
||||
if (
|
||||
postLuoMainProgressState?.activeTab !== 'progress' ||
|
||||
postLuoMainProgressState.campaignProgress?.completedKnown !== 31 ||
|
||||
postLuoMainProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postLuoMainProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postLuoMainProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postLuoMainProgressState.campaignProgress?.latestBattleTitle !== '낙성 본성 공략' ||
|
||||
postLuoMainProgressState.campaignProgress?.nextBattleTitle !== '면죽관 압박전'
|
||||
@@ -3916,7 +3916,7 @@ try {
|
||||
if (
|
||||
postMianzhuProgressState?.activeTab !== 'progress' ||
|
||||
postMianzhuProgressState.campaignProgress?.completedKnown !== 32 ||
|
||||
postMianzhuProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postMianzhuProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postMianzhuProgressState.campaignProgress?.activeChapter?.title !== '형주·익주 확보' ||
|
||||
postMianzhuProgressState.campaignProgress?.latestBattleTitle !== '면죽관 압박전' ||
|
||||
postMianzhuProgressState.campaignProgress?.nextBattleTitle !== '성도 항복 권고전'
|
||||
@@ -4070,7 +4070,7 @@ try {
|
||||
if (
|
||||
postChengduProgressState?.activeTab !== 'progress' ||
|
||||
postChengduProgressState.campaignProgress?.completedKnown !== 33 ||
|
||||
postChengduProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postChengduProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postChengduProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
|
||||
postChengduProgressState.campaignProgress?.latestBattleTitle !== '성도 항복 권고전' ||
|
||||
postChengduProgressState.campaignProgress?.nextBattleTitle !== '가맹관 마초 대면전'
|
||||
@@ -4225,7 +4225,7 @@ try {
|
||||
if (
|
||||
postJiamengProgressState?.activeTab !== 'progress' ||
|
||||
postJiamengProgressState.campaignProgress?.completedKnown !== 34 ||
|
||||
postJiamengProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postJiamengProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postJiamengProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
|
||||
postJiamengProgressState.campaignProgress?.latestBattleTitle !== '가맹관 마초 대면전' ||
|
||||
postJiamengProgressState.campaignProgress?.nextBattleTitle !== '양평관 정찰전'
|
||||
@@ -4381,7 +4381,7 @@ try {
|
||||
if (
|
||||
postYangpingProgressState?.activeTab !== 'progress' ||
|
||||
postYangpingProgressState.campaignProgress?.completedKnown !== 35 ||
|
||||
postYangpingProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postYangpingProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postYangpingProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
|
||||
postYangpingProgressState.campaignProgress?.latestBattleTitle !== '양평관 정찰전' ||
|
||||
postYangpingProgressState.campaignProgress?.nextBattleTitle !== '정군산 전초전'
|
||||
@@ -4538,7 +4538,7 @@ try {
|
||||
if (
|
||||
postDingjunProgressState?.activeTab !== 'progress' ||
|
||||
postDingjunProgressState.campaignProgress?.completedKnown !== 36 ||
|
||||
postDingjunProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postDingjunProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postDingjunProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
|
||||
postDingjunProgressState.campaignProgress?.latestBattleTitle !== '정군산 전초전' ||
|
||||
postDingjunProgressState.campaignProgress?.nextBattleTitle !== '한중 결전'
|
||||
@@ -4691,7 +4691,7 @@ try {
|
||||
if (
|
||||
postHanzhongProgressState?.activeTab !== 'progress' ||
|
||||
postHanzhongProgressState.campaignProgress?.completedKnown !== 37 ||
|
||||
postHanzhongProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postHanzhongProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postHanzhongProgressState.campaignProgress?.activeChapter?.title !== '촉한 건국' ||
|
||||
postHanzhongProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
|
||||
postHanzhongProgressState.campaignProgress?.nextBattleTitle !== '한중왕 즉위 준비'
|
||||
@@ -4752,7 +4752,7 @@ try {
|
||||
if (
|
||||
postKingCouncilProgressState?.activeTab !== 'progress' ||
|
||||
postKingCouncilProgressState.campaignProgress?.completedKnown !== 37 ||
|
||||
postKingCouncilProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postKingCouncilProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postKingCouncilProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
|
||||
postKingCouncilProgressState.campaignProgress?.nextBattleTitle !== '촉한 건국 선포'
|
||||
) {
|
||||
@@ -4812,7 +4812,7 @@ try {
|
||||
if (
|
||||
postFoundationProgressState?.activeTab !== 'progress' ||
|
||||
postFoundationProgressState.campaignProgress?.completedKnown !== 37 ||
|
||||
postFoundationProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postFoundationProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFoundationProgressState.campaignProgress?.latestBattleTitle !== '한중 결전' ||
|
||||
postFoundationProgressState.campaignProgress?.nextBattleTitle !== '형주 방위 전초전'
|
||||
) {
|
||||
@@ -4963,7 +4963,7 @@ try {
|
||||
if (
|
||||
postJingDefenseProgressState?.activeTab !== 'progress' ||
|
||||
postJingDefenseProgressState.campaignProgress?.completedKnown !== 38 ||
|
||||
postJingDefenseProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postJingDefenseProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postJingDefenseProgressState.campaignProgress?.latestBattleTitle !== '형주 방위 전초전' ||
|
||||
postJingDefenseProgressState.campaignProgress?.nextBattleTitle !== '번성 외곽 압박전'
|
||||
) {
|
||||
@@ -5116,7 +5116,7 @@ try {
|
||||
if (
|
||||
postFanCastleProgressState?.activeTab !== 'progress' ||
|
||||
postFanCastleProgressState.campaignProgress?.completedKnown !== 39 ||
|
||||
postFanCastleProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postFanCastleProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFanCastleProgressState.campaignProgress?.latestBattleTitle !== '번성 외곽 압박전' ||
|
||||
postFanCastleProgressState.campaignProgress?.nextBattleTitle !== '한수 수공'
|
||||
) {
|
||||
@@ -5270,7 +5270,7 @@ try {
|
||||
if (
|
||||
postHanRiverProgressState?.activeTab !== 'progress' ||
|
||||
postHanRiverProgressState.campaignProgress?.completedKnown !== 40 ||
|
||||
postHanRiverProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postHanRiverProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postHanRiverProgressState.campaignProgress?.latestBattleTitle !== '한수 수공' ||
|
||||
postHanRiverProgressState.campaignProgress?.nextBattleTitle !== '번성 공성전'
|
||||
) {
|
||||
@@ -5424,7 +5424,7 @@ try {
|
||||
if (
|
||||
postFanSiegeProgressState?.activeTab !== 'progress' ||
|
||||
postFanSiegeProgressState.campaignProgress?.completedKnown !== 41 ||
|
||||
postFanSiegeProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postFanSiegeProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFanSiegeProgressState.campaignProgress?.latestBattleTitle !== '번성 공성전' ||
|
||||
postFanSiegeProgressState.campaignProgress?.nextBattleTitle !== '강릉 나루 경계전'
|
||||
) {
|
||||
@@ -5586,7 +5586,7 @@ try {
|
||||
if (
|
||||
postJingRearProgressState?.activeTab !== 'progress' ||
|
||||
postJingRearProgressState.campaignProgress?.completedKnown !== 42 ||
|
||||
postJingRearProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postJingRearProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postJingRearProgressState.campaignProgress?.latestBattleTitle !== '강릉 나루 경계전' ||
|
||||
postJingRearProgressState.campaignProgress?.nextBattleTitle !== '공안 성문 변고'
|
||||
) {
|
||||
@@ -5741,7 +5741,7 @@ try {
|
||||
if (
|
||||
postGonganProgressState?.activeTab !== 'progress' ||
|
||||
postGonganProgressState.campaignProgress?.completedKnown !== 43 ||
|
||||
postGonganProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postGonganProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postGonganProgressState.campaignProgress?.latestBattleTitle !== '공안 성문 변고' ||
|
||||
postGonganProgressState.campaignProgress?.nextBattleTitle !== '맥성 고립전'
|
||||
) {
|
||||
@@ -5899,7 +5899,7 @@ try {
|
||||
if (
|
||||
postMaichengProgressState?.activeTab !== 'progress' ||
|
||||
postMaichengProgressState.campaignProgress?.completedKnown !== 44 ||
|
||||
postMaichengProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postMaichengProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postMaichengProgressState.campaignProgress?.latestBattleTitle !== '맥성 고립전' ||
|
||||
postMaichengProgressState.campaignProgress?.nextBattleTitle !== '이릉 진격로'
|
||||
) {
|
||||
@@ -6056,7 +6056,7 @@ try {
|
||||
if (
|
||||
postYilingProgressState?.activeTab !== 'progress' ||
|
||||
postYilingProgressState.campaignProgress?.completedKnown !== 45 ||
|
||||
postYilingProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postYilingProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postYilingProgressState.campaignProgress?.latestBattleTitle !== '이릉 진격로' ||
|
||||
postYilingProgressState.campaignProgress?.nextBattleTitle !== '이릉 화공전'
|
||||
) {
|
||||
@@ -6214,7 +6214,7 @@ try {
|
||||
if (
|
||||
postYilingFireProgressState?.activeTab !== 'progress' ||
|
||||
postYilingFireProgressState.campaignProgress?.completedKnown !== 46 ||
|
||||
postYilingFireProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postYilingFireProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postYilingFireProgressState.campaignProgress?.latestBattleTitle !== '이릉 화공전' ||
|
||||
postYilingFireProgressState.campaignProgress?.nextBattleTitle !== '백제성 유탁'
|
||||
) {
|
||||
@@ -6280,7 +6280,7 @@ try {
|
||||
if (
|
||||
postBaidiProgressState?.activeTab !== 'progress' ||
|
||||
postBaidiProgressState.campaignProgress?.completedKnown !== 46 ||
|
||||
postBaidiProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postBaidiProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postBaidiProgressState.campaignProgress?.latestBattleTitle !== '이릉 화공전' ||
|
||||
postBaidiProgressState.campaignProgress?.nextBattleTitle !== '남중 안정로'
|
||||
) {
|
||||
@@ -6441,7 +6441,7 @@ try {
|
||||
if (
|
||||
postNanzhongProgressState?.activeTab !== 'progress' ||
|
||||
postNanzhongProgressState.campaignProgress?.completedKnown !== 47 ||
|
||||
postNanzhongProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postNanzhongProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postNanzhongProgressState.campaignProgress?.latestBattleTitle !== '남중 안정로' ||
|
||||
postNanzhongProgressState.campaignProgress?.nextBattleTitle !== '맹획 본대전'
|
||||
) {
|
||||
@@ -6603,7 +6603,7 @@ try {
|
||||
if (
|
||||
postMengHuoProgressState?.activeTab !== 'progress' ||
|
||||
postMengHuoProgressState.campaignProgress?.completedKnown !== 48 ||
|
||||
postMengHuoProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postMengHuoProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postMengHuoProgressState.campaignProgress?.latestBattleTitle !== '맹획 본대전' ||
|
||||
postMengHuoProgressState.campaignProgress?.nextBattleTitle !== '칠종칠금 2차전'
|
||||
) {
|
||||
@@ -6765,7 +6765,7 @@ try {
|
||||
if (
|
||||
postSecondCaptureProgressState?.activeTab !== 'progress' ||
|
||||
postSecondCaptureProgressState.campaignProgress?.completedKnown !== 49 ||
|
||||
postSecondCaptureProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postSecondCaptureProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postSecondCaptureProgressState.campaignProgress?.latestBattleTitle !== '칠종칠금 2차전' ||
|
||||
postSecondCaptureProgressState.campaignProgress?.nextBattleTitle !== '칠종칠금 3차전'
|
||||
) {
|
||||
@@ -6930,14 +6930,180 @@ try {
|
||||
if (
|
||||
postThirdCaptureProgressState?.activeTab !== 'progress' ||
|
||||
postThirdCaptureProgressState.campaignProgress?.completedKnown !== 50 ||
|
||||
postThirdCaptureProgressState.campaignProgress?.totalKnown !== 50 ||
|
||||
postThirdCaptureProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postThirdCaptureProgressState.campaignProgress?.latestBattleTitle !== '칠종칠금 3차전' ||
|
||||
postThirdCaptureProgressState.campaignProgress?.nextBattleTitle !== '준비 중'
|
||||
postThirdCaptureProgressState.campaignProgress?.nextBattleTitle !== '칠종칠금 4차전'
|
||||
) {
|
||||
throw new Error(`Expected post-third-capture progress tab to complete the fiftieth battle and pause before the fourth capture arc: ${JSON.stringify(postThirdCaptureProgressState?.campaignProgress)}`);
|
||||
throw new Error(`Expected post-third-capture progress tab to complete the fiftieth battle and point to the fourth capture arc: ${JSON.stringify(postThirdCaptureProgressState?.campaignProgress)}`);
|
||||
}
|
||||
await page.screenshot({ path: 'dist/verification-post-third-capture-progress.png', fullPage: true });
|
||||
|
||||
await page.mouse.click(1120, 38);
|
||||
await page.waitForTimeout(180);
|
||||
const fourthCaptureSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
if (
|
||||
!fourthCaptureSortieState?.sortieVisible ||
|
||||
fourthCaptureSortieState.campaign?.step !== 'fiftieth-camp' ||
|
||||
fourthCaptureSortieState.campTitle !== '칠종칠금 3차전 후 군영' ||
|
||||
fourthCaptureSortieState.sortiePlan?.objectiveLine !== '칠종칠금 4차전 · 맹획 네 번째 생포와 회유 퇴로 유지' ||
|
||||
fourthCaptureSortieState.sortiePlan?.maxCount !== 7 ||
|
||||
fourthCaptureSortieState.sortiePlan?.recommendedTotal !== 7 ||
|
||||
!fourthCaptureSortieState.sortieRoster?.some((unit) => unit.id === 'zhuge-liang' && unit.selected && unit.required) ||
|
||||
!fourthCaptureSortieState.sortieRoster?.some((unit) => unit.id === 'ma-liang' && unit.recommended) ||
|
||||
!fourthCaptureSortieState.sortieRoster?.some((unit) => unit.id === 'huang-quan' && unit.recommended) ||
|
||||
!fourthCaptureSortieState.sortieRoster?.some((unit) => unit.id === 'ma-dai' && unit.recommended) ||
|
||||
!fourthCaptureSortieState.sortiePlan?.recruitedLine?.includes('합류 무장') ||
|
||||
fourthCaptureSortieState.sortieRoster?.some((unit) => unit.id === 'liu-bei')
|
||||
) {
|
||||
throw new Error(`Expected fourth Meng Huo sortie prep to expose clan-persuasion recommendations, Zhuge Liang lock, and the expanded recruited roster: ${JSON.stringify(fourthCaptureSortieState)}`);
|
||||
}
|
||||
assertSortieTacticalRoster(fourthCaptureSortieState, [
|
||||
'guan-yu',
|
||||
'zhang-fei',
|
||||
'jian-yong',
|
||||
'mi-zhu',
|
||||
'sun-qian',
|
||||
'zhao-yun',
|
||||
'zhuge-liang',
|
||||
'ma-liang',
|
||||
'yi-ji',
|
||||
'gong-zhi',
|
||||
'huang-zhong',
|
||||
'wei-yan',
|
||||
'pang-tong',
|
||||
'fa-zheng',
|
||||
'wu-yi',
|
||||
'yan-yan',
|
||||
'li-yan',
|
||||
'huang-quan',
|
||||
'ma-chao',
|
||||
'ma-dai',
|
||||
'wang-ping'
|
||||
]);
|
||||
|
||||
const fourthCapturePriorityUnits = ['ma-liang', 'huang-quan', 'wang-ping', 'zhao-yun', 'ma-chao', 'ma-dai'];
|
||||
for (const unitId of fourthCapturePriorityUnits) {
|
||||
const currentSortieState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
if (!currentSortieState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)) {
|
||||
const removable = currentSortieState.sortieRoster?.find(
|
||||
(unit) => unit.selected && !unit.required && !fourthCapturePriorityUnits.includes(unit.id)
|
||||
);
|
||||
if (removable) {
|
||||
await clickSortieRosterUnit(page, removable.id);
|
||||
}
|
||||
await clickSortieRosterUnit(page, unitId);
|
||||
}
|
||||
}
|
||||
|
||||
const fourthCaptureSortieReadyState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
if (
|
||||
!fourthCapturePriorityUnits.every((unitId) =>
|
||||
fourthCaptureSortieReadyState.sortieRoster?.some((unit) => unit.id === unitId && unit.selected)
|
||||
) ||
|
||||
!fourthCaptureSortieReadyState.sortieRoster?.some((unit) => unit.id === 'zhuge-liang' && unit.selected && unit.required) ||
|
||||
fourthCaptureSortieReadyState.sortieRoster?.some((unit) => unit.id === 'liu-bei') ||
|
||||
fourthCaptureSortieReadyState.sortiePlan?.selectedCount !== 7 ||
|
||||
fourthCaptureSortieReadyState.sortiePlan?.recommendedSelectedCount < 7
|
||||
) {
|
||||
throw new Error(`Expected fourth Meng Huo sortie to deploy Zhuge Liang, Ma Liang, Huang Quan, Wang Ping, Zhao Yun, Ma Chao, and Ma Dai: ${JSON.stringify(fourthCaptureSortieReadyState)}`);
|
||||
}
|
||||
await page.screenshot({ path: 'dist/verification-fourth-capture-sortie.png', fullPage: true });
|
||||
|
||||
await page.mouse.click(1068, 646);
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
return activeScenes.includes('StoryScene');
|
||||
});
|
||||
await page.screenshot({ path: 'dist/verification-fourth-capture-story.png', fullPage: true });
|
||||
|
||||
for (let i = 0; i < 70; i += 1) {
|
||||
const enteredFiftyFirstBattle = await page.evaluate(() => {
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
return state?.scene === 'BattleScene' && state?.battleId === 'fifty-first-battle-meng-huo-fourth-capture';
|
||||
});
|
||||
if (enteredFiftyFirstBattle) {
|
||||
break;
|
||||
}
|
||||
await page.keyboard.press('Space');
|
||||
await page.waitForTimeout(320);
|
||||
}
|
||||
await page.waitForFunction(() => {
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
return state?.scene === 'BattleScene' && state?.battleId === 'fifty-first-battle-meng-huo-fourth-capture' && state?.battleOutcome === null && state?.phase === 'idle';
|
||||
});
|
||||
await page.screenshot({ path: 'dist/verification-fifty-first-battle.png', fullPage: true });
|
||||
|
||||
const fiftyFirstBattleState = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
|
||||
const fiftyFirstEnemies = fiftyFirstBattleState.units.filter((unit) => unit.faction === 'enemy');
|
||||
const fiftyFirstAllies = fiftyFirstBattleState.units.filter((unit) => unit.faction === 'ally');
|
||||
const fiftyFirstEnemyBehaviors = new Set(fiftyFirstEnemies.map((unit) => unit.ai));
|
||||
if (
|
||||
fiftyFirstBattleState.camera?.mapWidth !== 102 ||
|
||||
fiftyFirstBattleState.camera?.mapHeight !== 84 ||
|
||||
fiftyFirstBattleState.victoryConditionLabel !== '맹획 네 번째 생포와 회유 퇴로 유지' ||
|
||||
!fiftyFirstBattleState.objectives?.some((objective) => objective.id === 'pacify-meng-huo-fourth' && objective.label === '맹획 네 번째 생포') ||
|
||||
!fiftyFirstBattleState.objectives?.some((objective) => objective.id === 'amnesty-route' && objective.label === '회유 퇴로 유지') ||
|
||||
fiftyFirstEnemies.length < 39 ||
|
||||
!fiftyFirstEnemyBehaviors.has('aggressive') ||
|
||||
!fiftyFirstEnemyBehaviors.has('guard') ||
|
||||
!fiftyFirstEnemyBehaviors.has('hold') ||
|
||||
!fiftyFirstEnemies.some((unit) => unit.id === 'menghuo-fourth-leader') ||
|
||||
!fiftyFirstEnemies.some((unit) => unit.id === 'menghuo-fourth-officer-wutugu') ||
|
||||
!fiftyFirstEnemies.some((unit) => unit.id === 'menghuo-fourth-officer-mangyachang') ||
|
||||
!fiftyFirstEnemies.some((unit) => unit.id === 'menghuo-fourth-officer-dongtuna') ||
|
||||
!fiftyFirstEnemies.some((unit) => unit.id === 'menghuo-fourth-officer-ahuinan') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'zhuge-liang') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'ma-liang') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'huang-quan') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'wang-ping') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'zhao-yun') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'ma-chao') ||
|
||||
!fiftyFirstAllies.some((unit) => unit.id === 'ma-dai') ||
|
||||
fiftyFirstAllies.some((unit) => unit.id === 'liu-bei')
|
||||
) {
|
||||
throw new Error(`Expected fifty-first battle to use the fourth Meng Huo map, amnesty-route objective, selected recruited officers, and mixed clan AI: ${JSON.stringify(fiftyFirstBattleState)}`);
|
||||
}
|
||||
|
||||
await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory'));
|
||||
await page.waitForFunction(() => {
|
||||
const state = window.__HEROS_DEBUG__?.battle();
|
||||
return state?.battleOutcome === 'victory' && state?.phase === 'resolved' && state?.resultVisible === true;
|
||||
});
|
||||
|
||||
await page.mouse.click(738, 642);
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
return activeScenes.includes('CampScene');
|
||||
});
|
||||
|
||||
const fiftyFirstCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
if (
|
||||
fiftyFirstCampState?.campBattleId !== 'fifty-first-battle-meng-huo-fourth-capture' ||
|
||||
fiftyFirstCampState.campTitle !== '칠종칠금 4차전 후 군영' ||
|
||||
fiftyFirstCampState.availableDialogueIds?.length !== 3 ||
|
||||
!fiftyFirstCampState.availableDialogueIds.every((id) => id.includes('fourth-capture')) ||
|
||||
fiftyFirstCampState.availableVisitIds?.length !== 2 ||
|
||||
!fiftyFirstCampState.availableVisitIds.every((id) => id.includes('fourth-capture')) ||
|
||||
fiftyFirstCampState.rosterCollection?.total < 21
|
||||
) {
|
||||
throw new Error(`Expected fifty-first camp to expose fourth capture dialogue/visit sets and preserve the deployable officer roster: ${JSON.stringify(fiftyFirstCampState)}`);
|
||||
}
|
||||
await page.screenshot({ path: 'dist/verification-fourth-capture-camp.png', fullPage: true });
|
||||
|
||||
await page.mouse.click(966, 38);
|
||||
await page.waitForTimeout(180);
|
||||
const postFourthCaptureProgressState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
if (
|
||||
postFourthCaptureProgressState?.activeTab !== 'progress' ||
|
||||
postFourthCaptureProgressState.campaignProgress?.completedKnown !== 51 ||
|
||||
postFourthCaptureProgressState.campaignProgress?.totalKnown !== 51 ||
|
||||
postFourthCaptureProgressState.campaignProgress?.latestBattleTitle !== '칠종칠금 4차전' ||
|
||||
postFourthCaptureProgressState.campaignProgress?.nextBattleTitle !== '준비 중'
|
||||
) {
|
||||
throw new Error(`Expected post-fourth-capture progress tab to complete the fifty-first battle and pause before the fifth capture arc: ${JSON.stringify(postFourthCaptureProgressState?.campaignProgress)}`);
|
||||
}
|
||||
await page.screenshot({ path: 'dist/verification-post-fourth-capture-progress.png', fullPage: true });
|
||||
|
||||
await page.evaluate(() => {
|
||||
const game = window.__HEROS_GAME__;
|
||||
game?.scene.stop('CampScene');
|
||||
@@ -6969,11 +7135,11 @@ try {
|
||||
activeScenes: window.__HEROS_DEBUG__?.activeScenes() ?? [],
|
||||
camp: window.__HEROS_DEBUG__?.camp?.() ?? null
|
||||
}));
|
||||
if (!titleContinueState.activeScenes.includes('CampScene') || titleContinueState.camp?.campaign?.step !== 'fiftieth-camp') {
|
||||
throw new Error(`Expected title continue to reopen the latest third Meng Huo capture camp: ${JSON.stringify(titleContinueState)}`);
|
||||
if (!titleContinueState.activeScenes.includes('CampScene') || titleContinueState.camp?.campaign?.step !== 'fifty-first-camp') {
|
||||
throw new Error(`Expected title continue to reopen the latest fourth Meng Huo capture camp: ${JSON.stringify(titleContinueState)}`);
|
||||
}
|
||||
|
||||
console.log(`Verified title-to-third-Meng-Huo-capture flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng, Yangping, Dingjun, Hanzhong decisive battle, King of Hanzhong council, Shu-Han foundation state, Jing Province defense vanguard, Fan Castle vanguard, Han River flood, Fan Castle siege, Jing rear crisis, Gongan collapse, Maicheng isolation, Yiling vanguard, Yiling fire attack, Baidi entrustment, Nanzhong stabilization, Meng Huo pacification, second capture, and third capture state at ${targetUrl}`);
|
||||
console.log(`Verified title-to-fourth-Meng-Huo-capture flow, recruited officer sortie selection, Ma Liang, Yi Ji, Gong Zhi, Huang Zhong, Wei Yan, Pang Tong, Fa Zheng, Wu Yi, Yan Yan, Li Yan, Huang Quan, Ma Chao, Ma Dai, Wang Ping joins, Luofeng, Luo main gate, Mianzhu, Chengdu surrender, Jiameng, Yangping, Dingjun, Hanzhong decisive battle, King of Hanzhong council, Shu-Han foundation state, Jing Province defense vanguard, Fan Castle vanguard, Han River flood, Fan Castle siege, Jing rear crisis, Gongan collapse, Maicheng isolation, Yiling vanguard, Yiling fire attack, Baidi entrustment, Nanzhong stabilization, Meng Huo pacification, second capture, third capture, and fourth capture state at ${targetUrl}`);
|
||||
} finally {
|
||||
await browser?.close();
|
||||
if (serverProcess && !serverProcess.killed) {
|
||||
|
||||
77
src/assets/images/battle/fifty-first-battle-map.svg
Normal file
77
src/assets/images/battle/fifty-first-battle-map.svg
Normal file
@@ -0,0 +1,77 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="5100" height="4200" viewBox="0 0 10200 8400" role="img" aria-label="Nanman fourth capture battlefield">
|
||||
<defs>
|
||||
<linearGradient id="ground" x1="0" x2="1" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#958657"/>
|
||||
<stop offset=".48" stop-color="#766c45"/>
|
||||
<stop offset="1" stop-color="#3e4f2d"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="marsh" cx=".52" cy=".56" r=".7">
|
||||
<stop offset="0" stop-color="#59764f"/>
|
||||
<stop offset=".54" stop-color="#334d37"/>
|
||||
<stop offset="1" stop-color="#172d2d"/>
|
||||
</radialGradient>
|
||||
<filter id="softNoise">
|
||||
<feTurbulence type="fractalNoise" baseFrequency=".018" numOctaves="4" seed="51"/>
|
||||
<feColorMatrix type="saturate" values=".45"/>
|
||||
<feBlend mode="multiply" in2="SourceGraphic"/>
|
||||
</filter>
|
||||
<pattern id="reed" width="220" height="220" patternUnits="userSpaceOnUse">
|
||||
<path d="M42 218c30-90 42-130 22-214M106 220c-6-82 12-142 58-202M176 218c-38-72-28-128 8-206" stroke="#283c24" stroke-width="18" stroke-linecap="round" opacity=".35"/>
|
||||
</pattern>
|
||||
<pattern id="ridge" width="340" height="280" patternUnits="userSpaceOnUse">
|
||||
<path d="M0 210c80-110 154-164 252-176 46-6 78-24 112-50" fill="none" stroke="#2b241a" stroke-width="34" opacity=".42"/>
|
||||
<path d="M16 226c68-80 140-118 226-122" fill="none" stroke="#b08a4b" stroke-width="18" opacity=".3"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="10200" height="8400" fill="url(#ground)"/>
|
||||
<rect width="10200" height="8400" fill="#000" opacity=".06" filter="url(#softNoise)"/>
|
||||
<path d="M0 7600C1120 7280 1680 7750 2760 7390c870-288 1084-990 2030-920 970 70 1230 760 2290 590 1070-172 1550-1040 3120-742v2082H0z" fill="url(#marsh)"/>
|
||||
<path d="M6280 0c-310 1020-240 1990 60 2800 350 948 470 1658 116 2560-248 612-140 1220 390 3040h-720c-606-1432-764-2442-430-3242 304-730 202-1320-130-2202-318-840-410-1848-104-2956z" fill="#233f44" opacity=".92"/>
|
||||
<path d="M6520 0c-224 980-94 1928 218 2760 322 860 396 1574 90 2312-258 622-170 1308 336 3328h-278c-436-1636-574-2608-240-3374 304-700 214-1348-102-2198-320-858-452-1770-224-2828z" fill="#6b9da3" opacity=".5"/>
|
||||
<path d="M0 0h3380v3200H0zM3220 0h3860v2480H3220zM7080 0h3120v3480H7080zM8520 2900h1680v2460H8520z" fill="url(#ridge)" opacity=".82"/>
|
||||
<path d="M180 4860c1620-920 3560-680 5260-720 1730-42 3040-440 4580-1220v720c-1550 734-2900 1120-4580 1176-1648 54-3460-92-5020 744z" fill="#3d5f2b" opacity=".72"/>
|
||||
<path d="M920 6550c1160-540 2520-550 4020-410 1260 118 2420 310 3950-300v690c-1490 512-2720 354-3970 240-1560-142-2730-118-4000 458z" fill="#496a2d" opacity=".7"/>
|
||||
<path d="M960 6580C2380 6040 3970 6060 5480 5920c1390-128 2530-420 3740-1110" fill="none" stroke="#c2a05a" stroke-width="280" opacity=".82"/>
|
||||
<path d="M2820 5600c760-720 1600-1080 2540-1080h3600" fill="none" stroke="#b89552" stroke-width="260" opacity=".8"/>
|
||||
<path d="M4320 7040c160-1260 20-2420 420-3500" fill="none" stroke="#ad8c4e" stroke-width="240" opacity=".78"/>
|
||||
<path d="M7780 4740c-470 580-496 1170-80 1760 420 596 310 1110-330 1620" fill="none" stroke="#b18d4a" stroke-width="220" opacity=".75"/>
|
||||
<g fill="url(#reed)" opacity=".7">
|
||||
<rect x="5880" y="2480" width="920" height="4980"/>
|
||||
<rect x="430" y="6680" width="2680" height="1560"/>
|
||||
<rect x="7480" y="5840" width="1620" height="1550"/>
|
||||
</g>
|
||||
<g fill="#274d2e" opacity=".78">
|
||||
<ellipse cx="1920" cy="5160" rx="920" ry="560"/>
|
||||
<ellipse cx="3520" cy="4820" rx="940" ry="510"/>
|
||||
<ellipse cx="5720" cy="4040" rx="1050" ry="560"/>
|
||||
<ellipse cx="8120" cy="3680" rx="1040" ry="570"/>
|
||||
<ellipse cx="8540" cy="5940" rx="900" ry="500"/>
|
||||
</g>
|
||||
<g fill="#a06928" opacity=".86">
|
||||
<rect x="2460" y="5220" width="760" height="520" rx="40"/>
|
||||
<rect x="3900" y="4300" width="840" height="540" rx="40"/>
|
||||
<rect x="7360" y="4860" width="880" height="560" rx="40"/>
|
||||
<rect x="8060" y="3220" width="860" height="520" rx="40"/>
|
||||
</g>
|
||||
<g fill="#d1b76c" stroke="#49331c" stroke-width="42">
|
||||
<path d="M2760 5480l300-230 300 230v280h-600z"/>
|
||||
<path d="M4200 4560l320-250 320 250v300h-640z"/>
|
||||
<path d="M7660 5120l330-260 330 260v330h-660z"/>
|
||||
<path d="M8360 3480l300-240 300 240v300h-600z"/>
|
||||
</g>
|
||||
<g fill="#523527" stroke="#d19042" stroke-width="50">
|
||||
<rect x="5280" y="3270" width="840" height="680" rx="48"/>
|
||||
<rect x="6740" y="5060" width="900" height="700" rx="48"/>
|
||||
<rect x="8620" y="4240" width="940" height="720" rx="48"/>
|
||||
</g>
|
||||
<g fill="#e08b31" opacity=".78">
|
||||
<circle cx="5700" cy="3600" r="130"/>
|
||||
<circle cx="7140" cy="5420" r="120"/>
|
||||
<circle cx="9020" cy="4580" r="140"/>
|
||||
</g>
|
||||
<g fill="none" stroke="#1b1f16" stroke-width="34" opacity=".32">
|
||||
<path d="M0 4800c1840-940 4000-770 5920-830 1430-44 2770-420 4280-1210"/>
|
||||
<path d="M600 6460c1360-490 2680-450 4180-330 1380 110 2660 360 4360-330"/>
|
||||
<path d="M6500 0c-360 1360 116 2820 420 3980 230 880-180 1660-20 2620"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
105
src/game/data/battleMapAssets.ts
Normal file
105
src/game/data/battleMapAssets.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import eighthBattleMapUrl from '../../assets/images/battle/eighth-battle-map.svg';
|
||||
import eighteenthBattleMapUrl from '../../assets/images/battle/eighteenth-battle-map.svg';
|
||||
import eleventhBattleMapUrl from '../../assets/images/battle/eleventh-battle-map.svg';
|
||||
import fiftiethBattleMapUrl from '../../assets/images/battle/fiftieth-battle-map.svg';
|
||||
import fiftyFirstBattleMapUrl from '../../assets/images/battle/fifty-first-battle-map.svg';
|
||||
import fifthBattleMapUrl from '../../assets/images/battle/fifth-battle-map.svg';
|
||||
import fifteenthBattleMapUrl from '../../assets/images/battle/fifteenth-battle-map.svg';
|
||||
import firstBattleMapUrl from '../../assets/images/battle/first-battle-map.png';
|
||||
import fortiethBattleMapUrl from '../../assets/images/battle/fortieth-battle-map.svg';
|
||||
import fortyEighthBattleMapUrl from '../../assets/images/battle/forty-eighth-battle-map.svg';
|
||||
import fortyFifthBattleMapUrl from '../../assets/images/battle/forty-fifth-battle-map.svg';
|
||||
import fortyFirstBattleMapUrl from '../../assets/images/battle/forty-first-battle-map.svg';
|
||||
import fortyFourthBattleMapUrl from '../../assets/images/battle/forty-fourth-battle-map.svg';
|
||||
import fortyNinthBattleMapUrl from '../../assets/images/battle/forty-ninth-battle-map.svg';
|
||||
import fortySecondBattleMapUrl from '../../assets/images/battle/forty-second-battle-map.svg';
|
||||
import fortySeventhBattleMapUrl from '../../assets/images/battle/forty-seventh-battle-map.svg';
|
||||
import fortySixthBattleMapUrl from '../../assets/images/battle/forty-sixth-battle-map.svg';
|
||||
import fortyThirdBattleMapUrl from '../../assets/images/battle/forty-third-battle-map.svg';
|
||||
import fourteenthBattleMapUrl from '../../assets/images/battle/fourteenth-battle-map.svg';
|
||||
import fourthBattleMapUrl from '../../assets/images/battle/fourth-battle-map.svg';
|
||||
import nineteenthBattleMapUrl from '../../assets/images/battle/nineteenth-battle-map.svg';
|
||||
import ninthBattleMapUrl from '../../assets/images/battle/ninth-battle-map.svg';
|
||||
import secondBattleMapUrl from '../../assets/images/battle/second-battle-map.svg';
|
||||
import seventhBattleMapUrl from '../../assets/images/battle/seventh-battle-map.svg';
|
||||
import seventeenthBattleMapUrl from '../../assets/images/battle/seventeenth-battle-map.svg';
|
||||
import sixteenthBattleMapUrl from '../../assets/images/battle/sixteenth-battle-map.svg';
|
||||
import sixthBattleMapUrl from '../../assets/images/battle/sixth-battle-map.svg';
|
||||
import tenthBattleMapUrl from '../../assets/images/battle/tenth-battle-map.svg';
|
||||
import thirteenthBattleMapUrl from '../../assets/images/battle/thirteenth-battle-map.svg';
|
||||
import thirtiethBattleMapUrl from '../../assets/images/battle/thirtieth-battle-map.svg';
|
||||
import thirtyEighthBattleMapUrl from '../../assets/images/battle/thirty-eighth-battle-map.svg';
|
||||
import thirtyFifthBattleMapUrl from '../../assets/images/battle/thirty-fifth-battle-map.svg';
|
||||
import thirtyFirstBattleMapUrl from '../../assets/images/battle/thirty-first-battle-map.svg';
|
||||
import thirtyFourthBattleMapUrl from '../../assets/images/battle/thirty-fourth-battle-map.svg';
|
||||
import thirtyNinthBattleMapUrl from '../../assets/images/battle/thirty-ninth-battle-map.svg';
|
||||
import thirtySecondBattleMapUrl from '../../assets/images/battle/thirty-second-battle-map.svg';
|
||||
import thirtySeventhBattleMapUrl from '../../assets/images/battle/thirty-seventh-battle-map.svg';
|
||||
import thirtySixthBattleMapUrl from '../../assets/images/battle/thirty-sixth-battle-map.svg';
|
||||
import thirtyThirdBattleMapUrl from '../../assets/images/battle/thirty-third-battle-map.svg';
|
||||
import thirdBattleMapUrl from '../../assets/images/battle/third-battle-map.svg';
|
||||
import twentiethBattleMapUrl from '../../assets/images/battle/twentieth-battle-map.svg';
|
||||
import twentyEighthBattleMapUrl from '../../assets/images/battle/twenty-eighth-battle-map.svg';
|
||||
import twentyFifthBattleMapUrl from '../../assets/images/battle/twenty-fifth-battle-map.svg';
|
||||
import twentyFirstBattleMapUrl from '../../assets/images/battle/twenty-first-battle-map.svg';
|
||||
import twentyFourthBattleMapUrl from '../../assets/images/battle/twenty-fourth-battle-map.svg';
|
||||
import twentyNinthBattleMapUrl from '../../assets/images/battle/twenty-ninth-battle-map.svg';
|
||||
import twentySecondBattleMapUrl from '../../assets/images/battle/twenty-second-battle-map.svg';
|
||||
import twentySeventhBattleMapUrl from '../../assets/images/battle/twenty-seventh-battle-map.svg';
|
||||
import twentySixthBattleMapUrl from '../../assets/images/battle/twenty-sixth-battle-map.svg';
|
||||
import twentyThirdBattleMapUrl from '../../assets/images/battle/twenty-third-battle-map.svg';
|
||||
import twelfthBattleMapUrl from '../../assets/images/battle/twelfth-battle-map.svg';
|
||||
|
||||
export const battleMapAssets: Record<string, string> = {
|
||||
'battle-map-first': firstBattleMapUrl,
|
||||
'battle-map-second': secondBattleMapUrl,
|
||||
'battle-map-third': thirdBattleMapUrl,
|
||||
'battle-map-fourth': fourthBattleMapUrl,
|
||||
'battle-map-fifth': fifthBattleMapUrl,
|
||||
'battle-map-sixth': sixthBattleMapUrl,
|
||||
'battle-map-seventh': seventhBattleMapUrl,
|
||||
'battle-map-eighth': eighthBattleMapUrl,
|
||||
'battle-map-ninth': ninthBattleMapUrl,
|
||||
'battle-map-tenth': tenthBattleMapUrl,
|
||||
'battle-map-eleventh': eleventhBattleMapUrl,
|
||||
'battle-map-twelfth': twelfthBattleMapUrl,
|
||||
'battle-map-thirteenth': thirteenthBattleMapUrl,
|
||||
'battle-map-fourteenth': fourteenthBattleMapUrl,
|
||||
'battle-map-fifteenth': fifteenthBattleMapUrl,
|
||||
'battle-map-sixteenth': sixteenthBattleMapUrl,
|
||||
'battle-map-seventeenth': seventeenthBattleMapUrl,
|
||||
'battle-map-eighteenth': eighteenthBattleMapUrl,
|
||||
'battle-map-nineteenth': nineteenthBattleMapUrl,
|
||||
'battle-map-twentieth': twentiethBattleMapUrl,
|
||||
'battle-map-twenty-first': twentyFirstBattleMapUrl,
|
||||
'battle-map-twenty-second': twentySecondBattleMapUrl,
|
||||
'battle-map-twenty-third': twentyThirdBattleMapUrl,
|
||||
'battle-map-twenty-fourth': twentyFourthBattleMapUrl,
|
||||
'battle-map-twenty-fifth': twentyFifthBattleMapUrl,
|
||||
'battle-map-twenty-sixth': twentySixthBattleMapUrl,
|
||||
'battle-map-twenty-seventh': twentySeventhBattleMapUrl,
|
||||
'battle-map-twenty-eighth': twentyEighthBattleMapUrl,
|
||||
'battle-map-twenty-ninth': twentyNinthBattleMapUrl,
|
||||
'battle-map-thirtieth': thirtiethBattleMapUrl,
|
||||
'battle-map-thirty-first': thirtyFirstBattleMapUrl,
|
||||
'battle-map-thirty-second': thirtySecondBattleMapUrl,
|
||||
'battle-map-thirty-third': thirtyThirdBattleMapUrl,
|
||||
'battle-map-thirty-fourth': thirtyFourthBattleMapUrl,
|
||||
'battle-map-thirty-fifth': thirtyFifthBattleMapUrl,
|
||||
'battle-map-thirty-sixth': thirtySixthBattleMapUrl,
|
||||
'battle-map-thirty-seventh': thirtySeventhBattleMapUrl,
|
||||
'battle-map-thirty-eighth': thirtyEighthBattleMapUrl,
|
||||
'battle-map-thirty-ninth': thirtyNinthBattleMapUrl,
|
||||
'battle-map-fortieth': fortiethBattleMapUrl,
|
||||
'battle-map-forty-first': fortyFirstBattleMapUrl,
|
||||
'battle-map-forty-second': fortySecondBattleMapUrl,
|
||||
'battle-map-forty-third': fortyThirdBattleMapUrl,
|
||||
'battle-map-forty-fourth': fortyFourthBattleMapUrl,
|
||||
'battle-map-forty-fifth': fortyFifthBattleMapUrl,
|
||||
'battle-map-forty-sixth': fortySixthBattleMapUrl,
|
||||
'battle-map-forty-seventh': fortySeventhBattleMapUrl,
|
||||
'battle-map-forty-eighth': fortyEighthBattleMapUrl,
|
||||
'battle-map-forty-ninth': fortyNinthBattleMapUrl,
|
||||
'battle-map-fiftieth': fiftiethBattleMapUrl,
|
||||
'battle-map-fifty-first': fiftyFirstBattleMapUrl
|
||||
};
|
||||
@@ -3,6 +3,10 @@ import {
|
||||
fiftiethBattleMap,
|
||||
fiftiethBattleUnits,
|
||||
fiftiethBattleVictoryPages,
|
||||
fiftyFirstBattleBonds,
|
||||
fiftyFirstBattleMap,
|
||||
fiftyFirstBattleUnits,
|
||||
fiftyFirstBattleVictoryPages,
|
||||
firstBattleBonds,
|
||||
fifteenthBattleBonds,
|
||||
fifteenthBattleMap,
|
||||
@@ -255,7 +259,8 @@ export type BattleScenarioId =
|
||||
| 'forty-seventh-battle-nanzhong-stabilization'
|
||||
| 'forty-eighth-battle-meng-huo-main-force'
|
||||
| 'forty-ninth-battle-meng-huo-second-capture'
|
||||
| 'fiftieth-battle-meng-huo-third-capture';
|
||||
| 'fiftieth-battle-meng-huo-third-capture'
|
||||
| 'fifty-first-battle-meng-huo-fourth-capture';
|
||||
|
||||
export type BattleObjectiveKind = 'defeat-leader' | 'pacify-leader' | 'keep-unit-alive' | 'secure-terrain' | 'quick-victory';
|
||||
|
||||
@@ -3247,6 +3252,73 @@ export const fiftiethBattleScenario: BattleScenarioDefinition = {
|
||||
nextCampScene: 'CampScene'
|
||||
};
|
||||
|
||||
export const fiftyFirstBattleScenario: BattleScenarioDefinition = {
|
||||
id: 'fifty-first-battle-meng-huo-fourth-capture',
|
||||
title: '칠종칠금 4차전',
|
||||
victoryConditionLabel: '맹획 네 번째 생포와 회유 퇴로 유지',
|
||||
defeatConditionLabel: '제갈량 퇴각',
|
||||
openingObjectiveLines: [
|
||||
'세 번째 생포 뒤 호족 회의에서 열어 둔 퇴로가 이번 전장의 핵심입니다. 물러설 뜻이 있는 호족을 몰살하면 남중은 다시 모두 적이 됩니다.',
|
||||
'오돌골의 등갑병과 독천 제사장들이 화덕 주변을 지키고 있습니다. 화덕 요새를 제압하되 마을과 포로장을 지켜, 촉한군의 약속이 전투 중에도 지켜진다는 것을 보여야 합니다.',
|
||||
'제갈량은 반드시 생존해야 합니다. 마량으로 호족 문서를 전하고, 황권과 왕평으로 장부와 퇴로를 지키며, 마초와 마대로 추격선을 조절하십시오.'
|
||||
],
|
||||
map: fiftyFirstBattleMap,
|
||||
units: fiftyFirstBattleUnits,
|
||||
bonds: fiftyFirstBattleBonds,
|
||||
mapTextureKey: 'battle-map-fifty-first',
|
||||
leaderUnitId: 'menghuo-fourth-leader',
|
||||
quickVictoryTurnLimit: 94,
|
||||
baseVictoryGold: 12280,
|
||||
objectives: [
|
||||
{
|
||||
id: 'pacify-meng-huo-fourth',
|
||||
kind: 'pacify-leader',
|
||||
label: '맹획 네 번째 생포',
|
||||
rewardGold: 8420,
|
||||
unitId: 'menghuo-fourth-leader'
|
||||
},
|
||||
{
|
||||
id: 'zhuge-liang',
|
||||
kind: 'keep-unit-alive',
|
||||
label: '제갈량 생존',
|
||||
rewardGold: 2140,
|
||||
unitId: 'zhuge-liang'
|
||||
},
|
||||
{
|
||||
id: 'amnesty-route',
|
||||
kind: 'secure-terrain',
|
||||
label: '회유 퇴로 유지',
|
||||
rewardGold: 4140,
|
||||
terrain: 'road'
|
||||
},
|
||||
{
|
||||
id: 'captive-camps',
|
||||
kind: 'secure-terrain',
|
||||
label: '포로장 보증 유지',
|
||||
rewardGold: 3360,
|
||||
terrain: 'camp'
|
||||
},
|
||||
{
|
||||
id: 'fire-forts',
|
||||
kind: 'secure-terrain',
|
||||
label: '화덕 요새 제압',
|
||||
rewardGold: 3640,
|
||||
terrain: 'fort'
|
||||
},
|
||||
{
|
||||
id: 'quick',
|
||||
kind: 'quick-victory',
|
||||
label: '94턴 이내 네 번째 생포',
|
||||
rewardGold: 2780,
|
||||
maxTurn: 94
|
||||
}
|
||||
],
|
||||
defeatConditions: [{ kind: 'unit-defeated', unitId: 'zhuge-liang' }],
|
||||
itemRewards: ['콩 66', '상처약 50', '탁주 22', '호족 보증 장부 1', '회유 퇴로 표식 1'],
|
||||
victoryPages: fiftyFirstBattleVictoryPages,
|
||||
nextCampScene: 'CampScene'
|
||||
};
|
||||
|
||||
export const defaultBattleScenarioId: BattleScenarioId = firstBattleScenario.id;
|
||||
|
||||
export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition> = {
|
||||
@@ -3299,7 +3371,8 @@ export const battleScenarios: Record<BattleScenarioId, BattleScenarioDefinition>
|
||||
'forty-seventh-battle-nanzhong-stabilization': fortySeventhBattleScenario,
|
||||
'forty-eighth-battle-meng-huo-main-force': fortyEighthBattleScenario,
|
||||
'forty-ninth-battle-meng-huo-second-capture': fortyNinthBattleScenario,
|
||||
'fiftieth-battle-meng-huo-third-capture': fiftiethBattleScenario
|
||||
'fiftieth-battle-meng-huo-third-capture': fiftiethBattleScenario,
|
||||
'fifty-first-battle-meng-huo-fourth-capture': fiftyFirstBattleScenario
|
||||
};
|
||||
|
||||
export const defaultBattleScenario = battleScenarios[defaultBattleScenarioId];
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
eighteenthBattleScenario,
|
||||
eleventhBattleScenario,
|
||||
fiftiethBattleScenario,
|
||||
fiftyFirstBattleScenario,
|
||||
fortiethBattleScenario,
|
||||
fortyFirstBattleScenario,
|
||||
fortySecondBattleScenario,
|
||||
@@ -62,6 +63,8 @@ import {
|
||||
eleventhBattleVictoryPages,
|
||||
fiftiethBattleIntroPages,
|
||||
fiftiethBattleVictoryPages,
|
||||
fiftyFirstBattleIntroPages,
|
||||
fiftyFirstBattleVictoryPages,
|
||||
fortiethBattleIntroPages,
|
||||
fortiethBattleVictoryPages,
|
||||
fortyFirstBattleIntroPages,
|
||||
@@ -731,13 +734,24 @@ const sortieFlows: Record<string, SortieFlow> = {
|
||||
},
|
||||
[fiftiethBattleScenario.id]: {
|
||||
afterBattleId: fiftiethBattleScenario.id,
|
||||
eyebrow: '다음 장 준비',
|
||||
title: '호족 회유 회의',
|
||||
eyebrow: '다음 전장',
|
||||
title: fiftyFirstBattleScenario.title,
|
||||
description:
|
||||
'맹획은 세 번째로 붙잡혔고, 그를 따르던 호족들의 말도 흔들리기 시작했습니다. 다음 장에서는 전투 전 회의에서 어떤 호족을 먼저 달랠지 고르고, 그 선택이 다음 남중 전장의 목표와 추천 출전에 영향을 주는 흐름을 준비합니다.',
|
||||
rewardHint: '다음 장: 남중 호족 회유 회의와 칠종칠금 4차전 준비 중',
|
||||
pages: fiftiethBattleVictoryPages,
|
||||
unavailableNotice: '칠종칠금 4차전은 다음 작업에서 이어집니다. 지금은 세 번째 생포 뒤의 호족 회유 선택지와 출전 추천 변화를 정비할 수 있습니다.'
|
||||
'세 번째 생포 뒤 열린 호족 회의는 전장의 조건을 바꾸었습니다. 이제 회유 퇴로를 남기고, 독천과 화덕 요새를 억제하며, 흔들리는 호족들이 직접 촉한군의 약속을 보게 해야 합니다.',
|
||||
rewardHint: `예상 보상: ${fiftyFirstBattleScenario.title} 개방 / 호족 보증 장부`,
|
||||
nextBattleId: fiftyFirstBattleScenario.id,
|
||||
campaignStep: 'fifty-first-battle',
|
||||
pages: [...fiftiethBattleVictoryPages, ...fiftyFirstBattleIntroPages]
|
||||
},
|
||||
[fiftyFirstBattleScenario.id]: {
|
||||
afterBattleId: fiftyFirstBattleScenario.id,
|
||||
eyebrow: '다음 장 준비',
|
||||
title: '더 깊은 남중 회유',
|
||||
description:
|
||||
'맹획은 네 번째로 붙잡혔고, 회유 퇴로와 보증 장부는 남중 호족들의 말 속에 남았습니다. 다음 장에서는 더 깊은 산채와 강경파 호족을 상대로 같은 약속을 지킬 수 있는지 다룹니다.',
|
||||
rewardHint: '다음 장: 칠종칠금 5차전과 남중 강경파 회유 준비 중',
|
||||
pages: fiftyFirstBattleVictoryPages,
|
||||
unavailableNotice: '칠종칠금 5차전은 다음 작업에서 이어집니다. 지금은 네 번째 생포 뒤의 보증 장부, 퇴로 표식, 강경파 분리 흐름을 정비할 수 있습니다.'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3297,6 +3297,59 @@ export const fiftiethBattleVictoryPages: StoryPage[] = [
|
||||
}
|
||||
];
|
||||
|
||||
export const fiftyFirstBattleIntroPages: StoryPage[] = [
|
||||
{
|
||||
id: 'fifty-first-clan-council-result',
|
||||
bgm: 'story-dark',
|
||||
chapter: '회유가 전장으로',
|
||||
background: 'story-militia',
|
||||
speaker: '마량',
|
||||
text: '호족 회의 뒤 일부 촌장은 맹획을 따르되 끝까지 싸우지는 않겠다고 속내를 보였습니다. 그들이 물러날 길을 남겨 두면 다음 전투는 섬멸보다 설득에 가까워질 것입니다.'
|
||||
},
|
||||
{
|
||||
id: 'fifty-first-fourth-capture-plan',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '네 번째 생포',
|
||||
background: 'story-three-heroes',
|
||||
speaker: '제갈량',
|
||||
text: '이번에는 맹획의 본영뿐 아니라 오돌골의 등갑병과 독천 제사장들이 전장을 뒤덮을 것입니다. 화덕과 독천을 함부로 건드리지 말고, 회유 퇴로와 마을 보증을 함께 지키십시오.'
|
||||
},
|
||||
{
|
||||
id: 'fifty-first-sortie',
|
||||
bgm: 'battle-prep',
|
||||
chapter: '칠종칠금 4차전',
|
||||
background: 'story-sortie',
|
||||
speaker: '왕평',
|
||||
text: '숲길은 더 좁고 강물은 더 깊습니다. 마량이 호족의 말을 붙잡고, 황권이 보증 장부를 지키며, 왕평과 마대가 열어 둔 산길을 따라 맹획을 네 번째 생포해야 합니다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const fiftyFirstBattleVictoryPages: StoryPage[] = [
|
||||
{
|
||||
id: 'fifty-first-victory-fourth-capture',
|
||||
bgm: 'militia-theme',
|
||||
chapter: '네 번째 생포',
|
||||
background: 'story-sortie',
|
||||
text: '맹획은 네 번째로 포위되었고, 등갑병의 화덕과 독천 제사장들은 마을까지 밀려오지 못했습니다. 회유 퇴로로 물러난 호족들은 촉한군이 약속한 길을 지켰다는 사실을 직접 보았습니다.'
|
||||
},
|
||||
{
|
||||
id: 'fifty-first-victory-amnesty-route',
|
||||
bgm: 'story-dark',
|
||||
chapter: '열어 둔 길',
|
||||
background: 'story-militia',
|
||||
speaker: '황권',
|
||||
text: '돌아간 자와 끝까지 싸운 자의 이름이 장부에 나뉘었습니다. 이제 남중의 호족들은 맹획의 고집만이 아니라, 촉한군의 약속이 지켜지는지도 함께 따지게 될 것입니다.'
|
||||
},
|
||||
{
|
||||
id: 'fifty-first-next-deeper-nanzhong',
|
||||
bgm: 'story-dark',
|
||||
chapter: '더 깊은 남중',
|
||||
background: 'story-three-heroes',
|
||||
speaker: '제갈량',
|
||||
text: '네 번 잡아도 맹획은 아직 남중 전체의 마음을 대표한다고 말합니다. 그렇다면 더 깊은 산채와 더 어려운 조건 앞에서도 같은 군율을 지켜 보여야 합니다.'
|
||||
}
|
||||
];
|
||||
|
||||
export const firstBattleMap: BattleMap = {
|
||||
width: 20,
|
||||
height: 18,
|
||||
@@ -3742,6 +3795,12 @@ export const fiftiethBattleMap: BattleMap = {
|
||||
terrain: createFiftiethBattleTerrain()
|
||||
};
|
||||
|
||||
export const fiftyFirstBattleMap: BattleMap = {
|
||||
width: 102,
|
||||
height: 84,
|
||||
terrain: createFiftyFirstBattleTerrain()
|
||||
};
|
||||
|
||||
export const firstBattleUnits: UnitData[] = [
|
||||
{
|
||||
id: 'liu-bei',
|
||||
@@ -16041,6 +16100,93 @@ export const fiftiethBattleUnits: UnitData[] = [
|
||||
createThirtyFirstEnemyUnit('menghuo-third-leader', '맹획', '남만왕', 'rebelLeader', 150, 1010, 248, 94, 41)
|
||||
];
|
||||
|
||||
const fiftyFirstBattleAllyPositions: Record<string, { x: number; y: number }> = {
|
||||
'guan-yu': { x: 14, y: 63 },
|
||||
'zhang-fei': { x: 19, y: 65 },
|
||||
'jian-yong': { x: 10, y: 70 },
|
||||
'mi-zhu': { x: 12, y: 68 },
|
||||
'sun-qian': { x: 16, y: 72 },
|
||||
'zhao-yun': { x: 24, y: 60 },
|
||||
'zhuge-liang': { x: 13, y: 60 },
|
||||
'ma-liang': { x: 17, y: 57 },
|
||||
'yi-ji': { x: 10, y: 75 },
|
||||
'gong-zhi': { x: 20, y: 73 },
|
||||
'huang-zhong': { x: 27, y: 61 },
|
||||
'wei-yan': { x: 32, y: 65 },
|
||||
'pang-tong': { x: 15, y: 54 },
|
||||
'fa-zheng': { x: 21, y: 55 },
|
||||
'wu-yi': { x: 34, y: 70 },
|
||||
'yan-yan': { x: 37, y: 63 },
|
||||
'li-yan': { x: 26, y: 53 },
|
||||
'huang-quan': { x: 10, y: 58 },
|
||||
'ma-chao': { x: 39, y: 60 },
|
||||
'ma-dai': { x: 42, y: 65 },
|
||||
'wang-ping': { x: 29, y: 56 }
|
||||
};
|
||||
|
||||
export const fiftyFirstBattleUnits: UnitData[] = [
|
||||
...[
|
||||
...firstBattleUnits.filter((unit) => unit.faction === 'ally' && unit.id !== 'liu-bei'),
|
||||
...xuzhouRecruitUnits,
|
||||
...caoBreakRecruitUnits,
|
||||
...liuBiaoRecruitUnits,
|
||||
...zhugeRecruitUnits,
|
||||
...jingzhouRecruitUnits,
|
||||
...guiyangRecruitUnits,
|
||||
...wulingRecruitUnits,
|
||||
...changshaRecruitUnits,
|
||||
...yizhouRecruitUnits,
|
||||
...fuPassRecruitUnits,
|
||||
...luoCastleRecruitUnits,
|
||||
...luoCastleProperRecruitUnits,
|
||||
...chengduPressureRecruitUnits,
|
||||
...chengduSurrenderRecruitUnits,
|
||||
...hanzhongOpeningRecruitUnits,
|
||||
...hanzhongScoutRecruitUnits,
|
||||
...hanzhongMainRecruitUnits
|
||||
].map((unit) => placeScenarioUnit(unit, fiftyFirstBattleAllyPositions[unit.id] ?? { x: unit.x, y: unit.y })),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-scout-a', '남만 회유 감시병', '서쪽 퇴로 감시', 'bandit', 148, 650, 196, 46, 36),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-scout-b', '남만 회유 감시병', '늪지 감시', 'bandit', 148, 650, 196, 61, 34),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-scout-c', '남만 회유 감시병', '장터 감시', 'bandit', 149, 658, 198, 76, 51),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-scout-d', '남만 회유 감시병', '동쪽 산길 감시', 'bandit', 149, 658, 198, 92, 66),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-scout-e', '남만 회유 감시병', '북쪽 협곡 감시', 'bandit', 150, 666, 200, 54, 24),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-a', '등갑 화덕병', '늪지 등갑병', 'yellowTurban', 149, 914, 232, 51, 45),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-b', '등갑 화덕병', '화덕 등갑병', 'yellowTurban', 150, 926, 234, 63, 48),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-c', '등갑 화덕병', '마을 등갑병', 'yellowTurban', 150, 926, 234, 76, 58),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-d', '등갑 화덕병', '본대 등갑병', 'yellowTurban', 151, 938, 236, 88, 50),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-e', '등갑 화덕병', '후위 등갑병', 'yellowTurban', 151, 938, 236, 96, 42),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-vine-f', '등갑 화덕병', '협곡 등갑병', 'yellowTurban', 152, 950, 238, 84, 31),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-archer-a', '남만 산림 궁병', '독천 궁병', 'archer', 148, 702, 208, 47, 28),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-archer-b', '남만 산림 궁병', '절벽 궁병', 'archer', 149, 710, 210, 62, 26),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-archer-c', '남만 산림 궁병', '마을 궁병', 'archer', 149, 710, 210, 74, 44),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-archer-d', '남만 산림 궁병', '늪지 궁병', 'archer', 150, 718, 212, 86, 62),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-archer-e', '남만 산림 궁병', '본영 궁병', 'archer', 150, 718, 212, 95, 55),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-beast-a', '남만 맹수 유인대', '강가 맹수대', 'cavalry', 150, 930, 236, 56, 38),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-beast-b', '남만 맹수 유인대', '늪지 맹수대', 'cavalry', 150, 930, 236, 69, 40),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-beast-c', '남만 맹수 유인대', '산채 맹수대', 'cavalry', 151, 942, 238, 81, 53),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-beast-d', '남만 맹수 유인대', '추격 맹수대', 'cavalry', 151, 942, 238, 93, 59),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-beast-e', '남만 맹수 유인대', '회유로 차단대', 'cavalry', 152, 954, 240, 67, 68),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-a', '호족 반전 매복병', '덩굴 매복병', 'bandit', 149, 670, 202, 38, 51),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-b', '호족 반전 매복병', '숲속 매복병', 'bandit', 150, 678, 204, 54, 54),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-c', '호족 반전 매복병', '강가 매복병', 'bandit', 150, 678, 204, 67, 67),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-d', '호족 반전 매복병', '후방 차단대', 'bandit', 151, 686, 206, 86, 74),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-e', '호족 반전 매복병', '서쪽 차단대', 'bandit', 151, 686, 206, 33, 64),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-ambusher-f', '호족 반전 매복병', '회유로 감시대', 'bandit', 152, 694, 208, 73, 72),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-guard-a', '맹획 사차 친위', '포로장 친위대', 'yellowTurban', 152, 966, 242, 71, 42),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-guard-b', '맹획 사차 친위', '산채 친위대', 'yellowTurban', 152, 966, 242, 83, 48),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-guard-c', '맹획 사차 친위', '본영 친위대', 'yellowTurban', 153, 978, 244, 94, 45),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-guard-d', '맹획 사차 친위', '화덕 친위대', 'yellowTurban', 153, 978, 244, 89, 35),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-shaman-a', '독천 제사장', '늪지 제사장', 'strategist', 151, 744, 218, 63, 36),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-shaman-b', '독천 제사장', '강가 제사장', 'strategist', 152, 752, 220, 77, 49),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-shaman-c', '독천 제사장', '산채 제사장', 'strategist', 152, 752, 220, 88, 38),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-shaman-d', '독천 제사장', '화덕 제사장', 'strategist', 153, 760, 222, 82, 57),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-officer-wutugu', '오돌골', '등갑병 두령', 'rebelLeader', 154, 1010, 252, 86, 37),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-officer-mangyachang', '망아장', '맹수 선봉장', 'rebelLeader', 154, 1010, 252, 81, 65),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-officer-dongtuna', '동도나', '흔들리는 호족장', 'rebelLeader', 153, 990, 246, 70, 60),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-officer-ahuinan', '아회남', '회유로 감시 호족', 'rebelLeader', 153, 990, 246, 66, 52),
|
||||
createThirtyFirstEnemyUnit('menghuo-fourth-leader', '맹획', '남만왕', 'rebelLeader', 156, 1048, 258, 96, 43)
|
||||
];
|
||||
|
||||
export const firstBattleBonds: BattleBond[] = [
|
||||
{
|
||||
id: 'liu-bei__guan-yu',
|
||||
@@ -16976,6 +17122,35 @@ export const mengHuoThirdCaptureBonds: BattleBond[] = [
|
||||
export const fiftiethBattleBonds: BattleBond[] = [...fortyNinthBattleBonds, ...mengHuoThirdCaptureBonds].map(
|
||||
cloneBattleBondForScenario
|
||||
);
|
||||
export const mengHuoFourthCaptureBonds: BattleBond[] = [
|
||||
{
|
||||
id: 'zhuge-liang__ma-liang_fourth-capture',
|
||||
unitIds: ['zhuge-liang', 'ma-liang'],
|
||||
title: '회유 회의의 결실',
|
||||
level: 51,
|
||||
exp: 0,
|
||||
description: '제갈량의 큰 회유책과 마량의 호족 설득문은 전장 안에서 물러날 길과 항복의 명분을 함께 만든다.'
|
||||
},
|
||||
{
|
||||
id: 'huang-quan__wang-ping_fourth-capture',
|
||||
unitIds: ['huang-quan', 'wang-ping'],
|
||||
title: '보증 장부와 퇴로',
|
||||
level: 47,
|
||||
exp: 0,
|
||||
description: '황권의 보증 장부와 왕평의 산길 판단은 흔들리는 호족들이 다시 창을 들지 않고 물러날 길을 보장한다.'
|
||||
},
|
||||
{
|
||||
id: 'ma-chao__ma-dai_fourth-capture',
|
||||
unitIds: ['ma-chao', 'ma-dai'],
|
||||
title: '남중 추격 차단',
|
||||
level: 43,
|
||||
exp: 0,
|
||||
description: '마초와 마대는 거친 남만 기병을 몰아붙이되, 회유 퇴로를 짓밟지 않도록 돌격의 선을 맞춘다.'
|
||||
}
|
||||
];
|
||||
export const fiftyFirstBattleBonds: BattleBond[] = [...fiftiethBattleBonds, ...mengHuoFourthCaptureBonds].map(
|
||||
cloneBattleBondForScenario
|
||||
);
|
||||
|
||||
function createEighthBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 22 }, (_, y) =>
|
||||
@@ -19549,6 +19724,74 @@ function createFiftiethBattleTerrain(): TerrainType[][] {
|
||||
);
|
||||
}
|
||||
|
||||
function createFiftyFirstBattleTerrain(): TerrainType[][] {
|
||||
return Array.from({ length: 84 }, (_, y) =>
|
||||
Array.from({ length: 102 }, (_, x): TerrainType => {
|
||||
if (
|
||||
(x >= 0 && x <= 101 && y >= 76) ||
|
||||
(x >= 62 && x <= 68 && y >= 0 && y <= 78) ||
|
||||
(x >= 5 && x <= 30 && y >= 67 && y <= 83) ||
|
||||
(x >= 76 && x <= 92 && y >= 58 && y <= 76)
|
||||
) {
|
||||
return 'river';
|
||||
}
|
||||
if (
|
||||
(x >= 9 && x <= 96 && y >= 63 && y <= 69) ||
|
||||
(x >= 27 && x <= 74 && y >= 42 && y <= 49) ||
|
||||
(x >= 70 && x <= 96 && y >= 34 && y <= 40) ||
|
||||
(x >= 37 && x <= 45 && y >= 39 && y <= 72) ||
|
||||
(x >= 76 && x <= 82 && y >= 48 && y <= 80)
|
||||
) {
|
||||
return 'road';
|
||||
}
|
||||
if (
|
||||
(x >= 18 && x <= 72 && y >= 20 && y <= 74) ||
|
||||
(x >= 55 && x <= 96 && y >= 28 && y <= 70) ||
|
||||
(x >= 2 && x <= 38 && y >= 49 && y <= 74) ||
|
||||
(x >= 78 && x <= 101 && y >= 41 && y <= 73)
|
||||
) {
|
||||
return 'forest';
|
||||
}
|
||||
if (
|
||||
(x >= 0 && x <= 31 && y <= 38) ||
|
||||
(x >= 33 && x <= 68 && y <= 28) ||
|
||||
(x >= 71 && x <= 101 && y <= 37) ||
|
||||
(x >= 86 && x <= 101 && y >= 33 && y <= 55)
|
||||
) {
|
||||
return 'hill';
|
||||
}
|
||||
if (
|
||||
(x <= 2 && y <= 74) ||
|
||||
(x >= 99 && y <= 70) ||
|
||||
(x >= 30 && x <= 36 && y >= 0 && y <= 40) ||
|
||||
(x >= 68 && x <= 74 && y >= 0 && y <= 34) ||
|
||||
(x >= 42 && x <= 48 && y >= 64 && y <= 83)
|
||||
) {
|
||||
return 'cliff';
|
||||
}
|
||||
if (
|
||||
(x >= 10 && x <= 25 && y >= 59 && y <= 71) ||
|
||||
(x >= 39 && x <= 54 && y >= 43 && y <= 56) ||
|
||||
(x >= 75 && x <= 91 && y >= 49 && y <= 61) ||
|
||||
(x >= 80 && x <= 94 && y >= 32 && y <= 44)
|
||||
) {
|
||||
return 'village';
|
||||
}
|
||||
if ((x >= 23 && x <= 37 && y >= 51 && y <= 62) || (x >= 63 && x <= 78 && y >= 56 && y <= 68)) {
|
||||
return 'camp';
|
||||
}
|
||||
if (
|
||||
(x >= 47 && x <= 63 && y >= 31 && y <= 42) ||
|
||||
(x >= 72 && x <= 92 && y >= 31 && y <= 45) ||
|
||||
(x >= 84 && x <= 96 && y >= 43 && y <= 54)
|
||||
) {
|
||||
return 'fort';
|
||||
}
|
||||
return 'plain';
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function placeScenarioUnit(unit: UnitData, position: { x: number; y: number }): UnitData {
|
||||
return {
|
||||
...cloneUnitForScenario(unit),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Phaser from 'phaser';
|
||||
import { soundDirector } from '../audio/SoundDirector';
|
||||
import { battleMapAssets } from '../data/battleMapAssets';
|
||||
import { type BattleBond, type UnitData, type UnitStats } from '../data/scenario';
|
||||
import { defaultBattleScenario, getBattleScenario, type BattleObjectiveDefinition, type BattleScenarioDefinition } from '../data/battles';
|
||||
import { getTerrainRule, getUnitClass, type TerrainType, type UnitClassKey } from '../data/battleRules';
|
||||
@@ -873,7 +874,16 @@ const unitTexture: Record<string, string> = {
|
||||
'menghuo-third-officer-zhurong-vanguard': 'unit-rebel-leader',
|
||||
'menghuo-third-officer-jinhuan': 'unit-rebel-leader',
|
||||
'menghuo-third-officer-ahuinan': 'unit-rebel-leader',
|
||||
'menghuo-third-leader': 'unit-rebel-leader'
|
||||
'menghuo-third-leader': 'unit-rebel-leader',
|
||||
'menghuo-fourth-shaman-a': 'unit-rebel-archer',
|
||||
'menghuo-fourth-shaman-b': 'unit-rebel-archer',
|
||||
'menghuo-fourth-shaman-c': 'unit-rebel-archer',
|
||||
'menghuo-fourth-shaman-d': 'unit-rebel-archer',
|
||||
'menghuo-fourth-officer-wutugu': 'unit-rebel-leader',
|
||||
'menghuo-fourth-officer-mangyachang': 'unit-rebel-leader',
|
||||
'menghuo-fourth-officer-dongtuna': 'unit-rebel-leader',
|
||||
'menghuo-fourth-officer-ahuinan': 'unit-rebel-leader',
|
||||
'menghuo-fourth-leader': 'unit-rebel-leader'
|
||||
};
|
||||
|
||||
const unitTextureByClass: Partial<Record<UnitClassKey, string>> = {
|
||||
@@ -2372,7 +2382,47 @@ const enemyAiByUnitId: Record<string, EnemyAiBehavior> = {
|
||||
'menghuo-third-officer-zhurong-vanguard': 'aggressive',
|
||||
'menghuo-third-officer-jinhuan': 'aggressive',
|
||||
'menghuo-third-officer-ahuinan': 'guard',
|
||||
'menghuo-third-leader': 'hold'
|
||||
'menghuo-third-leader': 'hold',
|
||||
'menghuo-fourth-scout-a': 'aggressive',
|
||||
'menghuo-fourth-scout-b': 'aggressive',
|
||||
'menghuo-fourth-scout-c': 'aggressive',
|
||||
'menghuo-fourth-scout-d': 'aggressive',
|
||||
'menghuo-fourth-scout-e': 'aggressive',
|
||||
'menghuo-fourth-vine-a': 'guard',
|
||||
'menghuo-fourth-vine-b': 'guard',
|
||||
'menghuo-fourth-vine-c': 'guard',
|
||||
'menghuo-fourth-vine-d': 'guard',
|
||||
'menghuo-fourth-vine-e': 'guard',
|
||||
'menghuo-fourth-vine-f': 'guard',
|
||||
'menghuo-fourth-archer-a': 'hold',
|
||||
'menghuo-fourth-archer-b': 'hold',
|
||||
'menghuo-fourth-archer-c': 'hold',
|
||||
'menghuo-fourth-archer-d': 'hold',
|
||||
'menghuo-fourth-archer-e': 'hold',
|
||||
'menghuo-fourth-beast-a': 'aggressive',
|
||||
'menghuo-fourth-beast-b': 'aggressive',
|
||||
'menghuo-fourth-beast-c': 'aggressive',
|
||||
'menghuo-fourth-beast-d': 'aggressive',
|
||||
'menghuo-fourth-beast-e': 'aggressive',
|
||||
'menghuo-fourth-ambusher-a': 'aggressive',
|
||||
'menghuo-fourth-ambusher-b': 'aggressive',
|
||||
'menghuo-fourth-ambusher-c': 'aggressive',
|
||||
'menghuo-fourth-ambusher-d': 'aggressive',
|
||||
'menghuo-fourth-ambusher-e': 'aggressive',
|
||||
'menghuo-fourth-ambusher-f': 'aggressive',
|
||||
'menghuo-fourth-guard-a': 'guard',
|
||||
'menghuo-fourth-guard-b': 'guard',
|
||||
'menghuo-fourth-guard-c': 'guard',
|
||||
'menghuo-fourth-guard-d': 'guard',
|
||||
'menghuo-fourth-shaman-a': 'hold',
|
||||
'menghuo-fourth-shaman-b': 'hold',
|
||||
'menghuo-fourth-shaman-c': 'hold',
|
||||
'menghuo-fourth-shaman-d': 'hold',
|
||||
'menghuo-fourth-officer-wutugu': 'guard',
|
||||
'menghuo-fourth-officer-mangyachang': 'aggressive',
|
||||
'menghuo-fourth-officer-dongtuna': 'guard',
|
||||
'menghuo-fourth-officer-ahuinan': 'guard',
|
||||
'menghuo-fourth-leader': 'hold'
|
||||
};
|
||||
|
||||
const defaultEnemyAiByClass: Partial<Record<UnitClassKey, EnemyAiBehavior>> = {
|
||||
@@ -2567,6 +2617,10 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.installDebugHotkeys();
|
||||
|
||||
this.add.rectangle(0, 0, width, height, 0x080b0d).setOrigin(0);
|
||||
this.ensureScenarioMapTexture(() => this.drawBattleScene());
|
||||
}
|
||||
|
||||
private drawBattleScene() {
|
||||
this.drawMap();
|
||||
this.drawUnits();
|
||||
this.drawSidePanel();
|
||||
@@ -2575,6 +2629,39 @@ export class BattleScene extends Phaser.Scene {
|
||||
this.renderRosterPanel('ally', '행동할 장수를 선택하세요.');
|
||||
}
|
||||
|
||||
private ensureScenarioMapTexture(onReady: () => void) {
|
||||
const textureKey = battleScenario.mapTextureKey;
|
||||
if (this.textures.exists(textureKey)) {
|
||||
onReady();
|
||||
return;
|
||||
}
|
||||
|
||||
const textureUrl = battleMapAssets[textureKey];
|
||||
if (!textureUrl) {
|
||||
throw new Error(`Missing battle map asset for ${textureKey}`);
|
||||
}
|
||||
|
||||
const loadingText = this.add.text(this.scale.width / 2, this.scale.height / 2, '전장 지도를 펼치는 중...', {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '22px',
|
||||
color: '#f5e6b8',
|
||||
stroke: '#05070a',
|
||||
strokeThickness: 4
|
||||
});
|
||||
loadingText.setOrigin(0.5);
|
||||
loadingText.setDepth(90);
|
||||
|
||||
this.load.once('complete', () => {
|
||||
loadingText.destroy();
|
||||
onReady();
|
||||
});
|
||||
this.load.once('loaderror', () => {
|
||||
loadingText.setText('전장 지도를 불러오지 못했습니다.');
|
||||
});
|
||||
this.load.image(textureKey, textureUrl);
|
||||
this.load.start();
|
||||
}
|
||||
|
||||
private resetBattleData(campaign?: CampaignState) {
|
||||
const selected = new Set(campaign?.selectedSortieUnitIds ?? []);
|
||||
const forcedAllyIds = new Set(
|
||||
|
||||
@@ -1,54 +1,4 @@
|
||||
import Phaser from 'phaser';
|
||||
import eighthBattleMapUrl from '../../assets/images/battle/eighth-battle-map.svg';
|
||||
import eighteenthBattleMapUrl from '../../assets/images/battle/eighteenth-battle-map.svg';
|
||||
import eleventhBattleMapUrl from '../../assets/images/battle/eleventh-battle-map.svg';
|
||||
import fiftiethBattleMapUrl from '../../assets/images/battle/fiftieth-battle-map.svg';
|
||||
import fifthBattleMapUrl from '../../assets/images/battle/fifth-battle-map.svg';
|
||||
import fifteenthBattleMapUrl from '../../assets/images/battle/fifteenth-battle-map.svg';
|
||||
import firstBattleMapUrl from '../../assets/images/battle/first-battle-map.png';
|
||||
import fortiethBattleMapUrl from '../../assets/images/battle/fortieth-battle-map.svg';
|
||||
import fortyFirstBattleMapUrl from '../../assets/images/battle/forty-first-battle-map.svg';
|
||||
import fortySecondBattleMapUrl from '../../assets/images/battle/forty-second-battle-map.svg';
|
||||
import fortyThirdBattleMapUrl from '../../assets/images/battle/forty-third-battle-map.svg';
|
||||
import fortyFourthBattleMapUrl from '../../assets/images/battle/forty-fourth-battle-map.svg';
|
||||
import fortyFifthBattleMapUrl from '../../assets/images/battle/forty-fifth-battle-map.svg';
|
||||
import fortyEighthBattleMapUrl from '../../assets/images/battle/forty-eighth-battle-map.svg';
|
||||
import fortyNinthBattleMapUrl from '../../assets/images/battle/forty-ninth-battle-map.svg';
|
||||
import fortySixthBattleMapUrl from '../../assets/images/battle/forty-sixth-battle-map.svg';
|
||||
import fortySeventhBattleMapUrl from '../../assets/images/battle/forty-seventh-battle-map.svg';
|
||||
import fourteenthBattleMapUrl from '../../assets/images/battle/fourteenth-battle-map.svg';
|
||||
import fourthBattleMapUrl from '../../assets/images/battle/fourth-battle-map.svg';
|
||||
import ninthBattleMapUrl from '../../assets/images/battle/ninth-battle-map.svg';
|
||||
import nineteenthBattleMapUrl from '../../assets/images/battle/nineteenth-battle-map.svg';
|
||||
import secondBattleMapUrl from '../../assets/images/battle/second-battle-map.svg';
|
||||
import seventhBattleMapUrl from '../../assets/images/battle/seventh-battle-map.svg';
|
||||
import sixthBattleMapUrl from '../../assets/images/battle/sixth-battle-map.svg';
|
||||
import sixteenthBattleMapUrl from '../../assets/images/battle/sixteenth-battle-map.svg';
|
||||
import seventeenthBattleMapUrl from '../../assets/images/battle/seventeenth-battle-map.svg';
|
||||
import tenthBattleMapUrl from '../../assets/images/battle/tenth-battle-map.svg';
|
||||
import thirteenthBattleMapUrl from '../../assets/images/battle/thirteenth-battle-map.svg';
|
||||
import thirtyFourthBattleMapUrl from '../../assets/images/battle/thirty-fourth-battle-map.svg';
|
||||
import thirtyEighthBattleMapUrl from '../../assets/images/battle/thirty-eighth-battle-map.svg';
|
||||
import thirtyFifthBattleMapUrl from '../../assets/images/battle/thirty-fifth-battle-map.svg';
|
||||
import thirtyFirstBattleMapUrl from '../../assets/images/battle/thirty-first-battle-map.svg';
|
||||
import thirtyNinthBattleMapUrl from '../../assets/images/battle/thirty-ninth-battle-map.svg';
|
||||
import thirtySecondBattleMapUrl from '../../assets/images/battle/thirty-second-battle-map.svg';
|
||||
import thirtyThirdBattleMapUrl from '../../assets/images/battle/thirty-third-battle-map.svg';
|
||||
import thirtySixthBattleMapUrl from '../../assets/images/battle/thirty-sixth-battle-map.svg';
|
||||
import thirtySeventhBattleMapUrl from '../../assets/images/battle/thirty-seventh-battle-map.svg';
|
||||
import thirtiethBattleMapUrl from '../../assets/images/battle/thirtieth-battle-map.svg';
|
||||
import thirdBattleMapUrl from '../../assets/images/battle/third-battle-map.svg';
|
||||
import twentyEighthBattleMapUrl from '../../assets/images/battle/twenty-eighth-battle-map.svg';
|
||||
import twentyFirstBattleMapUrl from '../../assets/images/battle/twenty-first-battle-map.svg';
|
||||
import twentySecondBattleMapUrl from '../../assets/images/battle/twenty-second-battle-map.svg';
|
||||
import twentyThirdBattleMapUrl from '../../assets/images/battle/twenty-third-battle-map.svg';
|
||||
import twentyFifthBattleMapUrl from '../../assets/images/battle/twenty-fifth-battle-map.svg';
|
||||
import twentyFourthBattleMapUrl from '../../assets/images/battle/twenty-fourth-battle-map.svg';
|
||||
import twentyNinthBattleMapUrl from '../../assets/images/battle/twenty-ninth-battle-map.svg';
|
||||
import twentySixthBattleMapUrl from '../../assets/images/battle/twenty-sixth-battle-map.svg';
|
||||
import twentySeventhBattleMapUrl from '../../assets/images/battle/twenty-seventh-battle-map.svg';
|
||||
import twentiethBattleMapUrl from '../../assets/images/battle/twentieth-battle-map.svg';
|
||||
import twelfthBattleMapUrl from '../../assets/images/battle/twelfth-battle-map.svg';
|
||||
import guanYuPortraitUrl from '../../assets/images/portraits/guan-yu.png';
|
||||
import liuBeiPortraitUrl from '../../assets/images/portraits/liu-bei.png';
|
||||
import zhangFeiPortraitUrl from '../../assets/images/portraits/zhang-fei.png';
|
||||
@@ -108,56 +58,6 @@ export class BootScene extends Phaser.Scene {
|
||||
this.load.image('story-three-heroes', storyThreeHeroesUrl);
|
||||
this.load.image('story-militia', storyMilitiaUrl);
|
||||
this.load.image('story-sortie', storySortieUrl);
|
||||
this.load.image('battle-map-first', firstBattleMapUrl);
|
||||
this.load.image('battle-map-second', secondBattleMapUrl);
|
||||
this.load.image('battle-map-third', thirdBattleMapUrl);
|
||||
this.load.image('battle-map-fourth', fourthBattleMapUrl);
|
||||
this.load.image('battle-map-fifth', fifthBattleMapUrl);
|
||||
this.load.image('battle-map-sixth', sixthBattleMapUrl);
|
||||
this.load.image('battle-map-seventh', seventhBattleMapUrl);
|
||||
this.load.image('battle-map-eighth', eighthBattleMapUrl);
|
||||
this.load.image('battle-map-ninth', ninthBattleMapUrl);
|
||||
this.load.image('battle-map-tenth', tenthBattleMapUrl);
|
||||
this.load.image('battle-map-eleventh', eleventhBattleMapUrl);
|
||||
this.load.image('battle-map-fiftieth', fiftiethBattleMapUrl);
|
||||
this.load.image('battle-map-twelfth', twelfthBattleMapUrl);
|
||||
this.load.image('battle-map-thirteenth', thirteenthBattleMapUrl);
|
||||
this.load.image('battle-map-fourteenth', fourteenthBattleMapUrl);
|
||||
this.load.image('battle-map-fifteenth', fifteenthBattleMapUrl);
|
||||
this.load.image('battle-map-sixteenth', sixteenthBattleMapUrl);
|
||||
this.load.image('battle-map-seventeenth', seventeenthBattleMapUrl);
|
||||
this.load.image('battle-map-eighteenth', eighteenthBattleMapUrl);
|
||||
this.load.image('battle-map-nineteenth', nineteenthBattleMapUrl);
|
||||
this.load.image('battle-map-twentieth', twentiethBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-first', twentyFirstBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-second', twentySecondBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-third', twentyThirdBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-fourth', twentyFourthBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-fifth', twentyFifthBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-sixth', twentySixthBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-seventh', twentySeventhBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-eighth', twentyEighthBattleMapUrl);
|
||||
this.load.image('battle-map-twenty-ninth', twentyNinthBattleMapUrl);
|
||||
this.load.image('battle-map-thirtieth', thirtiethBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-first', thirtyFirstBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-second', thirtySecondBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-third', thirtyThirdBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-fourth', thirtyFourthBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-fifth', thirtyFifthBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-sixth', thirtySixthBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-seventh', thirtySeventhBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-eighth', thirtyEighthBattleMapUrl);
|
||||
this.load.image('battle-map-thirty-ninth', thirtyNinthBattleMapUrl);
|
||||
this.load.image('battle-map-fortieth', fortiethBattleMapUrl);
|
||||
this.load.image('battle-map-forty-first', fortyFirstBattleMapUrl);
|
||||
this.load.image('battle-map-forty-second', fortySecondBattleMapUrl);
|
||||
this.load.image('battle-map-forty-third', fortyThirdBattleMapUrl);
|
||||
this.load.image('battle-map-forty-fourth', fortyFourthBattleMapUrl);
|
||||
this.load.image('battle-map-forty-fifth', fortyFifthBattleMapUrl);
|
||||
this.load.image('battle-map-forty-sixth', fortySixthBattleMapUrl);
|
||||
this.load.image('battle-map-forty-seventh', fortySeventhBattleMapUrl);
|
||||
this.load.image('battle-map-forty-eighth', fortyEighthBattleMapUrl);
|
||||
this.load.image('battle-map-forty-ninth', fortyNinthBattleMapUrl);
|
||||
this.load.image('portrait-liu-bei', liuBeiPortraitUrl);
|
||||
this.load.image('portrait-guan-yu', guanYuPortraitUrl);
|
||||
this.load.image('portrait-zhang-fei', zhangFeiPortraitUrl);
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
hanzhongScoutRecruitBonds,
|
||||
hanzhongScoutRecruitUnits,
|
||||
mengHuoThirdCaptureBonds,
|
||||
mengHuoFourthCaptureBonds,
|
||||
fanCastleBonds,
|
||||
fanCastleSiegeBonds,
|
||||
jingCollapseBonds,
|
||||
@@ -413,7 +414,8 @@ const campaignTimelineChapters: CampaignTimelineChapter[] = [
|
||||
'forty-seventh-battle-nanzhong-stabilization',
|
||||
'forty-eighth-battle-meng-huo-main-force',
|
||||
'forty-ninth-battle-meng-huo-second-capture',
|
||||
'fiftieth-battle-meng-huo-third-capture'
|
||||
'fiftieth-battle-meng-huo-third-capture',
|
||||
'fifty-first-battle-meng-huo-fourth-capture'
|
||||
],
|
||||
nextHints: ['왕업 선언', '번성 포위', '형주 위기', '이릉 화공', '남중 안정', '맹획 회유', '칠종칠금']
|
||||
}
|
||||
@@ -469,7 +471,8 @@ const campBattleIds = {
|
||||
fortySeventh: 'forty-seventh-battle-nanzhong-stabilization',
|
||||
fortyEighth: 'forty-eighth-battle-meng-huo-main-force',
|
||||
fortyNinth: 'forty-ninth-battle-meng-huo-second-capture',
|
||||
fiftieth: 'fiftieth-battle-meng-huo-third-capture'
|
||||
fiftieth: 'fiftieth-battle-meng-huo-third-capture',
|
||||
fiftyFirst: 'fifty-first-battle-meng-huo-fourth-capture'
|
||||
} as const;
|
||||
|
||||
const defaultRequiredSortieUnitIds = ['liu-bei'];
|
||||
@@ -1072,6 +1075,20 @@ const sortieRulesByBattleId: Partial<Record<BattleScenarioId, SortieRuleDefiniti
|
||||
{ unitId: 'huang-zhong', reason: '고지 궁병과 독천 주술사를 안전하게 견제합니다.' }
|
||||
],
|
||||
note: '칠종칠금 3차전은 맹획뿐 아니라 그를 따르는 호족들이 보는 싸움입니다. 제갈량을 중심으로 회유 문장, 장부, 산길 판단, 돌격 봉쇄를 균형 있게 배치하십시오.'
|
||||
},
|
||||
'fifty-first-battle-meng-huo-fourth-capture': {
|
||||
maxUnits: 7,
|
||||
requiredUnitIds: ['zhuge-liang'],
|
||||
recommended: [
|
||||
{ unitId: 'zhuge-liang', reason: '네 번째 생포와 회유 퇴로 유지의 필수 지휘관입니다.' },
|
||||
{ unitId: 'ma-liang', reason: '세 번째 생포 뒤 만든 호족 설득문을 전장 안에서 이어 갑니다.' },
|
||||
{ unitId: 'huang-quan', reason: '보증 장부로 회유 퇴로와 포로 귀환 약속을 지킵니다.' },
|
||||
{ unitId: 'wang-ping', reason: '열어 둔 산길과 독천 우회로를 읽어 호족 퇴로를 확보합니다.' },
|
||||
{ unitId: 'zhao-yun', reason: '등갑병과 맹수대가 회유로를 덮치지 못하게 중심을 지킵니다.' },
|
||||
{ unitId: 'ma-chao', reason: '남만 기병을 강하게 압박하되 추격선을 넘지 않게 합니다.' },
|
||||
{ unitId: 'ma-dai', reason: '마초와 함께 회유 퇴로 주변의 빠른 차단과 회수를 맡습니다.' }
|
||||
],
|
||||
note: '칠종칠금 4차전은 이전 군영의 호족 회유 선택이 전장 목표로 바뀌는 전투입니다. 생포만 노리지 말고, 회유 퇴로와 보증 장부를 지킬 편성을 고르십시오.'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5290,6 +5307,87 @@ const campDialogues: CampDialogue[] = [
|
||||
rewardExp: 19
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fourth-capture-zhuge-maliang-amnesty',
|
||||
title: '네 번째 석방의 조건',
|
||||
availableAfterBattleIds: [campBattleIds.fiftyFirst],
|
||||
unitIds: ['zhuge-liang', 'ma-liang'],
|
||||
bondId: 'zhuge-liang__ma-liang_fourth-capture',
|
||||
rewardExp: 64,
|
||||
lines: [
|
||||
'마량: 이번에는 물러난 호족들이 직접 회유 퇴로가 지켜졌다고 말할 것입니다.',
|
||||
'제갈량: 그 말이 남중 안에서 맹획의 말과 겨루게 됩니다. 네 번째 석방은 약함이 아니라 약속을 지키는 힘이어야 합니다.',
|
||||
'마량: 다음에는 강경파가 그 말을 끊으려 할 것입니다. 먼저 누구의 입을 열지 정해야겠습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'record-fourth-amnesty',
|
||||
label: '네 번째 보증문을 남긴다',
|
||||
response: '마량은 회유 퇴로를 통과한 호족들의 증언을 문서로 적었고, 제갈량은 다음 석방의 조건을 분명히 했습니다.',
|
||||
rewardExp: 23
|
||||
},
|
||||
{
|
||||
id: 'prepare-hardliner-questions',
|
||||
label: '강경파 질문을 준비한다',
|
||||
response: '제갈량은 끝까지 싸우려는 호족에게 던질 질문을 정했고, 마량은 마을 피해와 포로 귀환 기록을 함께 묶었습니다.',
|
||||
rewardExp: 22
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fourth-capture-huangquan-wangping-ledger',
|
||||
title: '퇴로와 장부의 보증',
|
||||
availableAfterBattleIds: [campBattleIds.fiftyFirst],
|
||||
unitIds: ['huang-quan', 'wang-ping'],
|
||||
bondId: 'huang-quan__wang-ping_fourth-capture',
|
||||
rewardExp: 60,
|
||||
lines: [
|
||||
'황권: 회유 퇴로를 열어 두었으니, 돌아간 자가 다시 창을 들면 장부가 먼저 흔들립니다.',
|
||||
'왕평: 그래서 길도 장부처럼 관리해야 합니다. 누구에게 열린 길인지, 어느 마을을 지나지 않는지 표시해야 합니다.',
|
||||
'황권: 다음 전투에서는 그 보증을 더 엄격히 봐야겠습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'seal-amnesty-ledger',
|
||||
label: '보증 장부를 봉한다',
|
||||
response: '황권은 회유 퇴로를 지난 이름들을 봉인했고, 왕평은 그들이 다시 병력으로 합류하지 못할 길을 표시했습니다.',
|
||||
rewardExp: 21
|
||||
},
|
||||
{
|
||||
id: 'separate-safe-roads',
|
||||
label: '안전 길목을 분리한다',
|
||||
response: '왕평은 마을길과 군용길을 다시 나누었고, 황권은 병사들이 보증 길목을 짓밟지 않도록 명령서를 적었습니다.',
|
||||
rewardExp: 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fourth-capture-machao-madai-pursuit',
|
||||
title: '추격하지 않는 속도',
|
||||
availableAfterBattleIds: [campBattleIds.fiftyFirst],
|
||||
unitIds: ['ma-chao', 'ma-dai'],
|
||||
bondId: 'ma-chao__ma-dai_fourth-capture',
|
||||
rewardExp: 58,
|
||||
lines: [
|
||||
'마대: 형님, 이번에는 달려가서 베는 것보다 멈추는 것이 더 어려웠습니다.',
|
||||
'마초: 남중의 기병은 밀어붙여야 무너진다. 하지만 퇴로를 밟으면 우리가 이긴 전장이 다시 적지가 된다.',
|
||||
'마대: 다음에는 빠르게 막되, 물러나는 길은 더 분명히 남기겠습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'mark-pursuit-line',
|
||||
label: '추격 금지선을 긋는다',
|
||||
response: '마초와 마대는 기병이 넘지 말아야 할 회유선을 정했고, 빠른 압박과 절제를 함께 훈련했습니다.',
|
||||
rewardExp: 20
|
||||
},
|
||||
{
|
||||
id: 'train-cavalry-recall',
|
||||
label: '기병 회수 신호를 맞춘다',
|
||||
response: '마대는 회수 신호를 짧게 정했고, 마초는 돌격대가 신호에 맞춰 멈추는 훈련을 반복시켰습니다.',
|
||||
rewardExp: 19
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -7478,6 +7576,65 @@ const campVisits: CampVisitDefinition[] = [
|
||||
itemRewards: ['상처약 10']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fourth-capture-ledger-seal',
|
||||
title: '보증 장부 봉인',
|
||||
location: '남중 포로장',
|
||||
availableAfterBattleIds: [campBattleIds.fiftyFirst],
|
||||
bondId: 'huang-quan__wang-ping_fourth-capture',
|
||||
description: '황권과 왕평이 네 번째 생포 뒤 회유 퇴로를 지나간 호족과 포로의 이름을 따로 봉인합니다.',
|
||||
lines: [
|
||||
'황권: 이 장부는 항복한 자를 벌하기 위한 것이 아니라, 약속을 지키기 위한 증거입니다.',
|
||||
'왕평: 길목마다 같은 표식을 세우겠습니다. 병사도 호족도 이 선을 넘지 말아야 합니다.',
|
||||
'포로장 한가운데에는 봉인된 장부와 회유 퇴로 표식이 함께 놓였습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'seal-clan-guarantees',
|
||||
label: '호족 보증을 봉한다',
|
||||
response: '황권은 보증 장부를 봉했고, 왕평은 퇴로 표식을 각 길목에 나누어 보냈습니다.',
|
||||
bondExp: 50,
|
||||
itemRewards: ['호족 보증 장부 1']
|
||||
},
|
||||
{
|
||||
id: 'mark-returning-families',
|
||||
label: '돌아간 가족을 표시한다',
|
||||
response: '왕평은 귀환한 가족들의 마을을 표시했고, 황권은 병사들이 그 마을을 징발하지 못하게 했습니다.',
|
||||
bondExp: 48,
|
||||
gold: 1680,
|
||||
itemRewards: ['회유 퇴로 표식 1']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fourth-capture-fire-forts',
|
||||
title: '화덕 요새의 불씨',
|
||||
location: '남중 화덕 요새',
|
||||
availableAfterBattleIds: [campBattleIds.fiftyFirst],
|
||||
bondId: 'ma-chao__ma-dai_fourth-capture',
|
||||
description: '마초와 마대가 등갑병의 화덕 요새를 살펴, 다음 전투에서 불씨가 마을로 번지지 않게 정리합니다.',
|
||||
lines: [
|
||||
'마초: 화덕은 무기로도 쓰이고 겁주는 표식으로도 쓰이는군.',
|
||||
'마대: 불씨를 모두 꺼 버리면 산마을의 밤도 위험합니다. 쓸 곳과 막을 곳을 나누겠습니다.',
|
||||
'요새 주변에는 꺼진 화덕과 남겨 둘 신호불이 따로 표시되었습니다.'
|
||||
],
|
||||
choices: [
|
||||
{
|
||||
id: 'separate-war-fires',
|
||||
label: '전투 화덕을 분리한다',
|
||||
response: '마초는 전투용 화덕을 치웠고, 마대는 마을 신호불만 남겨 병사들이 혼동하지 않게 했습니다.',
|
||||
bondExp: 46,
|
||||
itemRewards: ['상처약 12']
|
||||
},
|
||||
{
|
||||
id: 'train-fire-breaks',
|
||||
label: '방화선을 훈련한다',
|
||||
response: '마대는 숲과 마을 사이의 방화선을 표시했고, 마초는 기병이 불길을 피해 우회하는 길을 익혔습니다.',
|
||||
bondExp: 48,
|
||||
itemRewards: ['탁주 4']
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -7576,7 +7733,8 @@ export class CampScene extends Phaser.Scene {
|
||||
battleId === campBattleIds.fortySeventh ||
|
||||
battleId === campBattleIds.fortyEighth ||
|
||||
battleId === campBattleIds.fortyNinth ||
|
||||
battleId === campBattleIds.fiftieth
|
||||
battleId === campBattleIds.fiftieth ||
|
||||
battleId === campBattleIds.fiftyFirst
|
||||
) {
|
||||
this.campaign = ensureCampaignRosterUnits(
|
||||
[
|
||||
@@ -7629,7 +7787,8 @@ export class CampScene extends Phaser.Scene {
|
||||
...nanzhongRecoveryBonds,
|
||||
...mengHuoPacificationBonds,
|
||||
...mengHuoSecondCaptureBonds,
|
||||
...mengHuoThirdCaptureBonds
|
||||
...mengHuoThirdCaptureBonds,
|
||||
...mengHuoFourthCaptureBonds
|
||||
]
|
||||
);
|
||||
this.report = this.campaign.firstBattleReport ?? this.report;
|
||||
@@ -8267,6 +8426,9 @@ export class CampScene extends Phaser.Scene {
|
||||
if (this.campaign?.step === 'baidi-entrustment-camp') {
|
||||
return '백제성 유탁 후 군영';
|
||||
}
|
||||
if (battleId === campBattleIds.fiftyFirst) {
|
||||
return '칠종칠금 4차전 후 군영';
|
||||
}
|
||||
if (battleId === campBattleIds.fiftieth) {
|
||||
return '칠종칠금 3차전 후 군영';
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
eighteenthBattleScenario,
|
||||
eleventhBattleScenario,
|
||||
fiftiethBattleScenario,
|
||||
fiftyFirstBattleScenario,
|
||||
fortiethBattleScenario,
|
||||
fortyFirstBattleScenario,
|
||||
fortySecondBattleScenario,
|
||||
@@ -400,6 +401,7 @@ export class TitleScene extends Phaser.Scene {
|
||||
campaign.step === 'forty-eighth-camp' ||
|
||||
campaign.step === 'forty-ninth-camp' ||
|
||||
campaign.step === 'fiftieth-camp' ||
|
||||
campaign.step === 'fifty-first-camp' ||
|
||||
campaign.step === 'hanzhong-king-camp' ||
|
||||
campaign.step === 'shu-han-foundation-camp' ||
|
||||
campaign.step === 'baidi-entrustment-camp'
|
||||
@@ -658,6 +660,11 @@ export class TitleScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'fifty-first-battle') {
|
||||
this.scene.start('BattleScene', { battleId: fiftyFirstBattleScenario.id });
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'first-victory-story') {
|
||||
this.scene.start('StoryScene', { pages: firstBattleVictoryPages, nextScene: 'TitleScene' });
|
||||
return;
|
||||
|
||||
@@ -142,6 +142,8 @@ export type CampaignStep =
|
||||
| 'forty-ninth-camp'
|
||||
| 'fiftieth-battle'
|
||||
| 'fiftieth-camp'
|
||||
| 'fifty-first-battle'
|
||||
| 'fifty-first-camp'
|
||||
| 'hanzhong-king-camp'
|
||||
| 'shu-han-foundation-camp'
|
||||
| 'baidi-entrustment-camp';
|
||||
@@ -300,7 +302,8 @@ const campaignBattleSteps: Record<string, { victory: CampaignStep; retry: Campai
|
||||
'forty-seventh-battle-nanzhong-stabilization': { victory: 'forty-seventh-camp', retry: 'forty-seventh-battle' },
|
||||
'forty-eighth-battle-meng-huo-main-force': { victory: 'forty-eighth-camp', retry: 'forty-eighth-battle' },
|
||||
'forty-ninth-battle-meng-huo-second-capture': { victory: 'forty-ninth-camp', retry: 'forty-ninth-battle' },
|
||||
'fiftieth-battle-meng-huo-third-capture': { victory: 'fiftieth-camp', retry: 'fiftieth-battle' }
|
||||
'fiftieth-battle-meng-huo-third-capture': { victory: 'fiftieth-camp', retry: 'fiftieth-battle' },
|
||||
'fifty-first-battle-meng-huo-fourth-capture': { victory: 'fifty-first-camp', retry: 'fifty-first-battle' }
|
||||
};
|
||||
|
||||
export type CampaignSaveSlotSummary = {
|
||||
|
||||
Reference in New Issue
Block a user