Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 132 additions & 3 deletions scripts/smoke-secondary-journeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const CAMPAIGN_MOBILE_RENDER_BUDGETS = Object.freeze({
}),
reef: Object.freeze({
displayCount: 205,
activeTweenCount: 45,
activeTweenCount: 24,
performanceTier: 'custom'
}),
voidPeaks: Object.freeze({
Expand Down Expand Up @@ -2404,7 +2404,30 @@ async function smokeLevel(session, route, sceneName, exceptions, {
dustParticleCount: scene.cosmicDustParticles.length,
entryLayerCount: scene.children?.list?.filter(
item => item === scene.entryCosmicParticleLayer
).length || 0
).length || 0,
decorativeTweenCount: (() => {
const routeState = scene.optionalRouteRewards?.get?.(
'reef_star_trench'
);
const targets = new Set([
...(scene.nebulaParticles || []),
...(scene.voidRifts || []),
...(scene.starFragments || []).map(item => item?.graphics),
scene.shipPart?.graphics,
scene.shipPart?.label,
routeState?.marker,
routeState?.choice?.mainMarker,
scene.abyssAscentCurrent?.visual,
scene.abyssAscentCurrent?.label,
scene.driftAscentCurrent?.visual,
scene.driftAscentCurrent?.label,
scene.travelerAscentCurrent?.visual,
scene.travelerAscentCurrent?.label
].filter(Boolean));
return (scene.tweens?.getTweens?.() || []).filter(
tween => (tween?.targets || []).some(target => targets.has(target))
).length;
})()
} : null,
currentEcologyPlacement: scene?.currentEcologyNode ? (() => {
const node = scene.currentEcologyNode;
Expand Down Expand Up @@ -2535,8 +2558,9 @@ async function smokeLevel(session, route, sceneName, exceptions, {
state.reefAmbientRendering?.nebulaLayerCount !== 2 ||
state.reefAmbientRendering?.riftLayerCount !== 1 ||
state.reefAmbientRendering?.dustLayerCount !== 1 ||
state.reefAmbientRendering?.dustParticleCount > 12 ||
state.reefAmbientRendering?.dustParticleCount > 6 ||
state.reefAmbientRendering?.entryLayerCount > 1 ||
state.reefAmbientRendering?.decorativeTweenCount !== 0 ||
state.currentEcologyPlacement?.supportId !== 'reef-opening-3' ||
state.currentEcologyPlacement?.x <
state.currentEcologyPlacement?.supportLeft ||
Expand Down Expand Up @@ -3675,6 +3699,111 @@ async function smokeLevel(session, route, sceneName, exceptions, {
await startCampaignScene(session, { route, sceneName });
await delay(400);
}
if (route === 'reef') {
const mainRouteStaged = await evaluate(session, `(() => {
const scene = window.mythicalGame.scene.getScene('ReefLevel');
const routeState = scene?.optionalRouteRewards?.get?.(
'reef_star_trench'
);
const support = scene?.getTraversalSupport?.(
routeState?.choice?.mainSupportIds?.[0]
);
if (!scene?.player?.body || !routeState?.choice || !support?.body) {
return null;
}
scene.player.body.reset(
support.x,
support.body.top - scene.player.body.height - 4
);
scene.player.setVelocity?.(0, 0);
return { supportId: support.traversalId };
})()`);
if (!mainRouteStaged) {
throw new Error(`${sceneName} could not stage its Signal Current`);
}
mainRouteEffect = await waitFor(
() => evaluate(session, `(() => {
const scene = window.mythicalGame.scene.getScene('ReefLevel');
const routeState = scene?.optionalRouteRewards?.get?.(
'reef_star_trench'
);
if (routeState?.choice?.selectedPath !== 'main') return null;
const target = scene.enemies?.getChildren?.().find(
enemy => enemy?.active
);
if (!target) return null;
const optionalAccepted = scene.recordOptionalRouteProgress(
'reef_star_trench',
{ x: scene.player.x, y: scene.player.y }
);
const objectiveBefore = scene.getReefObjectiveText?.() || '';
const persistedBefore = scene.getExpeditionRouteState?.()
.reefCurrentEdgeReady;
const baseDamage = (
Number(scene.katanaCombatProfile?.meleeDamage) || 2
) + 1;
scene.enemies.getChildren().forEach(enemy => {
enemy.x = -10000;
enemy.y = -10000;
});
scene.player.facingRight = true;
target.x = scene.player.x + 70;
target.y = scene.player.y;
const originalDamageEnemy = scene.damageEnemy;
const damageCalls = [];
scene.damageEnemy = (_enemy, amount) => {
damageCalls.push(amount);
return true;
};
scene.performAttack();
scene.damageEnemy = originalDamageEnemy;
return {
selectedPath: routeState.choice.selectedPath,
reefRouteChoice: scene.reefRouteChoice,
optionalAccepted,
progress: routeState.progress,
completed: routeState.completed,
objectiveBefore,
objective: scene.getReefObjectiveText?.() || '',
baseDamage,
damageCalls,
edgeReadyBefore: persistedBefore,
edgeReadyAfter: scene.reefCurrentEdgeReady,
persistedAfter: scene.getExpeditionRouteState?.()
.reefCurrentEdgeReady
};
})()`),
{ timeoutMs: 2500, message: `${sceneName} Signal Current selection` }
);
if (
mainRouteEffect.selectedPath !== 'main' ||
mainRouteEffect.reefRouteChoice !== 'main' ||
mainRouteEffect.optionalAccepted !== false ||
mainRouteEffect.progress !== 0 ||
mainRouteEffect.completed !== false ||
mainRouteEffect.damageCalls?.[0] !==
mainRouteEffect.baseDamage + 2 ||
mainRouteEffect.edgeReadyBefore !== true ||
mainRouteEffect.edgeReadyAfter !== false ||
mainRouteEffect.persistedAfter !== false ||
!mainRouteEffect.objectiveBefore.includes(
'NEXT KATANA HIT +2 READY'
) ||
!mainRouteEffect.objective.includes('CURRENT EDGE SPENT') ||
!choicePresentation.mainTradeoff.includes('KATANA HIT +2') ||
!choicePresentation.challengeLabel.includes('2 RELICS') ||
!choicePresentation.rewardLabel.includes('FREE SUPER BLAST')
) {
throw new Error(
`${sceneName} route rewards contradicted their promise: ` +
JSON.stringify({ choicePresentation, mainRouteEffect })
);
}
// Prove the Star Trench from a clean scene; the Signal Current
// intentionally commits the route and spends only its own reward.
await startCampaignScene(session, { route, sceneName });
await delay(400);
}
if (route === 'crystalCaves') {
const mainRouteStaged = await evaluate(session, `(() => {
const scene = window.mythicalGame.scene.getScene(
Expand Down
14 changes: 11 additions & 3 deletions src/__tests__/LevelTraversalQualityContract.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,8 @@ describe('campaign traversal quality contracts', () => {

expect(source).toContain('for (let layerIndex = 0; layerIndex < 2; layerIndex += 1)');
expect(source).toContain('this.voidRifts.push(riftLayer);');
expect(source).toContain('this.cosmicDustParticles.length >= 12');
expect(source).toContain('this.cosmicDustParticles.length >= particleLimit');
expect(source).toContain('shouldAnimateReefDecorations()');
expect(source).toContain('updateCosmicDust(delta)');
expect(source).toContain('targets: [...allElements, entryParticles].filter(Boolean)');
expect(source).not.toContain('this.nebulaParticles.push(wisp);');
Expand Down Expand Up @@ -995,6 +996,12 @@ describe('campaign traversal quality contracts', () => {

expect(source).toContain("title: 'STAR TRENCH'");
expect(source).toContain("rewardLabel: 'FREE SUPER BLAST'");
expect(source).toContain(
"mainTradeoff: 'FAST + PATROLS\\nEARNS: NEXT KATANA HIT +2'"
);
expect(source).toContain(
"challengeLabel: 'DEEP WATER + 2 RELICS'"
);
expect(source).toContain("returnLabel: 'STAR TRENCH RETURN ↑ // SIGNAL ROUTE →'");
expect(source).toContain('this.freeSpecialAttackCharges += 1;');
expect(source).toContain('createAbyssAscentCurrent()');
Expand Down Expand Up @@ -1560,7 +1567,7 @@ describe('campaign traversal quality contracts', () => {
'levels/ReefLevel.js',
"id: 'reef_star_trench'",
"mainLabel: 'SIGNAL CURRENT →'",
"mainTradeoff: 'FAST // ENEMY PATROLS'",
"mainTradeoff: 'FAST + PATROLS\\nEARNS: NEXT KATANA HIT +2'",
"challengeLabel: 'DEEP WATER + 2 RELICS'"
],
[
Expand Down Expand Up @@ -2587,7 +2594,8 @@ describe('campaign traversal quality contracts', () => {
expect(smoke).toContain('state.caveCoinRendering?.physicsCoinCount !== 0');
expect(smoke).toContain('state.caveCrystalRendering?.layerCount !== 1');
expect(smoke).toContain('state.reefAmbientRendering?.nebulaLayerCount !== 2');
expect(smoke).toContain('state.reefAmbientRendering?.dustParticleCount > 12');
expect(smoke).toContain('state.reefAmbientRendering?.dustParticleCount > 6');
expect(smoke).toContain('state.reefAmbientRendering?.decorativeTweenCount !== 0');
expect(smoke).toContain('state.peaksAmbientRendering?.starCount !== 35');
expect(smoke).toContain('state.peaksAmbientRendering?.emberLayerCount !== 1');
expect(smoke).toContain('smokeForestBatchedCoinPickup(session)');
Expand Down
38 changes: 37 additions & 1 deletion src/__tests__/ThirdExpeditionRescueLoop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,30 @@ describe('third expedition rescue loop', () => {

expect(source).toContain('CURRENT LINK ACTIVE // KATANA STRIKES AMPLIFIED');
expect(source).toContain('const currentLinkedDamage = meleeDamage + 1');
expect(source).toContain('const getStrikeDamage = () => currentLinkedDamage');
expect(source).toContain(
"this.resolveBossHit(currentLinkedDamage, { source: 'katana_current' })"
"{ source: 'katana_current' }"
);
expect(source).toContain('reefAmplified: true');
});

test('makes the direct Signal Current earn a saved one-hit katana reward', () => {
const source = readLevel();

expect(source).toContain(
"mainTradeoff: 'FAST + PATROLS\\nEARNS: NEXT KATANA HIT +2'"
);
expect(source).toContain(
"challengeLabel: 'DEEP WATER + 2 RELICS'"
);
expect(source).toContain('this.reefCurrentEdgeReady = true');
expect(source).toContain('reefCurrentEdgeReady: this.reefRouteChoice');
expect(source).toContain('routeState.reefCurrentEdgeReady !== false');
expect(source).toContain('consumeReefCurrentEdge()');
expect(source).toContain('NEXT KATANA HIT +2 READY');
expect(source).toContain('CURRENT EDGE SPENT');
});

test('makes the Star Trench return current visible, narrow, and mechanically honest', () => {
const source = readLevel();

Expand Down Expand Up @@ -257,12 +275,26 @@ describe('third expedition rescue loop', () => {
expect(source).toContain('shipPartCollected: this.shipPartCollected === true');
expect(source).toContain('reefFragmentMask: this.reefCollectedFragmentMask');
expect(source).toContain('starTrenchProgress: Number(route?.progress)');
expect(source).toContain('reefCurrentEdgeReady: this.reefRouteChoice');
expect(source).toContain('restoreReefRouteState(resume.routeState');
expect(source).toContain('this.clearShipPartPickup();');
expect(source).toContain('this.retireCollectedReefFragments();');
expect(source).toContain('onFreeSpecialAttackConsumed()');
});

test('keeps compact Reef guidance vivid without offscreen decorative tweens', () => {
const source = readLevel();

expect(source).toContain('shouldAnimateReefDecorations()');
expect(source).toContain(
'return !(this.isMobile || width <= 480 || height < 620);'
);
expect(source).toContain(
'const particleLimit = this.shouldAnimateReefDecorations() ? 12 : 6;'
);
expect(source).toContain('this.shouldAnimateReefDecorations()\n ? this.tweens.add({');
});

test('makes the Reef entry keyboard accessible and single-fire', () => {
const source = readLevel();
const entry = source.match(
Expand All @@ -277,6 +309,10 @@ describe('third expedition rescue loop', () => {
expect(source).toMatch(
/shutdown\(\)[\s\S]*this\.clearLevelEntryKeyHandler\(\)/
);
expect(entry).toContain('const leftDecoration = this.addCosmicDecoration(');
expect(entry).toContain('const rightDecoration = this.addCosmicDecoration(');
expect(entry).toContain('leftDecoration,\n rightDecoration,');
expect(source).toMatch(/addCosmicDecoration\(x, y\)[\s\S]*return orb;/);
});

test('keeps harmless crystal facets inside safe platform silhouettes', () => {
Expand Down
Loading