feat: Add mutant death and god mode face animations, update HUD rendering and player damage handling

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-23 12:29:56 +01:00
parent 400ce4f680
commit 827b8c779e
8 changed files with 124 additions and 5 deletions
@@ -162,6 +162,72 @@ void main() {
);
},
);
test('fatal mutant hit shows mutant death face', () {
final engine = _buildEngine();
engine.init();
engine.player.health = 10;
engine.player.takeDamage(20, attackerType: EnemyType.mutant);
final renderer = _HudProbeRenderer(vgaImages: engine.data.vgaImages);
renderer.drawHudForTest(engine);
final expectedMutantDeathFaceIndex = engine.data.registry.hud
.resolve(HudKey.faceMutantDeath)
?.vgaIndex;
expect(expectedMutantDeathFaceIndex, isNotNull);
final faceCall = renderer.drawCalls.firstWhere(
(call) => call.startY == 164 && call.startX == 136,
orElse: () => throw StateError('Face slot was not rendered.'),
);
expect(faceCall.imageIndex, expectedMutantDeathFaceIndex);
});
test('god mode face renders in spear demo HUD mapping', () {
final engine = _buildEngine(
version: GameVersion.spearOfDestinyDemo,
registry: SpearDemoAssetRegistry(),
);
engine.init();
engine.player.health = 90;
engine.player.setGodModeFaceEnabled(true);
final renderer = _HudProbeRenderer(vgaImages: engine.data.vgaImages);
renderer.drawHudForTest(engine);
final expectedGodModeFaceIndex = engine.data.registry.hud
.resolve(HudKey.faceGodMode)
?.vgaIndex;
expect(expectedGodModeFaceIndex, isNotNull);
final faceCall = renderer.drawCalls.firstWhere(
(call) => call.startY == 164 && call.startX == 136,
orElse: () => throw StateError('Face slot was not rendered.'),
);
expect(faceCall.imageIndex, expectedGodModeFaceIndex);
});
test('god mode face falls back to health face when unmapped', () {
final engine = _buildEngine();
engine.init();
engine.player.health = 90;
engine.player.setGodModeFaceEnabled(true);
final renderer = _HudProbeRenderer(vgaImages: engine.data.vgaImages);
renderer.drawHudForTest(engine);
final expectedHealthFaceIndex = engine.data.registry.hud
.faceForHealth(engine.player.health)
?.vgaIndex;
expect(expectedHealthFaceIndex, isNotNull);
final faceCall = renderer.drawCalls.firstWhere(
(call) => call.startY == 164 && call.startX == 136,
orElse: () => throw StateError('Face slot was not rendered.'),
);
expect(faceCall.imageIndex, expectedHealthFaceIndex);
});
}
class _HudProbeRenderer extends RendererBackend<int> {
@@ -233,7 +299,10 @@ class _HudDrawCall {
});
}
WolfEngine _buildEngine() {
WolfEngine _buildEngine({
GameVersion version = GameVersion.retail,
AssetRegistry? registry,
}) {
final wallGrid = _buildGrid();
final objectGrid = _buildGrid();
@@ -242,9 +311,9 @@ WolfEngine _buildEngine() {
return WolfEngine(
data: WolfensteinData(
version: GameVersion.retail,
version: version,
dataVersion: DataVersion.unknown,
registry: RetailAssetRegistry(),
registry: registry ?? RetailAssetRegistry(),
walls: [
_solidSprite(1),
_solidSprite(1),