#pragma once #include "CoreMinimal.h" class UDescentTerrainSubsystem; /** Constants of the helm (DESIGN_UE.md section 3.6; requirements U4, U9, V12). */ namespace Descent::Tune::Helm { constexpr double TopSpeedMps = 2.0; // U9: kept constexpr double SpeedTau = 1.2; // U9: 90 % of top speed 2.8 s after the lever is full (v2: about 20 s) constexpr double LeverPerSec = 1.5; constexpr double ThrottleMin = -0.5, ThrottleMax = 1.0; constexpr double LateralMps = 0.6, LateralTau = 1.5; constexpr double BallastMps = 1.3, BallastTau = 1.5; constexpr double AimYawDegPerPixel = 0.05, AimPitchDegPerPixel = 0.03; // U4: the mouse moves the aim point constexpr double AimYawLimitDeg = 40.0, AimPitchLimitDeg = 10.0; constexpr double YawGain = 1.2, YawRateMax = 0.10, YawTau = 0.8, YawAccelBase = 0.03, YawAccelPerMps = 0.01; // rad, s constexpr double PitchTau = 2.5, PitchMinSpeed = 0.3; constexpr double RollPerYawRate = -0.25; constexpr double ContactBand = 0.5, PushScale = 0.6, PushPerContact = 0.35, NormalRemove = 0.9, YawTorque = 0.00006, ContactDrag = 1.5; constexpr double DamageBase = 0.08, DamagePerMps = 0.9; constexpr double PowerDrainPerThrottle = 0.05, PowerRegen = 0.02; constexpr double RatingM = 3250.0; constexpr double CrippledThrottle = 0.25, CrippledBallast = 0.4; constexpr double ProximityRangeM = 30.0, ProximityHz = 4.0; constexpr double WaypointReachM = 14.0, StallAfterSec = 40.0; constexpr int32 NumViews = 5; } /** The carrier under the helm, as plain data: the automation tests fly it without an actor. Metres, degrees; yaw rate in rad/s. */ struct THEDESCENT_API FCarrierHelmState { FVector PosM = FVector::ZeroVector; double YawDeg = 0.0, PitchDeg = 0.0; double VFwd = 0.0, VLat = 0.0, VBal = 0.0; double YawRate = 0.0; // commands double Throttle = 0.0; // the lever, -0.5 .. 1 double AimYawDeg = 0.0, AimPitchDeg = 0.0; double Ballast = 0.0, Strafe = 0.0; // -1 .. 1 // consequences double Hull = 100.0, Power = 100.0; int32 Contacts = 0; double Scrape = 0.0, SumPen = 0.0; FVector VelocityMps() const; bool IsCrippled() const { return Hull <= 0.0; } bool IsAtRest() const; /** Leaving the helm: every target to zero, the aim on the hull. */ void AllStop(); /** The mouse: moves the aim, kept within 40 degrees of the heading and 10 degrees of level. */ void AddAim(double DeltaYawDeg, double DeltaPitchDeg); /** One step of section 3.6 against the density field (null terrain: open water). */ void Step(double Dt, UDescentTerrainSubsystem* Terrain); }; /** Follows a carrier route of section 2.10 waypoint by waypoint through the same helm commands a player has. */ struct THEDESCENT_API FCarrierAutopilot { bool bOn = false; int32 Route = 0; // 0 .. 2 int32 Index = 0; bool bStalled = false, bDone = false; double LineUpSec = 0.0; // time spent lining up over a well before the descent double StallTimer = 0.0, BestDist = 1e9; void Start(int32 InRoute); void Stop() { bOn = false; } void Step(FCarrierHelmState& Helm, double Dt); };