A camera component for a player, it reads mouse input and head rotation to control the scene camera and head transform. It also adjusts a body model renderer visibility and moves the camera down when the player is ducking.
using System;
using Sandbox;
[Icon("smartphone")]
public class SourceCamera : Component {
[Property] public float Sensitivity { get; set; } = 0.1f;
[Property] public SourceMovement Player { get; set; }
[Property] public CharacterController Controller { get; set; }
[Property] public GameObject Head { get; set; }
[Property] public GameObject Body { get; set; }
[Property] public GameObject Target { get; set; }
private ModelRenderer BodyRenderer;
private Vector3 CurrentOffset = Vector3.Zero;
protected override void OnAwake() {
BodyRenderer = Body.GetComponent<ModelRenderer>();
}
protected override void OnUpdate() {
if (Network.IsProxy) {
if (BodyRenderer is not null) {
BodyRenderer.RenderType = ModelRenderer.ShadowRenderType.On;
}
return;
}
var eyeAngles = Head.WorldRotation.Angles();
eyeAngles.pitch += Input.MouseDelta.y * Sensitivity;
eyeAngles.yaw -= Input.MouseDelta.x * Sensitivity;
eyeAngles.roll = 0f;
eyeAngles.pitch = Math.Clamp(eyeAngles.pitch, -89.9f, 89.9f);
Head.WorldRotation = eyeAngles.ToRotation();
var tarOffset = Vector3.Zero;
if (Player.IsDucking) tarOffset = Vector3.Down * 32f;
CurrentOffset = Vector3.Lerp(CurrentOffset, tarOffset, Time.Delta * 10f);
if (Scene.Camera is not null) {
Scene.Camera.WorldPosition = Head.WorldPosition + CurrentOffset;
Scene.Camera.WorldRotation = eyeAngles.ToRotation();
if (BodyRenderer is not null) {
BodyRenderer.RenderType = ModelRenderer.ShadowRenderType.ShadowsOnly;
}
}
}
}