Wire class pick to auto-open the skill tree console
- On a confirmed class lock-in, GameScene now sets `_skillTreeAfterPick` and, once the class window's close beat finishes, delays 320 ms then opens SkillWindow with `source: 'classPick'`, handing the player straight into spending their banked points. - Add an e2e check in classes-browser.test.mjs that a confirmed pick closes the class console and opens the skill tree with spendable points. - Refresh skills-window screenshot fixtures to match current rendering.
|
|
@ -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)})`);
|
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).
|
// ── THE VOLLEYS through the REAL firing code (the classState seam in CombatSystem).
|
||||||
// Same capture-stub trick, run against the live prototype method: Phaser exists
|
// 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.
|
// in the page, so this is the half dev/class-combat.test.mjs cannot do in node.
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 513 KiB After Width: | Height: | Size: 535 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 191 KiB |
|
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 193 KiB |
|
|
@ -7968,6 +7968,10 @@ export class GameScene extends Phaser.Scene {
|
||||||
*
|
*
|
||||||
* Once a class is on file the door never fires again; closing without picking
|
* 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.
|
* 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. */
|
/** 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 = {}) => {
|
onClose: (o = {}) => {
|
||||||
if (o?.picked || this.classState?.hasClass) {
|
if (o?.picked || this.classState?.hasClass) {
|
||||||
this._classAutoOpen = false;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (this._classAutoOpen) {
|
if (this._classAutoOpen) {
|
||||||
|
|
@ -8614,6 +8626,9 @@ export class GameScene extends Phaser.Scene {
|
||||||
if (!res.ok) return res;
|
if (!res.ok) return res;
|
||||||
this.registry.set('playerClass', this.classState);
|
this.registry.set('playerClass', this.classState);
|
||||||
this._classPrompted = true;
|
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
|
// THE COMBAT SEAM: the firing code reads the ledger through the combat
|
||||||
// system (dualCannon → the twin-barrel volley, targetingComputer → the
|
// system (dualCannon → the twin-barrel volley, targetingComputer → the
|
||||||
// leading solve). See js/combat/CombatSystem.js.
|
// leading solve). See js/combat/CombatSystem.js.
|
||||||
|
|
|
||||||