Player controller component. Reads input, moves a CharacterController, applies gravity and jumping, toggles third/first person, positions the camera, traces for third-person camera clipping, and updates model visibility and FOV.
using Sandbox;
public class Player__Controller : Component
{ PhysicsWorld Physics_World = new PhysicsWorld();
[Property] public CharacterController Character_Controller {get;set;}
[Property] public ModelRenderer Model_Renderer {get;set;}
[Property] public float Walk_Speed {get;set;} = 8192;
[Property] public float Run_Speed {get;set;} = 16384;
[Property] public float Duck_Speed {get;set;} = 4096;
[Property] public float Jump_Power {get;set;} = 200;
[Property] public float Camera_Offset {get;set;} = 64;
GameObject c;
protected override void OnStart()
{c = Scene.Camera.GameObject;}
float w;
float a;
float s;
float d;
float Speed;
float x;
float y;
[Sync] public bool IsThirdPerson {get;set;}
public string State
{
get
{
if (Character_Controller.Velocity.WithX(0).WithY(0).LengthSquared > 0)
{
if (Character_Controller.Velocity.z > 0)
return "jump";
return "fall";
}
if (Character_Controller.Velocity.WithZ(0).LengthSquared > 0)
{
if (Input.Down("shift"))
return "run";
return "walk";
}
return "idle"; }
}
public bool IsDucking {get {return Input.Down("ctrl");}}
public float Offset {get {return IsDucking ? Camera_Offset / 2 : Camera_Offset;}}
public Vector3 Aim {get {return new Angles(-y, 0, 0).Forward;}}
protected override void OnUpdate()
{ Visibility(); if (IsProxy) return;
Control(); Camera(); }
void Control()
{
w = Input.Down("w") ? 1 : 0;
a = Input.Down("a") ? -1 : 0;
s = Input.Down("s") ? -1 : 0;
d = Input.Down("d") ? 1 : 0;
if (Input.Down("ctrl"))
Speed = Duck_Speed;
else if (Input.Down("shift"))
Speed = Run_Speed;
else Speed = Walk_Speed;
var Forward = new Vector3(c.WorldRotation.Forward.x, c.WorldRotation.Forward.y, 0).Normal;
var Right = new Vector3(c.WorldRotation.Right.x, c.WorldRotation.Right.y, 0).Normal;
var Direction = (w * Forward + s * Forward + a * Right + d * Right).Normal * Time.Delta * Speed;
Character_Controller.Velocity = Character_Controller.Velocity.WithX(Direction.x).WithY(Direction.y);
Character_Controller.Velocity += Physics_World.Gravity * Time.Delta;
if (Input.Pressed("space") && Character_Controller.IsOnGround)
Character_Controller.Punch(Vector3.Zero.WithZ(Jump_Power));
if (Input.Pressed("x"))
IsThirdPerson = !IsThirdPerson;
Character_Controller.Move(); Character_Controller.Height = Offset; }
void Camera()
{
var Delta = Input.MouseDelta * Time.Delta * Preferences.Sensitivity;
x = (x + Delta.x) % 360;
y = (y - Delta.y).Clamp(-89f, 89f);
c.WorldPosition = WorldPosition + Vector3.Zero.WithZ(Offset); c.WorldRotation = new Angles(-y, -x, 0);
WorldRotation = new Angles(WorldRotation.Pitch(), c.WorldRotation.Yaw(), WorldRotation.Roll());
if (IsThirdPerson)
{ c.WorldPosition += c.WorldRotation * Vector3.Zero.WithX(-64);
SceneTraceResult Ray = Scene.Trace
.Ray(WorldPosition + Vector3.Zero.WithZ(Offset), c.WorldPosition)
.IgnoreGameObject(GameObject).Run();
if (Ray.Hit)
c.WorldPosition = Ray.HitPosition;
}
c.GetComponent<CameraComponent>().FieldOfView = Preferences.FieldOfView; }
void Visibility()
{
if (IsProxy || IsThirdPerson) {Model_Renderer.RenderType = ModelRenderer.ShadowRenderType.On; return;}
Model_Renderer.RenderType = ModelRenderer.ShadowRenderType.ShadowsOnly;
}
}