Fix thrusters, add new max velocity calculation (#19688)

This commit is contained in:
router
2023-09-04 22:33:47 +03:00
committed by GitHub
parent a20211a1df
commit 0b94825182
3 changed files with 62 additions and 11 deletions

View File

@@ -232,6 +232,29 @@ namespace Content.Server.Physics.Controllers
component.CurTickBraking += brake * fraction;
}
/// <summary>
/// Helper function to extrapolate max velocity for a given Vector2 (really, its angle) and shuttle.
/// </summary>
private Vector2 ObtainMaxVel(Vector2 vel, ShuttleComponent shuttle)
{
if (vel.Length() == 0f)
return Vector2.Zero;
// this math could PROBABLY be simplified for performance
// probably
// __________________________________
// / / __ __ \2 / __ __ \2
// O = I : _ / |I * | 1/H | | + |I * | 0 | |
// V \ |_ 0 _| / \ |_1/V_| /
var horizIndex = vel.X > 0 ? 1 : 3; // east else west
var vertIndex = vel.Y > 0 ? 2 : 0; // north else south
var horizComp = MathF.Pow(Vector2.Dot(vel, new (shuttle.BaseLinearThrust[horizIndex] / shuttle.LinearThrust[horizIndex], 0f)), 2);
var vertComp = MathF.Pow(Vector2.Dot(vel, new (0f, shuttle.BaseLinearThrust[vertIndex] / shuttle.LinearThrust[vertIndex])), 2);
return shuttle.BaseMaxLinearVelocity * vel * MathF.ReciprocalSqrtEstimate(horizComp + vertComp);
}
private void HandleShuttleMovement(float frameTime)
{
var newPilots = new Dictionary<EntityUid, (ShuttleComponent Shuttle, List<(EntityUid PilotUid, PilotComponent Pilot, InputMoverComponent Mover, TransformComponent ConsoleXform)>)>();
@@ -478,19 +501,27 @@ namespace Content.Server.Physics.Controllers
totalForce += impulse;
}
totalForce = shuttleNorthAngle.RotateVec(totalForce);
var forceMul = frameTime * body.InvMass;
var maxVelocity = (ShuttleComponent.MaxLinearVelocity - body.LinearVelocity.Length()) / forceMul;
if (maxVelocity != 0f)
{
// Don't overshoot
if (totalForce.Length() > maxVelocity)
totalForce = totalForce.Normalized() * maxVelocity;
var localVel = (-shuttleNorthAngle).RotateVec(body.LinearVelocity);
var maxVelocity = ObtainMaxVel(localVel, shuttle); // max for current travel dir
var maxWishVelocity = ObtainMaxVel(totalForce, shuttle);
var properAccel = (maxWishVelocity - localVel) / forceMul;
PhysicsSystem.ApplyForce(shuttleUid, totalForce, body: body);
}
var finalForce = Vector2.Dot(totalForce, properAccel.Normalized()) * properAccel.Normalized();
if (localVel.Length() >= maxVelocity.Length() && Vector2.Dot(totalForce, localVel) > 0f)
finalForce = Vector2.Zero; // burn would be faster if used as such
if (finalForce.Length() > properAccel.Length())
finalForce = properAccel; // don't overshoot
//Logger.Info($"shuttle: maxVelocity {maxVelocity} totalForce {totalForce} finalForce {finalForce} forceMul {forceMul} properAccel {properAccel}");
finalForce = shuttleNorthAngle.RotateVec(finalForce);
if (finalForce.Length() > 0f)
PhysicsSystem.ApplyForce(shuttleUid, finalForce, body: body);
}
if (MathHelper.CloseTo(angularInput, 0f))

View File

@@ -16,7 +16,11 @@ namespace Content.Server.Shuttles.Components
/// </summary>
public const float BrakeCoefficient = 1.5f;
public const float MaxLinearVelocity = 20f;
/// <summary>
/// Maximum velocity assuming unupgraded, tier 1 thrusters
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float BaseMaxLinearVelocity = 20f;
public const float MaxAngularVelocity = 4f;
@@ -26,6 +30,12 @@ namespace Content.Server.Shuttles.Components
[ViewVariables]
public readonly float[] LinearThrust = new float[4];
/// <summary>
/// The cached thrust available for each cardinal direction, if all thrusters are T1
/// </summary>
[ViewVariables]
public readonly float[] BaseLinearThrust = new float[4];
/// <summary>
/// The thrusters contributing to each direction for impulse.
/// </summary>

View File

@@ -173,10 +173,12 @@ public sealed class ThrusterSystem : EntitySystem
var direction = (int) args.NewRotation.GetCardinalDir() / 2;
shuttleComponent.LinearThrust[oldDirection] -= component.Thrust;
shuttleComponent.BaseLinearThrust[oldDirection] -= component.BaseThrust;
DebugTools.Assert(shuttleComponent.LinearThrusters[oldDirection].Contains(uid));
shuttleComponent.LinearThrusters[oldDirection].Remove(uid);
shuttleComponent.LinearThrust[direction] += component.Thrust;
shuttleComponent.BaseLinearThrust[direction] += component.BaseThrust;
DebugTools.Assert(!shuttleComponent.LinearThrusters[direction].Contains(uid));
shuttleComponent.LinearThrusters[direction].Add(uid);
}
@@ -257,6 +259,7 @@ public sealed class ThrusterSystem : EntitySystem
var direction = (int) xform.LocalRotation.GetCardinalDir() / 2;
shuttleComponent.LinearThrust[direction] += component.Thrust;
shuttleComponent.BaseLinearThrust[direction] += component.BaseThrust;
DebugTools.Assert(!shuttleComponent.LinearThrusters[direction].Contains(uid));
shuttleComponent.LinearThrusters[direction].Add(uid);
@@ -355,6 +358,7 @@ public sealed class ThrusterSystem : EntitySystem
var direction = (int) angle.Value.GetCardinalDir() / 2;
shuttleComponent.LinearThrust[direction] -= component.Thrust;
shuttleComponent.BaseLinearThrust[direction] -= component.BaseThrust;
DebugTools.Assert(shuttleComponent.LinearThrusters[direction].Contains(uid));
shuttleComponent.LinearThrusters[direction].Remove(uid);
break;
@@ -552,9 +556,15 @@ public sealed class ThrusterSystem : EntitySystem
private void OnRefreshParts(EntityUid uid, ThrusterComponent component, RefreshPartsEvent args)
{
if (component.IsOn) // safely disable thruster to prevent negative thrust
DisableThruster(uid, component);
var thrustRating = args.PartRatings[component.MachinePartThrust];
component.Thrust = component.BaseThrust * MathF.Pow(component.PartRatingThrustMultiplier, thrustRating - 1);
if (component.Enabled && CanEnable(uid, component))
EnableThruster(uid, component);
}
private void OnUpgradeExamine(EntityUid uid, ThrusterComponent component, UpgradeExamineEvent args)