diff --git a/dev/classes-browser.test.mjs b/dev/classes-browser.test.mjs index 94dc620..d9f1c77 100644 --- a/dev/classes-browser.test.mjs +++ b/dev/classes-browser.test.mjs @@ -146,6 +146,27 @@ const locked = await page.evaluate(() => { }); check(locked.r.ok === true && locked.plate?.name === 'VANGUARD' && locked.plate?.insignia === 0, `the class plate replaces the door (${JSON.stringify(locked.plate)})`); +// THE HAND-OFF: a CONFIRMED lock-in walks the player to the SKILL TREE the +// moment the class console finishes closing (GameScene's onClose seam). +await page.evaluate(() => window.game.scene.getScene('GameScene').classWindow.close({ picked: 'vanguard' })); +const handed = await page.waitForFunction( + () => { + const g = window.game.scene.getScene('GameScene'); + return g.classWindow.openState === 'closed' && g.skillWindow?.isOpen === true; + }, + null, + { timeout: 40000 } +).then(() => + page.evaluate(() => { + const g = window.game.scene.getScene('GameScene'); + const res = { classClosed: g.classWindow.openState === 'closed', skillOpen: g.skillWindow.isOpen, points: g.classState.skillPoints }; + g.skillWindow.close?.(); // the test does not keep the console open + return res; + }) +); +check(handed.classClosed && handed.skillOpen, 'a confirmed pick hands the player to the skill tree console'); +check(handed.points > 0, `the banked points (${handed.points}) are spendable on arrival`) + // ── THE VOLLEYS through the REAL firing code (the classState seam in CombatSystem). // Same capture-stub trick, run against the live prototype method: Phaser exists // in the page, so this is the half dev/class-combat.test.mjs cannot do in node. diff --git a/dev/shots/skills-window-chain.png b/dev/shots/skills-window-chain.png index 09b2f5e..63ff9eb 100644 Binary files a/dev/shots/skills-window-chain.png and b/dev/shots/skills-window-chain.png differ diff --git a/dev/shots/skills-window-closed.png b/dev/shots/skills-window-closed.png index 999c503..3ed9b22 100644 Binary files a/dev/shots/skills-window-closed.png and b/dev/shots/skills-window-closed.png differ diff --git a/dev/shots/skills-window-long-tree.png b/dev/shots/skills-window-long-tree.png index 31f7bdd..19099b2 100644 Binary files a/dev/shots/skills-window-long-tree.png and b/dev/shots/skills-window-long-tree.png differ diff --git a/dev/shots/skills-window-ranked.png b/dev/shots/skills-window-ranked.png index 3e9f69d..6b13a85 100644 Binary files a/dev/shots/skills-window-ranked.png and b/dev/shots/skills-window-ranked.png differ diff --git a/dev/shots/skills-window-selected.png b/dev/shots/skills-window-selected.png index 83cdf7e..5e99935 100644 Binary files a/dev/shots/skills-window-selected.png and b/dev/shots/skills-window-selected.png differ diff --git a/js/scenes/GameScene.js b/js/scenes/GameScene.js index b040f43..8b3a2aa 100644 --- a/js/scenes/GameScene.js +++ b/js/scenes/GameScene.js @@ -7968,6 +7968,10 @@ export class GameScene extends Phaser.Scene { * * Once a class is on file the door never fires again; closing without picking * spends the AUTO prompt (the game does not nag) but leaves the door. + * + * AFTER A PICK — the CONFIRMED lock-in hands the player to the SKILL TREE + * console (js/ui/SkillWindow.js) as soon as this one finishes closing: the + * class just banked skill points, so the tree opens on the beat. */ /** The dev door: index.html?level5 (or ?class) opens the console on boot. */ @@ -8009,6 +8013,14 @@ export class GameScene extends Phaser.Scene { onClose: (o = {}) => { if (o?.picked || this.classState?.hasClass) { this._classAutoOpen = false; + // A CONFIRMED lock-in walks straight into the SKILL TREE: the run + // just banked points (or changed class), so the moment this + // console's close beat lands, the player is handed to the tree. + if (o?.picked && this._skillTreeAfterPick) { + this._skillTreeAfterPick = false; + // past the close tween (220 ms) — the full-screen hand-off + this.time.delayedCall(320, () => this.openSkillWindow({ source: 'classPick' })); + } return; } if (this._classAutoOpen) { @@ -8614,6 +8626,9 @@ export class GameScene extends Phaser.Scene { if (!res.ok) return res; this.registry.set('playerClass', this.classState); this._classPrompted = true; + // THE HAND-OFF: the pick is CONFIRMED, so the class console's close + // (onClose) walks the player to the SKILL TREE to spend the points. + this._skillTreeAfterPick = true; // THE COMBAT SEAM: the firing code reads the ledger through the combat // system (dualCannon → the twin-barrel volley, targetingComputer → the // leading solve). See js/combat/CombatSystem.js.