169 lines
5.4 KiB
JavaScript
169 lines
5.4 KiB
JavaScript
|
|
import { expect } from "@esm-bundle/chai";
|
||
|
|
import { TurnSystem } from "../../src/systems/TurnSystem.js";
|
||
|
|
import { VoxelGrid } from "../../src/grid/VoxelGrid.js";
|
||
|
|
import { UnitManager } from "../../src/managers/UnitManager.js";
|
||
|
|
import { EffectProcessor } from "../../src/systems/EffectProcessor.js";
|
||
|
|
|
||
|
|
describe("Systems: Environmental Hazards", function () {
|
||
|
|
let turnSystem;
|
||
|
|
let grid;
|
||
|
|
let unitManager;
|
||
|
|
let effectProcessor;
|
||
|
|
let unit;
|
||
|
|
let mockRegistry;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
// Create mock registry
|
||
|
|
mockRegistry = new Map();
|
||
|
|
mockRegistry.set("CLASS_VANGUARD", {
|
||
|
|
id: "CLASS_VANGUARD",
|
||
|
|
name: "Vanguard",
|
||
|
|
type: "EXPLORER",
|
||
|
|
base_stats: {
|
||
|
|
health: 100,
|
||
|
|
attack: 10,
|
||
|
|
defense: 5,
|
||
|
|
speed: 10,
|
||
|
|
movement: 4,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
unitManager = new UnitManager(mockRegistry);
|
||
|
|
grid = new VoxelGrid(20, 5, 20);
|
||
|
|
|
||
|
|
// Create walkable floor
|
||
|
|
for (let x = 0; x < 20; x++) {
|
||
|
|
for (let z = 0; z < 20; z++) {
|
||
|
|
grid.setCell(x, 0, z, 1); // Floor
|
||
|
|
grid.setCell(x, 1, z, 0); // Air (walkable)
|
||
|
|
grid.setCell(x, 2, z, 0); // Headroom
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
effectProcessor = new EffectProcessor(grid, unitManager);
|
||
|
|
turnSystem = new TurnSystem(unitManager);
|
||
|
|
turnSystem.setHazardContext(grid, effectProcessor);
|
||
|
|
|
||
|
|
// Create test unit
|
||
|
|
unit = unitManager.createUnit("CLASS_VANGUARD", "PLAYER");
|
||
|
|
unit.position = { x: 5, y: 1, z: 5 };
|
||
|
|
unit.currentHealth = 100;
|
||
|
|
unit.maxHealth = 100;
|
||
|
|
grid.placeUnit(unit, unit.position);
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("Integration Point 3: Environmental Hazards", () => {
|
||
|
|
it("should apply fire hazard damage when unit starts turn on fire", () => {
|
||
|
|
// Place fire hazard at unit's position
|
||
|
|
grid.addHazard(unit.position, "HAZARD_FIRE", 3);
|
||
|
|
|
||
|
|
const initialHP = unit.currentHealth;
|
||
|
|
const defense = unit.baseStats.defense || 0;
|
||
|
|
const expectedDamage = Math.max(0, 5 - defense); // 5 fire damage - defense
|
||
|
|
|
||
|
|
// Start turn (should process hazards)
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Unit should have taken fire damage (reduced by defense)
|
||
|
|
expect(unit.currentHealth).to.be.lessThanOrEqual(initialHP);
|
||
|
|
expect(unit.currentHealth).to.equal(initialHP - expectedDamage);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should apply acid hazard damage when unit starts turn on acid", () => {
|
||
|
|
// Place acid hazard at unit's position
|
||
|
|
grid.addHazard(unit.position, "HAZARD_ACID", 2);
|
||
|
|
|
||
|
|
const initialHP = unit.currentHealth;
|
||
|
|
const defense = unit.baseStats.defense || 0;
|
||
|
|
const expectedDamage = Math.max(0, 5 - defense); // 5 acid damage - defense
|
||
|
|
|
||
|
|
// Start turn
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Unit should have taken acid damage (reduced by defense)
|
||
|
|
expect(unit.currentHealth).to.be.lessThanOrEqual(initialHP);
|
||
|
|
expect(unit.currentHealth).to.equal(initialHP - expectedDamage);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should decrement hazard duration after processing", () => {
|
||
|
|
// Place hazard with duration 2
|
||
|
|
grid.addHazard(unit.position, "HAZARD_FIRE", 2);
|
||
|
|
|
||
|
|
const hazard = grid.getHazardAt(unit.position);
|
||
|
|
expect(hazard.duration).to.equal(2);
|
||
|
|
|
||
|
|
// Start turn (should decrement duration)
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
const hazardAfter = grid.getHazardAt(unit.position);
|
||
|
|
expect(hazardAfter.duration).to.equal(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should remove hazard when duration reaches 0", () => {
|
||
|
|
// Place hazard with duration 1
|
||
|
|
grid.addHazard(unit.position, "HAZARD_FIRE", 1);
|
||
|
|
|
||
|
|
expect(grid.getHazardAt(unit.position)).to.exist;
|
||
|
|
|
||
|
|
// Start turn (should remove hazard)
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Hazard should be removed
|
||
|
|
expect(grid.getHazardAt(unit.position)).to.be.undefined;
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should not process hazards if unit is not on a hazard tile", () => {
|
||
|
|
const initialHP = unit.currentHealth;
|
||
|
|
|
||
|
|
// Start turn without any hazard
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Health should be unchanged (except for status effects if any)
|
||
|
|
expect(unit.currentHealth).to.equal(initialHP);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should handle unknown hazard types with default damage", () => {
|
||
|
|
// Place unknown hazard type
|
||
|
|
grid.addHazard(unit.position, "HAZARD_UNKNOWN", 1);
|
||
|
|
|
||
|
|
const initialHP = unit.currentHealth;
|
||
|
|
const defense = unit.baseStats.defense || 0;
|
||
|
|
const expectedDamage = Math.max(0, 5 - defense); // Default 5 damage - defense
|
||
|
|
|
||
|
|
// Start turn
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Unit should still take damage (default 5, reduced by defense)
|
||
|
|
if (expectedDamage > 0) {
|
||
|
|
expect(unit.currentHealth).to.be.lessThan(initialHP);
|
||
|
|
}
|
||
|
|
expect(unit.currentHealth).to.equal(initialHP - expectedDamage);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("should process hazards before status effects in turn order", () => {
|
||
|
|
// Add hazard and status effect
|
||
|
|
grid.addHazard(unit.position, "HAZARD_FIRE", 1);
|
||
|
|
unit.statusEffects = [
|
||
|
|
{
|
||
|
|
id: "poison",
|
||
|
|
type: "DOT",
|
||
|
|
damage: 3,
|
||
|
|
duration: 1,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const initialHP = unit.currentHealth;
|
||
|
|
const defense = unit.baseStats.defense || 0;
|
||
|
|
const hazardDamage = Math.max(0, 5 - defense); // 5 fire damage - defense
|
||
|
|
const poisonDamage = 3; // Poison damage (not reduced by defense in current implementation)
|
||
|
|
|
||
|
|
// Start turn
|
||
|
|
turnSystem.startTurn(unit);
|
||
|
|
|
||
|
|
// Should have taken both hazard damage and poison damage
|
||
|
|
expect(unit.currentHealth).to.equal(initialHP - hazardDamage - poisonDamage);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|