Code/PlayerControllerPlus/Modes/ExternalMoveMode.cs
namespace Sandbox.MovementPlus;
/// <summary>
/// Base class for external move modes that plug into PlayerControllerPlus.
/// Add as a component on the same GameObject as the player controller.
/// Override Score to control when this mode activates (higher score wins).
/// The default animation pipeline always runs; override UpdateAnimator to add extra animation on top.
/// </summary>
[Icon( "extension" )]
public abstract class ExternalMoveMode : Component
{
public PlayerControllerPlus Controller { get; internal set; }
/// <summary>
/// Return a score to compete with built-in modes. Walk is 0, Ladder is 5, Swim is 10, Sit is 10000.
/// Return negative to opt out.
/// </summary>
public abstract int Score( PlayerControllerPlus controller );
public virtual bool AllowGrounding => false;
public virtual bool AllowFalling => false;
/// <summary>
/// Whether the given trace result is a surface the player can stand on.
/// Default allows any surface within 45 degrees of flat.
/// </summary>
public virtual bool IsStandableSurface( in SceneTraceResult result )
{
return result.Normal.Angle( Vector3.Up ) <= 45f;
}
/// <summary>
/// Called when this mode becomes the active mode.
/// </summary>
public virtual void OnModeBegin() { }
/// <summary>
/// Called when this mode is being replaced by another mode.
/// </summary>
public virtual void OnModeEnd() { }
/// <summary>
/// Add velocity to the physics body. Default does nothing (no physics-driven movement).
/// </summary>
public virtual void AddVelocity() { }
public virtual void PrePhysicsStep() { }
public virtual void PostPhysicsStep() { }
/// <summary>
/// Configure the rigidbody for this mode. Default disables gravity and applies high damping.
/// </summary>
public virtual void UpdateRigidBody( Rigidbody body )
{
body.Gravity = false;
body.LinearDamping = 10f;
body.AngularDamping = 1f;
}
/// <summary>
/// Process movement input and return a wish velocity. Default returns zero.
/// </summary>
public virtual Vector3 UpdateMove( Rotation eyes, Vector3 input ) => Vector3.Zero;
/// <summary>
/// Called after the default animation pipeline runs. Override to set extra animation parameters.
/// </summary>
public virtual void UpdateAnimator( SkinnedModelRenderer renderer ) { }
/// <summary>
/// Override to provide a custom eye transform. Return null to use the default calculation.
/// </summary>
public virtual Transform? GetEyeTransform() => null;
}