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); }); }); });