Delete the aether drive: behaviour, union 12, hardpoint type, aggregates, settings, presenters, prefab
AetherDriveData and AetherDrive, Union(12) (now a retired-do-not-reuse comment, as 26 is), HardpointType.AetherDrive (last member, nothing shifts), Ship's drive sets, aggregates and Axis write, the five request-field rows, GameplaySettings Aether multipliers, ShipInstance's drive particles, SchematicDisplay's RPM display and AetherDriveUi, the undock refusal's drive clause, the drive prefab and material, and AetherDb's drive roles and brownout row. The design is kept at parked/aether-drive. Adds EveryShippedShipHullHasATopSpeed. ARPG.unity still holds stale serialized references to the removed SchematicDisplay fields and the RPM Display object; the next commit removes them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4656857420
commit
2cfdc72853
21 changed files with 36 additions and 5234 deletions
|
|
@ -1,185 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using GameCult.Caching;
|
||||
using MessagePack;
|
||||
using Newtonsoft.Json;
|
||||
using CultMath;
|
||||
using static CultMath.math;
|
||||
|
||||
[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), RuntimeInspectable]
|
||||
public class AetherDriveData : BehaviorData
|
||||
{
|
||||
[Inspectable, JsonProperty("diameters"), Key(1)]
|
||||
public float3 RotorDiameter;
|
||||
|
||||
[Inspectable, JsonProperty("masses"), Key(2)]
|
||||
public float3 RotorMass;
|
||||
|
||||
[Inspectable, JsonProperty("rpm"), Key(3), RuntimeInspectable]
|
||||
public PerformanceStat MaximumRpm;
|
||||
|
||||
[Inspectable, JsonProperty("couplingLambdas"), Key(4)]
|
||||
public float3 CouplingLambda;
|
||||
|
||||
[Inspectable, JsonProperty("lambdaMultiplier"), Key(5)]
|
||||
public PerformanceStat LambdaMultiplier;
|
||||
|
||||
[Inspectable, JsonProperty("couplingEfficiency"), Key(6), RuntimeInspectable]
|
||||
public PerformanceStat CouplingEfficiency;
|
||||
|
||||
[Inspectable, JsonProperty("torque"), Key(7), RuntimeInspectable]
|
||||
public PerformanceStat Torque;
|
||||
|
||||
[Inspectable, JsonProperty("torqueProfile"), Key(8), RuntimeInspectable]
|
||||
public BezierCurve TorqueProfile;
|
||||
|
||||
[Inspectable, JsonProperty("draw"), Key(9), RuntimeInspectable]
|
||||
public PerformanceStat EnergyDraw;
|
||||
|
||||
[Inspectable, JsonProperty("passiveCoupling"), Key(10), RuntimeInspectable]
|
||||
public PerformanceStat PassiveCoupling;
|
||||
|
||||
[Inspectable, JsonProperty("rpmAudio"), Key(11), RuntimeInspectable]
|
||||
public uint RpmAudioParameter;
|
||||
|
||||
[Inspectable, JsonProperty("torqueAudio"), Key(12), RuntimeInspectable]
|
||||
public uint TorqueRatioAudioParameter;
|
||||
|
||||
[Inspectable, CultInspectorAssetGuid, JsonProperty("particles"), Key(13)]
|
||||
public string Particles;
|
||||
|
||||
public override Behavior CreateInstance(EquippedItem item)
|
||||
{
|
||||
return new AetherDrive(this, item);
|
||||
}
|
||||
|
||||
public override Behavior CreateInstance(ConsumableItemEffect item)
|
||||
{
|
||||
return new AetherDrive(this, item);
|
||||
}
|
||||
}
|
||||
|
||||
public class AetherDrive : Behavior, IPowerConsumer
|
||||
{
|
||||
private AetherDriveData _data;
|
||||
private float3 _axis;
|
||||
|
||||
public float3 Thrust { get; private set; }
|
||||
public float3 Rpm { get; private set; }
|
||||
public float MaximumRpm { get; private set; }
|
||||
public float2 ThrustDirection { get; private set; }
|
||||
|
||||
public AetherDriveData DriveData => _data;
|
||||
|
||||
// Cut 8 (operator ask 2026-09-19): the equivalent quantity to Thruster.Condition -- Torque is the stat that
|
||||
// actually governs this behaviour's rotor spin-up (PowerRequest/Execute above both read it), so it is what
|
||||
// "broken" means for a drive. 1f for the item-less ConsumableItemEffect case, same reasoning as Thruster.
|
||||
public float Condition => Item?.ConditionRatio(_data.Torque) ?? 1f;
|
||||
|
||||
public float3 Axis
|
||||
{
|
||||
get => _axis;
|
||||
set => _axis = clamp(value, -1, 1);
|
||||
}
|
||||
|
||||
public AetherDrive(AetherDriveData data, EquippedItem item) : base(data, item)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public AetherDrive(AetherDriveData data, ConsumableItemEffect item) : base(data, item)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
// Cut 3 (docs/stats-and-power-cut.md): the request PowerBus needs before Execute runs. Only the rotor
|
||||
// spin-up (torque accelerating Rpm toward MaximumRpm) costs power -- spending existing spin into thrust
|
||||
// (Execute's decay-to-thrust arithmetic below) is free, same as before. Pure and side-effect-free: it reads
|
||||
// Rpm but does not write it, so Execute's own identical arithmetic a few lines later -- which does perform
|
||||
// the real decay -- produces the same numbers Rpm actually moves by. Accepts the recompute (Q3's ruling).
|
||||
//
|
||||
// Nominal-request ruling (docs/stats-and-power-cut.md, operator ruling 2026-09-19): Torque, LambdaMultiplier,
|
||||
// MaximumRpm, PassiveCoupling and EnergyDraw are all registered request fields (StatValidation.
|
||||
// PowerRequestFields) -- read nominally (what full power would produce) so Torque carrying its own
|
||||
// PowerSupply term (Cut 7's brownout curve) no longer makes this tick's request depend on this tick's own
|
||||
// grant. Execute below is unchanged: it calls the real, curved Evaluate, so the actual spin-up still
|
||||
// degrades with whatever the bus actually grants.
|
||||
public float PowerRequest(float dt)
|
||||
{
|
||||
var couplingLambda = _data.CouplingLambda * Item.EvaluateNominalPower(_data.LambdaMultiplier) * max(abs(_axis), EvaluateNominalPower(_data.PassiveCoupling));
|
||||
var rpmAfterDecay = decay(Rpm, couplingLambda, dt);
|
||||
var maximumRpm = EvaluateNominalPower(_data.MaximumRpm);
|
||||
var torqueProfile = float3(
|
||||
_data.TorqueProfile.Evaluate(rpmAfterDecay.x / maximumRpm),
|
||||
_data.TorqueProfile.Evaluate(rpmAfterDecay.y / maximumRpm),
|
||||
_data.TorqueProfile.Evaluate(rpmAfterDecay.z / maximumRpm));
|
||||
var potentialTorque = EvaluateNominalPower(_data.Torque) * torqueProfile;
|
||||
var potentialRpmDelta = potentialTorque / length(_data.RotorMass) * dt;
|
||||
var actualRpmDelta = min(maximumRpm - rpmAfterDecay, potentialRpmDelta);
|
||||
var torqueRatio = actualRpmDelta / potentialRpmDelta;
|
||||
var draw = torqueRatio * EvaluateNominalPower(_data.EnergyDraw) / 3;
|
||||
return (draw.x + draw.y + draw.z) * dt;
|
||||
}
|
||||
|
||||
// Cut 5 (docs/stats-and-power-cut.md §1.3, PowerTiers.cs): Medium -- mobility, same as Thruster.
|
||||
public int DefaultPowerTier => PowerTiers.Medium;
|
||||
|
||||
public override bool Execute(float dt)
|
||||
{
|
||||
var rotorSpeed = Rpm * _data.RotorDiameter / 100;
|
||||
|
||||
var forward = normalize(Entity.Direction);
|
||||
var right = forward.Rotate(ItemRotation.Clockwise);
|
||||
|
||||
var speed = float2(dot(Entity.Velocity, forward), dot(Entity.Velocity, right));
|
||||
var couplingEfficiency = Evaluate(_data.CouplingEfficiency);
|
||||
var efficiency = float3(saturate(1 - speed / max(rotorSpeed.xy, 1) * sign(_axis.xy)) * couplingEfficiency, 1);
|
||||
|
||||
Thrust = (Rpm - decay(Rpm, _data.CouplingLambda, dt)) * _data.RotorMass * efficiency;
|
||||
|
||||
var couplingLambda = _data.CouplingLambda * Item.Evaluate(_data.LambdaMultiplier) * max(abs(_axis), Evaluate(_data.PassiveCoupling));
|
||||
var previousRpm = Rpm;
|
||||
Rpm = decay(Rpm, couplingLambda, dt);
|
||||
var rpmLoss = previousRpm - Rpm;
|
||||
var force = rpmLoss * _data.RotorMass * efficiency;
|
||||
|
||||
var heat = rpmLoss * _data.RotorMass * (1 - couplingEfficiency);
|
||||
AddHeat((heat.x + heat.y + heat.z)*ItemManager.GameplaySettings.AetherHeatMultiplier);
|
||||
|
||||
ThrustDirection = forward * (_axis.x * force.x / Entity.Mass) + right * (_axis.y * force.y / Entity.Mass);
|
||||
Entity.Velocity += ThrustDirection;
|
||||
|
||||
Entity.Direction = mul(Entity.Direction,
|
||||
CultMath.float2x2.Rotate(force.z * _axis.z * ItemManager.GameplaySettings.AetherTorqueMultiplier / Entity.Mass));
|
||||
|
||||
if(float.IsNaN(Entity.Velocity.x))
|
||||
ItemManager.Log("FUCK FUCK FUCK FUCK");
|
||||
|
||||
MaximumRpm = Evaluate(_data.MaximumRpm);
|
||||
var torqueProfile = float3(
|
||||
_data.TorqueProfile.Evaluate(Rpm.x / MaximumRpm),
|
||||
_data.TorqueProfile.Evaluate(Rpm.y / MaximumRpm),
|
||||
_data.TorqueProfile.Evaluate(Rpm.z / MaximumRpm));
|
||||
var potentialTorque = Evaluate(_data.Torque) * torqueProfile;
|
||||
var potentialRpmDelta = potentialTorque / length(_data.RotorMass) * dt;
|
||||
var actualRpmDelta = min(MaximumRpm - Rpm, potentialRpmDelta);
|
||||
var torqueRatio = actualRpmDelta / potentialRpmDelta;
|
||||
|
||||
Item.SetAudioParameter(SpecialAudioParameter.Intensity, max(max(abs(_axis.x), abs(_axis.y)), abs(_axis.z)));
|
||||
Item.SetAudioParameter(_data.RpmAudioParameter, (Rpm.x + Rpm.y + Rpm.z) / 3 / MaximumRpm);
|
||||
Item.SetAudioParameter(_data.TorqueRatioAudioParameter, max(max(torqueRatio.x, torqueRatio.y), torqueRatio.z));
|
||||
|
||||
// Cut 7 (docs/stats-and-power-target.md): actualRpmDelta already derives from Evaluate(_data.Torque)
|
||||
// above, so a Torque stat carrying a PowerSupply term already shrinks the rotor's spin-up under a
|
||||
// partial grant -- this no longer demands a full one, only that supply has not been cut to true zero.
|
||||
if (Item.PowerSupply > 1e-4f)
|
||||
{
|
||||
Rpm += actualRpmDelta;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2022c838bbc64a0d86cfbd477e6a379c
|
||||
timeCreated: 1618332827
|
||||
|
|
@ -157,7 +157,7 @@ public interface IPowerConsumer
|
|||
Union(9, typeof(WearData)),
|
||||
Union(10, typeof(VelocityConversionData)),
|
||||
Union(11, typeof(VelocityLimitData)),
|
||||
Union(12, typeof(AetherDriveData)),
|
||||
// Union(12): retired, do not reuse -- was AetherDriveData (retire-longinusx; parked/aether-drive)
|
||||
// Union(14, typeof(TowingControllerData)),
|
||||
Union(15, typeof(CooldownData)),
|
||||
Union(16, typeof(HeatData)),
|
||||
|
|
|
|||
|
|
@ -1818,7 +1818,7 @@ public class EquippedItem : IStatContext
|
|||
// RefreshInputCapacitor implementation now calls for a request-field stat, and it pins that stat's own
|
||||
// PowerSupplyFactor to 1 regardless of what Terms the stat declares -- so a direct PowerSupply term on a
|
||||
// request field can no longer make the request depend on its own answer, and the six shipped records this
|
||||
// ruling exists to make legal again (RadiatorData.PumpedHeat, AetherDriveData.Torque) are not an authoring
|
||||
// ruling exists to make legal again (RadiatorData.PumpedHeat) are not an authoring
|
||||
// error to refuse. What is still refused: a request field fed a PowerSupply-tainted value through a
|
||||
// *modifier chain* (StatModifier.ValidateNoPowerSupplyChain, StatModifier.cs) -- EvaluateNominalPower
|
||||
// forwards ScaleModifier/ConstantModifier to the item's real, non-nominal resolver entries (same as
|
||||
|
|
@ -1834,8 +1834,8 @@ public class EquippedItem : IStatContext
|
|||
// Nominal-request ruling (docs/stats-and-power-cut.md, operator ruling 2026-09-19): what this item wants at
|
||||
// full power supply, not what it is currently managing -- the read every PowerRequest/RefreshReserve/
|
||||
// RefreshInputCapacitor implementation uses for a stat named in StatValidation.PowerRequestFields, so a stat
|
||||
// that is both what a request asks for and what it also produces (RadiatorData.PumpedHeat, AetherDriveData.
|
||||
// Torque) stops being circular at the root instead of being forbidden outright. Only PowerSupply is pinned:
|
||||
// that is both what a request asks for and what it also produces (RadiatorData.PumpedHeat)
|
||||
// stops being circular at the root instead of being forbidden outright. Only PowerSupply is pinned:
|
||||
// Heat and Durability are NOT, because they are not the term a request would be circular through -- this
|
||||
// tick's PowerBus.Step (which calls PowerRequest) always runs before this tick's grant exists, so nothing
|
||||
// here could depend on an answer that has not been computed yet, and a hot or worn item honestly asking for
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@ public enum HardpointType
|
|||
Energy,
|
||||
Ballistic,
|
||||
Launcher,
|
||||
ControlModule,
|
||||
AetherDrive
|
||||
ControlModule
|
||||
}
|
||||
|
||||
public enum WeaponType
|
||||
|
|
|
|||
|
|
@ -855,8 +855,7 @@ public static class StatValidation
|
|||
//
|
||||
// F6 (docs/stats-and-power-cut.md, Soul pass 2026-09-19) named every field a PowerRequest implementation
|
||||
// actually reads, not just each consumer's top-level request field: Radiator.PowerRequest also reads
|
||||
// PumpedHeat and WasteHeat, AetherDrive.PowerRequest also reads Torque, LambdaMultiplier, MaximumRpm and
|
||||
// PassiveCoupling, Shield.PowerRequest (via RefreshReserve) also reads RefillDuration and RestoreDuration,
|
||||
// PumpedHeat and WasteHeat, Shield.PowerRequest (via RefreshReserve) also reads RefillDuration and RestoreDuration,
|
||||
// InstantWeapon.PowerRequest (via RefreshInputCapacitor) also reads Cooldown and Count, and Sensor.
|
||||
// PowerRequest (via RefreshInputCapacitor) also reads PingCooldown. Audited directly against each
|
||||
// PowerRequest method's own body (and RefreshReserve/RefreshInputCapacitor, which PowerRequest calls into)
|
||||
|
|
@ -892,11 +891,6 @@ public static class StatValidation
|
|||
(typeof(RadiatorData), nameof(RadiatorData.EnergyUsage)),
|
||||
(typeof(RadiatorData), nameof(RadiatorData.PumpedHeat)),
|
||||
(typeof(RadiatorData), nameof(RadiatorData.WasteHeat)),
|
||||
(typeof(AetherDriveData), nameof(AetherDriveData.EnergyDraw)),
|
||||
(typeof(AetherDriveData), nameof(AetherDriveData.Torque)),
|
||||
(typeof(AetherDriveData), nameof(AetherDriveData.LambdaMultiplier)),
|
||||
(typeof(AetherDriveData), nameof(AetherDriveData.MaximumRpm)),
|
||||
(typeof(AetherDriveData), nameof(AetherDriveData.PassiveCoupling)),
|
||||
};
|
||||
|
||||
// Whether `stat` is the request stat of some IPowerConsumer behaviour on `data` -- used by StatModifier's
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// every other item on the hull (EquippedItem.UpdatePerformance). Feed it first or lose the rest anyway.
|
||||
// - High: Shield. Hull survival the player is actively trading power for; not a life-support constant, so it
|
||||
// sits below Radiator rather than beside it.
|
||||
// - Medium: Thruster, AetherDrive. Mobility -- needed to hold position, evade, or disengage, but a ship that
|
||||
// - Medium: Thruster. Mobility -- needed to hold position, evade, or disengage, but a ship that
|
||||
// loses thrust for a tick under brownout is inconvenienced, not dead the way an overheating hull is.
|
||||
// - Low: ConstantWeapon, InstantWeapon. Offense. The ruling's own framing ("low-priority subsystems starve
|
||||
// first") names weapons as the default example of what a reactor throttle should sacrifice first.
|
||||
|
|
|
|||
|
|
@ -213,8 +213,6 @@ public class GameplaySettings
|
|||
public ExponentialLerp LockSpinSpeed;
|
||||
public float TorqueFloor;
|
||||
public float TorqueMultiplier;
|
||||
public float AetherTorqueMultiplier;
|
||||
public float AetherHeatMultiplier;
|
||||
public float VisibilityDecay;
|
||||
public float TargetInfoDecay;
|
||||
public float TargetDetectionInfoThreshold;
|
||||
|
|
@ -240,7 +238,7 @@ public class GameplaySettings
|
|||
// UnaidedTracking above -- FireControl.Precision falls back to this the same way it already falls back to
|
||||
// UnaidedAccuracy/UnaidedTracking. Precision is now a grouping tightness (FireControl.Sigma = 1/Precision,
|
||||
// in hull-schematic cell units), not the old coin-flip probability, so the unaided floor has to be
|
||||
// authored on that scale. .3 -> sigma 3.33 cells: against the live catalog's own hulls (LonginusX 6x17,
|
||||
// authored on that scale. .3 -> sigma 3.33 cells: against the live catalog's own hulls (Longinus 6x17,
|
||||
// Zenith 12x12, Turret 8x8) that puts pOnHull at the hull's own centre of mass around .5-.84 -- broadly
|
||||
// sprayed across the whole silhouette (sigma is a large fraction of the hull's own width) while still
|
||||
// landing on the ship more often than not. A tighter floor (e.g. .1, sigma 10) was tried first and
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ public class Ship : Entity
|
|||
private HashSet<Thruster> _leftThrusters;
|
||||
private HashSet<Thruster> _clockwiseThrusters;
|
||||
private HashSet<Thruster> _counterClockwiseThrusters;
|
||||
private HashSet<EquippedItem> _aetherDriveItems;
|
||||
private HashSet<AetherDrive> _aetherDrives;
|
||||
|
||||
private bool _exitingWormhole = false;
|
||||
private bool _enteringWormhole = false;
|
||||
|
|
@ -96,9 +94,6 @@ public class Ship : Entity
|
|||
{
|
||||
base.Activate();
|
||||
|
||||
_aetherDrives = new HashSet<AetherDrive>(GetBehaviors<AetherDrive>());
|
||||
_aetherDriveItems = new HashSet<EquippedItem>(_aetherDrives.Select(x => x.Item));
|
||||
|
||||
_allThrusters = GetBehaviors<Thruster>().ToArray();
|
||||
_thrusterItems = new HashSet<EquippedItem>(_allThrusters.Select(x=>x.Item));
|
||||
|
||||
|
|
@ -124,13 +119,6 @@ public class Ship : Entity
|
|||
public Ship(ItemManager itemManager, Zone zone, EquippableItem hull, EntitySettings settings) : base(itemManager, zone, hull, settings)
|
||||
{
|
||||
ItemDestroyed.Where(item=>_thrusterItems.Contains(item)).Subscribe(RemoveThruster);
|
||||
ItemDestroyed.Where(item=>_aetherDriveItems.Contains(item)).Subscribe(RemoveAetherDrive);
|
||||
}
|
||||
|
||||
private void RemoveAetherDrive(EquippedItem item)
|
||||
{
|
||||
_aetherDriveItems.Remove(item);
|
||||
_aetherDrives.Remove(item.GetBehavior<AetherDrive>());
|
||||
}
|
||||
|
||||
private void RemoveThruster(EquippedItem item)
|
||||
|
|
@ -176,10 +164,6 @@ public class Ship : Entity
|
|||
foreach (var thruster in _forwardThrusters)
|
||||
if (thruster.Item.Active.Value)
|
||||
ForwardThrust += thruster.Thrust;
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
ForwardThrust += drive.Thrust.x;
|
||||
}
|
||||
|
||||
private void RecalculateReverseThrust()
|
||||
|
|
@ -188,10 +172,6 @@ public class Ship : Entity
|
|||
foreach (var thruster in _reverseThrusters)
|
||||
if (thruster.Item.Active.Value)
|
||||
ReverseThrust += thruster.Thrust;
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
ReverseThrust += drive.Thrust.x;
|
||||
}
|
||||
|
||||
private void RecalculateLeftStrafeThrust()
|
||||
|
|
@ -210,10 +190,6 @@ public class Ship : Entity
|
|||
foreach(var thruster in _leftThrusters)
|
||||
if (abs(sign(thruster.Torque) - sign(LeftStrafeTotalTorque)) < .01f)
|
||||
LeftStrafeTorqueThrusters.Add(thruster);
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
LeftStrafeThrust += drive.Thrust.y;
|
||||
}
|
||||
|
||||
private void RecalculateRightStrafeThrust()
|
||||
|
|
@ -232,10 +208,6 @@ public class Ship : Entity
|
|||
foreach(var thruster in _rightThrusters)
|
||||
if (abs(sign(thruster.Torque) - sign(RightStrafeTotalTorque)) < .01f)
|
||||
RightStrafeTorqueThrusters.Add(thruster);
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
RightStrafeThrust += drive.Thrust.y;
|
||||
}
|
||||
|
||||
private void RecalculateClockwiseTorque()
|
||||
|
|
@ -244,10 +216,6 @@ public class Ship : Entity
|
|||
foreach (var thruster in _clockwiseThrusters)
|
||||
if (thruster.Item.Active.Value)
|
||||
ClockwiseTorque += thruster.Torque;
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
ClockwiseTorque += drive.Thrust.z;
|
||||
}
|
||||
|
||||
private void RecalculateCounterClockwiseTorque()
|
||||
|
|
@ -256,10 +224,6 @@ public class Ship : Entity
|
|||
foreach (var thruster in _counterClockwiseThrusters)
|
||||
if (thruster.Item.Active.Value)
|
||||
CounterClockwiseTorque -= thruster.Torque;
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
if (drive.Item.Active.Value)
|
||||
CounterClockwiseTorque += drive.Thrust.z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -293,9 +257,6 @@ public class Ship : Entity
|
|||
|
||||
foreach (var thruster in _clockwiseThrusters) thruster.Axis += Turn;
|
||||
foreach (var thruster in _counterClockwiseThrusters) thruster.Axis += -Turn;
|
||||
|
||||
foreach (var drive in _aetherDrives)
|
||||
drive.Axis = float3(MovementDirection.y, MovementDirection.x, Turn);
|
||||
}
|
||||
|
||||
var velocityMagnitude = length(Velocity);
|
||||
|
|
|
|||
Loading…
Reference in a new issue