Add third campaign battle path
This commit is contained in:
@@ -51,6 +51,17 @@ const unitTexture: Record<string, string> = {
|
||||
'pursuit-leader-han-seok': 'unit-rebel-leader'
|
||||
};
|
||||
|
||||
const unitTextureByClass: Partial<Record<UnitClassKey, string>> = {
|
||||
lord: 'unit-liu-bei',
|
||||
infantry: 'unit-guan-yu',
|
||||
spearman: 'unit-zhang-fei',
|
||||
archer: 'unit-rebel-archer',
|
||||
cavalry: 'unit-rebel-cavalry',
|
||||
bandit: 'unit-rebel',
|
||||
yellowTurban: 'unit-rebel',
|
||||
rebelLeader: 'unit-rebel-leader'
|
||||
};
|
||||
|
||||
const unitFrameRows: Record<UnitDirection, number> = {
|
||||
south: 0,
|
||||
east: 1,
|
||||
@@ -806,7 +817,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
private drawUnits() {
|
||||
battleUnits.forEach((unit) => {
|
||||
const sizeRatio = unit.faction === 'ally' ? 1.16 : 1.1;
|
||||
const textureBase = unitTexture[unit.id] ?? 'unit-rebel';
|
||||
const textureBase = unitTexture[unit.id] ?? unitTextureByClass[unit.classKey] ?? 'unit-rebel';
|
||||
const sprite = this.add.sprite(this.tileCenterX(unit.x), this.tileCenterY(unit.y), textureBase, this.unitFrameIndex('south'));
|
||||
sprite.setName(`unit-${unit.id}`);
|
||||
sprite.setDisplaySize(this.layout.tileSize * sizeRatio, this.layout.tileSize * sizeRatio);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Phaser from 'phaser';
|
||||
import firstBattleMapUrl from '../../assets/images/battle/first-battle-map.png';
|
||||
import secondBattleMapUrl from '../../assets/images/battle/second-battle-map.svg';
|
||||
import thirdBattleMapUrl from '../../assets/images/battle/third-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';
|
||||
@@ -62,6 +63,7 @@ export class BootScene extends Phaser.Scene {
|
||||
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('portrait-liu-bei', liuBeiPortraitUrl);
|
||||
this.load.image('portrait-guan-yu', guanYuPortraitUrl);
|
||||
this.load.image('portrait-zhang-fei', zhangFeiPortraitUrl);
|
||||
|
||||
@@ -2,8 +2,8 @@ import Phaser from 'phaser';
|
||||
import { soundDirector } from '../audio/SoundDirector';
|
||||
import { equipmentExpToNext, equipmentSlotLabels, equipmentSlots, getItem, type EquipmentSlot } from '../data/battleItems';
|
||||
import { getUnitClass } from '../data/battleRules';
|
||||
import { defaultBattleScenario, secondBattleScenario } from '../data/battles';
|
||||
import { firstBattleBonds, firstBattleUnits, secondBattleIntroPages, type PortraitKey, type UnitData } from '../data/scenario';
|
||||
import { defaultBattleScenario, secondBattleScenario, thirdBattleScenario } from '../data/battles';
|
||||
import { firstBattleBonds, firstBattleUnits, secondBattleIntroPages, thirdBattleIntroPages, type PortraitKey, type UnitData } from '../data/scenario';
|
||||
import {
|
||||
applyCampBondExp,
|
||||
getCampaignState,
|
||||
@@ -398,17 +398,30 @@ export class CampScene extends Phaser.Scene {
|
||||
bg.setStrokeStyle(1, palette.gold, 0.4);
|
||||
const completedDialogues = this.completedCampDialogues().length;
|
||||
const inventory = this.inventoryLabels().join(', ');
|
||||
const reward = this.campaign?.latestBattleId === secondBattleScenario.id ? '예상 보상: 다음 장 개방' : '예상 보상: 군자금, 소모품, 의용군 명성';
|
||||
const reward =
|
||||
this.campaign?.latestBattleId === thirdBattleScenario.id
|
||||
? '다음 장: 광종 본전 준비 중'
|
||||
: this.campaign?.latestBattleId === secondBattleScenario.id
|
||||
? `예상 보상: ${thirdBattleScenario.title} 개방`
|
||||
: '예상 보상: 군자금, 소모품, 의용군 명성';
|
||||
this.trackSortie(this.add.text(x + 16, y + 10, reward, this.textStyle(13, '#f2e3bf', true))).setDepth(depth + 1);
|
||||
this.trackSortie(this.add.text(x + 16, y + 30, `현재 준비: 대화 ${completedDialogues}/${campDialogues.length} · 보유 ${inventory || '없음'}`, this.textStyle(12, '#d4dce6'))).setDepth(depth + 1);
|
||||
}
|
||||
|
||||
private nextSortieBriefing() {
|
||||
if (this.campaign?.latestBattleId === thirdBattleScenario.id) {
|
||||
return {
|
||||
eyebrow: '다음 장 준비',
|
||||
title: '광종 본전',
|
||||
description: '광종 구원로는 열렸지만 황건 본대는 아직 건재합니다. 다음 작업에서 광종 본전과 더 큰 전장 목표를 이어 붙일 수 있습니다.'
|
||||
};
|
||||
}
|
||||
|
||||
if (this.campaign?.latestBattleId === secondBattleScenario.id) {
|
||||
return {
|
||||
eyebrow: '다음 이야기',
|
||||
title: '넓어지는 전장',
|
||||
description: '황건 잔당 추격을 마친 의용군은 탁현을 넘어 더 큰 난세의 흐름을 마주합니다. 다음 장으로 향하기 전 전투 결과를 정리합니다.'
|
||||
eyebrow: '다음 전장',
|
||||
title: thirdBattleScenario.title,
|
||||
description: '탁현을 넘어 광종으로 향하는 길목에서 황건 전령이 관군의 움직임을 본대로 전하려 합니다. 강가 요새와 좁은 길을 돌파해야 합니다.'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -471,8 +484,19 @@ export class CampScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private startVictoryStory() {
|
||||
if (this.campaign?.latestBattleId === thirdBattleScenario.id) {
|
||||
this.hideSortiePrep();
|
||||
this.showCampNotice('광종 본전은 다음 장으로 이어집니다. 군영에서 성장 상태를 정비하세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.campaign?.latestBattleId === secondBattleScenario.id) {
|
||||
this.scene.start('StoryScene', { pages: secondBattleScenario.victoryPages, nextScene: 'TitleScene' });
|
||||
markCampaignStep('third-battle');
|
||||
this.scene.start('StoryScene', {
|
||||
pages: [...secondBattleScenario.victoryPages, ...thirdBattleIntroPages],
|
||||
nextScene: 'BattleScene',
|
||||
nextSceneData: { battleId: thirdBattleScenario.id }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Phaser from 'phaser';
|
||||
import { soundDirector } from '../audio/SoundDirector';
|
||||
import { firstBattleVictoryPages } from '../data/scenario';
|
||||
import { secondBattleScenario } from '../data/battles';
|
||||
import { secondBattleScenario, thirdBattleScenario } from '../data/battles';
|
||||
import { hasCampaignSave, loadCampaignState, startNewCampaign } from '../state/campaignState';
|
||||
import { palette } from '../ui/palette';
|
||||
|
||||
@@ -299,7 +299,7 @@ export class TitleScene extends Phaser.Scene {
|
||||
soundDirector.playSelect();
|
||||
|
||||
const campaign = loadCampaignState();
|
||||
if (campaign.step === 'first-camp' || campaign.step === 'second-camp') {
|
||||
if (campaign.step === 'first-camp' || campaign.step === 'second-camp' || campaign.step === 'third-camp') {
|
||||
this.scene.start('CampScene');
|
||||
return;
|
||||
}
|
||||
@@ -314,6 +314,11 @@ export class TitleScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'third-battle') {
|
||||
this.scene.start('BattleScene', { battleId: thirdBattleScenario.id });
|
||||
return;
|
||||
}
|
||||
|
||||
if (campaign.step === 'first-victory-story') {
|
||||
this.scene.start('StoryScene', { pages: firstBattleVictoryPages, nextScene: 'TitleScene' });
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user