Player/PlayerController.Movement.cs
namespace Opium;
public partial class PlayerController
{
[Property] public CameraEffect JumpCameraEffect { get; set; }
[Property] public CameraEffect LandCameraEffect { get; set; }
bool wasOnGround = true;
float totalJumps = 0;
TimeSince lastJump = 1;
public override Angles GetEyeAngles()
{
return EyeAngles;
}
protected void UpdateMouse()
{
if ( !LockCameraMovement && !LockMouseMovementOverride )
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles
.WithPitch( EyeAngles.pitch.Clamp( -90, 90 ) )
.WithRoll( 0f );
Transform.Rotation = new Angles( 0, EyeAngles.yaw, 0 );
}
float CalculateJumpForce( float totalJumps )
{
return 250 / (1 + totalJumps * 0.05f);
}
float JumpStaminaDrain => 10f;
protected void Jump()
{
if ( JumpCameraEffect is not null )
{
JumpCameraEffect.Player = this;
JumpCameraEffect.Enabled = true;
}
GetMechanic<StaminaMechanic>().RemoveStamina( JumpStaminaDrain );
CharacterController.Punch( Vector3.Up * CalculateJumpForce( totalJumps ) );
}
protected override void BuildWishInput()
{
WishMove = Input.AnalogMove.Normal;
}
private void ApplyAccceleration()
{
if ( CurrentAccelerationOverride is not null )
{
CharacterController.Acceleration = CurrentAccelerationOverride.Value;
}
else
{
CharacterController.Acceleration = baseAcceleration;
}
}
protected override void BuildWishVelocity()
{
base.BuildWishVelocity();
if ( LockMovement || LockMovementOverride )
WishVelocity = 0f;
}
private void UpdateJump()
{
if ( !LockMovement && !LockMovementOverride && lastGrounded < 0.2f && lastJump > 0.3f && Input.WantsToJump && totalJumps < 5 )
{
lastJump = 0;
totalJumps++;
CharacterController.Punch( Vector3.Up * CalculateJumpForce( totalJumps ) );
}
}
protected override void OnMechanicsUpdate()
{
// Do nothing
}
protected override void UpdateMovement()
{
if ( CharacterController is null ) return;
Vector3 halfGravity = Scene.PhysicsWorld.Gravity * Time.Delta * 0.5f;
BuildWishInput();
// Mechanics
DoMechanicsUpdate();
BuildWishVelocity();
ApplyAccceleration();
UpdateJump();
if ( lastJump > 0.15f )
{
totalJumps = Math.Max( 0, totalJumps - (Time.Delta * 0.5f) );
}
CharacterController.ApplyFriction( GetFriction() );
if ( !wasOnGround && CharacterController.IsOnGround )
{
OnLanded();
}
wasOnGround = CharacterController.IsOnGround;
if ( CharacterController.IsOnGround )
{
CharacterController.Accelerate( WishVelocity );
CharacterController.Velocity = CharacterController.Velocity.WithZ( 0 );
}
else
{
CharacterController.Velocity += halfGravity;
CharacterController.Accelerate( WishVelocity );
}
//
// Don't walk through other players, let them push you out of the way
//
var pushVelocity = PlayerPusher.GetPushVector( Transform.Position + Vector3.Up * 40.0f, Scene, GameObject );
if ( !pushVelocity.IsNearlyZero() )
{
var travelDot = CharacterController.Velocity.Dot( pushVelocity.Normal );
if ( travelDot < 0 )
{
CharacterController.Velocity -= pushVelocity.Normal * travelDot * 0.6f;
}
CharacterController.Velocity += pushVelocity * 128.0f;
}
CharacterController.Move();
if ( !CharacterController.IsOnGround )
{
CharacterController.Velocity += halfGravity;
}
else
{
CharacterController.Velocity = CharacterController.Velocity.WithZ( 0 );
}
if ( CharacterController.IsOnGround )
{
lastGrounded = 0;
}
else
{
lastUngrounded = 0;
}
}
protected void OnLanded()
{
if ( LandCameraEffect is not null )
{
LandCameraEffect.Player = this;
LandCameraEffect.Enabled = true;
}
}
}