Another refactor

This commit is contained in:
Peter Stockings
2026-01-05 13:24:56 +11:00
parent ac86d612e2
commit ce68470ab1
17 changed files with 853 additions and 801 deletions

View File

@@ -15,6 +15,8 @@ import { generateWorld } from "../engine/world/generator";
import { DungeonRenderer } from "../rendering/DungeonRenderer";
import { GAME_CONFIG } from "../core/config/GameConfig";
import { EntityManager } from "../engine/EntityManager";
import { ProgressionManager } from "../engine/ProgressionManager";
export class GameScene extends Phaser.Scene {
private world!: World;
@@ -38,6 +40,9 @@ export class GameScene extends Phaser.Scene {
private isInventoryOpen = false;
private isCharacterOpen = false;
private entityManager!: EntityManager;
private progressionManager: ProgressionManager = new ProgressionManager();
constructor() {
super("GameScene");
}
@@ -121,13 +126,22 @@ export class GameScene extends Phaser.Scene {
});
this.events.on("allocate-stat", (statName: string) => {
this.allocateStat(statName);
const player = this.world.actors.get(this.playerId) as CombatantActor;
if (player) {
this.progressionManager.allocateStat(player, statName);
this.emitUIUpdate();
}
});
this.events.on("allocate-passive", (nodeId: string) => {
this.allocatePassive(nodeId);
const player = this.world.actors.get(this.playerId) as CombatantActor;
if (player) {
this.progressionManager.allocatePassive(player, nodeId);
this.emitUIUpdate();
}
});
// Mouse click -> compute path (only during player turn, and not while menu/minimap is open)
this.input.on("pointerdown", (p: Phaser.Input.Pointer) => {
if (!this.awaitingPlayer) return;
@@ -146,14 +160,15 @@ export class GameScene extends Phaser.Scene {
a.category === "combatant" && a.pos.x === tx && a.pos.y === ty && !a.isPlayer
);
const player = this.world.actors.get(this.playerId) as CombatantActor;
const path = findPathAStar(
this.world,
this.dungeonRenderer.seenArray,
{ ...player.pos },
{ x: tx, y: ty },
{ ignoreBlockedTarget: isEnemy }
);
const player = this.world.actors.get(this.playerId) as CombatantActor;
const path = findPathAStar(
this.world,
this.dungeonRenderer.seenArray,
{ ...player.pos },
{ x: tx, y: ty },
{ ignoreBlockedTarget: isEnemy }
);
if (path.length >= 2) this.playerPath = path;
this.dungeonRenderer.render(this.playerPath);
@@ -176,7 +191,7 @@ export class GameScene extends Phaser.Scene {
return;
}
if (isBlocked(this.world, next.x, next.y)) {
if (isBlocked(this.world, next.x, next.y, this.entityManager)) {
// Check if it's an enemy at 'next'
const targetId = [...this.world.actors.values()].find(
a => a.category === "combatant" && a.pos.x === next.x && a.pos.y === next.y && !a.isPlayer
@@ -242,10 +257,11 @@ export class GameScene extends Phaser.Scene {
private commitPlayerAction(action: Action) {
this.awaitingPlayer = false;
const playerEvents = applyAction(this.world, this.playerId, action);
const enemyStep = stepUntilPlayerTurn(this.world, this.playerId);
const playerEvents = applyAction(this.world, this.playerId, action, this.entityManager);
const enemyStep = stepUntilPlayerTurn(this.world, this.playerId, this.entityManager);
this.awaitingPlayer = enemyStep.awaitingPlayerId === this.playerId;
// Process events for visual fx
const allEvents = [...playerEvents, ...enemyStep.events];
for (const ev of allEvents) {
@@ -306,6 +322,8 @@ export class GameScene extends Phaser.Scene {
const { world, playerId } = generateWorld(floor, this.runState);
this.world = world;
this.playerId = playerId;
this.entityManager = new EntityManager(this.world);
// Reset transient state
this.playerPath = [];
@@ -318,9 +336,10 @@ export class GameScene extends Phaser.Scene {
this.dungeonRenderer.initializeFloor(this.world);
// Step until player turn
const enemyStep = stepUntilPlayerTurn(this.world, this.playerId);
const enemyStep = stepUntilPlayerTurn(this.world, this.playerId, this.entityManager);
this.awaitingPlayer = enemyStep.awaitingPlayerId === this.playerId;
this.dungeonRenderer.computeFov(this.playerId);
this.centerCameraOnPlayer();
this.dungeonRenderer.render(this.playerPath);
@@ -355,50 +374,5 @@ export class GameScene extends Phaser.Scene {
);
}
private allocateStat(statName: string) {
const p = this.world.actors.get(this.playerId) as CombatantActor;
if (!p || p.category !== "combatant" || !p.stats || p.stats.statPoints <= 0) return;
p.stats.statPoints--;
if (statName === "strength") {
p.stats.strength++;
p.stats.maxHp += 2;
p.stats.hp += 2;
p.stats.attack += 0.2; // Small boost per Str
} else if (statName === "dexterity") {
p.stats.dexterity++;
p.speed += 1;
} else if (statName === "intelligence") {
p.stats.intelligence++;
// Maybe defense every 5 points?
if (p.stats.intelligence % 5 === 0) {
p.stats.defense++;
}
}
this.emitUIUpdate();
}
private allocatePassive(nodeId: string) {
const p = this.world.actors.get(this.playerId) as CombatantActor;
if (!p || p.category !== "combatant" || !p.stats || p.stats.skillPoints <= 0) return;
if (p.stats.passiveNodes.includes(nodeId)) return;
p.stats.skillPoints--;
p.stats.passiveNodes.push(nodeId);
// Apply bonuses
if (nodeId === "off_1") p.stats.attack += 2;
else if (nodeId === "off_2") p.stats.attack += 4;
else if (nodeId === "def_1") {
p.stats.maxHp += 10;
p.stats.hp += 10;
}
else if (nodeId === "def_2") p.stats.defense += 2;
else if (nodeId === "util_1") p.speed += 5;
else if (nodeId === "util_2") p.stats.expToNextLevel = Math.floor(p.stats.expToNextLevel * 0.9);
this.emitUIUpdate();
}
}