< Summary

Information
Class: Trailblazer.Navigation.Motor.MoveLocomotion
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Navigation/Motor/Locomotion/MoveLocomotion.cs
Line coverage
100%
Covered lines: 55
Uncovered lines: 0
Coverable lines: 55
Total lines: 223
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor()100%11100%
get_IsEnabled()100%11100%
set_IsEnabled(...)100%22100%
RecordData(...)100%44100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Navigation/Motor/Locomotion/MoveLocomotion.cs

#LineLine coverage
 1//=======================================================================
 2// MoveLocomotion.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using Chronicler;
 9using FixedMathSharp;
 10using Trailblazer.Support;
 11
 12namespace Trailblazer.Navigation.Motor;
 13
 14/// <summary>
 15/// Handles the scout's movement, including speed limits, acceleration, and velocity calculations.
 16/// </summary>
 17/// <remarks>
 18/// This locomotion module governs how the scout accelerates, decelerates, and interacts with terrain slopes.
 19/// It tracks position changes and velocity updates for consistent movement behavior.
 20/// </remarks>
 21public class MoveLocomotion : ILocomotion
 22{
 23    #region Constants
 24
 25    /// <summary>
 26    /// The minimum velocity threshold below which movement is considered negligible.
 27    /// </summary>
 128    public static readonly Fixed64 VelocityEpsilon = Fixed64.FromRaw(0x418938L); //0.001f;
 29
 30    /// <summary>
 31    /// Default maximum walking speed.
 32    /// </summary>
 133    public static readonly Fixed64 DefaultMaxSlowSpeed = Fixed64.FromFraction(1, 10);//1d;
 34
 35    /// <summary>
 36    /// Default maximum jogging speed.
 37    /// </summary>
 138    public static readonly Fixed64 DefaultMaxModerateSpeed = Fixed64.Quarter;//2d;
 39
 40    /// <summary>
 41    /// Default maximum sprinting speed.
 42    /// </summary>
 143    public static readonly Fixed64 DefaultMaxFastSpeed = Fixed64.Half;//3d;
 44
 45    /// <summary>
 46    /// Default maximum sideways movement speed.
 47    /// </summary>
 148    public static readonly Fixed64 DefaultMaxSidewaysSpeed = Fixed64.FromFraction(3, 20);//2d;
 49
 50    /// <summary>
 51    /// Default maximum backward movement speed.
 52    /// </summary>
 153    public static readonly Fixed64 DefaultMaxBackwardsSpeed = Fixed64.FromFraction(3, 20);//2d;
 54
 55    /// <summary>
 56    /// Default maximum acceleration when moving on the ground.
 57    /// </summary>
 58    /// <remarks>
 59    /// This is timescaled, with a default TimeDelta of `0.03125` this resolves to 1.
 60    /// </remarks>
 161    public static readonly Fixed64 DefaultMaxGroundAcceleration = (Fixed64)32;
 62
 63    /// <summary>
 64    /// Default maximum acceleration when moving in the air.
 65    /// </summary>
 66    /// <remarks>
 67    /// This is timescaled, with a default TimeDelta of `0.03125` this resolves to `0.625`.
 68    /// </remarks>
 169    public static readonly Fixed64 DefaultMaxAirAcceleration = (Fixed64)20;
 70
 71    /// <summary>
 72    /// Default slope speed modifier curve, determining speed adjustments based on incline.
 73    /// </summary>
 74    /// <remarks>
 75    /// - Full downward slope (-90°) retains full speed.
 76    /// - Flat ground (0°) retains full speed.
 77    /// - Full upward slope (90°) reduces speed to zero.
 78    /// </remarks>
 179    public static readonly FixedCurve DefaultSlopeSpeedModifier = new(FixedCurveMode.Linear,
 180            new FixedCurveKey((Fixed64)(-90), Fixed64.FromFraction(3, 2)),  // Full downward slope boosts speed 1.5x
 181            new FixedCurveKey((Fixed64)(-45), Fixed64.FromFraction(6, 5)),  // Moderate downward slope boosts speed 1.2x
 182            new FixedCurveKey(Fixed64.Zero, Fixed64.One),                  // Flat ground, normal speed
 183            new FixedCurveKey((Fixed64)45, Fixed64.FromFraction(4, 5)),    // Moderate uphill slows down
 184            new FixedCurveKey((Fixed64)90, Fixed64.Zero)                   // Full uphill completely stops movement
 185        );
 86
 87    /// <summary>
 88    /// The default maximum slope angle before a surface is considered too steep for normal control.
 89    /// </summary>
 190    public static readonly Fixed64 DefaultSlopeLimit = Fixed64.FromRaw(0x2D00000000L); // 45f;
 91
 92    /// <summary>
 93    /// The default passive drag factor applied while moving through water.
 94    /// </summary>
 195    public static readonly Fixed64 DefaultWaterDragFactor = Fixed64.FromRaw(0x10000000L); // ~0.0625
 96
 97    #endregion
 98
 99    #region Configuration State
 100
 101    /// <summary>
 102    /// Determines whether movement mechanics are enabled.
 103    /// </summary>
 1201104    private bool _isEnabled = true;
 105
 106    /// <summary>
 107    /// The maximum speed when walking.
 108    /// </summary>
 1201109    public Fixed64 MaxSlowSpeed = DefaultMaxSlowSpeed;
 110
 111    /// <summary>
 112    /// The maximum speed when jogging.
 113    /// </summary>
 1201114    public Fixed64 MaxModerateSpeed = DefaultMaxModerateSpeed;
 115
 116    /// <summary>
 117    /// The maximum speed when sprinting.
 118    /// </summary>
 1201119    public Fixed64 MaxFastSpeed = DefaultMaxFastSpeed;
 120
 121    /// <summary>
 122    /// The maximum speed when moving sideways.
 123    /// </summary>
 1201124    public Fixed64 MaxSidewaysSpeed = DefaultMaxSidewaysSpeed;
 125
 126    /// <summary>
 127    /// The maximum speed when moving backward.
 128    /// </summary>
 1201129    public Fixed64 MaxBackwardsSpeed = DefaultMaxBackwardsSpeed;
 130
 131    /// <summary>
 132    /// The maximum acceleration when moving on the ground.
 133    /// Higher values result in quicker acceleration.
 134    /// </summary>
 1201135    public Fixed64 MaxGroundAcceleration = DefaultMaxGroundAcceleration;
 136
 137    /// <summary>
 138    /// The maximum acceleration when moving in the air.
 139    /// </summary>
 1201140    public Fixed64 MaxAirAcceleration = DefaultMaxAirAcceleration;
 141
 142    /// <summary>
 143    /// A global multiplier applied to movement speed.
 144    /// </summary>
 1201145    public Fixed64 MoveSpeedMultiplier = Fixed64.One;
 146
 147    /// <summary>
 148    /// Determines whether movement speed is adjusted based on the slope of the terrain.
 149    /// </summary>
 1201150    public bool ModifySpeedOnSlope = true;
 151
 152    /// <summary>
 153    /// A curve controlling how speed is affected by terrain slope.
 154    /// </summary>
 1201155    public FixedCurve SlopeSpeedMultiplier = DefaultSlopeSpeedModifier;
 156
 157    /// <summary>
 158    /// The slope angle threshold at which a surface becomes too steep for normal movement control.
 159    /// </summary>
 1201160    public Fixed64 SlopeLimit = DefaultSlopeLimit;
 161
 162    /// <summary>
 163    /// Passive drag applied whenever the motor is in water, even if the water locomotion is absent or inactive.
 164    /// </summary>
 1201165    public Fixed64 WaterDragFactor = DefaultWaterDragFactor;
 166
 167    #endregion
 168
 169    #region Transient State
 170
 171    /// <inheritdoc cref="ILocomotion.IsEnabled"/>
 172    public bool IsEnabled
 173    {
 21174        get => _isEnabled;
 175        set
 176        {
 3177            _isEnabled = value;
 3178            if (!_isEnabled)
 2179                this.ClearTransientState();
 3180        }
 181    }
 182
 183    /// <summary>
 184    /// The scout’s current velocity in world space.
 185    /// </summary>
 186    [Transient]
 187    public Vector3d FrameVelocity { get; set; }
 188
 189    #endregion
 190
 191    #region Serialization
 192
 193    /// <inheritdoc />
 194    public void RecordData(IChronicler chronicler)
 195    {
 164196        RecordValues.Look(chronicler, ref _isEnabled, "IsEnabled", true);
 164197        RecordValues.Look(chronicler, ref MaxSlowSpeed, "MaxSlowSpeed", DefaultMaxSlowSpeed);
 164198        RecordValues.Look(chronicler, ref MaxModerateSpeed, "MaxModerateSpeed", DefaultMaxModerateSpeed);
 164199        RecordValues.Look(chronicler, ref MaxFastSpeed, "MaxFastSpeed", DefaultMaxFastSpeed);
 164200        RecordValues.Look(chronicler, ref MaxSidewaysSpeed, "MaxSidewaysSpeed", DefaultMaxSidewaysSpeed);
 164201        RecordValues.Look(chronicler, ref MaxBackwardsSpeed, "MaxBackwardsSpeed", DefaultMaxBackwardsSpeed);
 164202        RecordValues.Look(chronicler, ref MaxGroundAcceleration, "MaxGroundAcceleration", DefaultMaxGroundAcceleration);
 164203        RecordValues.Look(chronicler, ref MaxAirAcceleration, "MaxAirAcceleration", DefaultMaxAirAcceleration);
 164204        RecordValues.Look(chronicler, ref MoveSpeedMultiplier, "MoveSpeedMultiplier", Fixed64.One);
 164205        RecordValues.Look(chronicler, ref ModifySpeedOnSlope, "ModifySpeedOnSlope", true);
 164206        RecordValues.Look(chronicler, ref SlopeSpeedMultiplier, "SlopeSpeedMultiplier", DefaultSlopeSpeedModifier);
 164207        RecordValues.Look(chronicler, ref SlopeLimit, "SlopeLimit", DefaultSlopeLimit);
 164208        RecordValues.Look(chronicler, ref WaterDragFactor, "WaterDragFactor", DefaultWaterDragFactor);
 209
 164210        Vector3d frameVelocity = FrameVelocity;
 164211        RecordValues.Look(chronicler, ref frameVelocity, "FrameVelocity", Vector3d.Zero);
 212
 164213        if (chronicler.Mode == SerializationMode.Loading)
 214        {
 77215            FrameVelocity = frameVelocity;
 216
 77217            if (!_isEnabled)
 2218                this.ClearTransientState();
 219        }
 164220    }
 221
 222    #endregion
 223}