Use rot-js for scheduling & path finding
This commit is contained in:
@@ -5,6 +5,7 @@ import { findPathAStar } from "../world/pathfinding";
|
||||
import { GAME_CONFIG } from "../../core/config/GameConfig";
|
||||
import { type EntityManager } from "../EntityManager";
|
||||
import { FOV } from "rot-js";
|
||||
import * as ROT from "rot-js";
|
||||
|
||||
|
||||
export function applyAction(w: World, actorId: EntityId, action: Action, em?: EntityManager): SimEvent[] {
|
||||
@@ -26,10 +27,7 @@ export function applyAction(w: World, actorId: EntityId, action: Action, em?: En
|
||||
break;
|
||||
}
|
||||
|
||||
// Spend energy for any action (move/wait/attack)
|
||||
if (actor.category === "combatant") {
|
||||
actor.energy -= GAME_CONFIG.gameplay.actionCost;
|
||||
}
|
||||
// Note: Energy is now managed by ROT.Scheduler, no need to deduct manually
|
||||
|
||||
return events;
|
||||
}
|
||||
@@ -380,7 +378,7 @@ export function decideEnemyAction(w: World, enemy: CombatantActor, player: Comba
|
||||
}
|
||||
|
||||
/**
|
||||
* Energy/speed scheduler: runs until it's the player's turn and the game needs input.
|
||||
* Speed-based scheduler using rot-js: runs until it's the player's turn and the game needs input.
|
||||
* Returns enemy events accumulated along the way.
|
||||
*/
|
||||
export function stepUntilPlayerTurn(w: World, playerId: EntityId, em?: EntityManager): { awaitingPlayerId: EntityId; events: SimEvent[] } {
|
||||
@@ -389,26 +387,36 @@ export function stepUntilPlayerTurn(w: World, playerId: EntityId, em?: EntityMan
|
||||
|
||||
const events: SimEvent[] = [];
|
||||
|
||||
while (true) {
|
||||
while (![...w.actors.values()].some(a => a.category === "combatant" && a.energy >= GAME_CONFIG.gameplay.energyThreshold)) {
|
||||
for (const a of w.actors.values()) {
|
||||
if (a.category === "combatant") {
|
||||
a.energy += a.speed;
|
||||
}
|
||||
// Create scheduler and add all combatants
|
||||
const scheduler = new ROT.Scheduler.Speed();
|
||||
|
||||
for (const actor of w.actors.values()) {
|
||||
if (actor.category === "combatant") {
|
||||
// ROT.Scheduler.Speed expects actors to have a getSpeed() method
|
||||
// Add it dynamically if it doesn't exist
|
||||
const actorWithGetSpeed = actor as any;
|
||||
if (!actorWithGetSpeed.getSpeed) {
|
||||
actorWithGetSpeed.getSpeed = function() { return this.speed; };
|
||||
}
|
||||
scheduler.add(actorWithGetSpeed, true);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// Get next actor from scheduler
|
||||
const actor = scheduler.next() as CombatantActor | null;
|
||||
|
||||
if (!actor || !w.actors.has(actor.id)) {
|
||||
// Actor was removed (died), continue to next
|
||||
continue;
|
||||
}
|
||||
|
||||
const ready = [...w.actors.values()].filter(a =>
|
||||
a.category === "combatant" && a.energy >= GAME_CONFIG.gameplay.energyThreshold
|
||||
) as CombatantActor[];
|
||||
|
||||
ready.sort((a, b) => (b.energy - a.energy) || (a.id - b.id));
|
||||
const actor = ready[0];
|
||||
|
||||
if (actor.isPlayer) {
|
||||
// Player's turn - return control to the user
|
||||
return { awaitingPlayerId: actor.id, events };
|
||||
}
|
||||
|
||||
// Enemy turn - decide action and apply it
|
||||
const decision = decideEnemyAction(w, actor, player, em);
|
||||
|
||||
// Emit alert event if enemy just spotted player
|
||||
@@ -429,3 +437,5 @@ export function stepUntilPlayerTurn(w: World, playerId: EntityId, em?: EntityMan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user