Refactor enemy sound handling and improve enemy type definitions

- Updated enemy classes to include alert and attack sound IDs.
- Refactored checkWakeUp and attack logic to play sounds appropriately.
- Enhanced enemy type definitions with sound mappings.
- Added unit tests for enemy spawn and validation.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-18 02:26:44 +01:00
parent b040b88d8a
commit 806c9b6966
13 changed files with 179 additions and 33 deletions

View File

@@ -0,0 +1,47 @@
import 'package:test/test.dart';
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
import 'package:wolf_3d_dart/wolf_3d_entities.dart';
void main() {
group('Enemy map IDs', () {
test('maps officers, dogs, and mutants to the correct enemy types', () {
expect(EnemyType.fromMapId(116), EnemyType.officer);
expect(EnemyType.fromMapId(134), EnemyType.dog);
expect(EnemyType.fromMapId(216), EnemyType.mutant);
});
test('uses the original mutant 18-ID difficulty offset', () {
expect(EnemyType.mutant.mapData.getNormalizedId(216, Difficulty.easy), 216);
expect(
EnemyType.mutant.mapData.getNormalizedId(234, Difficulty.medium),
216,
);
expect(
EnemyType.mutant.mapData.getNormalizedId(252, Difficulty.hard),
216,
);
});
});
group('Enemy spawn facing', () {
test('spawns dog directions using the original dog map IDs', () {
expect(_spawnEnemy(134).angle, CardinalDirection.east.radians);
expect(_spawnEnemy(135).angle, CardinalDirection.north.radians);
expect(_spawnEnemy(136).angle, CardinalDirection.west.radians);
expect(_spawnEnemy(137).angle, CardinalDirection.south.radians);
});
test('maps patrol variants to the same facing directions', () {
expect(_spawnEnemy(138).angle, CardinalDirection.east.radians);
expect(_spawnEnemy(139).angle, CardinalDirection.north.radians);
expect(_spawnEnemy(140).angle, CardinalDirection.west.radians);
expect(_spawnEnemy(141).angle, CardinalDirection.south.radians);
});
});
}
Enemy _spawnEnemy(int mapId) {
final enemy = Enemy.spawn(mapId, 8.5, 8.5, Difficulty.hard);
expect(enemy, isNotNull);
return enemy!;
}

View File

@@ -1,7 +1,7 @@
import 'dart:math' as math;
import 'package:test/test.dart';
import 'package:wolf_3d_dart/src/entities/entities/enemies/enemy_type.dart';
import 'package:wolf_3d_dart/wolf_3d_entities.dart';
void main() {
group('Enemy Sprite Range Validation', () {
@@ -22,6 +22,16 @@ void main() {
// Skip if we are comparing the exact same animation on the same enemy
if (enemyA == enemyB && animA == animB) return;
// Dogs intentionally reuse some standing frames as walking frames.
final isDogIdleWalkReuse =
enemyA == EnemyType.dog &&
enemyB == EnemyType.dog &&
((animA == EnemyAnimation.idle &&
animB == EnemyAnimation.walking) ||
(animA == EnemyAnimation.walking &&
animB == EnemyAnimation.idle));
if (isDogIdleWalkReuse) return;
if (rangeA.overlaps(rangeB)) {
// Determine the specific frames that are clashing
final start = math.max(rangeA.start, rangeB.start);