From 6c55136d5b1c7a33aff5ac0ad798a3d703b04057 Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Sun, 15 Mar 2026 18:16:46 +0100 Subject: [PATCH] Update enemy AI Signed-off-by: Hans Kokx --- .../entities/enemies/bosses/hans_grosse.dart | 16 +++++++----- .../lib/src/entities/enemies/dog.dart | 26 ++++++++++++++++--- .../lib/src/entities/enemies/mutant.dart | 15 ++++++++--- .../lib/src/entities/enemies/officer.dart | 16 +++++++++--- .../lib/src/entities/enemies/ss.dart | 15 ++++++++--- 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/packages/wolf_3d_entities/lib/src/entities/enemies/bosses/hans_grosse.dart b/packages/wolf_3d_entities/lib/src/entities/enemies/bosses/hans_grosse.dart index a180fad..0c14c33 100644 --- a/packages/wolf_3d_entities/lib/src/entities/enemies/bosses/hans_grosse.dart +++ b/packages/wolf_3d_entities/lib/src/entities/enemies/bosses/hans_grosse.dart @@ -69,8 +69,11 @@ class HansGrosse extends Enemy { }) { Coordinate2D movement = const Coordinate2D(0, 0); - // Bosses lack directional sprites, they always look straight at the player - double newAngle = position.angleTo(playerPosition); + double newAngle = angle; + + if (isAlerted && state != EntityState.dead) { + newAngle = position.angleTo(playerPosition); + } checkWakeUp( elapsedMs: elapsedMs, @@ -87,9 +90,10 @@ class HansGrosse extends Enemy { break; case EntityState.patrolling: - if (distance > 1.5) { - double moveX = math.cos(newAngle) * speed; - double moveY = math.sin(newAngle) * speed; + if (!isAlerted || distance > 1.5) { + double currentMoveAngle = isAlerted ? newAngle : angle; + double moveX = math.cos(currentMoveAngle) * speed; + double moveY = math.sin(currentMoveAngle) * speed; movement = getValidMovement( Coordinate2D(moveX, moveY), isWalkable, @@ -100,7 +104,7 @@ class HansGrosse extends Enemy { int walkFrame = (elapsedMs ~/ 150) % 4; spriteIndex = (_baseSprite + 1) + walkFrame; - if (distance < 8.0 && elapsedMs - lastActionTime > 1000) { + if (isAlerted && distance < 8.0 && elapsedMs - lastActionTime > 1000) { if (hasLineOfSight(playerPosition, isWalkable)) { state = EntityState.attacking; lastActionTime = elapsedMs; diff --git a/packages/wolf_3d_entities/lib/src/entities/enemies/dog.dart b/packages/wolf_3d_entities/lib/src/entities/enemies/dog.dart index d370654..76bc177 100644 --- a/packages/wolf_3d_entities/lib/src/entities/enemies/dog.dart +++ b/packages/wolf_3d_entities/lib/src/entities/enemies/dog.dart @@ -66,10 +66,28 @@ class Dog extends Enemy { angleDiff: diff, ); - if (state == EntityState.patrolling && distance < 1.0) { - state = EntityState.attacking; - lastActionTime = elapsedMs; - _hasBittenThisCycle = false; + if (isAlerted && state != EntityState.dead) { + newAngle = angleToPlayer; + } + + // Dogs attack based on distance, so wrap the movement and attack in alert checks + if (state == EntityState.patrolling) { + if (!isAlerted || distance > 1.0) { + double currentMoveAngle = isAlerted ? angleToPlayer : angle; + double moveX = math.cos(currentMoveAngle) * speed; + double moveY = math.sin(currentMoveAngle) * speed; + movement = getValidMovement( + Coordinate2D(moveX, moveY), + isWalkable, + tryOpenDoor, + ); + } + + if (isAlerted && distance < 1.0) { + state = EntityState.attacking; + lastActionTime = elapsedMs; + _hasBittenThisCycle = false; + } } if (state == EntityState.attacking) { diff --git a/packages/wolf_3d_entities/lib/src/entities/enemies/mutant.dart b/packages/wolf_3d_entities/lib/src/entities/enemies/mutant.dart index e72c2be..0c782ea 100644 --- a/packages/wolf_3d_entities/lib/src/entities/enemies/mutant.dart +++ b/packages/wolf_3d_entities/lib/src/entities/enemies/mutant.dart @@ -69,10 +69,16 @@ class Mutant extends Enemy { angleDiff: diff, ); + if (isAlerted && state != EntityState.dead) { + newAngle = angleToPlayer; + } + if (state == EntityState.patrolling) { - if (distance > 0.8) { - double moveX = math.cos(angleToPlayer) * speed; - double moveY = math.sin(angleToPlayer) * speed; + // FIX 2: Move along patrol angle if unalerted, chase if alerted + if (!isAlerted || distance > 0.8) { + double currentMoveAngle = isAlerted ? angleToPlayer : angle; + double moveX = math.cos(currentMoveAngle) * speed; + double moveY = math.sin(currentMoveAngle) * speed; movement = getValidMovement( Coordinate2D(moveX, moveY), isWalkable, @@ -80,7 +86,8 @@ class Mutant extends Enemy { ); } - if (distance < 6.0 && elapsedMs - lastActionTime > 1500) { + // FIX 3: Only attack if alerted (Adjust the distance/timing per enemy class!) + if (isAlerted && distance < 6.0 && elapsedMs - lastActionTime > 1500) { if (hasLineOfSight(playerPosition, isWalkable)) { state = EntityState.attacking; lastActionTime = elapsedMs; diff --git a/packages/wolf_3d_entities/lib/src/entities/enemies/officer.dart b/packages/wolf_3d_entities/lib/src/entities/enemies/officer.dart index 35aa063..d805f9d 100644 --- a/packages/wolf_3d_entities/lib/src/entities/enemies/officer.dart +++ b/packages/wolf_3d_entities/lib/src/entities/enemies/officer.dart @@ -69,17 +69,25 @@ class Officer extends Enemy { angleDiff: diff, ); + if (isAlerted && state != EntityState.dead) { + newAngle = angleToPlayer; + } + if (state == EntityState.patrolling) { - if (distance > 0.8) { - double moveX = math.cos(angleToPlayer) * speed; - double moveY = math.sin(angleToPlayer) * speed; + // FIX 2: Move along patrol angle if unalerted, chase if alerted + if (!isAlerted || distance > 0.8) { + double currentMoveAngle = isAlerted ? angleToPlayer : angle; + double moveX = math.cos(currentMoveAngle) * speed; + double moveY = math.sin(currentMoveAngle) * speed; movement = getValidMovement( Coordinate2D(moveX, moveY), isWalkable, tryOpenDoor, ); } - if (distance < 6.0 && elapsedMs - lastActionTime > 1000) { + + // FIX 3: Only attack if alerted (Adjust the distance/timing per enemy class!) + if (isAlerted && distance < 6.0 && elapsedMs - lastActionTime > 1500) { if (hasLineOfSight(playerPosition, isWalkable)) { state = EntityState.attacking; lastActionTime = elapsedMs; diff --git a/packages/wolf_3d_entities/lib/src/entities/enemies/ss.dart b/packages/wolf_3d_entities/lib/src/entities/enemies/ss.dart index cdd2daf..26e1854 100644 --- a/packages/wolf_3d_entities/lib/src/entities/enemies/ss.dart +++ b/packages/wolf_3d_entities/lib/src/entities/enemies/ss.dart @@ -69,10 +69,16 @@ class SS extends Enemy { angleDiff: diff, ); + if (isAlerted && state != EntityState.dead) { + newAngle = angleToPlayer; + } + if (state == EntityState.patrolling) { - if (distance > 0.8) { - double moveX = math.cos(angleToPlayer) * speed; - double moveY = math.sin(angleToPlayer) * speed; + // FIX 2: Move along patrol angle if unalerted, chase if alerted + if (!isAlerted || distance > 0.8) { + double currentMoveAngle = isAlerted ? angleToPlayer : angle; + double moveX = math.cos(currentMoveAngle) * speed; + double moveY = math.sin(currentMoveAngle) * speed; movement = getValidMovement( Coordinate2D(moveX, moveY), isWalkable, @@ -80,7 +86,8 @@ class SS extends Enemy { ); } - if (distance < 6.0 && elapsedMs - lastActionTime > 1500) { + // FIX 3: Only attack if alerted (Adjust the distance/timing per enemy class!) + if (isAlerted && distance < 6.0 && elapsedMs - lastActionTime > 1500) { if (hasLineOfSight(playerPosition, isWalkable)) { state = EntityState.attacking; lastActionTime = elapsedMs;