PlayerCameraEffects.cs
using Sandbox.Diagnostics;
public class PlayerCameraEffects : Component, IPlayerEvent, ILocalPlayerEvent
{
[RequireComponent]
public Player Player { get; set; }
List<BaseCameraShake> effects = new();
protected override void OnUpdate()
{
foreach ( var effect in effects )
{
effect.Update();
}
effects.RemoveAll( x => x.IsDone );
}
void IPlayerEvent.OnJump()
{
if ( IsProxy ) return;
var punch = new CameraPunch( new Vector3( -20, 0, 0 ), 0.5f, 2.0f, 1.0f );
effects.Add( punch );
}
void IPlayerEvent.OnLand( float distance, Vector3 velocity )
{
if ( IsProxy ) return;
if ( Player.Controller.ThirdPerson ) return;
var punch = new CameraPunch( new Vector3( 0.3f * distance, Random.Shared.Float( -1, 1 ), Random.Shared.Float( -1, 1 ) ), 1.0f, 1.5f, 0.7f );
effects.Add( punch );
}
void ILocalPlayerEvent.OnCameraPostSetup( Sandbox.CameraComponent camera )
{
if ( IsProxy ) return;
foreach ( var effect in effects )
{
effect.ModifyCamera( camera );
}
MovementEffects( camera );
}
float roll;
private void MovementEffects( CameraComponent camera )
{
if ( Player.Controller.ThirdPerson ) return;
Assert.NotNull( Player );
Assert.NotNull( Player.Controller );
//if ( pc.BodyController.IsOnGround )
//{
// distance += pc.BodyController.Velocity.Length * Time.Delta;
//}
var scaler = Player.Controller.WishVelocity.Length.Remap( 0, Player.Controller.RunSpeed, 0, 1 );
// bob
// undone: made me feel sick
//camera.Transform.Position += Vector3.Up * scaler * MathF.Sin( distance * 0.06f ) * 0.2f;
// side movement
var r = Player.Controller.WishVelocity.Dot( Player.EyeTransform.Left ) / -100.0f;
roll = MathX.Lerp( roll, r, Time.Delta * 8.0f, true );
camera.WorldRotation *= new Angles( 0, 0, roll );
}
abstract class BaseCameraShake
{
public virtual void Update() { }
public virtual bool IsDone => true;
public abstract void ModifyCamera( CameraComponent cc );
}
class CameraPunch : BaseCameraShake
{
float deathTime;
float lifeTime = 0.0f;
public CameraPunch( Vector3 target, float time, float frequency, float damp )
{
damping.Current = target;
damping.Target = 0;
damping.SmoothTime = time;
damping.Frequency = frequency;
damping.Damping = damp;
deathTime = damping.SmoothTime;
}
public override bool IsDone => deathTime <= 0;
Vector3.SpringDamped damping;
public override void Update()
{
deathTime -= Time.Delta;
lifeTime += Time.Delta;
damping.Update( Time.Delta );
}
public override void ModifyCamera( CameraComponent cc )
{
var amount = lifeTime.Remap( 0, 0.3f, 0, 1 );
cc.WorldRotation *= new Angles( damping.Current * amount );
}
}
}