feat: deepen battle atmosphere and portrait eras

This commit is contained in:
2026-07-21 23:32:34 +09:00
parent f39de4f47d
commit 3a41f8b671
20 changed files with 1471 additions and 58 deletions

View File

@@ -19,6 +19,14 @@ const campaignSlotStorageKey = 'heros-web:campaign-state:slot-1';
const campaignSnapshotPath = process.env.QA_CAMPAIGN_SNAPSHOT_PATH;
const resumeCampaignSnapshot = process.env.QA_RESUME_CAMPAIGN_SNAPSHOT === '1';
const baselineViewport = desktopBrowserViewport;
const battleEnvironmentExpectations = new Map([
['ninth-battle-xuzhou-gate-night-raid', { profileId: 'xuzhou-night-mist', ambienceKey: 'river-night-ambience', objectCount: 5, depthRange: [3.04, 3.12] }],
['twenty-second-battle-red-cliffs-fire', { profileId: 'red-cliffs-firestorm', ambienceKey: 'battle-fire', objectCount: 26, depthRange: [3.04, 3.3] }],
['fortieth-battle-han-river-flood', { profileId: 'han-river-flood-rain', ambienceKey: 'battle-rain', objectCount: 34, depthRange: [3.04, 3.3] }],
['forty-sixth-battle-yiling-fire', { profileId: 'yiling-burning-forest', ambienceKey: 'battle-fire', objectCount: 29, depthRange: [3.04, 3.3] }],
['sixty-first-battle-hanzhong-rain-defense', { profileId: 'hanzhong-defense-rain', ambienceKey: 'battle-rain', objectCount: 39, depthRange: [3.04, 3.3] }],
['sixty-sixth-battle-wuzhang-final', { profileId: 'wuzhang-snow-wind', ambienceKey: 'mountain-wind-ambience', objectCount: 35, depthRange: [3.04, 3.3] }]
]);
function withRenderer(url, renderer) {
if (!['canvas', 'webgl'].includes(renderer)) {
@@ -1348,6 +1356,7 @@ async function setupBattle(page, battle) {
{ timeout: 90000 }
);
await startDeploymentIfNeeded(page, battle.id);
await verifyBattleEnvironment(page, battle.id);
await verifySortieDoctrine(page, battle);
await normalizeRepresentativeBattleUnits(page, battle);
}
@@ -1535,6 +1544,7 @@ async function setupCumulativeBattle(page, battle, firstBattle, route) {
{ timeout: 90000 }
);
await startDeploymentIfNeeded(page, battle.id);
await verifyBattleEnvironment(page, battle.id);
await verifySortieDoctrine(page, battle);
await normalizeRepresentativeBattleUnits(page, battle);
return preparation;
@@ -1653,6 +1663,48 @@ async function startDeploymentIfNeeded(page, battleId) {
);
}
async function verifyBattleEnvironment(page, battleId) {
const state = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
const environment = state?.environment;
const expected = battleEnvironmentExpectations.get(battleId);
const actualAmbienceKey = state?.audio?.currentAmbienceKey ?? state?.audio?.pendingAmbienceKey ?? null;
if (!expected) {
if (
environment?.profileId !== null ||
actualAmbienceKey !== null ||
environment?.active !== false ||
environment?.objectCount !== 0 ||
environment?.particleCount !== 0 ||
environment?.hazeCount !== 0
) {
throw new Error(`Unexpected battle environment for ${battleId}: ${JSON.stringify(environment)}`);
}
return;
}
const depthRange = environment?.depthRange;
const depthMatches = depthRange &&
Math.abs(depthRange.minimum - expected.depthRange[0]) < 0.001 &&
Math.abs(depthRange.maximum - expected.depthRange[1]) < 0.001;
if (
environment?.profileId !== expected.profileId ||
environment?.ambienceKey !== expected.ambienceKey ||
actualAmbienceKey !== expected.ambienceKey ||
environment?.active !== true ||
environment?.objectCount !== expected.objectCount ||
environment?.maskedObjectCount !== expected.objectCount ||
environment?.masked !== true ||
environment?.fixedPool !== true ||
environment?.verification?.valid !== true ||
!depthMatches
) {
throw new Error(
`Battle environment mismatch for ${battleId}: ${JSON.stringify({ expected, actualAmbienceKey, environment })}`
);
}
}
async function verifySortieDoctrine(page, battle) {
const state = await page.evaluate(() => window.__HEROS_DEBUG__?.battle());
const doctrine = state?.sortieDoctrine;