import 'dart:math' as math; import 'package:wolf_dart/classes/coordinate_2d.dart'; import 'package:wolf_dart/features/entities/enemies/enemy.dart'; import 'package:wolf_dart/features/entities/entity.dart'; enum WeaponState { idle, firing } enum WeaponType { knife, pistol, machineGun, chainGun } abstract class Weapon { final WeaponType type; final int idleSprite; final List fireFrames; final int damage; final int msPerFrame; WeaponState state = WeaponState.idle; int frameIndex = 0; int lastFrameTime = 0; Weapon({ required this.type, required this.idleSprite, required this.fireFrames, required this.damage, this.msPerFrame = 100, }); int get currentSprite => state == WeaponState.idle ? idleSprite : fireFrames[frameIndex]; bool fire(int currentTime, {required int currentAmmo}) { if (state == WeaponState.idle && currentAmmo > 0) { state = WeaponState.firing; frameIndex = 0; lastFrameTime = currentTime; return true; } return false; } void update(int currentTime) { if (state == WeaponState.firing) { if (currentTime - lastFrameTime > msPerFrame) { frameIndex++; lastFrameTime = currentTime; if (frameIndex >= fireFrames.length) { state = WeaponState.idle; frameIndex = 0; } } } } // NEW: The weapon calculates its own hits and applies damage! void performHitscan({ required double playerX, required double playerY, required double playerAngle, required List entities, required bool Function(int x, int y) isWalkable, required int currentTime, required void Function(int scoreToAdd) onEnemyKilled, }) { Enemy? closestEnemy; double minDistance = 15.0; for (Entity entity in entities) { if (entity is Enemy && entity.state != EntityState.dead) { double dx = entity.x - playerX; double dy = entity.y - playerY; double angleToEnemy = math.atan2(dy, dx); double angleDiff = playerAngle - angleToEnemy; while (angleDiff <= -math.pi) { angleDiff += 2 * math.pi; } while (angleDiff > math.pi) { angleDiff -= 2 * math.pi; } double dist = math.sqrt(dx * dx + dy * dy); double threshold = 0.2 / dist; if (angleDiff.abs() < threshold) { Coordinate2D source = Coordinate2D(playerX, playerY); // Delegate to the enemy to check if it's visible if (entity.hasLineOfSightFrom( source, playerAngle, dist, isWalkable, )) { if (dist < minDistance) { minDistance = dist; closestEnemy = entity; } } } } } if (closestEnemy != null) { closestEnemy.takeDamage(damage, currentTime); if (closestEnemy.state == EntityState.dead) { onEnemyKilled(100); } } } }