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);
}
}
}
}