using System; using CounterDrone.Core.Algorithms; using CounterDrone.Core.Models; namespace CounterDrone.Core.Simulation { public enum PlatformState { Idle, FlyingToTarget, ReadyToRelease } public class PlatformEntity { public string Id { get; } public EquipmentRole Role { get; } public PlatformType? PlatformType { get; } public float PosX { get; private set; } public float PosY { get; private set; } public float PosZ { get; private set; } public AerosolType? AerosolType { get; } public int MunitionCount { get; private set; } public float Cooldown { get; } public float CooldownRemaining { get; private set; } public PlatformState State { get; private set; } = PlatformState.Idle; // 空基平台 public float CruiseSpeed { get; } public float PatrolX { get; } public float PatrolY { get; } public float PatrolZ { get; } public float ReleaseAltitude { get; } private float _targetX, _targetY, _targetZ; private float _flightDistance; private float _flownDistance; /// 空基平台精确投放时刻(计算值) public float ExactReleaseTime => _exactReleaseTime; private float _exactReleaseTime; // 地基平台 public float MuzzleVelocity { get; } /// Ready 包含:冷却就绪 + 有弹药 + 非飞行中 public bool Ready => CooldownRemaining <= 0 && MunitionCount > 0 && State != PlatformState.FlyingToTarget; public PlatformEntity(string id, EquipmentDeployment config) { Id = id; Role = (EquipmentRole)config.EquipmentRole; PlatformType = config.PlatformType.HasValue ? (PlatformType?)config.PlatformType.Value : null; PosX = (float)config.PositionX; PosY = (float)config.PositionY; PosZ = (float)config.PositionZ; AerosolType = config.AerosolType.HasValue ? (AerosolType?)config.AerosolType.Value : null; MunitionCount = config.MunitionCount ?? 1; Cooldown = (float)config.Cooldown; MuzzleVelocity = (float)(config.MuzzleVelocity ?? 0f); CruiseSpeed = (float)(config.CruiseSpeed ?? 0f); ReleaseAltitude = (float)(config.ReleaseAltitude ?? 0f); PatrolX = PosX; PatrolY = PosY; PatrolZ = PosZ; } public void Update(float deltaTime) { if (CooldownRemaining > 0) CooldownRemaining -= deltaTime; if (State != PlatformState.FlyingToTarget) return; float step = CruiseSpeed * deltaTime; _flownDistance += step; if (_flownDistance >= _flightDistance || _flightDistance < 0.01f) { PosX = _targetX; PosY = _targetY; PosZ = _targetZ; State = PlatformState.ReadyToRelease; return; } float t = _flownDistance / _flightDistance; PosX = PatrolX + (_targetX - PatrolX) * t; PosY = PatrolY + (_targetY - PatrolY) * t; PosZ = PatrolZ + (_targetZ - PatrolZ) * t; } /// 下令空基平台飞往投放点 public void CommandFlyTo(float targetX, float targetY, float targetZ, float fireTime) { if (PlatformType != Models.PlatformType.AirBased) return; _targetX = targetX; _targetY = targetY; _targetZ = targetZ; float dx = targetX - PosX; float dy = targetY - PosY; float dz = targetZ - PosZ; _flightDistance = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz); _flownDistance = 0; float flightTime = CruiseSpeed > 0 ? _flightDistance / CruiseSpeed : 0f; _exactReleaseTime = fireTime + flightTime; State = PlatformState.FlyingToTarget; } /// 地基:直接发射;空基:投弹后冷却 public void Release() { MunitionCount--; CooldownRemaining = Cooldown; State = PlatformState.Idle; } /// 空基平台到达投放点后可投弹 public bool CanRelease => State == PlatformState.ReadyToRelease && CooldownRemaining <= 0 && MunitionCount > 0; /// 当前速度矢量(空基平台:飞行方向 × 巡航速度;地基:零矢量) public (float Vx, float Vy, float Vz) CurrentVelocity { get { if (PlatformType != Models.PlatformType.AirBased) return (0, 0, 0); return Kinematics.DirectionVelocity(PatrolX, PatrolY, PatrolZ, _targetX, _targetY, _targetZ, CruiseSpeed); } } } }