- Introduce the MissionDebrief component to display after-action reports, including XP, rewards, and squad status. - Implement the MissionGenerator class to create procedural side missions, enhancing replayability and resource management. - Update mission schema to include mission objects for INTERACT objectives, improving mission complexity. - Enhance GameLoop and MissionManager to support new mission features and interactions. - Add tests for MissionDebrief and MissionGenerator to ensure functionality and integration within the game architecture.
151 lines
4.3 KiB
JavaScript
151 lines
4.3 KiB
JavaScript
import { expect } from "@esm-bundle/chai";
|
|
import { GameLoop } from "../../../src/core/GameLoop.js";
|
|
import {
|
|
createGameLoopSetup,
|
|
cleanupGameLoop,
|
|
createRunData,
|
|
createMockGameStateManagerForCombat,
|
|
setupCombatUnits,
|
|
cleanupTurnSystem,
|
|
} from "./helpers.js";
|
|
|
|
describe("Core: GameLoop - Combat Turn System", function () {
|
|
this.timeout(30000);
|
|
|
|
let gameLoop;
|
|
let container;
|
|
let mockGameStateManager;
|
|
let playerUnit;
|
|
let enemyUnit;
|
|
|
|
beforeEach(async () => {
|
|
const setup = createGameLoopSetup();
|
|
gameLoop = setup.gameLoop;
|
|
container = setup.container;
|
|
|
|
gameLoop.stop();
|
|
if (
|
|
gameLoop.turnSystem &&
|
|
typeof gameLoop.turnSystem.reset === "function"
|
|
) {
|
|
gameLoop.turnSystem.reset();
|
|
}
|
|
|
|
gameLoop.init(container);
|
|
mockGameStateManager = createMockGameStateManagerForCombat();
|
|
gameLoop.gameStateManager = mockGameStateManager;
|
|
|
|
const runData = createRunData({
|
|
squad: [{ id: "u1", classId: "CLASS_VANGUARD" }],
|
|
});
|
|
await gameLoop.startLevel(runData, { startAnimation: false });
|
|
|
|
const units = setupCombatUnits(gameLoop);
|
|
playerUnit = units.playerUnit;
|
|
enemyUnit = units.enemyUnit;
|
|
});
|
|
|
|
afterEach(() => {
|
|
gameLoop.clearMovementHighlights();
|
|
gameLoop.clearSpawnZoneHighlights();
|
|
cleanupTurnSystem(gameLoop);
|
|
cleanupGameLoop(gameLoop, container);
|
|
});
|
|
|
|
it("CoA 12: should end turn and advance turn queue", () => {
|
|
const allUnits = [playerUnit, enemyUnit];
|
|
gameLoop.turnSystem.startCombat(allUnits);
|
|
|
|
const activeUnit = gameLoop.turnSystem.getActiveUnit();
|
|
expect(activeUnit).to.exist;
|
|
|
|
const initialCharge = activeUnit.chargeMeter;
|
|
expect(initialCharge).to.be.greaterThanOrEqual(100);
|
|
|
|
gameLoop.endTurn();
|
|
|
|
expect(activeUnit.chargeMeter).to.be.a("number");
|
|
expect(activeUnit.chargeMeter).to.be.at.least(0);
|
|
const minExpectedAfterSubtraction = Math.max(0, initialCharge - 100);
|
|
expect(activeUnit.chargeMeter).to.be.at.least(minExpectedAfterSubtraction);
|
|
|
|
const nextUnit = gameLoop.turnSystem?.getActiveUnit();
|
|
expect(nextUnit).to.exist;
|
|
expect(nextUnit.chargeMeter).to.be.greaterThanOrEqual(100);
|
|
});
|
|
|
|
it("CoA 13: should restore AP for units when their turn starts (via TurnSystem)", () => {
|
|
enemyUnit.currentAP = 0;
|
|
playerUnit.baseStats.speed = 10;
|
|
enemyUnit.baseStats.speed = 10;
|
|
|
|
const allUnits = [playerUnit, enemyUnit];
|
|
gameLoop.turnSystem.startCombat(allUnits);
|
|
|
|
let attempts = 0;
|
|
while (
|
|
gameLoop.turnSystem.getActiveUnit() !== playerUnit &&
|
|
attempts < 10
|
|
) {
|
|
const current = gameLoop.turnSystem.getActiveUnit();
|
|
if (current) {
|
|
gameLoop.turnSystem.endTurn(current);
|
|
} else {
|
|
break;
|
|
}
|
|
attempts++;
|
|
}
|
|
|
|
expect(gameLoop.turnSystem.getActiveUnit()).to.equal(playerUnit);
|
|
gameLoop.endTurn();
|
|
|
|
attempts = 0;
|
|
while (gameLoop.turnSystem.getActiveUnit() !== enemyUnit && attempts < 10) {
|
|
const current = gameLoop.turnSystem.getActiveUnit();
|
|
if (current && current !== enemyUnit) {
|
|
gameLoop.endTurn();
|
|
} else {
|
|
break;
|
|
}
|
|
attempts++;
|
|
}
|
|
|
|
const activeUnit = gameLoop.turnSystem.getActiveUnit();
|
|
expect(activeUnit).to.equal(enemyUnit);
|
|
expect(enemyUnit.currentAP).to.equal(5);
|
|
});
|
|
|
|
it("CoA 16: should initialize all units with full AP when combat starts", () => {
|
|
const fastUnit = gameLoop.unitManager.createUnit(
|
|
"CLASS_VANGUARD",
|
|
"PLAYER"
|
|
);
|
|
fastUnit.baseStats.speed = 20;
|
|
fastUnit.position = { x: 3, y: 1, z: 3 };
|
|
gameLoop.grid.placeUnit(fastUnit, fastUnit.position);
|
|
|
|
const slowUnit = gameLoop.unitManager.createUnit(
|
|
"CLASS_VANGUARD",
|
|
"PLAYER"
|
|
);
|
|
slowUnit.baseStats.speed = 5;
|
|
slowUnit.position = { x: 4, y: 1, z: 4 };
|
|
gameLoop.grid.placeUnit(slowUnit, slowUnit.position);
|
|
|
|
const enemyUnit2 = gameLoop.unitManager.createUnit(
|
|
"ENEMY_DEFAULT",
|
|
"ENEMY"
|
|
);
|
|
enemyUnit2.baseStats.speed = 8;
|
|
enemyUnit2.position = { x: 10, y: 1, z: 10 };
|
|
gameLoop.grid.placeUnit(enemyUnit2, enemyUnit2.position);
|
|
|
|
gameLoop.initializeCombatUnits();
|
|
|
|
expect(fastUnit.currentAP).to.equal(10);
|
|
expect(slowUnit.currentAP).to.equal(10);
|
|
expect(enemyUnit2.currentAP).to.equal(10);
|
|
expect(fastUnit.chargeMeter).to.be.greaterThan(slowUnit.chargeMeter);
|
|
});
|
|
});
|
|
|