Working on fixing enemy identification
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -16,14 +16,13 @@ class Dog extends Enemy {
|
||||
required super.angle,
|
||||
required super.mapId,
|
||||
}) : super(
|
||||
spriteIndex: 99,
|
||||
spriteIndex: EnemyType.dog.spriteBaseIdx,
|
||||
state: EntityState.idle,
|
||||
);
|
||||
|
||||
static Dog? trySpawn(int objId, double x, double y, Difficulty _) {
|
||||
// Dogs span 216 to 251.
|
||||
if (objId >= MapObject.dogStart && objId <= MapObject.dogStart + 35) {
|
||||
bool isPatrolling = objId >= MapObject.dogStart + 18;
|
||||
if (EnemyType.dog.claimsMapId(objId)) {
|
||||
bool isPatrolling = objId >= EnemyType.dog.mapBaseId + 18;
|
||||
|
||||
return Dog(
|
||||
x: x,
|
||||
|
||||
@@ -3,6 +3,49 @@ import 'dart:math' as math;
|
||||
import 'package:wolf_dart/classes/coordinate_2d.dart';
|
||||
import 'package:wolf_dart/features/entities/entity.dart';
|
||||
|
||||
enum EnemyType {
|
||||
guard(mapBaseId: 108, spriteBaseIdx: 50),
|
||||
dog(mapBaseId: 216, spriteBaseIdx: 99),
|
||||
ss(mapBaseId: 180, spriteBaseIdx: 138),
|
||||
mutant(mapBaseId: 252, spriteBaseIdx: 187),
|
||||
officer(mapBaseId: 144, spriteBaseIdx: 238),
|
||||
;
|
||||
|
||||
final int mapBaseId;
|
||||
final int spriteBaseIdx;
|
||||
|
||||
const EnemyType({
|
||||
required this.mapBaseId,
|
||||
required this.spriteBaseIdx,
|
||||
});
|
||||
|
||||
/// Helper to check if a specific TED5 Map ID belongs to this enemy
|
||||
bool claimsMapId(int id) => id >= mapBaseId && id <= mapBaseId + 35;
|
||||
|
||||
/// Helper to find which EnemyType a given Map ID belongs to
|
||||
static EnemyType? fromMapId(int id) {
|
||||
for (final type in EnemyType.values) {
|
||||
if (type.claimsMapId(id)) return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool claimsSpriteIndex(int index) {
|
||||
return switch (this) {
|
||||
// Walk, Action, & Death: 50-98
|
||||
EnemyType.guard => index >= 50 && index <= 98,
|
||||
// Walk, Action, & Death: 99-137
|
||||
EnemyType.dog => index >= 99 && index <= 137,
|
||||
// Walk, Action, & Death: 138-186
|
||||
EnemyType.ss => index >= 138 && index <= 186,
|
||||
// Walk, Action, & Death: 187-237
|
||||
EnemyType.mutant => index >= 187 && index <= 237,
|
||||
// Walk, Action, & Death: 238-287
|
||||
EnemyType.officer => index >= 238 && index <= 287,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Enemy extends Entity {
|
||||
Enemy({
|
||||
required super.x,
|
||||
|
||||
@@ -16,18 +16,13 @@ class Guard extends Enemy {
|
||||
required super.angle,
|
||||
required super.mapId,
|
||||
}) : super(
|
||||
spriteIndex: 50,
|
||||
spriteIndex: EnemyType.guard.spriteBaseIdx,
|
||||
state: EntityState.idle,
|
||||
);
|
||||
|
||||
static Guard? trySpawn(int objId, double x, double y, Difficulty difficulty) {
|
||||
// Guards span 108 to 143. (124 and 125 are decorative dead bodies).
|
||||
if (objId >= MapObject.guardStart &&
|
||||
objId <= MapObject.guardStart + 35 &&
|
||||
objId != 124 &&
|
||||
objId != 125) {
|
||||
// If the ID is in the second half of the block, it's a Patrolling guard
|
||||
bool isPatrolling = objId >= MapObject.guardStart + 18;
|
||||
static Guard? trySpawn(int objId, double x, double y, Difficulty _) {
|
||||
if (EnemyType.guard.claimsMapId(objId) && objId != 124 && objId != 125) {
|
||||
bool isPatrolling = objId >= EnemyType.guard.mapBaseId + 18;
|
||||
|
||||
return Guard(
|
||||
x: x,
|
||||
@@ -110,15 +105,15 @@ class Guard extends Enemy {
|
||||
case EntityState.attacking:
|
||||
int timeShooting = elapsedMs - lastActionTime;
|
||||
if (timeShooting < 150) {
|
||||
spriteIndex = 96; // Aiming
|
||||
spriteIndex = 90; // Aiming
|
||||
} else if (timeShooting < 300) {
|
||||
spriteIndex = 97; // Firing
|
||||
spriteIndex = 91; // Firing
|
||||
if (!_hasFiredThisCycle) {
|
||||
onDamagePlayer(10);
|
||||
_hasFiredThisCycle = true;
|
||||
}
|
||||
} else if (timeShooting < 450) {
|
||||
spriteIndex = 98; // Recoil
|
||||
spriteIndex = 90; // Recoil (back to aim pose)
|
||||
} else {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -126,8 +121,7 @@ class Guard extends Enemy {
|
||||
break;
|
||||
|
||||
case EntityState.pain:
|
||||
spriteIndex = 94; // Ouch frame
|
||||
// Stay in pain for a brief moment, then resume attacking
|
||||
spriteIndex = 92; // Ouch frame
|
||||
if (elapsedMs - lastActionTime > 250) {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -137,15 +131,14 @@ class Guard extends Enemy {
|
||||
case EntityState.dead:
|
||||
if (isDying) {
|
||||
int deathFrame = (elapsedMs - lastActionTime) ~/ 150;
|
||||
if (deathFrame < 4) {
|
||||
// FIX: Removed the buggy "- 1"
|
||||
spriteIndex = 90 + deathFrame;
|
||||
if (deathFrame < 3) {
|
||||
spriteIndex = 93 + deathFrame; // Cycles 93, 94, 95
|
||||
} else {
|
||||
spriteIndex = 95; // Final dead frame
|
||||
isDying = false;
|
||||
}
|
||||
} else {
|
||||
spriteIndex = 95;
|
||||
spriteIndex = 95; // Final dead frame
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:wolf_dart/features/entities/map_objects.dart';
|
||||
|
||||
class Mutant extends Enemy {
|
||||
static const double speed = 0.045;
|
||||
static const int _baseSprite = 187;
|
||||
bool _hasFiredThisCycle = false;
|
||||
|
||||
Mutant({
|
||||
@@ -17,22 +16,16 @@ class Mutant extends Enemy {
|
||||
required super.angle,
|
||||
required super.mapId,
|
||||
}) : super(
|
||||
spriteIndex: _baseSprite,
|
||||
spriteIndex: EnemyType.mutant.spriteBaseIdx,
|
||||
state: EntityState.idle,
|
||||
) {
|
||||
health = 45;
|
||||
damage = 10;
|
||||
}
|
||||
|
||||
static Mutant? trySpawn(
|
||||
int objId,
|
||||
double x,
|
||||
double y,
|
||||
Difficulty difficulty,
|
||||
) {
|
||||
// Mutants span 252 to 287
|
||||
if (objId >= MapObject.mutantStart && objId <= MapObject.mutantStart + 35) {
|
||||
bool isPatrolling = objId >= MapObject.mutantStart + 18;
|
||||
static Mutant? trySpawn(int objId, double x, double y, Difficulty _) {
|
||||
if (EnemyType.mutant.claimsMapId(objId)) {
|
||||
bool isPatrolling = objId >= EnemyType.mutant.mapBaseId + 18;
|
||||
|
||||
return Mutant(
|
||||
x: x,
|
||||
@@ -81,7 +74,7 @@ class Mutant extends Enemy {
|
||||
|
||||
switch (state) {
|
||||
case EntityState.idle:
|
||||
spriteIndex = _baseSprite + octant;
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + octant;
|
||||
break;
|
||||
|
||||
case EntityState.patrolling:
|
||||
@@ -96,7 +89,8 @@ class Mutant extends Enemy {
|
||||
}
|
||||
|
||||
int walkFrame = (elapsedMs ~/ 150) % 4;
|
||||
spriteIndex = (_baseSprite + 8) + (walkFrame * 8) + octant;
|
||||
spriteIndex =
|
||||
(EnemyType.mutant.spriteBaseIdx + 8) + (walkFrame * 8) + octant;
|
||||
|
||||
if (distance < 6.0 && elapsedMs - lastActionTime > 1000) {
|
||||
if (hasLineOfSight(playerPosition, isWalkable)) {
|
||||
@@ -110,15 +104,15 @@ class Mutant extends Enemy {
|
||||
case EntityState.attacking:
|
||||
int timeShooting = elapsedMs - lastActionTime;
|
||||
if (timeShooting < 150) {
|
||||
spriteIndex = _baseSprite + 46; // Aiming
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 46; // Aiming
|
||||
} else if (timeShooting < 300) {
|
||||
spriteIndex = _baseSprite + 47; // Firing
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 47; // Firing
|
||||
if (!_hasFiredThisCycle) {
|
||||
onDamagePlayer(damage);
|
||||
_hasFiredThisCycle = true;
|
||||
}
|
||||
} else if (timeShooting < 450) {
|
||||
spriteIndex = _baseSprite + 48; // Recoil
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 48; // Recoil
|
||||
} else {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -126,7 +120,7 @@ class Mutant extends Enemy {
|
||||
break;
|
||||
|
||||
case EntityState.pain:
|
||||
spriteIndex = _baseSprite + 44;
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 44;
|
||||
if (elapsedMs - lastActionTime > 250) {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -137,13 +131,13 @@ class Mutant extends Enemy {
|
||||
if (isDying) {
|
||||
int deathFrame = (elapsedMs - lastActionTime) ~/ 150;
|
||||
if (deathFrame < 4) {
|
||||
spriteIndex = (_baseSprite + 40) + deathFrame;
|
||||
spriteIndex = (EnemyType.mutant.spriteBaseIdx + 40) + deathFrame;
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 45;
|
||||
isDying = false;
|
||||
}
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.mutant.spriteBaseIdx + 45;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:wolf_dart/features/entities/map_objects.dart';
|
||||
|
||||
class Officer extends Enemy {
|
||||
static const double speed = 0.055;
|
||||
static const int _baseSprite = 50;
|
||||
bool _hasFiredThisCycle = false;
|
||||
|
||||
Officer({
|
||||
@@ -17,22 +16,16 @@ class Officer extends Enemy {
|
||||
required super.angle,
|
||||
required super.mapId,
|
||||
}) : super(
|
||||
spriteIndex: _baseSprite,
|
||||
spriteIndex: EnemyType.officer.spriteBaseIdx,
|
||||
state: EntityState.idle,
|
||||
) {
|
||||
health = 50;
|
||||
damage = 15;
|
||||
}
|
||||
|
||||
static Officer? trySpawn(
|
||||
int objId,
|
||||
double x,
|
||||
double y,
|
||||
Difficulty difficulty,
|
||||
) {
|
||||
if (objId >= MapObject.officerStart &&
|
||||
objId <= MapObject.officerStart + 35) {
|
||||
bool isPatrolling = objId >= MapObject.officerStart + 18;
|
||||
static Officer? trySpawn(int objId, double x, double y, Difficulty _) {
|
||||
if (EnemyType.officer.claimsMapId(objId)) {
|
||||
bool isPatrolling = objId >= EnemyType.officer.mapBaseId + 18;
|
||||
|
||||
return Officer(
|
||||
x: x,
|
||||
@@ -81,7 +74,7 @@ class Officer extends Enemy {
|
||||
|
||||
switch (state) {
|
||||
case EntityState.idle:
|
||||
spriteIndex = _baseSprite + octant;
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + octant;
|
||||
break;
|
||||
|
||||
case EntityState.patrolling:
|
||||
@@ -96,7 +89,8 @@ class Officer extends Enemy {
|
||||
}
|
||||
|
||||
int walkFrame = (elapsedMs ~/ 150) % 4;
|
||||
spriteIndex = (_baseSprite + 8) + (walkFrame * 8) + octant;
|
||||
spriteIndex =
|
||||
(EnemyType.officer.spriteBaseIdx + 8) + (walkFrame * 8) + octant;
|
||||
|
||||
if (distance < 6.0 && elapsedMs - lastActionTime > 1000) {
|
||||
if (hasLineOfSight(playerPosition, isWalkable)) {
|
||||
@@ -110,15 +104,15 @@ class Officer extends Enemy {
|
||||
case EntityState.attacking:
|
||||
int timeShooting = elapsedMs - lastActionTime;
|
||||
if (timeShooting < 150) {
|
||||
spriteIndex = _baseSprite + 46; // Aiming
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 40; // Aiming
|
||||
} else if (timeShooting < 300) {
|
||||
spriteIndex = _baseSprite + 47; // Firing
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 41; // Firing
|
||||
if (!_hasFiredThisCycle) {
|
||||
onDamagePlayer(damage);
|
||||
_hasFiredThisCycle = true;
|
||||
}
|
||||
} else if (timeShooting < 450) {
|
||||
spriteIndex = _baseSprite + 48; // Recoil
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 40; // Recoil
|
||||
} else {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -126,7 +120,7 @@ class Officer extends Enemy {
|
||||
break;
|
||||
|
||||
case EntityState.pain:
|
||||
spriteIndex = _baseSprite + 44;
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 42;
|
||||
if (elapsedMs - lastActionTime > 250) {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -136,14 +130,14 @@ class Officer extends Enemy {
|
||||
case EntityState.dead:
|
||||
if (isDying) {
|
||||
int deathFrame = (elapsedMs - lastActionTime) ~/ 150;
|
||||
if (deathFrame < 4) {
|
||||
spriteIndex = (_baseSprite + 40) + deathFrame;
|
||||
if (deathFrame < 3) {
|
||||
spriteIndex = (EnemyType.officer.spriteBaseIdx + 43) + deathFrame;
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 45;
|
||||
isDying = false;
|
||||
}
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.officer.spriteBaseIdx + 45;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:wolf_dart/features/entities/map_objects.dart';
|
||||
|
||||
class SS extends Enemy {
|
||||
static const double speed = 0.04;
|
||||
static const int _baseSprite = 138;
|
||||
bool _hasFiredThisCycle = false;
|
||||
|
||||
SS({
|
||||
@@ -17,16 +16,16 @@ class SS extends Enemy {
|
||||
required super.angle,
|
||||
required super.mapId,
|
||||
}) : super(
|
||||
spriteIndex: _baseSprite,
|
||||
spriteIndex: EnemyType.ss.spriteBaseIdx,
|
||||
state: EntityState.idle,
|
||||
) {
|
||||
health = 100;
|
||||
damage = 20;
|
||||
}
|
||||
|
||||
static SS? trySpawn(int objId, double x, double y, Difficulty difficulty) {
|
||||
if (objId >= MapObject.ssStart && objId <= MapObject.ssStart + 35) {
|
||||
bool isPatrolling = objId >= MapObject.ssStart + 18;
|
||||
static SS? trySpawn(int objId, double x, double y, Difficulty _) {
|
||||
if (EnemyType.ss.claimsMapId(objId)) {
|
||||
bool isPatrolling = objId >= EnemyType.ss.mapBaseId + 18;
|
||||
|
||||
return SS(
|
||||
x: x,
|
||||
@@ -75,7 +74,7 @@ class SS extends Enemy {
|
||||
|
||||
switch (state) {
|
||||
case EntityState.idle:
|
||||
spriteIndex = _baseSprite + octant;
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + octant;
|
||||
break;
|
||||
|
||||
case EntityState.patrolling:
|
||||
@@ -90,7 +89,8 @@ class SS extends Enemy {
|
||||
}
|
||||
|
||||
int walkFrame = (elapsedMs ~/ 150) % 4;
|
||||
spriteIndex = (_baseSprite + 8) + (walkFrame * 8) + octant;
|
||||
spriteIndex =
|
||||
(EnemyType.ss.spriteBaseIdx + 8) + (walkFrame * 8) + octant;
|
||||
|
||||
if (distance < 6.0 && elapsedMs - lastActionTime > 1500) {
|
||||
if (hasLineOfSight(playerPosition, isWalkable)) {
|
||||
@@ -105,15 +105,15 @@ class SS extends Enemy {
|
||||
// SS machine gun fires much faster than a standard pistol!
|
||||
int timeShooting = elapsedMs - lastActionTime;
|
||||
if (timeShooting < 100) {
|
||||
spriteIndex = _baseSprite + 46; // Aiming
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 46; // Aiming
|
||||
} else if (timeShooting < 200) {
|
||||
spriteIndex = _baseSprite + 47; // Firing
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 47; // Firing
|
||||
if (!_hasFiredThisCycle) {
|
||||
onDamagePlayer(damage);
|
||||
_hasFiredThisCycle = true;
|
||||
}
|
||||
} else if (timeShooting < 300) {
|
||||
spriteIndex = _baseSprite + 48; // Recoil
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 48; // Recoil
|
||||
} else {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -121,7 +121,7 @@ class SS extends Enemy {
|
||||
break;
|
||||
|
||||
case EntityState.pain:
|
||||
spriteIndex = _baseSprite + 44;
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 44;
|
||||
if (elapsedMs - lastActionTime > 250) {
|
||||
state = EntityState.patrolling;
|
||||
lastActionTime = elapsedMs;
|
||||
@@ -132,13 +132,13 @@ class SS extends Enemy {
|
||||
if (isDying) {
|
||||
int deathFrame = (elapsedMs - lastActionTime) ~/ 150;
|
||||
if (deathFrame < 4) {
|
||||
spriteIndex = (_baseSprite + 40) + deathFrame;
|
||||
spriteIndex = (EnemyType.ss.spriteBaseIdx + 40) + deathFrame;
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 45;
|
||||
isDying = false;
|
||||
}
|
||||
} else {
|
||||
spriteIndex = _baseSprite + 45;
|
||||
spriteIndex = EnemyType.ss.spriteBaseIdx + 45;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:wolf_dart/features/entities/collectible.dart';
|
||||
import 'package:wolf_dart/features/entities/decorative.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/bosses/hans_grosse.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/dog.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/enemy.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/guard.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/mutant.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/officer.dart';
|
||||
@@ -50,6 +51,11 @@ abstract class EntityRegistry {
|
||||
for (final spawner in _spawners) {
|
||||
Entity? entity = spawner(objId, x, y, difficulty);
|
||||
|
||||
final EnemyType? type = EnemyType.fromMapId(objId);
|
||||
if (type != null) {
|
||||
print("Spawning ${type.name} enemy");
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
// Safety bounds check for the VSWAP array
|
||||
if (entity.spriteIndex >= 0 && entity.spriteIndex < maxSprites) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:wolf_dart/classes/cardinal_direction.dart';
|
||||
import 'package:wolf_dart/features/difficulty/difficulty.dart';
|
||||
import 'package:wolf_dart/features/entities/enemies/enemy.dart';
|
||||
|
||||
abstract class MapObject {
|
||||
// --- Player Spawns ---
|
||||
@@ -81,10 +82,10 @@ abstract class MapObject {
|
||||
|
||||
// --- Enemy Range Constants ---
|
||||
static const int guardStart = 108; // 108-143
|
||||
static const int officerStart = 144; // 144-179 (WL6)
|
||||
static const int ssStart = 180; // 180-215 (WL6)
|
||||
static const int officerStart = 144; // 144-179
|
||||
static const int ssStart = 180; // 180-215
|
||||
static const int dogStart = 216; // 216-251
|
||||
static const int mutantStart = 252; // 252-287 (WL6)
|
||||
static const int mutantStart = 252; // 252-287
|
||||
|
||||
// --- Missing Decorative Bodies ---
|
||||
static const int deadGuard = 124; // Decorative only in WL1
|
||||
@@ -112,6 +113,7 @@ abstract class MapObject {
|
||||
}
|
||||
|
||||
static double getAngle(int id) {
|
||||
// Player spawn
|
||||
switch (id) {
|
||||
case playerNorth:
|
||||
return CardinalDirection.north.radians;
|
||||
@@ -123,52 +125,34 @@ abstract class MapObject {
|
||||
return CardinalDirection.west.radians;
|
||||
}
|
||||
|
||||
// FIX: Expand the boundary to include ALL enemies (Dogs and Mutants)
|
||||
if (id < guardStart || id > (mutantStart + 35)) return 0.0;
|
||||
// Boss check
|
||||
if (id == bossHansGrosse) return 0.0;
|
||||
|
||||
int baseId;
|
||||
if (id >= mutantStart) {
|
||||
baseId = mutantStart;
|
||||
} else if (id >= dogStart) {
|
||||
baseId = dogStart;
|
||||
} else if (id >= ssStart) {
|
||||
baseId = ssStart;
|
||||
} else if (id >= officerStart) {
|
||||
baseId = officerStart;
|
||||
} else {
|
||||
baseId = guardStart;
|
||||
}
|
||||
final EnemyType? type = EnemyType.fromMapId(id);
|
||||
if (type == null) return 0.0; // Not a standard directional enemy
|
||||
|
||||
// FIX: Normalize patrolling enemies back to the standing block, THEN get the 4-way angle
|
||||
int directionIndex = ((id - baseId) % 18) % 4;
|
||||
// Normalize patrolling enemies back to the standing block, THEN get the
|
||||
// 4-way angle
|
||||
int directionIndex = ((id - type.mapBaseId) % 18) % 4;
|
||||
return CardinalDirection.fromEnemyIndex(directionIndex).radians;
|
||||
}
|
||||
|
||||
static bool shouldSpawn(int id, Difficulty selectedDifficulty) {
|
||||
// FIX: Expand the boundary so Dogs and Mutants aren't bypassing difficulty checks
|
||||
if (id < guardStart || id > (mutantStart + 35)) return true;
|
||||
EnemyType? type = EnemyType.fromMapId(id);
|
||||
|
||||
int baseId;
|
||||
if (id >= mutantStart) {
|
||||
baseId = mutantStart;
|
||||
} else if (id >= dogStart) {
|
||||
baseId = dogStart;
|
||||
} else if (id >= ssStart) {
|
||||
baseId = ssStart;
|
||||
} else if (id >= officerStart) {
|
||||
baseId = officerStart;
|
||||
} else {
|
||||
baseId = guardStart;
|
||||
}
|
||||
// If it's not a standard enemy (it's a decoration, boss, or player), spawn it
|
||||
if (type == null) return true;
|
||||
|
||||
int relativeId = (id - baseId) % 18;
|
||||
int offset = id - type.mapBaseId;
|
||||
int normalizedOffset = offset >= 18 ? offset - 18 : offset;
|
||||
|
||||
return switch (relativeId) {
|
||||
< 4 => true,
|
||||
< 8 => selectedDifficulty.level >= Difficulty.dontHurtMe.level,
|
||||
< 12 => selectedDifficulty.level >= Difficulty.bringEmOn.level,
|
||||
< 16 => selectedDifficulty.level >= Difficulty.iAmDeathIncarnate.level,
|
||||
_ => true,
|
||||
return switch (normalizedOffset) {
|
||||
< 4 => true, // Spawns on all difficulties
|
||||
< 8 => selectedDifficulty.level >= Difficulty.bringEmOn.level, // Normal
|
||||
< 16 =>
|
||||
selectedDifficulty.level >=
|
||||
Difficulty.iAmDeathIncarnate.level, // Hard & Ambush
|
||||
_ => true, // Dead bodies (decorations)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,11 @@ import 'package:wolf_3d_data/wolf_3d_data.dart';
|
||||
|
||||
class WolfLevel {
|
||||
final String name;
|
||||
final int width; // Always 64 in standard Wolf3D
|
||||
final int height; // Always 64
|
||||
final Sprite wallGrid;
|
||||
final Sprite objectGrid;
|
||||
|
||||
WolfLevel({
|
||||
required this.name,
|
||||
required this.width,
|
||||
required this.height,
|
||||
required this.wallGrid,
|
||||
required this.objectGrid,
|
||||
});
|
||||
|
||||
@@ -29,8 +29,8 @@ class WolfMap {
|
||||
gameMaps,
|
||||
isShareware: true,
|
||||
);
|
||||
final parsedTextures = VswapParser.parseWalls(vswap);
|
||||
final parsedSprites = VswapParser.parseSprites(vswap);
|
||||
final parsedTextures = WLParser.parseWalls(vswap);
|
||||
final parsedSprites = WLParser.parseSprites(vswap);
|
||||
|
||||
// 3. Return the populated instance!
|
||||
return WolfMap._(
|
||||
@@ -49,8 +49,8 @@ class WolfMap {
|
||||
|
||||
// 2. Parse the data using the parser we just built
|
||||
final parsedLevels = WolfMapParser.parseMaps(mapHead, gameMaps);
|
||||
final parsedTextures = VswapParser.parseWalls(vswap);
|
||||
final parsedSprites = VswapParser.parseSprites(vswap);
|
||||
final parsedTextures = WLParser.parseWalls(vswap);
|
||||
final parsedSprites = WLParser.parseSprites(vswap);
|
||||
|
||||
// 3. Return the populated instance!
|
||||
return WolfMap._(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:wolf_3d_data/wolf_3d_data.dart';
|
||||
import 'package:wolf_dart/features/entities/map_objects.dart';
|
||||
import 'package:wolf_dart/features/map/wolf_level.dart';
|
||||
|
||||
@@ -40,10 +39,6 @@ abstract class WolfMapParser {
|
||||
int plane0Length = gameMaps.getUint16(mapOffset + 12, Endian.little);
|
||||
int plane1Length = gameMaps.getUint16(mapOffset + 14, Endian.little);
|
||||
|
||||
// Dimensions (Always 64x64, but we read it anyway for accuracy)
|
||||
int width = gameMaps.getUint16(mapOffset + 18, Endian.little);
|
||||
int height = gameMaps.getUint16(mapOffset + 20, Endian.little);
|
||||
|
||||
// Map Name (16 bytes of ASCII text)
|
||||
List<int> nameBytes = [];
|
||||
for (int n = 0; n < 16; n++) {
|
||||
@@ -86,25 +81,23 @@ abstract class WolfMapParser {
|
||||
}
|
||||
}
|
||||
|
||||
Sprite wallGrid = [];
|
||||
Sprite objectGrid = []; // NEW
|
||||
List<List<int>> wallGrid = [];
|
||||
List<List<int>> objectGrid = [];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int y = 0; y < 64; y++) {
|
||||
List<int> wallRow = [];
|
||||
List<int> objectRow = []; // NEW
|
||||
for (int x = 0; x < width; x++) {
|
||||
wallRow.add(flatWallGrid[y * width + x]);
|
||||
objectRow.add(flatObjectGrid[y * width + x]); // NEW
|
||||
List<int> objectRow = [];
|
||||
for (int x = 0; x < 64; x++) {
|
||||
wallRow.add(flatWallGrid[y * 64 + x]);
|
||||
objectRow.add(flatObjectGrid[y * 64 + x]);
|
||||
}
|
||||
wallGrid.add(wallRow);
|
||||
objectGrid.add(objectRow); // NEW
|
||||
objectGrid.add(objectRow);
|
||||
}
|
||||
|
||||
levels.add(
|
||||
WolfLevel(
|
||||
name: name,
|
||||
width: width,
|
||||
height: height,
|
||||
wallGrid: wallGrid,
|
||||
objectGrid: objectGrid,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user