Enemies now react to shots being fired in the same area
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -75,6 +75,9 @@ class WolfEngine {
|
|||||||
|
|
||||||
bool isInitialized = false;
|
bool isInitialized = false;
|
||||||
|
|
||||||
|
/// Tracks the last time a sound wave was emitted to prevent BFS spam.
|
||||||
|
int _lastAcousticAlertTime = 0;
|
||||||
|
|
||||||
/// Initializes the engine, sets the starting episode, and loads the first level.
|
/// Initializes the engine, sets the starting episode, and loads the first level.
|
||||||
void init() {
|
void init() {
|
||||||
_currentEpisodeIndex = startingEpisode;
|
_currentEpisodeIndex = startingEpisode;
|
||||||
@@ -222,8 +225,15 @@ class WolfEngine {
|
|||||||
if (input.requestedWeapon != null) {
|
if (input.requestedWeapon != null) {
|
||||||
player.requestWeaponSwitch(input.requestedWeapon!);
|
player.requestWeaponSwitch(input.requestedWeapon!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.isFiring) {
|
if (input.isFiring) {
|
||||||
player.fire(_timeAliveMs);
|
player.fire(_timeAliveMs);
|
||||||
|
|
||||||
|
// Throttle the acoustic flood-fill to emit a "wave" every 400ms while firing
|
||||||
|
if (_timeAliveMs - _lastAcousticAlertTime > 400) {
|
||||||
|
_propagateGunfire();
|
||||||
|
_lastAcousticAlertTime = _timeAliveMs;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
player.releaseTrigger();
|
player.releaseTrigger();
|
||||||
}
|
}
|
||||||
@@ -363,6 +373,70 @@ class WolfEngine {
|
|||||||
if (itemsToAdd.isNotEmpty) entities.addAll(itemsToAdd);
|
if (itemsToAdd.isNotEmpty) entities.addAll(itemsToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Propagates weapon noise through corridors and open doors using a Breadth-First Search.
|
||||||
|
void _propagateGunfire() {
|
||||||
|
int maxAcousticRange = 20; // How many tiles the sound wave travels
|
||||||
|
int startX = player.x.toInt();
|
||||||
|
int startY = player.y.toInt();
|
||||||
|
|
||||||
|
// Track visited tiles using a 1D index to prevent infinite loops
|
||||||
|
Set<int> visited = {startY * 64 + startX};
|
||||||
|
|
||||||
|
List<({int x, int y})> queue = [(x: startX, y: startY)];
|
||||||
|
|
||||||
|
int distance = 0;
|
||||||
|
|
||||||
|
while (queue.isNotEmpty && distance < maxAcousticRange) {
|
||||||
|
List<({int x, int y})> nextQueue = [];
|
||||||
|
|
||||||
|
for (var tile in queue) {
|
||||||
|
// 1. Alert any enemies standing on this specific tile
|
||||||
|
for (var entity in entities) {
|
||||||
|
if (entity is Enemy &&
|
||||||
|
!entity.isAlerted &&
|
||||||
|
entity.state != EntityState.dead) {
|
||||||
|
if (entity.position.x.toInt() == tile.x &&
|
||||||
|
entity.position.y.toInt() == tile.y) {
|
||||||
|
entity.isAlerted = true;
|
||||||
|
|
||||||
|
// Wake them up!
|
||||||
|
if (entity.state == EntityState.idle ||
|
||||||
|
entity.state == EntityState.ambush) {
|
||||||
|
entity.state = EntityState.patrolling;
|
||||||
|
entity.lastActionTime = _timeAliveMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Expand the sound wave outward to North, East, South, West
|
||||||
|
final neighbors = <({int x, int y})>[
|
||||||
|
(x: tile.x + 1, y: tile.y),
|
||||||
|
(x: tile.x - 1, y: tile.y),
|
||||||
|
(x: tile.x, y: tile.y + 1),
|
||||||
|
(x: tile.x, y: tile.y - 1),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var n in neighbors) {
|
||||||
|
// Keep it within the 64x64 grid limits
|
||||||
|
if (n.x >= 0 && n.x < 64 && n.y >= 0 && n.y < 64) {
|
||||||
|
int idx = n.y * 64 + n.x;
|
||||||
|
if (!visited.contains(idx)) {
|
||||||
|
visited.add(idx);
|
||||||
|
|
||||||
|
// Sound only travels through walkable tiles (air and OPEN doors).
|
||||||
|
if (isWalkable(n.x, n.y)) {
|
||||||
|
nextQueue.add(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue = nextQueue;
|
||||||
|
distance++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if a tile is empty or contains a door that is sufficiently open.
|
/// Returns true if a tile is empty or contains a door that is sufficiently open.
|
||||||
bool isWalkable(int x, int y) {
|
bool isWalkable(int x, int y) {
|
||||||
if (currentLevel[y][x] == 0) return true;
|
if (currentLevel[y][x] == 0) return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user