fix: preserve pursuit target through finisher
This commit is contained in:
@@ -73,6 +73,79 @@ async function clickSceneBounds(page, sceneKey, bounds) {
|
|||||||
await page.mouse.click(point.x, point.y);
|
await page.mouse.click(point.x, point.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function clickTitleContinue(page, slot = 1) {
|
||||||
|
const continueItem = await page.evaluate(() => {
|
||||||
|
const state =
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('TitleScene')
|
||||||
|
?.getDebugState?.();
|
||||||
|
return (
|
||||||
|
state?.focus?.scope === 'main'
|
||||||
|
? state.focus.items.find(
|
||||||
|
(item) =>
|
||||||
|
item.id === 'continue' &&
|
||||||
|
item.enabled === true
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
) ?? null;
|
||||||
|
});
|
||||||
|
assert(
|
||||||
|
continueItem?.bounds,
|
||||||
|
`Expected an enabled title continue control: ${JSON.stringify(
|
||||||
|
continueItem
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
await clickSceneBounds(
|
||||||
|
page,
|
||||||
|
'TitleScene',
|
||||||
|
continueItem.bounds
|
||||||
|
);
|
||||||
|
await page.waitForFunction(
|
||||||
|
() => {
|
||||||
|
const activeScenes =
|
||||||
|
window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||||
|
const state =
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('TitleScene')
|
||||||
|
?.getDebugState?.();
|
||||||
|
return (
|
||||||
|
!activeScenes.includes('TitleScene') ||
|
||||||
|
state?.navigating === true ||
|
||||||
|
state?.panels?.saveSlots === true
|
||||||
|
);
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
{ timeout: 10000 }
|
||||||
|
);
|
||||||
|
|
||||||
|
const saveSlotItem = await page.evaluate(
|
||||||
|
(requestedSlot) => {
|
||||||
|
const state =
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('TitleScene')
|
||||||
|
?.getDebugState?.();
|
||||||
|
if (state?.panels?.saveSlots !== true) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
state.focus?.items?.find(
|
||||||
|
(item) =>
|
||||||
|
item.id === `slot-${requestedSlot}` &&
|
||||||
|
item.enabled === true
|
||||||
|
) ?? null
|
||||||
|
);
|
||||||
|
},
|
||||||
|
slot
|
||||||
|
);
|
||||||
|
if (saveSlotItem) {
|
||||||
|
await clickSceneBounds(
|
||||||
|
page,
|
||||||
|
'TitleScene',
|
||||||
|
saveSlotItem.bounds
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function clickBattleDeploymentStart(page) {
|
async function clickBattleDeploymentStart(page) {
|
||||||
const point = await page.evaluate(() => {
|
const point = await page.evaluate(() => {
|
||||||
const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene');
|
const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene');
|
||||||
@@ -223,7 +296,7 @@ try {
|
|||||||
);
|
);
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForStoryReady(page);
|
await waitForStoryReady(page);
|
||||||
const resumedPrologue = await page.evaluate(() => window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.());
|
const resumedPrologue = await page.evaluate(() => window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.());
|
||||||
const resumedPrologueSave = await readCampaignSave(page);
|
const resumedPrologueSave = await readCampaignSave(page);
|
||||||
@@ -1398,11 +1471,13 @@ try {
|
|||||||
cutInOrder.push(isPrimary ? 'primary' : result === counterResult || result.isCounter ? 'counter' : 'other');
|
cutInOrder.push(isPrimary ? 'primary' : result === counterResult || result.isCounter ? 'counter' : 'other');
|
||||||
if (isPrimary) {
|
if (isPrimary) {
|
||||||
primaryCutInStarted = true;
|
primaryCutInStarted = true;
|
||||||
|
this.updateCameraView();
|
||||||
visibleAtCutInStart = viewState();
|
visibleAtCutInStart = viewState();
|
||||||
}
|
}
|
||||||
await originalPlayCombatCutIn.call(this, result);
|
await originalPlayCombatCutIn.call(this, result);
|
||||||
if (isPrimary) {
|
if (isPrimary) {
|
||||||
primaryCutInCompleted = true;
|
primaryCutInCompleted = true;
|
||||||
|
this.updateCameraView();
|
||||||
visibleAtCutInEnd = viewState();
|
visibleAtCutInEnd = viewState();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1448,6 +1523,10 @@ try {
|
|||||||
visibleAtCutInEnd,
|
visibleAtCutInEnd,
|
||||||
defeatApplications,
|
defeatApplications,
|
||||||
visibleAfterWrapper: viewState(),
|
visibleAfterWrapper: viewState(),
|
||||||
|
pendingDefeatPresentationAfterWrapper:
|
||||||
|
scene.pendingDefeatPresentationUnitIds.has(
|
||||||
|
target.id
|
||||||
|
),
|
||||||
counterCalls,
|
counterCalls,
|
||||||
counterProduced,
|
counterProduced,
|
||||||
cutInOrder,
|
cutInOrder,
|
||||||
@@ -1594,8 +1673,10 @@ try {
|
|||||||
productionFinisher.visibleAfterWrapper.spriteVisible === false &&
|
productionFinisher.visibleAfterWrapper.spriteVisible === false &&
|
||||||
productionFinisher.visibleAfterWrapper.spriteAlpha === 0 &&
|
productionFinisher.visibleAfterWrapper.spriteAlpha === 0 &&
|
||||||
productionFinisher.visibleAfterWrapper.labelVisible === false &&
|
productionFinisher.visibleAfterWrapper.labelVisible === false &&
|
||||||
|
productionFinisher.visibleAfterWrapper.hitZoneVisible === false &&
|
||||||
productionFinisher.visibleAfterWrapper.miniMapDotVisible === false &&
|
productionFinisher.visibleAfterWrapper.miniMapDotVisible === false &&
|
||||||
productionFinisher.counterCalls === 1 &&
|
productionFinisher.pendingDefeatPresentationAfterWrapper === false &&
|
||||||
|
productionFinisher.counterCalls === 0 &&
|
||||||
productionFinisher.counterProduced === false &&
|
productionFinisher.counterProduced === false &&
|
||||||
productionFinisher.result.counter === false &&
|
productionFinisher.result.counter === false &&
|
||||||
JSON.stringify(productionFinisher.cutInOrder) === JSON.stringify(['primary']),
|
JSON.stringify(productionFinisher.cutInOrder) === JSON.stringify(['primary']),
|
||||||
@@ -2692,7 +2773,7 @@ try {
|
|||||||
);
|
);
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForStoryReady(page);
|
await waitForStoryReady(page);
|
||||||
const resumedFirstAftermath = await page.evaluate(() => window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.());
|
const resumedFirstAftermath = await page.evaluate(() => window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.());
|
||||||
const resumedFirstAftermathSave = await readCampaignSave(page);
|
const resumedFirstAftermathSave = await readCampaignSave(page);
|
||||||
@@ -5826,7 +5907,7 @@ try {
|
|||||||
});
|
});
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
|
|
||||||
const requiredCasualtyRecruitment = await page.evaluate(() => {
|
const requiredCasualtyRecruitment = await page.evaluate(() => {
|
||||||
@@ -5893,7 +5974,7 @@ try {
|
|||||||
|
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
const requiredCasualtyCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
const requiredCasualtyCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||||
assert(
|
assert(
|
||||||
@@ -6204,7 +6285,7 @@ try {
|
|||||||
});
|
});
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
const midCampaignSelectionFixture = await page.evaluate((requestedUnitIds) => {
|
const midCampaignSelectionFixture = await page.evaluate((requestedUnitIds) => {
|
||||||
const scene = window.__HEROS_GAME__?.scene.getScene('CampScene');
|
const scene = window.__HEROS_GAME__?.scene.getScene('CampScene');
|
||||||
@@ -7351,7 +7432,7 @@ try {
|
|||||||
|
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
const restoredUnderCapacityState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
const restoredUnderCapacityState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||||
assert(
|
assert(
|
||||||
@@ -8334,7 +8415,7 @@ try {
|
|||||||
});
|
});
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
await waitForCampSkinTransition(page, 'northern');
|
await waitForCampSkinTransition(page, 'northern');
|
||||||
await waitForCampSoundscapeTransition(page, 'camp-frontier', 'mountain-wind-ambience');
|
await waitForCampSoundscapeTransition(page, 'camp-frontier', 'mountain-wind-ambience');
|
||||||
@@ -8476,7 +8557,7 @@ try {
|
|||||||
|
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForCamp(page);
|
await waitForCamp(page);
|
||||||
await waitForCampSkinTransition(page, 'northern');
|
await waitForCampSkinTransition(page, 'northern');
|
||||||
const resumedFinalCampAfterRewardClose = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
const resumedFinalCampAfterRewardClose = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||||
@@ -8515,7 +8596,7 @@ try {
|
|||||||
|
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
await waitForTitle(page);
|
await waitForTitle(page);
|
||||||
await clickLegacyUi(page, 962, 310);
|
await clickTitleContinue(page);
|
||||||
await waitForEnding(page);
|
await waitForEnding(page);
|
||||||
await page.screenshot({ path: `${screenshotDir}/rc-ending-continue.png`, fullPage: true });
|
await page.screenshot({ path: `${screenshotDir}/rc-ending-continue.png`, fullPage: true });
|
||||||
await assertCanvasPainted(page, 'ending continue');
|
await assertCanvasPainted(page, 'ending continue');
|
||||||
@@ -8573,8 +8654,28 @@ async function waitForTitle(page) {
|
|||||||
await page.waitForFunction(() => window.__HEROS_DEBUG__ !== undefined, undefined, { timeout: 90000 });
|
await page.waitForFunction(() => window.__HEROS_DEBUG__ !== undefined, undefined, { timeout: 90000 });
|
||||||
await page.waitForFunction(() => {
|
await page.waitForFunction(() => {
|
||||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||||
return activeScenes.includes('TitleScene');
|
const state =
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('TitleScene')
|
||||||
|
?.getDebugState?.();
|
||||||
|
return (
|
||||||
|
activeScenes.includes('TitleScene') &&
|
||||||
|
state?.scene === 'TitleScene' &&
|
||||||
|
state.navigating === false &&
|
||||||
|
Array.isArray(state.focus?.items) &&
|
||||||
|
state.focus.items.some(
|
||||||
|
(item) =>
|
||||||
|
item.enabled === true &&
|
||||||
|
Number.isFinite(item.bounds?.x) &&
|
||||||
|
Number.isFinite(item.bounds?.y) &&
|
||||||
|
Number.isFinite(item.bounds?.width) &&
|
||||||
|
Number.isFinite(item.bounds?.height)
|
||||||
|
)
|
||||||
|
);
|
||||||
}, undefined, { timeout: 90000 });
|
}, undefined, { timeout: 90000 });
|
||||||
|
await page.evaluate(() => new Promise((resolve) => {
|
||||||
|
requestAnimationFrame(() => requestAnimationFrame(resolve));
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function assertReleaseShellReady(page) {
|
async function assertReleaseShellReady(page) {
|
||||||
@@ -10641,16 +10742,41 @@ async function waitForBattleOutcome(page, outcome) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function waitForCamp(page) {
|
async function waitForCamp(page) {
|
||||||
await page.waitForFunction(() => {
|
try {
|
||||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
await page.waitForFunction(() => {
|
||||||
const scene = window.__HEROS_DEBUG__?.scene('CampScene');
|
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||||
return (
|
const scene = window.__HEROS_DEBUG__?.scene('CampScene');
|
||||||
activeScenes.includes('CampScene') &&
|
return (
|
||||||
!activeScenes.includes('BattleScene') &&
|
activeScenes.includes('CampScene') &&
|
||||||
window.__HEROS_DEBUG__?.camp()?.scene === 'CampScene' &&
|
!activeScenes.includes('BattleScene') &&
|
||||||
(scene?.contentObjects?.length ?? 0) > 0
|
window.__HEROS_DEBUG__?.camp()?.scene === 'CampScene' &&
|
||||||
|
(scene?.contentObjects?.length ?? 0) > 0
|
||||||
|
);
|
||||||
|
}, undefined, { timeout: 90000 });
|
||||||
|
} catch (error) {
|
||||||
|
const diagnostic = await page.evaluate(() => ({
|
||||||
|
activeScenes:
|
||||||
|
window.__HEROS_DEBUG__?.activeScenes() ?? [],
|
||||||
|
title:
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('TitleScene')
|
||||||
|
?.getDebugState?.() ?? null,
|
||||||
|
battle:
|
||||||
|
window.__HEROS_DEBUG__?.battle?.() ?? null,
|
||||||
|
camp:
|
||||||
|
window.__HEROS_DEBUG__?.camp?.() ?? null,
|
||||||
|
story:
|
||||||
|
window.__HEROS_DEBUG__
|
||||||
|
?.scene('StoryScene')
|
||||||
|
?.getDebugState?.() ?? null
|
||||||
|
}));
|
||||||
|
throw new Error(
|
||||||
|
`Expected a ready camp scene: ${JSON.stringify(
|
||||||
|
diagnostic
|
||||||
|
)}`,
|
||||||
|
{ cause: error }
|
||||||
);
|
);
|
||||||
}, undefined, { timeout: 90000 });
|
}
|
||||||
await page.evaluate(() => new Promise((resolve) => {
|
await page.evaluate(() => new Promise((resolve) => {
|
||||||
requestAnimationFrame(() => requestAnimationFrame(resolve));
|
requestAnimationFrame(() => requestAnimationFrame(resolve));
|
||||||
}));
|
}));
|
||||||
@@ -12411,12 +12537,33 @@ async function readBattleDoctrineProbe(page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function seedCampaignSave(page, options) {
|
async function seedCampaignSave(page, options) {
|
||||||
|
await page.evaluate(() => {
|
||||||
|
const game = window.__HEROS_GAME__;
|
||||||
|
game?.scene
|
||||||
|
.getScenes(true)
|
||||||
|
.forEach((scene) =>
|
||||||
|
game.scene.stop(scene.scene.key)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await page.evaluate(
|
||||||
|
() =>
|
||||||
|
new Promise((resolve) =>
|
||||||
|
requestAnimationFrame(() =>
|
||||||
|
requestAnimationFrame(resolve)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
await page.evaluate((seed) => {
|
await page.evaluate((seed) => {
|
||||||
const storageKey = 'heros-web:campaign-state';
|
const storageKey = 'heros-web:campaign-state';
|
||||||
const current = JSON.parse(window.localStorage.getItem(storageKey) ?? 'null');
|
const current = JSON.parse(window.localStorage.getItem(storageKey) ?? 'null');
|
||||||
if (!current?.firstBattleReport) {
|
if (!current?.firstBattleReport) {
|
||||||
throw new Error('Expected an existing campaign report before seeding RC save.');
|
throw new Error('Expected an existing campaign report before seeding RC save.');
|
||||||
}
|
}
|
||||||
|
// These fixtures model a completed victory already resting at camp.
|
||||||
|
// Do not inherit a live battle auto-save or an older navigation checkpoint.
|
||||||
|
Object.keys(window.localStorage)
|
||||||
|
.filter((key) => key.startsWith('heros-web:battle:'))
|
||||||
|
.forEach((key) => window.localStorage.removeItem(key));
|
||||||
|
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
const objectives = [
|
const objectives = [
|
||||||
@@ -12492,6 +12639,12 @@ async function seedCampaignSave(page, options) {
|
|||||||
step: seed.step,
|
step: seed.step,
|
||||||
activeSaveSlot: 1,
|
activeSaveSlot: 1,
|
||||||
gold: seed.gold,
|
gold: seed.gold,
|
||||||
|
pendingAftermathBattleId: undefined,
|
||||||
|
activeCityStayId: undefined,
|
||||||
|
activeCampVisitId: undefined,
|
||||||
|
storyCheckpoint: undefined,
|
||||||
|
explorationCheckpoint: undefined,
|
||||||
|
sortiePreparationCheckpoint: undefined,
|
||||||
inventory: { ...(current.inventory ?? {}), 콩: 12, 상처약: 6, 탁주: 4 },
|
inventory: { ...(current.inventory ?? {}), 콩: 12, 상처약: 6, 탁주: 4 },
|
||||||
selectedSortieUnitIds: seed.selectedSortieUnitIds,
|
selectedSortieUnitIds: seed.selectedSortieUnitIds,
|
||||||
latestBattleId: seed.battleId,
|
latestBattleId: seed.battleId,
|
||||||
@@ -12516,6 +12669,26 @@ async function seedCampaignSave(page, options) {
|
|||||||
|
|
||||||
window.localStorage.setItem(storageKey, JSON.stringify(next));
|
window.localStorage.setItem(storageKey, JSON.stringify(next));
|
||||||
window.localStorage.setItem(`${storageKey}:slot-1`, JSON.stringify(next));
|
window.localStorage.setItem(`${storageKey}:slot-1`, JSON.stringify(next));
|
||||||
|
const persisted = JSON.parse(
|
||||||
|
window.localStorage.getItem(
|
||||||
|
`${storageKey}:slot-1`
|
||||||
|
) ?? 'null'
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
persisted?.step !== seed.step ||
|
||||||
|
persisted?.storyCheckpoint ||
|
||||||
|
persisted?.explorationCheckpoint ||
|
||||||
|
persisted?.sortiePreparationCheckpoint ||
|
||||||
|
persisted?.pendingAftermathBattleId ||
|
||||||
|
persisted?.activeCityStayId ||
|
||||||
|
persisted?.activeCampVisitId
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Camp seed retained a navigation checkpoint: ${JSON.stringify(
|
||||||
|
persisted
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
}, options);
|
}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4121,6 +4121,7 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
private miniMapObjectiveMarkers: Phaser.GameObjects.Rectangle[] = [];
|
private miniMapObjectiveMarkers: Phaser.GameObjects.Rectangle[] = [];
|
||||||
private miniMapViewport?: Phaser.GameObjects.Rectangle;
|
private miniMapViewport?: Phaser.GameObjects.Rectangle;
|
||||||
private miniMapVisible = true;
|
private miniMapVisible = true;
|
||||||
|
private pendingDefeatPresentationUnitIds = new Set<string>();
|
||||||
private recentActionLogLayout?: RecentActionLogLayout;
|
private recentActionLogLayout?: RecentActionLogLayout;
|
||||||
private cameraTileX = 0;
|
private cameraTileX = 0;
|
||||||
private cameraTileY = 0;
|
private cameraTileY = 0;
|
||||||
@@ -4299,6 +4300,7 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
this.miniMapObjectiveMarkers = [];
|
this.miniMapObjectiveMarkers = [];
|
||||||
this.miniMapViewport = undefined;
|
this.miniMapViewport = undefined;
|
||||||
this.miniMapVisible = true;
|
this.miniMapVisible = true;
|
||||||
|
this.pendingDefeatPresentationUnitIds.clear();
|
||||||
this.recentActionLogLayout = undefined;
|
this.recentActionLogLayout = undefined;
|
||||||
this.edgeScrollElapsed = 0;
|
this.edgeScrollElapsed = 0;
|
||||||
this.pointerFeedbackMarker = undefined;
|
this.pointerFeedbackMarker = undefined;
|
||||||
@@ -4428,6 +4430,7 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
this.mapResultPopupObjects.forEach((object) => object.active && object.destroy());
|
this.mapResultPopupObjects.forEach((object) => object.active && object.destroy());
|
||||||
this.mapResultPopupObjects = [];
|
this.mapResultPopupObjects = [];
|
||||||
this.hideBattleSoundCaption();
|
this.hideBattleSoundCaption();
|
||||||
|
this.pendingDefeatPresentationUnitIds.clear();
|
||||||
this.battleAutosaveReady = false;
|
this.battleAutosaveReady = false;
|
||||||
this.uninstallBattleAutosaveHandlers();
|
this.uninstallBattleAutosaveHandlers();
|
||||||
});
|
});
|
||||||
@@ -8377,14 +8380,16 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
if (!unit) {
|
if (!unit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const presentationVisible =
|
||||||
|
this.unitPresentationVisible(unit);
|
||||||
const selected = this.selectedUnit?.id === unit.id;
|
const selected = this.selectedUnit?.id === unit.id;
|
||||||
const objective = unit.id === leaderUnitId;
|
const objective = unit.id === leaderUnitId;
|
||||||
const baseSize = Math.max(this.battleUiLength(3), cellSize);
|
const baseSize = Math.max(this.battleUiLength(3), cellSize);
|
||||||
const markerSize = baseSize + (objective ? this.battleUiLength(2) : 0) + (selected ? this.battleUiLength(2) : 0);
|
const markerSize = baseSize + (objective ? this.battleUiLength(2) : 0) + (selected ? this.battleUiLength(2) : 0);
|
||||||
dot.setPosition(x + unit.x * cellSize + cellSize / 2, y + unit.y * cellSize + cellSize / 2);
|
dot.setPosition(x + unit.x * cellSize + cellSize / 2, y + unit.y * cellSize + cellSize / 2);
|
||||||
dot.setDisplaySize(markerSize, markerSize);
|
dot.setDisplaySize(markerSize, markerSize);
|
||||||
dot.setVisible(unit.hp > 0);
|
dot.setVisible(presentationVisible);
|
||||||
dot.setFillStyle(unit.faction === 'ally' ? 0x4aa9ff : 0xff715f, unit.hp > 0 ? 0.96 : 0.18);
|
dot.setFillStyle(unit.faction === 'ally' ? 0x4aa9ff : 0xff715f, presentationVisible ? 0.96 : 0.18);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
dot.setStrokeStyle(this.battleUiLength(2), 0xffffff, 1);
|
dot.setStrokeStyle(this.battleUiLength(2), 0xffffff, 1);
|
||||||
} else if (objective) {
|
} else if (objective) {
|
||||||
@@ -8607,7 +8612,11 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
this.setUnitBasePosition(view, this.tileCenterX(unit.x), this.tileCenterY(unit.y));
|
this.setUnitBasePosition(view, this.tileCenterX(unit.x), this.tileCenterY(unit.y));
|
||||||
view.label.setPosition(view.baseX, view.baseY + this.layout.tileSize * 0.52);
|
view.label.setPosition(view.baseX, view.baseY + this.layout.tileSize * 0.52);
|
||||||
this.setUnitRoleSealPosition(view, view.baseX, view.baseY);
|
this.setUnitRoleSealPosition(view, view.baseX, view.baseY);
|
||||||
const visible = unit.hp > 0 && this.isTileVisible(unit.x, unit.y);
|
const presentationVisible =
|
||||||
|
this.unitPresentationVisible(unit);
|
||||||
|
const visible =
|
||||||
|
presentationVisible &&
|
||||||
|
this.isTileVisible(unit.x, unit.y);
|
||||||
view.sprite.setVisible(visible);
|
view.sprite.setVisible(visible);
|
||||||
this.setUnitHitZoneEnabled(view, visible);
|
this.setUnitHitZoneEnabled(view, visible);
|
||||||
view.label.setVisible(visible);
|
view.label.setVisible(visible);
|
||||||
@@ -8701,10 +8710,19 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.setUnitStatusBadgePositions(view, view.baseX, view.baseY);
|
this.setUnitStatusBadgePositions(view, view.baseX, view.baseY);
|
||||||
const visible = unit.hp > 0 && this.isTileVisible(unit.x, unit.y);
|
const visible =
|
||||||
|
this.unitPresentationVisible(unit) &&
|
||||||
|
this.isTileVisible(unit.x, unit.y);
|
||||||
view.statusBadges.forEach((badge) => badge.container.setVisible(visible));
|
view.statusBadges.forEach((badge) => badge.container.setVisible(visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unitPresentationVisible(unit: UnitData) {
|
||||||
|
return (
|
||||||
|
unit.hp > 0 ||
|
||||||
|
this.pendingDefeatPresentationUnitIds.has(unit.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private refreshUnitLegibilityStyles() {
|
private refreshUnitLegibilityStyles() {
|
||||||
battleUnits.forEach((unit) => this.applyUnitLegibilityStyle(unit));
|
battleUnits.forEach((unit) => this.applyUnitLegibilityStyle(unit));
|
||||||
}
|
}
|
||||||
@@ -8714,7 +8732,7 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unit.hp <= 0) {
|
if (!this.unitPresentationVisible(unit)) {
|
||||||
this.applyDefeatedStyle(unit, view);
|
this.applyDefeatedStyle(unit, view);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -14333,14 +14351,34 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
this.triggerFirstEngagementEvent(attacker, target);
|
this.triggerFirstEngagementEvent(attacker, target);
|
||||||
this.phase = 'animating';
|
this.phase = 'animating';
|
||||||
const result = this.resolveCombatAction(attacker, target, action, false, usable);
|
const result = this.resolveCombatAction(attacker, target, action, false, usable);
|
||||||
this.clearMarkers();
|
const pendingDefeatPresentationUnitId =
|
||||||
await this.showBondMapEffect(result);
|
result.bondChain?.defeated
|
||||||
await this.presentCombatResult(result);
|
? result.defender.id
|
||||||
if (result.bondChain?.defeated) {
|
: undefined;
|
||||||
this.applyDefeatedStyle(result.defender);
|
if (pendingDefeatPresentationUnitId) {
|
||||||
this.updateMiniMap();
|
this.pendingDefeatPresentationUnitIds.add(
|
||||||
|
pendingDefeatPresentationUnitId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
result.counter = this.resolveCounterAttack(result);
|
this.clearMarkers();
|
||||||
|
try {
|
||||||
|
await this.showBondMapEffect(result);
|
||||||
|
await this.presentCombatResult(result);
|
||||||
|
} finally {
|
||||||
|
if (pendingDefeatPresentationUnitId) {
|
||||||
|
this.pendingDefeatPresentationUnitIds.delete(
|
||||||
|
pendingDefeatPresentationUnitId
|
||||||
|
);
|
||||||
|
if (this.scene.isActive()) {
|
||||||
|
this.applyDefeatedStyle(result.defender);
|
||||||
|
this.updateMiniMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.counter =
|
||||||
|
result.defender.hp > 0
|
||||||
|
? this.resolveCounterAttack(result)
|
||||||
|
: undefined;
|
||||||
if (result.counter) {
|
if (result.counter) {
|
||||||
await this.delay(180);
|
await this.delay(180);
|
||||||
await this.presentCombatResult(result.counter);
|
await this.presentCombatResult(result.counter);
|
||||||
@@ -23332,6 +23370,7 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private applyBattleSaveState(state: BattleSaveState) {
|
private applyBattleSaveState(state: BattleSaveState) {
|
||||||
|
this.pendingDefeatPresentationUnitIds.clear();
|
||||||
this.clearBattleEvents();
|
this.clearBattleEvents();
|
||||||
this.battleEventPresentationCount = 0;
|
this.battleEventPresentationCount = 0;
|
||||||
this.tacticalEventReactionHistory = [];
|
this.tacticalEventReactionHistory = [];
|
||||||
@@ -29626,6 +29665,9 @@ export class BattleScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private applyDefeatedStyle(unit: UnitData, view = this.unitViews.get(unit.id)) {
|
private applyDefeatedStyle(unit: UnitData, view = this.unitViews.get(unit.id)) {
|
||||||
|
if (this.pendingDefeatPresentationUnitIds.has(unit.id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.losePendingTacticalInitiativeEffect(unit);
|
this.losePendingTacticalInitiativeEffect(unit);
|
||||||
this.battleBuffs.delete(unit.id);
|
this.battleBuffs.delete(unit.id);
|
||||||
this.battleStatuses.delete(unit.id);
|
this.battleStatuses.delete(unit.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user