Add shareware support and spawn correctly for difficulty levels

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-14 17:01:01 +01:00
parent 690ac1e7e6
commit 278c73a256
19 changed files with 383 additions and 238 deletions

View File

@@ -1,11 +1,13 @@
import 'dart:math' as math;
import 'package:wolf_dart/classes/coordinate_2d.dart';
import 'package:wolf_dart/features/difficulty/difficulty.dart';
import 'package:wolf_dart/features/entities/enemies/enemy.dart';
import 'package:wolf_dart/features/entities/entity.dart';
import 'package:wolf_dart/features/entities/map_objects.dart'; // NEW
class Dog extends Enemy {
static const double speed = 0.05; // Dogs are much faster than guards!
static const double speed = 0.05;
bool _hasBittenThisCycle = false;
Dog({
@@ -14,32 +16,17 @@ class Dog extends Enemy {
required super.angle,
required super.mapId,
}) : super(
spriteIndex: 99, // Dogs start at index 99 in VSWAP
spriteIndex: 99,
state: EntityState.idle,
);
static Dog? trySpawn(int objId, double x, double y, int difficultyLevel) {
bool canSpawn = false;
switch (difficultyLevel) {
case 0:
canSpawn = objId >= 116 && objId <= 119;
break;
case 1:
canSpawn = objId >= 152 && objId <= 155;
break;
case 2:
canSpawn = objId >= 188 && objId <= 191;
break;
case 3:
canSpawn = objId >= 224 && objId <= 227;
break;
}
if (canSpawn) {
static Dog? trySpawn(int objId, double x, double y, Difficulty difficulty) {
// The renderer already checked difficulty, so we just check the ID block!
if (objId >= MapObject.dogStart && objId <= MapObject.dogStart + 17) {
return Dog(
x: x,
y: y,
angle: Enemy.getInitialAngle(objId),
angle: MapObject.getAngle(objId),
mapId: objId,
);
}
@@ -51,23 +38,19 @@ class Dog extends Enemy {
required int elapsedMs,
required Coordinate2D playerPosition,
required bool Function(int x, int y) isWalkable,
required void Function(int x, int y) tryOpenDoor, // NEW
required void Function(int x, int y) tryOpenDoor,
required void Function(int damage) onDamagePlayer,
}) {
Coordinate2D movement = const Coordinate2D(0, 0);
double newAngle = angle;
// 1. Wake up logic
if (state == EntityState.idle &&
hasLineOfSight(playerPosition, isWalkable)) {
if (reactionTimeMs == 0) {
reactionTimeMs = elapsedMs + 100 + math.Random().nextInt(200);
} else if (elapsedMs >= reactionTimeMs) {
state = EntityState.patrolling;
lastActionTime = elapsedMs;
reactionTimeMs = 0;
}
}
checkWakeUp(
elapsedMs: elapsedMs,
playerPosition: playerPosition,
isWalkable: isWalkable,
baseReactionMs: 100,
reactionVarianceMs: 200,
);
double distance = position.distanceTo(playerPosition);
double angleToPlayer = position.angleTo(playerPosition);
@@ -76,13 +59,10 @@ class Dog extends Enemy {
newAngle = angleToPlayer;
}
double diff = newAngle - angleToPlayer;
while (diff <= -math.pi) {
diff += 2 * math.pi;
}
while (diff > math.pi) {
diff -= 2 * math.pi;
}
double diff = angleToPlayer - newAngle;
while (diff <= -math.pi) diff += 2 * math.pi;
while (diff > math.pi) diff -= 2 * math.pi;
int octant = ((diff + (math.pi / 8)) / (math.pi / 4)).floor() % 8;
if (octant < 0) octant += 8;
@@ -95,15 +75,12 @@ class Dog extends Enemy {
case EntityState.patrolling:
if (distance > 0.8) {
double deltaX = playerPosition.x - position.x;
double deltaY = playerPosition.y - position.y;
double moveX = deltaX > 0 ? speed : (deltaX < 0 ? -speed : 0);
double moveY = deltaY > 0 ? speed : (deltaY < 0 ? -speed : 0);
// UPGRADED: Smooth vector movement instead of grid-snapping
double moveX = math.cos(angleToPlayer) * speed;
double moveY = math.sin(angleToPlayer) * speed;
Coordinate2D intendedMovement = Coordinate2D(moveX, moveY);
// Pass tryOpenDoor down!
movement = getValidMovement(
intendedMovement,
isWalkable,
@@ -135,6 +112,22 @@ class Dog extends Enemy {
}
break;
// Make sure dogs have a death state so they don't stay standing!
case EntityState.dead:
if (isDying) {
int deathFrame = (elapsedMs - lastActionTime) ~/ 100;
if (deathFrame < 4) {
spriteIndex =
140 + deathFrame; // Dog death frames usually start here
} else {
spriteIndex = 143; // Dead dog on floor
isDying = false;
}
} else {
spriteIndex = 143;
}
break;
default:
break;
}