|
|
|
|
@@ -128,9 +128,13 @@ const campBattleIds = {
|
|
|
|
|
third: 'third-battle-guangzong-road',
|
|
|
|
|
fourth: 'fourth-battle-guangzong-camp',
|
|
|
|
|
fifth: 'fifth-battle-sishui-vanguard',
|
|
|
|
|
sixth: 'sixth-battle-jieqiao-relief'
|
|
|
|
|
sixth: 'sixth-battle-jieqiao-relief',
|
|
|
|
|
seventh: 'seventh-battle-xuzhou-rescue'
|
|
|
|
|
} as const;
|
|
|
|
|
|
|
|
|
|
const requiredSortieUnitIds = new Set(['liu-bei']);
|
|
|
|
|
const maxSortieUnits = 6;
|
|
|
|
|
|
|
|
|
|
const campDialogues: CampDialogue[] = [
|
|
|
|
|
{
|
|
|
|
|
id: 'liu-guan-after-first-battle',
|
|
|
|
|
@@ -617,6 +621,87 @@ const campDialogues: CampDialogue[] = [
|
|
|
|
|
rewardExp: 6
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'liu-guan-after-xuzhou',
|
|
|
|
|
title: '서주의 무게',
|
|
|
|
|
availableAfterBattleIds: [campBattleIds.seventh],
|
|
|
|
|
unitIds: ['liu-bei', 'guan-yu'],
|
|
|
|
|
bondId: 'liu-bei__guan-yu',
|
|
|
|
|
rewardExp: 22,
|
|
|
|
|
lines: [
|
|
|
|
|
'유비: 도겸 공은 서주를 맡아 달라 하나, 내 그릇이 백성을 감당할 수 있을지 두렵소.',
|
|
|
|
|
'관우: 형님께서 두려워하시는 까닭은 땅이 아니라 백성을 먼저 보기 때문입니다. 그래서 맡을 수 있는 일입니다.',
|
|
|
|
|
'유비: 운장의 말처럼 두려움이 의를 잊지 않게 하는 끈이라면, 그 끈을 놓지 않겠소.'
|
|
|
|
|
],
|
|
|
|
|
choices: [
|
|
|
|
|
{
|
|
|
|
|
id: 'accept-responsibility',
|
|
|
|
|
label: '책임을 피하지 않는다',
|
|
|
|
|
response: '관우는 유비가 명분보다 책임을 먼저 말하는 것을 보고 깊이 고개를 끄덕였다.',
|
|
|
|
|
rewardExp: 9
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'listen-to-xuzhou',
|
|
|
|
|
label: '서주 사람들의 뜻을 듣는다',
|
|
|
|
|
response: '두 사람은 성급히 자리를 받기보다 백성의 마음을 먼저 살피기로 했다.',
|
|
|
|
|
rewardExp: 8
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'liu-zhang-after-xuzhou',
|
|
|
|
|
title: '성급함을 다스리다',
|
|
|
|
|
availableAfterBattleIds: [campBattleIds.seventh],
|
|
|
|
|
unitIds: ['liu-bei', 'zhang-fei'],
|
|
|
|
|
bondId: 'liu-bei__zhang-fei',
|
|
|
|
|
rewardExp: 22,
|
|
|
|
|
lines: [
|
|
|
|
|
'장비: 형님, 서주가 우리를 부른다면 시원하게 맡으면 되지 않습니까?',
|
|
|
|
|
'유비: 익덕, 기뻐할 일만은 아니오. 성 하나를 맡는다는 것은 그 성의 굶주림과 두려움도 함께 맡는 일이오.',
|
|
|
|
|
'장비: 그렇다면 제가 먼저 군량과 길목을 지키겠습니다. 백성이 굶는 일부터 막아야겠지요.'
|
|
|
|
|
],
|
|
|
|
|
choices: [
|
|
|
|
|
{
|
|
|
|
|
id: 'guard-supplies',
|
|
|
|
|
label: '군량 길목을 맡긴다',
|
|
|
|
|
response: '장비는 싸움보다 지키는 일이 더 어렵다는 말을 마음에 새겼다.',
|
|
|
|
|
rewardExp: 8
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'calm-the-temper',
|
|
|
|
|
label: '분노보다 절제를 당부한다',
|
|
|
|
|
response: '유비의 당부에 장비는 주먹을 풀고, 백성을 놀라게 하지 않겠다고 답했다.',
|
|
|
|
|
rewardExp: 9
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'guan-zhang-after-xuzhou',
|
|
|
|
|
title: '새 군영의 좌우',
|
|
|
|
|
availableAfterBattleIds: [campBattleIds.seventh],
|
|
|
|
|
unitIds: ['guan-yu', 'zhang-fei'],
|
|
|
|
|
bondId: 'guan-yu__zhang-fei',
|
|
|
|
|
rewardExp: 20,
|
|
|
|
|
lines: [
|
|
|
|
|
'관우: 서주는 넓고 사람의 마음은 아직 흩어져 있다. 우리가 먼저 흔들리면 형님의 짐이 더 무거워질 것이다.',
|
|
|
|
|
'장비: 걱정 마시오. 운장 형님이 군율을 세우면, 나는 군심을 붙잡겠습니다.',
|
|
|
|
|
'관우: 좋다. 이제 우리는 전장에서뿐 아니라 군영에서도 형님의 좌우가 되어야 한다.'
|
|
|
|
|
],
|
|
|
|
|
choices: [
|
|
|
|
|
{
|
|
|
|
|
id: 'divide-camp-duties',
|
|
|
|
|
label: '군율과 군심을 나눈다',
|
|
|
|
|
response: '관우와 장비는 서로의 강점을 인정하며 새 군영을 안정시키기로 했다.',
|
|
|
|
|
rewardExp: 8
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 'train-new-recruits',
|
|
|
|
|
label: '새 병사를 함께 훈련한다',
|
|
|
|
|
response: '두 장수의 훈련 방식은 달랐지만, 병사들은 그 사이에서 빠르게 자리를 잡았다.',
|
|
|
|
|
rewardExp: 7
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
@@ -631,6 +716,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
private sortieObjects: Phaser.GameObjects.GameObject[] = [];
|
|
|
|
|
private tabButtons: CampTabButtonView[] = [];
|
|
|
|
|
private visitedTabs = new Set<CampTab>();
|
|
|
|
|
private selectedSortieUnitIds: string[] = [];
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
super('CampScene');
|
|
|
|
|
@@ -645,6 +731,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
this.campaign = getCampaignState();
|
|
|
|
|
this.report = this.campaign.firstBattleReport ?? getFirstBattleReport() ?? this.createFallbackReport();
|
|
|
|
|
this.selectedUnitId = this.currentUnits().find((unit) => unit.faction === 'ally')?.id ?? 'liu-bei';
|
|
|
|
|
this.selectedSortieUnitIds = this.normalizedSortieUnitIds(this.campaign.selectedSortieUnitIds);
|
|
|
|
|
this.selectedDialogueId = this.availableCampDialogues()[0]?.id ?? campDialogues[0].id;
|
|
|
|
|
soundDirector.playMusic('militia-theme');
|
|
|
|
|
|
|
|
|
|
@@ -702,6 +789,9 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
|
|
|
|
|
private currentCampTitle() {
|
|
|
|
|
const battleId = this.currentCampBattleId();
|
|
|
|
|
if (battleId === campBattleIds.seventh) {
|
|
|
|
|
return '서주 인수 준비 군영';
|
|
|
|
|
}
|
|
|
|
|
if (battleId === campBattleIds.fifth) {
|
|
|
|
|
return '공손찬 진영 군영';
|
|
|
|
|
}
|
|
|
|
|
@@ -830,6 +920,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
this.hideSortiePrep();
|
|
|
|
|
this.campaign = getCampaignState();
|
|
|
|
|
this.report = this.campaign.firstBattleReport ?? this.report;
|
|
|
|
|
this.selectedSortieUnitIds = this.normalizedSortieUnitIds(this.campaign.selectedSortieUnitIds);
|
|
|
|
|
|
|
|
|
|
const depth = 40;
|
|
|
|
|
const width = 900;
|
|
|
|
|
@@ -850,7 +941,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
const title = this.trackSortie(this.add.text(x + 34, y + 28, '출진 준비', this.textStyle(30, '#f2e3bf', true)));
|
|
|
|
|
title.setDepth(depth + 2);
|
|
|
|
|
const subtitle = this.trackSortie(
|
|
|
|
|
this.add.text(x + 34, y + 70, '다음 전장으로 향하기 전 부대 상태와 준비 항목을 확인합니다.', this.textStyle(15, '#d4dce6'))
|
|
|
|
|
this.add.text(x + 34, y + 70, '대화, 보급, 상인 정비를 마친 뒤 함께 출전할 무장을 선택합니다.', this.textStyle(15, '#d4dce6'))
|
|
|
|
|
);
|
|
|
|
|
subtitle.setDepth(depth + 2);
|
|
|
|
|
|
|
|
|
|
@@ -910,25 +1001,39 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
bg.setOrigin(0);
|
|
|
|
|
bg.setDepth(depth);
|
|
|
|
|
bg.setStrokeStyle(1, palette.blue, 0.48);
|
|
|
|
|
this.trackSortie(this.add.text(x + 18, y + 14, '출진 부대', this.textStyle(18, '#f2e3bf', true))).setDepth(depth + 1);
|
|
|
|
|
const allies = this.sortieAllies();
|
|
|
|
|
const selectedCount = this.selectedSortieUnitIds.length;
|
|
|
|
|
this.trackSortie(
|
|
|
|
|
this.add.text(x + 18, y + 14, `출전 무장 선택 ${selectedCount}/${Math.min(maxSortieUnits, allies.length)}`, this.textStyle(18, '#f2e3bf', true))
|
|
|
|
|
).setDepth(depth + 1);
|
|
|
|
|
this.trackSortie(this.add.text(x + width - 18, y + 17, '클릭해서 출전/대기 전환', this.textStyle(12, '#9fb0bf'))).setOrigin(1, 0).setDepth(depth + 1);
|
|
|
|
|
|
|
|
|
|
this.currentUnits()
|
|
|
|
|
.filter((unit) => unit.faction === 'ally')
|
|
|
|
|
.forEach((unit, index) => {
|
|
|
|
|
const rowY = y + 52 + index * 30;
|
|
|
|
|
this.trackSortie(this.add.text(x + 18, rowY, `${unit.name} Lv ${unit.level}`, this.textStyle(14, '#f2e3bf', true))).setDepth(depth + 1);
|
|
|
|
|
this.trackSortie(this.add.text(x + 132, rowY, unit.className, this.textStyle(13, '#9fb0bf', true))).setDepth(depth + 1);
|
|
|
|
|
this.trackSortie(this.add.text(x + 236, rowY, `병력 ${unit.hp}/${unit.maxHp}`, this.textStyle(13, '#d4dce6', true))).setDepth(depth + 1);
|
|
|
|
|
this.drawSortieBar(x + 338, rowY + 6, 128, 7, unit.hp / unit.maxHp, palette.green, depth + 1);
|
|
|
|
|
allies.forEach((unit, index) => {
|
|
|
|
|
const rowY = y + 48 + index * 30;
|
|
|
|
|
const selected = this.isSortieSelected(unit.id);
|
|
|
|
|
const required = requiredSortieUnitIds.has(unit.id);
|
|
|
|
|
const row = this.trackSortie(this.add.rectangle(x + 18, rowY - 5, width - 36, 26, selected ? 0x172a22 : 0x151b24, selected ? 0.96 : 0.82));
|
|
|
|
|
row.setOrigin(0);
|
|
|
|
|
row.setDepth(depth + 1);
|
|
|
|
|
row.setStrokeStyle(1, selected ? palette.green : 0x53606c, selected ? 0.62 : 0.38);
|
|
|
|
|
row.setInteractive({ useHandCursor: !required });
|
|
|
|
|
row.on('pointerdown', () => this.toggleSortieUnit(unit.id));
|
|
|
|
|
|
|
|
|
|
const equipment = equipmentSlots
|
|
|
|
|
.map((slot) => {
|
|
|
|
|
const state = unit.equipment[slot];
|
|
|
|
|
return `${equipmentSlotLabels[slot]} Lv${state.level}`;
|
|
|
|
|
})
|
|
|
|
|
.join(' ');
|
|
|
|
|
this.trackSortie(this.add.text(x + 496, rowY, equipment, this.textStyle(12, '#d4dce6'))).setDepth(depth + 1);
|
|
|
|
|
});
|
|
|
|
|
const marker = selected ? '출전' : '대기';
|
|
|
|
|
this.trackSortie(this.add.text(x + 30, rowY, required ? '필수' : marker, this.textStyle(12, required ? '#ffdf7b' : selected ? '#a8ffd0' : '#9fb0bf', true))).setDepth(depth + 2);
|
|
|
|
|
this.trackSortie(this.add.text(x + 84, rowY, `${unit.name} Lv ${unit.level}`, this.textStyle(14, selected ? '#f2e3bf' : '#87919c', true))).setDepth(depth + 2);
|
|
|
|
|
this.trackSortie(this.add.text(x + 198, rowY, unit.className, this.textStyle(13, selected ? '#d4dce6' : '#77818c', true))).setDepth(depth + 2);
|
|
|
|
|
this.trackSortie(this.add.text(x + 310, rowY, `병력 ${unit.hp}/${unit.maxHp}`, this.textStyle(13, selected ? '#d4dce6' : '#77818c', true))).setDepth(depth + 2);
|
|
|
|
|
this.drawSortieBar(x + 414, rowY + 6, 102, 7, unit.hp / unit.maxHp, selected ? palette.green : 0x53606c, depth + 2);
|
|
|
|
|
|
|
|
|
|
const equipment = equipmentSlots
|
|
|
|
|
.map((slot) => {
|
|
|
|
|
const state = unit.equipment[slot];
|
|
|
|
|
return `${equipmentSlotLabels[slot]} Lv${state.level}`;
|
|
|
|
|
})
|
|
|
|
|
.join(' ');
|
|
|
|
|
this.trackSortie(this.add.text(x + 542, rowY, equipment, this.textStyle(12, selected ? '#d4dce6' : '#77818c'))).setDepth(depth + 2);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private renderSortieRewardHint(x: number, y: number, width: number, height: number, depth: number) {
|
|
|
|
|
@@ -939,9 +1044,10 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
const availableDialogues = this.availableCampDialogues();
|
|
|
|
|
const completedDialogues = this.completedAvailableDialogues().length;
|
|
|
|
|
const inventory = this.inventoryLabels().join(', ');
|
|
|
|
|
const selectedNames = this.selectedSortieUnits().map((unit) => unit.name).join(', ');
|
|
|
|
|
const reward = getSortieFlow(this.campaign?.latestBattleId).rewardHint;
|
|
|
|
|
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}/${availableDialogues.length} · 보유 ${inventory || '없음'}`, this.textStyle(12, '#d4dce6'))).setDepth(depth + 1);
|
|
|
|
|
this.trackSortie(this.add.text(x + 16, y + 30, `현재 준비: 대화 ${completedDialogues}/${availableDialogues.length} · 출전 ${selectedNames || '없음'} · 보유 ${inventory || '없음'}`, this.textStyle(12, '#d4dce6'))).setDepth(depth + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private nextSortieBriefing() {
|
|
|
|
|
@@ -960,6 +1066,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
const supplyCount = campSupplies.reduce((total, supply) => total + this.inventoryAmount(supply.label), 0);
|
|
|
|
|
const availableDialogues = this.availableCampDialogues();
|
|
|
|
|
const completedDialogues = this.completedAvailableDialogues().length;
|
|
|
|
|
const selected = this.selectedSortieUnits();
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
label: '유비 생존',
|
|
|
|
|
@@ -971,6 +1078,11 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
complete: injured.length === 0,
|
|
|
|
|
detail: injured.length === 0 ? '전원 완전한 병력' : `${injured.map((unit) => unit.name).join(', ')} 회복 권장`
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '출전 구성',
|
|
|
|
|
complete: selected.some((unit) => unit.id === 'liu-bei') && selected.length > 0,
|
|
|
|
|
detail: selected.length > 0 ? selected.map((unit) => unit.name).join(', ') : '출전 무장 선택 필요'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '소모품 보유',
|
|
|
|
|
complete: supplyCount > 0,
|
|
|
|
|
@@ -1007,6 +1119,10 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
|
|
|
|
|
private startVictoryStory() {
|
|
|
|
|
const flow = getSortieFlow(this.campaign?.latestBattleId);
|
|
|
|
|
if (!this.ensureSortieSelectionSaved()) {
|
|
|
|
|
this.showCampNotice('출전할 무장을 선택하세요. 유비는 반드시 출전해야 합니다.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!flow.nextBattleId || !flow.campaignStep || flow.pages.length === 0) {
|
|
|
|
|
this.hideSortiePrep();
|
|
|
|
|
@@ -1618,6 +1734,84 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
return this.report?.bonds ?? [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private sortieAllies() {
|
|
|
|
|
return this.currentUnits().filter((unit) => unit.faction === 'ally' && unit.hp > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private selectedSortieUnits() {
|
|
|
|
|
const selected = new Set(this.selectedSortieUnitIds);
|
|
|
|
|
return this.sortieAllies().filter((unit) => selected.has(unit.id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private normalizedSortieUnitIds(candidateIds?: string[]) {
|
|
|
|
|
const allies = this.sortieAllies();
|
|
|
|
|
const allyIds = new Set(allies.map((unit) => unit.id));
|
|
|
|
|
const useDefaultSelection = !candidateIds || candidateIds.length === 0;
|
|
|
|
|
const candidateSet = new Set((candidateIds ?? []).filter((id) => allyIds.has(id)));
|
|
|
|
|
requiredSortieUnitIds.forEach((id) => {
|
|
|
|
|
if (allyIds.has(id)) {
|
|
|
|
|
candidateSet.add(id);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (useDefaultSelection) {
|
|
|
|
|
allies.slice(0, maxSortieUnits).forEach((unit) => candidateSet.add(unit.id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const required = allies.filter((unit) => requiredSortieUnitIds.has(unit.id)).map((unit) => unit.id);
|
|
|
|
|
const optional = allies
|
|
|
|
|
.filter((unit) => !requiredSortieUnitIds.has(unit.id) && candidateSet.has(unit.id))
|
|
|
|
|
.slice(0, Math.max(0, maxSortieUnits - required.length))
|
|
|
|
|
.map((unit) => unit.id);
|
|
|
|
|
|
|
|
|
|
return [...new Set([...required, ...optional])].slice(0, maxSortieUnits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isSortieSelected(unitId: string) {
|
|
|
|
|
return this.selectedSortieUnitIds.includes(unitId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private toggleSortieUnit(unitId: string) {
|
|
|
|
|
const unit = this.sortieAllies().find((candidate) => candidate.id === unitId);
|
|
|
|
|
if (!unit) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (requiredSortieUnitIds.has(unitId)) {
|
|
|
|
|
this.showCampNotice(`${unit.name}는 반드시 출전해야 합니다.`);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const selected = new Set(this.selectedSortieUnitIds);
|
|
|
|
|
if (selected.has(unitId)) {
|
|
|
|
|
selected.delete(unitId);
|
|
|
|
|
} else if (selected.size >= maxSortieUnits) {
|
|
|
|
|
this.showCampNotice(`이번 전투는 최대 ${maxSortieUnits}명까지 출전할 수 있습니다.`);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
selected.add(unitId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.selectedSortieUnitIds = this.normalizedSortieUnitIds(Array.from(selected));
|
|
|
|
|
this.persistSortieSelection();
|
|
|
|
|
soundDirector.playSelect();
|
|
|
|
|
this.showSortiePrep();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ensureSortieSelectionSaved() {
|
|
|
|
|
this.selectedSortieUnitIds = this.normalizedSortieUnitIds(this.selectedSortieUnitIds);
|
|
|
|
|
if (!this.selectedSortieUnitIds.some((id) => requiredSortieUnitIds.has(id)) || this.selectedSortieUnitIds.length === 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
this.persistSortieSelection();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private persistSortieSelection() {
|
|
|
|
|
const campaign = this.campaign ?? getCampaignState();
|
|
|
|
|
campaign.selectedSortieUnitIds = [...this.selectedSortieUnitIds];
|
|
|
|
|
this.campaign = saveCampaignState(campaign);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private completedCampDialogues() {
|
|
|
|
|
if (this.campaign) {
|
|
|
|
|
return this.campaign.completedCampDialogues;
|
|
|
|
|
@@ -1684,6 +1878,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
sortieVisible: this.sortieObjects.length > 0,
|
|
|
|
|
selectedUnitId: this.selectedUnitId,
|
|
|
|
|
selectedDialogueId: this.selectedDialogueId,
|
|
|
|
|
selectedSortieUnitIds: [...this.selectedSortieUnitIds],
|
|
|
|
|
campBattleId: this.currentCampBattleId(),
|
|
|
|
|
campTitle: this.currentCampTitle(),
|
|
|
|
|
availableDialogueIds: this.availableCampDialogues().map((dialogue) => dialogue.id),
|
|
|
|
|
@@ -1693,6 +1888,7 @@ export class CampScene extends Phaser.Scene {
|
|
|
|
|
step: this.campaign.step,
|
|
|
|
|
gold: this.campaign.gold,
|
|
|
|
|
inventory: this.campaign.inventory,
|
|
|
|
|
selectedSortieUnitIds: this.campaign.selectedSortieUnitIds,
|
|
|
|
|
roster: this.campaign.roster.map((unit) => ({
|
|
|
|
|
id: unit.id,
|
|
|
|
|
name: unit.name,
|
|
|
|
|
|