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
19 changes: 13 additions & 6 deletions scripts/smoke-secondary-journeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -9222,13 +9222,15 @@ async function smokeGuardianPacing(session, exceptions) {
);

let openingFraming = null;
if (sceneName === 'ReefLevel') {
if (['CrystalCavesLevel', 'ReefLevel'].includes(sceneName)) {
openingFraming = await waitFor(
() => evaluate(session, `(() => {
const scene = window.mythicalGame.scene.getScene('ReefLevel');
const scene = window.mythicalGame.scene.getScene(${JSON.stringify(sceneName)});
const camera = scene?.cameras?.main;
const player = scene?.player;
const boss = scene?.bossBody;
const boss = ${JSON.stringify(sceneName)} === 'ReefLevel'
? scene?.bossBody
: scene?.boss;
const view = camera?.worldView;
const orientationElapsed = scene?.time?.now -
scene?.bossCombatReadyAt;
Expand All @@ -9252,15 +9254,19 @@ async function smokeGuardianPacing(session, exceptions) {
openingAttackPending:
Boolean(scene.bossAttackPreviewTimer),
contactDamageArmed:
scene.bossContactDamageArmed === true,
${JSON.stringify(sceneName)} === 'ReefLevel' &&
scene.bossContactDamageArmed === true,
playerVisible: view.contains(player.x, player.y),
bossVisible: view.contains(boss.x, boss.y),
playerScreenX: Math.round((player.x - view.x) * camera.zoom),
bossScreenX: Math.round((boss.x - view.x) * camera.zoom),
viewportWidth: camera.width
};
})()`),
{ timeoutMs: 15000, message: 'Reef mobile guardian framing' }
{
timeoutMs: 15000,
message: `${sceneName} mobile guardian framing`
}
);
if (
openingFraming.zoom !== 1 ||
Expand All @@ -9274,7 +9280,8 @@ async function smokeGuardianPacing(session, exceptions) {
openingFraming.bossScreenX > openingFraming.viewportWidth - 24
) {
throw new Error(
`Reef guardian opened outside the playable view: ${JSON.stringify(openingFraming)}`
`${sceneName} guardian opened outside the playable view: ` +
JSON.stringify(openingFraming)
);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/__tests__/FirstLevelRescueLoop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ describe('first expedition rescue loop', () => {
expect(gameSource).toContain("urlParams.get('testAttack')");
expect(gameSource).toContain('platformerPreviewSize:');
expect(gameSource).toContain("urlParams.get('previewSize') === 'mobile'");
expect(gameSource).toContain("crystal: 'CrystalCavesLevel'");
expect(hatchingSource).toMatch(
/if \(\s*isLocalPreview &&\s*\([\s\S]*previewParams\.has\('testBoss'\)/
);
Expand Down
28 changes: 28 additions & 0 deletions src/__tests__/GuardianPacingContract.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,34 @@ describe('guardian encounter pacing contracts', () => {
expect(source).toContain('this.bossAttackPreviewTimer?.remove?.();');
});

test('Crystal frames the mobile arena before enabling controls or attacks', () => {
const source = readLevel('CrystalCavesLevel.js');

expect(source).toContain(
'const CRYSTAL_GUARDIAN_ARENA = Object.freeze({'
);
expect(source).toContain('stageCrystalGuardianArenaEntry() {');
expect(source).toMatch(
/startBossFight\(\)[\s\S]*this\.hidePlatformerMobileControls\(\);[\s\S]*this\.stageCrystalGuardianArenaEntry\(\);/
);
expect(source).toContain(
'beginCrystalGuardianCombat(camera = this.cameras.main)'
);
expect(source).toContain('openingGraceMs: 3000');
expect(source).toContain(
'const CRYSTAL_GUARDIAN_MOBILE_DISPLAY_HEIGHT = 170;'
);
expect(source).toContain('this.bossCombatReadyAt = this.time.now;');
expect(source).toMatch(
/beginCrystalGuardianCombat[\s\S]*this\.physics\.resume\(\);[\s\S]*this\.showPlatformerMobileControls\(\);[\s\S]*this\.startBossAI\(\);/
);
expect(source).toMatch(
/if \(isMobileLayout\) \{\s*this\.cameras\.main\.setZoom\(1\);/
);
expect(source).toContain('!this.bossCombatReady ||');
expect(source).toContain('this.bossAttackPreviewTimer?.remove?.();');
});

test('Reef echo summons use the shared readable combat contract', () => {
const source = readLevel('ReefLevel.js');
const createMinion = source.match(
Expand Down
5 changes: 5 additions & 0 deletions src/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -791,11 +791,16 @@ async function initializeGame() {
setTimeout(async () => {
const testBossScenes = {
mythicalForest: 'MythicalForestLevel',
forest: 'MythicalForestLevel',
crystalCaves: 'CrystalCavesLevel',
crystal: 'CrystalCavesLevel',
reef: 'ReefLevel',
auroraDepths: 'AuroraDepthsLevel',
aurora: 'AuroraDepthsLevel',
voidPeaks: 'VoidPeaksLevel',
peaks: 'VoidPeaksLevel',
finalVoid: 'FinalVoidLevel',
final: 'FinalVoidLevel',
victory: 'VictoryScene'
};

Expand Down
Loading