A MoveMode implementation named Simple Noclip for player movement. It disables gravity, sets noclip tag on the Rigidbody, provides flying movement based on view and input, doubles speed when shift is held, and updates animator parameters to idle/noclip states when entering/exiting the mode.
using Sandbox.Movement;
[Title( "Simple Noclip" )]
[Category( "Movement" )]
[Icon( "flight" )]
public sealed class NoclipMoveMode : MoveMode
{
[Property]
public float Speed { get; set; } = 1200;
public override int Score( PlayerController controller ) => 1000;
public override void UpdateRigidBody( Rigidbody body )
{
body.Gravity = false;
body.LinearDamping = 5.0f;
body.AngularDamping = 1f;
body.Tags.Set( "noclip", true );
}
public override void OnModeBegin()
{
Controller.Body.Gravity = false;
ResetToIdle( Controller.Renderer );
}
public override void OnModeEnd( MoveMode next )
{
Controller.Body.Velocity = Controller.Body.Velocity.ClampLength( Controller.RunSpeed );
Controller.Body.Tags.Set( "noclip", false );
ResetToIdle( Controller.Renderer );
}
protected override void OnUpdateAnimatorState( SkinnedModelRenderer renderer )
{
ApplyIdleState( renderer );
}
protected override void OnUpdateAnimatorVelocity( SkinnedModelRenderer renderer )
{
ApplyIdleVelocity( renderer );
}
public override Vector3 UpdateMove( Rotation eyes, Vector3 input )
{
var direction = eyes * input.ClampLength( 1 );
if ( Input.Down( "jump" ) ) direction += Vector3.Up;
if ( Input.Down( "duck" ) ) direction += Vector3.Down;
var speed = Speed;
if ( Input.Keyboard.Down( "SHIFT" ) || Input.Keyboard.Down( "RSHIFT" ) )
speed *= 2f;
return direction * speed;
}
static void ResetToIdle( SkinnedModelRenderer renderer )
{
if ( renderer is null )
return;
renderer.ClearParameters();
ApplyIdleState( renderer );
ApplyIdleVelocity( renderer );
}
static void ApplyIdleState( SkinnedModelRenderer renderer )
{
renderer.Set( "b_grounded", true );
renderer.Set( "duck", 0f );
renderer.Set( "b_noclip", false );
}
static void ApplyIdleVelocity( SkinnedModelRenderer renderer )
{
renderer.Set( "move_x", 0f );
renderer.Set( "move_y", 0f );
renderer.Set( "move_z", 0f );
renderer.Set( "wish_x", 0f );
renderer.Set( "wish_y", 0f );
renderer.Set( "wish_z", 0f );
}
}