mirror of
https://github.com/Facepunch/sbox-public.git
synced 2025-12-23 22:48:07 -05:00
189 lines
3.8 KiB
C#
189 lines
3.8 KiB
C#
namespace Sandbox;
|
|
|
|
public sealed partial class PlayerController : Component
|
|
{
|
|
/// <summary>
|
|
/// The direction we're looking in input space.
|
|
/// </summary>
|
|
[Sync( SyncFlags.Interpolate )]
|
|
public Angles EyeAngles { get; set; }
|
|
|
|
/// <summary>
|
|
/// The player's eye position, in first person mode
|
|
/// </summary>
|
|
public Vector3 EyePosition => EyeTransform.Position;
|
|
|
|
/// <summary>
|
|
/// The player's eye position, in first person mode
|
|
/// </summary>
|
|
public Transform EyeTransform { get; private set; }
|
|
|
|
/// <summary>
|
|
/// True if this player is ducking
|
|
/// </summary>
|
|
[Sync]
|
|
public bool IsDucking { get; set; }
|
|
|
|
/// <summary>
|
|
/// The distance from the top of the head to the closest ceiling.
|
|
/// </summary>
|
|
public float Headroom { get; set; }
|
|
|
|
|
|
protected override void OnUpdate()
|
|
{
|
|
UpdateGroundEyeRotation();
|
|
|
|
if ( Scene.IsEditor )
|
|
return;
|
|
|
|
UpdateEyeTransform();
|
|
|
|
if ( !IsProxy )
|
|
{
|
|
GameObject.RunEvent<IEvents>( x => x.PreInput() );
|
|
|
|
if ( UseInputControls && UseLookControls )
|
|
{
|
|
UpdateEyeAngles();
|
|
UpdateLookAt();
|
|
}
|
|
|
|
if ( UseCameraControls )
|
|
{
|
|
UpdateCameraPosition();
|
|
}
|
|
|
|
UpdateEyeTransform();
|
|
}
|
|
|
|
UpdateBodyVisibility();
|
|
|
|
if ( UseAnimatorControls && Renderer.IsValid() )
|
|
{
|
|
UpdateAnimation( Renderer );
|
|
}
|
|
}
|
|
|
|
protected override void OnFixedUpdate()
|
|
{
|
|
if ( Scene.IsEditor ) return;
|
|
|
|
UpdateHeadroom();
|
|
UpdateFalling();
|
|
|
|
prevPosition = WorldPosition;
|
|
|
|
if ( IsProxy ) return;
|
|
if ( !UseInputControls ) return;
|
|
|
|
InputMove();
|
|
UpdateDucking( Input.Down( "duck" ) );
|
|
InputJump();
|
|
|
|
UpdateEyeTransform();
|
|
}
|
|
|
|
void UpdateHeadroom()
|
|
{
|
|
var tr = TraceBody( WorldPosition + Vector3.Up * CurrentHeight * 0.5f, WorldPosition + Vector3.Up * (100 + CurrentHeight * 0.5f), 0.75f, 0.5f );
|
|
Headroom = tr.Distance;
|
|
}
|
|
|
|
bool _wasFalling = false;
|
|
float fallDistance = 0;
|
|
Vector3 prevPosition;
|
|
|
|
void UpdateFalling()
|
|
{
|
|
if ( Mode is null || !Mode.AllowFalling )
|
|
{
|
|
_wasFalling = false;
|
|
fallDistance = 0;
|
|
return;
|
|
}
|
|
|
|
if ( !IsOnGround || _wasFalling )
|
|
{
|
|
var fallDelta = WorldPosition - prevPosition;
|
|
if ( fallDelta.z < 0.0f )
|
|
{
|
|
_wasFalling = true;
|
|
fallDistance -= fallDelta.z;
|
|
}
|
|
}
|
|
|
|
if ( IsOnGround )
|
|
{
|
|
if ( _wasFalling && fallDistance > 1.0f )
|
|
{
|
|
IEvents.PostToGameObject( GameObject, x => x.OnLanded( fallDistance, Velocity ) );
|
|
|
|
// play land sounds
|
|
if ( EnableFootstepSounds )
|
|
{
|
|
var volume = Velocity.Length.Remap( 50, 800, 0.5f, 5 );
|
|
var vel = Velocity.Length;
|
|
|
|
PlayFootstepSound( WorldPosition, volume, 0 );
|
|
PlayFootstepSound( WorldPosition, volume, 1 );
|
|
}
|
|
}
|
|
|
|
_wasFalling = false;
|
|
fallDistance = 0;
|
|
}
|
|
}
|
|
|
|
Transform localGroundTransform;
|
|
int groundHash;
|
|
|
|
void UpdateGroundEyeRotation()
|
|
{
|
|
if ( GroundObject is null )
|
|
{
|
|
groundHash = default;
|
|
return;
|
|
}
|
|
|
|
if ( !RotateWithGround )
|
|
{
|
|
groundHash = default;
|
|
return;
|
|
}
|
|
|
|
var hash = HashCode.Combine( GroundObject );
|
|
|
|
// Get out transform locally to the ground object
|
|
var localTransform = GroundObject.WorldTransform.ToLocal( WorldTransform );
|
|
|
|
// Work out the rotation delta chance since last frame
|
|
var delta = localTransform.Rotation.Inverse * localGroundTransform.Rotation;
|
|
|
|
// we only care about the yaw
|
|
var deltaYaw = delta.Angles().yaw;
|
|
|
|
//DebugDrawSystem.Current.Text( WorldPosition, $"{delta.Angles().yaw}" );
|
|
|
|
// If we're on the same ground and we've rotated
|
|
if ( hash == groundHash && deltaYaw != 0 )
|
|
{
|
|
// rotate the eye angles
|
|
EyeAngles = EyeAngles.WithYaw( EyeAngles.yaw + deltaYaw );
|
|
|
|
// rotate the body to avoid it animating to the new position
|
|
if ( UseAnimatorControls && Renderer.IsValid() )
|
|
{
|
|
Renderer.WorldRotation *= new Angles( 0, deltaYaw, 0 );
|
|
}
|
|
}
|
|
|
|
// Keep for next frame
|
|
groundHash = hash;
|
|
localGroundTransform = localTransform;
|
|
}
|
|
|
|
|
|
|
|
}
|