aether-shards/test/systems/EnvironmentalHazards.test.js

169 lines
5.4 KiB
JavaScript
Raw Normal View History

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