From 71db52c5443a7bf82d9a23a770994a42b043be04 Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Thu, 27 Jul 2023 22:11:31 +0100 Subject: Initial commit --- code/pawn/PlayerController.cs | 177 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 code/pawn/PlayerController.cs (limited to 'code/pawn/PlayerController.cs') diff --git a/code/pawn/PlayerController.cs b/code/pawn/PlayerController.cs new file mode 100644 index 0000000..d638bb0 --- /dev/null +++ b/code/pawn/PlayerController.cs @@ -0,0 +1,177 @@ +using Sandbox; +using System; +using System.Collections.Generic; + +namespace MurderGame; + +public class PlayerController : EntityComponent +{ + public int StepSize => 12; + public int GroundAngle => 45; + public int JumpSpeed => 300; + public float Gravity => 800f; + public float SpeedMultiplier { get; set; } = 1; + + HashSet ControllerEvents = new( StringComparer.OrdinalIgnoreCase ); + + bool Grounded => Entity.GroundEntity.IsValid(); + + public void Simulate( IClient cl ) + { + ControllerEvents.Clear(); + + var movement = Entity.InputDirection.Normal; + var angles = Entity.ViewAngles.WithPitch( 0 ); + var moveVector = Rotation.From( angles ) * movement * 320f; + var groundEntity = CheckForGround(); + var team = Entity.CurrentTeam; + + if ( groundEntity.IsValid() ) + { + if ( !Grounded ) + { + Entity.Velocity = Entity.Velocity.WithZ( 0 ); + AddEvent( "grounded" ); + } + var sprintMultiplier = TeamOperations.CanSprint( team ) ? (Input.Down( "run" ) ? 2.5f : 1f) : 1f; + + Entity.Velocity = Accelerate( Entity.Velocity, moveVector.Normal, moveVector.Length, SpeedMultiplier * 200.0f * sprintMultiplier, 7.5f ); + Entity.Velocity = ApplyFriction( Entity.Velocity, 4.0f ); + } + else + { + Entity.Velocity = Accelerate( Entity.Velocity, moveVector.Normal, moveVector.Length, SpeedMultiplier * 100, 20f ); + Entity.Velocity += Vector3.Down * Gravity * Time.Delta * (1/SpeedMultiplier); + } + + if ( Input.Pressed( "jump" ) ) + { + DoJump(); + } + + var mh = new MoveHelper( Entity.Position, Entity.Velocity ); + mh.Trace = mh.Trace.Size( Entity.Hull ).Ignore( Entity ); + + if ( mh.TryMoveWithStep( Time.Delta, StepSize ) > 0 ) + { + if ( Grounded ) + { + mh.Position = StayOnGround( mh.Position ); + } + Entity.Position = mh.Position; + Entity.Velocity = mh.Velocity; + } + + Entity.GroundEntity = groundEntity; + } + + void DoJump() + { + if ( Grounded ) + { + Entity.Velocity = ApplyJump( Entity.Velocity, "jump" ); + } + } + + Entity CheckForGround() + { + if ( Entity.Velocity.z > 100f ) + return null; + + var trace = Entity.TraceBBox( Entity.Position, Entity.Position + Vector3.Down, 2f ); + + if ( !trace.Hit ) + return null; + + if ( trace.Normal.Angle( Vector3.Up ) > GroundAngle ) + return null; + + return trace.Entity; + } + + Vector3 ApplyFriction( Vector3 input, float frictionAmount ) + { + float StopSpeed = 100.0f; + + var speed = input.Length; + if ( speed < 0.1f ) return input; + + // Bleed off some speed, but if we have less than the bleed + // threshold, bleed the threshold amount. + float control = (speed < StopSpeed) ? StopSpeed : speed; + + // Add the amount to the drop amount. + var drop = control * Time.Delta * frictionAmount; + + // scale the velocity + float newspeed = speed - drop; + if ( newspeed < 0 ) newspeed = 0; + if ( newspeed == speed ) return input; + + newspeed /= speed; + input *= newspeed; + + return input; + } + + Vector3 Accelerate( Vector3 input, Vector3 wishdir, float wishspeed, float speedLimit, float acceleration ) + { + if ( speedLimit > 0 && wishspeed > speedLimit ) + wishspeed = speedLimit; + + var currentspeed = input.Dot( wishdir ); + var addspeed = wishspeed - currentspeed; + + if ( addspeed <= 0 ) + return input; + + var accelspeed = acceleration * Time.Delta * wishspeed; + + if ( accelspeed > addspeed ) + accelspeed = addspeed; + + input += wishdir * accelspeed; + + return input; + } + + Vector3 ApplyJump( Vector3 input, string jumpType ) + { + AddEvent( jumpType ); + + return input + Vector3.Up * JumpSpeed; + } + + Vector3 StayOnGround( Vector3 position ) + { + var start = position + Vector3.Up * 2; + var end = position + Vector3.Down * StepSize; + + // See how far up we can go without getting stuck + var trace = Entity.TraceBBox( position, start ); + start = trace.EndPosition; + + // Now trace down from a known safe position + trace = Entity.TraceBBox( start, end ); + + if ( trace.Fraction <= 0 ) return position; + if ( trace.Fraction >= 1 ) return position; + if ( trace.StartedSolid ) return position; + if ( Vector3.GetAngle( Vector3.Up, trace.Normal ) > GroundAngle ) return position; + + return trace.EndPosition; + } + + public bool HasEvent( string eventName ) + { + return ControllerEvents.Contains( eventName ); + } + + void AddEvent( string eventName ) + { + if ( HasEvent( eventName ) ) + return; + + ControllerEvents.Add( eventName ); + } +} -- cgit v1.2.3-70-g09d2