feat: add second-victory relief exploration
This commit is contained in:
@@ -39,6 +39,11 @@ import {
|
||||
resolveFirstPursuitScoutMemory
|
||||
} from '../data/firstPursuitScoutMemory';
|
||||
import { firstPursuitScoutVisitDefinition } from '../data/firstPursuitScoutVisit';
|
||||
import {
|
||||
secondBattleReliefExplorationDefinition,
|
||||
secondBattleReliefSourceBattleId,
|
||||
secondBattleReliefVisitId
|
||||
} from '../data/secondBattleReliefExploration';
|
||||
import {
|
||||
findCityStayAfterBattle,
|
||||
type CityEquipmentOffer,
|
||||
@@ -231,6 +236,7 @@ import {
|
||||
collectCityStayInformation,
|
||||
purchaseCityStayEquipment
|
||||
} from '../state/cityStayActions';
|
||||
import { secondBattleReliefProgress } from '../state/secondBattleReliefActions';
|
||||
import { clearCampaignBattleSavesForSlot } from '../state/battleSaveKeys';
|
||||
import { releaseTextureSource } from '../render/loaderLifecycle';
|
||||
import { palette } from '../ui/palette';
|
||||
@@ -300,6 +306,11 @@ type CampVisitChoice = {
|
||||
itemRewards?: string[];
|
||||
};
|
||||
|
||||
const directExplorationVisitIds = new Set([
|
||||
firstPursuitScoutVisitId,
|
||||
secondBattleReliefVisitId
|
||||
]);
|
||||
|
||||
type CampTabButtonView = {
|
||||
tab: CampTab;
|
||||
bg: Phaser.GameObjects.Rectangle;
|
||||
@@ -8410,6 +8421,26 @@ const campVisits: CampVisitDefinition[] = [
|
||||
itemRewards: [...choice.itemRewards]
|
||||
}))
|
||||
},
|
||||
{
|
||||
id: secondBattleReliefExplorationDefinition.id,
|
||||
title: secondBattleReliefExplorationDefinition.title,
|
||||
location: secondBattleReliefExplorationDefinition.location,
|
||||
availableAfterBattleIds: [secondBattleReliefSourceBattleId],
|
||||
availableDuringSteps: ['second-camp'],
|
||||
description: secondBattleReliefExplorationDefinition.description,
|
||||
lines: secondBattleReliefExplorationDefinition.introLines.map(
|
||||
(line) => `${line.speaker}: ${line.text}`
|
||||
),
|
||||
choices: secondBattleReliefExplorationDefinition.choices.map(
|
||||
(choice) => ({
|
||||
id: choice.id,
|
||||
label: choice.label,
|
||||
response: choice.response,
|
||||
bondExp: choice.bondExp,
|
||||
itemRewards: [...choice.itemRewards]
|
||||
})
|
||||
)
|
||||
},
|
||||
{
|
||||
id: 'jingzhou-scholar-rumors',
|
||||
title: '형주 선비들의 모임',
|
||||
@@ -11389,6 +11420,7 @@ export class CampScene extends Phaser.Scene {
|
||||
private campDialogueBodyText?: Phaser.GameObjects.Text;
|
||||
private selectedVisitId = campVisits[0].id;
|
||||
private firstPursuitExplorationButton?: Phaser.GameObjects.Rectangle;
|
||||
private secondBattleReliefExplorationButton?: Phaser.GameObjects.Rectangle;
|
||||
private equipmentInventoryPage = 0;
|
||||
private equipmentPanelBackground?: Phaser.GameObjects.Rectangle;
|
||||
private equipmentInventoryPreviousButton?: Phaser.GameObjects.Rectangle;
|
||||
@@ -11514,6 +11546,7 @@ export class CampScene extends Phaser.Scene {
|
||||
this.campDialogueChoiceButtons = {};
|
||||
this.campDialogueBodyText = undefined;
|
||||
this.firstPursuitExplorationButton = undefined;
|
||||
this.secondBattleReliefExplorationButton = undefined;
|
||||
this.dialogueObjects = [];
|
||||
this.sortieObjects = [];
|
||||
this.sortieComparisonPanelView = undefined;
|
||||
@@ -11625,12 +11658,13 @@ export class CampScene extends Phaser.Scene {
|
||||
} else if (this.activeTab === 'city') {
|
||||
this.activeTab = 'status';
|
||||
}
|
||||
const pendingFirstPursuitScoutVisit = this.availableCampVisits().some(
|
||||
const pendingDirectExplorationVisit = this.availableCampVisits().find(
|
||||
(visit) =>
|
||||
visit.id === firstPursuitScoutVisitId &&
|
||||
directExplorationVisitIds.has(visit.id) &&
|
||||
!this.completedCampVisits().includes(visit.id)
|
||||
);
|
||||
if (!cityStay && pendingFirstPursuitScoutVisit && this.activeTab === 'status') {
|
||||
if (!cityStay && pendingDirectExplorationVisit) {
|
||||
this.selectedVisitId = pendingDirectExplorationVisit.id;
|
||||
this.activeTab = 'visit';
|
||||
}
|
||||
soundDirector.playSoundscape({
|
||||
@@ -23361,20 +23395,32 @@ export class CampScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
if (visit.id === firstPursuitScoutVisitId) {
|
||||
if (directExplorationVisitIds.has(visit.id)) {
|
||||
const secondRelief = visit.id === secondBattleReliefVisitId;
|
||||
const reliefProgress = secondRelief && this.campaign
|
||||
? secondBattleReliefProgress(this.campaign)
|
||||
: undefined;
|
||||
const guide = this.track(this.add.rectangle(x + 18, y + height - 102, width - 36, 84, 0x151f2a, 0.96));
|
||||
guide.setOrigin(0);
|
||||
guide.setStrokeStyle(1, palette.blue, 0.62);
|
||||
this.track(this.add.text(
|
||||
x + 32,
|
||||
y + height - 90,
|
||||
'유비를 움직여 간옹에게 직접 말을 거세요.',
|
||||
secondRelief
|
||||
? reliefProgress?.choiceReady
|
||||
? '현장 확인 완료 · 간옹과 광종 진군 방침을 정하세요.'
|
||||
: reliefProgress && reliefProgress.completedObjectiveIds.length > 0
|
||||
? `유비를 움직여 현장 수습을 이어가세요 · ${Math.min(3, reliefProgress.completedObjectiveIds.length)}/3 기록됨`
|
||||
: '유비를 움직여 북쪽 마을과 나루를 직접 살피세요.'
|
||||
: '유비를 움직여 간옹에게 직접 말을 거세요.',
|
||||
this.textStyle(13, '#d4dce6', true)
|
||||
));
|
||||
this.track(this.add.text(
|
||||
x + 32,
|
||||
y + height - 68,
|
||||
'WASD·방향키 이동 · E/Space 대화',
|
||||
secondRelief
|
||||
? '관우 → 사공 → 장비 → 간옹 · 진행 자동 저장'
|
||||
: 'WASD·방향키 이동 · E/Space 대화',
|
||||
this.textStyle(11, '#9fb0bf')
|
||||
));
|
||||
|
||||
@@ -23389,12 +23435,22 @@ export class CampScene extends Phaser.Scene {
|
||||
button.on('pointerover', () => button.setFillStyle(0x654c25, 1));
|
||||
button.on('pointerout', () => button.setFillStyle(0x4a371d, 0.98));
|
||||
button.on('pointerdown', openExploration);
|
||||
this.firstPursuitExplorationButton = button;
|
||||
if (secondRelief) {
|
||||
this.secondBattleReliefExplorationButton = button;
|
||||
} else {
|
||||
this.firstPursuitExplorationButton = button;
|
||||
}
|
||||
|
||||
const label = this.track(this.add.text(
|
||||
x + width / 2,
|
||||
buttonY,
|
||||
'정찰막으로 이동',
|
||||
secondRelief
|
||||
? reliefProgress?.choiceReady
|
||||
? '광종 진군 방침 결정'
|
||||
: reliefProgress && reliefProgress.completedObjectiveIds.length > 0
|
||||
? '현장 수습 이어가기'
|
||||
: '북쪽 마을·나루로 이동'
|
||||
: '정찰막으로 이동',
|
||||
this.textStyle(14, '#fff2b8', true)
|
||||
));
|
||||
label.setOrigin(0.5);
|
||||
@@ -24942,6 +24998,7 @@ export class CampScene extends Phaser.Scene {
|
||||
this.campDialogueChoiceButtons = {};
|
||||
this.campDialogueBodyText = undefined;
|
||||
this.firstPursuitExplorationButton = undefined;
|
||||
this.secondBattleReliefExplorationButton = undefined;
|
||||
this.campRosterLayout = undefined;
|
||||
this.cityPanelBackground = undefined;
|
||||
this.cityExploreButton = undefined;
|
||||
@@ -25102,6 +25159,14 @@ export class CampScene extends Phaser.Scene {
|
||||
(visit) => visit.id === firstPursuitScoutVisitId
|
||||
);
|
||||
const firstPursuitScoutMemory = this.firstPursuitScoutMemoryForNextSortie();
|
||||
const secondBattleReliefVisit = this.availableCampVisits().find(
|
||||
(visit) => visit.id === secondBattleReliefVisitId
|
||||
);
|
||||
const secondReliefProgress = this.campaign
|
||||
? secondBattleReliefProgress(this.campaign)
|
||||
: undefined;
|
||||
const secondReliefChoiceId =
|
||||
this.campaign?.campVisitChoiceIds[secondBattleReliefVisitId] ?? null;
|
||||
const availableCampDialogues = this.availableCampDialogues();
|
||||
const selectedCampDialogue = availableCampDialogues.find(
|
||||
(dialogue) => dialogue.id === this.selectedDialogueId
|
||||
@@ -25289,6 +25354,39 @@ export class CampScene extends Phaser.Scene {
|
||||
openingLines: firstPursuitScoutMemory ? [...firstPursuitScoutMemory.openingLines] : [],
|
||||
briefingSummaryBounds: this.sortieTextBoundsDebug(this.sortieBriefingScoutSummaryText)
|
||||
},
|
||||
secondBattleReliefExploration: {
|
||||
visitId: secondBattleReliefVisitId,
|
||||
sourceBattleId: secondBattleReliefSourceBattleId,
|
||||
available: Boolean(secondBattleReliefVisit),
|
||||
selected: this.selectedVisitId === secondBattleReliefVisitId,
|
||||
completed: Boolean(secondReliefProgress?.completed),
|
||||
mode: secondReliefProgress?.completed
|
||||
? 'completed'
|
||||
: secondBattleReliefVisit
|
||||
? secondReliefProgress &&
|
||||
secondReliefProgress.completedObjectiveIds.length > 0
|
||||
? 'resume-walkable-relief'
|
||||
: 'walkable-relief'
|
||||
: 'unavailable',
|
||||
explorationButtonBounds: this.sortieInteractiveObjectBoundsDebug(
|
||||
this.secondBattleReliefExplorationButton
|
||||
),
|
||||
explorationInteractive: Boolean(
|
||||
this.secondBattleReliefExplorationButton?.input?.enabled
|
||||
),
|
||||
completedObjectiveIds:
|
||||
secondReliefProgress?.completedObjectiveIds ?? [],
|
||||
nextObjectiveId: secondReliefProgress?.nextObjectiveId ?? null,
|
||||
choiceReady: secondReliefProgress?.choiceReady ?? false,
|
||||
choiceId: secondReliefChoiceId,
|
||||
choices:
|
||||
secondBattleReliefVisit?.choices.map((choice) => ({
|
||||
id: choice.id,
|
||||
label: choice.label,
|
||||
response: choice.response,
|
||||
rewardText: this.visitRewardText(choice)
|
||||
})) ?? []
|
||||
},
|
||||
selectedDialogue: selectedCampDialogue
|
||||
? {
|
||||
id: selectedCampDialogue.id,
|
||||
|
||||
Reference in New Issue
Block a user