Shot trap status/damage of affected entity rather then just player
This commit is contained in:
@@ -608,7 +608,6 @@ export class GameScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process traps and status effects
|
// Process traps and status effects
|
||||||
console.log(`[GameScene] Processing traps. Player Pos: ${player.pos.x},${player.pos.y}`);
|
|
||||||
this.ecsRegistry.updateAll();
|
this.ecsRegistry.updateAll();
|
||||||
|
|
||||||
// Handle trap events from ECS
|
// Handle trap events from ECS
|
||||||
@@ -618,17 +617,19 @@ export class GameScene extends Phaser.Scene {
|
|||||||
}
|
}
|
||||||
for (const ev of trapEvents) {
|
for (const ev of trapEvents) {
|
||||||
if (ev.type === "trigger_activated") {
|
if (ev.type === "trigger_activated") {
|
||||||
// Get trap trigger data for status effect display
|
const activator = this.entityAccessor.getActor(ev.activatorId);
|
||||||
const trapTrigger = this.ecsWorld.getComponent(ev.triggerId, "trigger");
|
const trapTrigger = this.ecsWorld.getComponent(ev.triggerId, "trigger");
|
||||||
|
|
||||||
if (trapTrigger?.effect) {
|
if (trapTrigger?.effect && activator) {
|
||||||
const color = getEffectColor(trapTrigger.effect);
|
const color = getEffectColor(trapTrigger.effect);
|
||||||
const text = getEffectName(trapTrigger.effect);
|
const text = getEffectName(trapTrigger.effect);
|
||||||
this.dungeonRenderer.showFloatingText(player.pos.x, player.pos.y, text, color);
|
this.dungeonRenderer.showFloatingText(activator.pos.x, activator.pos.y, text, color);
|
||||||
}
|
}
|
||||||
} else if (ev.type === "damage") {
|
} else if (ev.type === "damage") {
|
||||||
// Show damage number from trap
|
const victim = this.entityAccessor.getActor(ev.entityId);
|
||||||
this.dungeonRenderer.showDamage(player.pos.x, player.pos.y, ev.amount);
|
if (victim) {
|
||||||
|
this.dungeonRenderer.showDamage(victim.pos.x, victim.pos.y, ev.amount);
|
||||||
|
}
|
||||||
} else if (ev.type === "status_applied") {
|
} else if (ev.type === "status_applied") {
|
||||||
// Already handled above via trigger_activated
|
// Already handled above via trigger_activated
|
||||||
} else if (ev.type === "status_tick" && ev.entityId) {
|
} else if (ev.type === "status_tick" && ev.entityId) {
|
||||||
|
|||||||
@@ -146,6 +146,70 @@ vi.mock('../../engine/ecs/systems/StatusEffectSystem', () => ({
|
|||||||
StatusEffectSystem: class {},
|
StatusEffectSystem: class {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock('../systems/TargetingSystem', () => ({
|
||||||
|
TargetingSystem: class {
|
||||||
|
isActive = false;
|
||||||
|
itemId = null;
|
||||||
|
cursorPos = null;
|
||||||
|
startTargeting = vi.fn();
|
||||||
|
cancel = vi.fn();
|
||||||
|
updateCursor = vi.fn();
|
||||||
|
executeThrow = vi.fn();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../systems/CameraController', () => ({
|
||||||
|
CameraController: class {
|
||||||
|
constructor() {}
|
||||||
|
handleWheel = vi.fn();
|
||||||
|
handlePan = vi.fn();
|
||||||
|
enableFollowMode = vi.fn();
|
||||||
|
setBounds = vi.fn();
|
||||||
|
centerOnTile = vi.fn();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../systems/ItemManager', () => ({
|
||||||
|
ItemManager: class {
|
||||||
|
constructor() {}
|
||||||
|
updateWorld = vi.fn();
|
||||||
|
setEntityAccessor = vi.fn();
|
||||||
|
handleUse = vi.fn(() => ({ success: true, consumed: false }));
|
||||||
|
removeFromInventory = vi.fn(() => true);
|
||||||
|
spawnItem = vi.fn();
|
||||||
|
tryPickup = vi.fn();
|
||||||
|
getItem = vi.fn(() => ({ id: 'test', name: 'Test' }));
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../engine/ProgressionManager', () => ({
|
||||||
|
ProgressionManager: class {
|
||||||
|
allocateStat = vi.fn();
|
||||||
|
allocatePassive = vi.fn();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../engine/systems/UpgradeManager', () => ({
|
||||||
|
UpgradeManager: {
|
||||||
|
applyUpgrade: vi.fn(),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../engine/systems/EquipmentService', () => ({
|
||||||
|
equipItem: vi.fn(),
|
||||||
|
deEquipItem: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../../engine/systems/LootSystem', () => ({
|
||||||
|
generateLoot: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../systems/EventRenderer', () => ({
|
||||||
|
renderSimEvents: vi.fn(),
|
||||||
|
getEffectColor: vi.fn((e) => e === 'poison' ? '#00ff00' : "#ffffff"),
|
||||||
|
getEffectName: vi.fn((e) => e === 'poison' ? 'Poisoned!' : e),
|
||||||
|
}));
|
||||||
|
|
||||||
vi.mock('../../engine/world/world-logic', () => ({
|
vi.mock('../../engine/world/world-logic', () => ({
|
||||||
inBounds: vi.fn(function() { return true; }),
|
inBounds: vi.fn(function() { return true; }),
|
||||||
isBlocked: vi.fn(function() { return false; }),
|
isBlocked: vi.fn(function() { return false; }),
|
||||||
@@ -231,4 +295,50 @@ describe('GameScene', () => {
|
|||||||
|
|
||||||
expect(mockUI.showDeathScreen).toHaveBeenCalled();
|
expect(mockUI.showDeathScreen).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show damage text at the entity position when a trap damages a non-player entity', () => {
|
||||||
|
const enemyActor = {
|
||||||
|
id: 5,
|
||||||
|
pos: { x: 5, y: 5 },
|
||||||
|
category: 'combatant',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup mocks
|
||||||
|
(scene as any).entityAccessor.getActor = vi.fn((id) => (id === 5 ? enemyActor : null));
|
||||||
|
(scene as any).ecsEventBus.drain = vi.fn(() => [
|
||||||
|
{ type: 'damage', entityId: 5, amount: 10 }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Trigger action that processes traps (like move)
|
||||||
|
(simulation.applyAction as any).mockReturnValue([{ type: 'move', targetId: 1, dx: 1, dy: 0 }]);
|
||||||
|
(scene as any).commitPlayerAction({ type: 'move', dx: 1, dy: 0 });
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
expect((scene as any).dungeonRenderer.showDamage).toHaveBeenCalledWith(5, 5, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show effect text at the entity position when a trap triggers an effect on a non-player entity', () => {
|
||||||
|
const enemyActor = {
|
||||||
|
id: 7,
|
||||||
|
pos: { x: 7, y: 7 },
|
||||||
|
category: 'combatant',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup mocks
|
||||||
|
(scene as any).entityAccessor.getActor = vi.fn((id) => (id === 7 ? enemyActor : null));
|
||||||
|
(scene as any).ecsEventBus.drain = vi.fn(() => [
|
||||||
|
{ type: 'trigger_activated', triggerId: 10, activatorId: 7 }
|
||||||
|
]);
|
||||||
|
(scene as any).ecsWorld.getComponent = vi.fn((id, type) => {
|
||||||
|
if (id === 10 && type === 'trigger') return { effect: 'poison' };
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger action
|
||||||
|
(simulation.applyAction as any).mockReturnValue([{ type: 'move', targetId: 1, dx: 1, dy: 0 }]);
|
||||||
|
(scene as any).commitPlayerAction({ type: 'move', dx: 1, dy: 0 });
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
expect((scene as any).dungeonRenderer.showFloatingText).toHaveBeenCalledWith(7, 7, 'Poisoned!', '#00ff00');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user