Code/Example/Complex/PlayerWalkControllerComplex.Body.cs
using Sandbox;
using Sandbox.Citizen;
namespace XMovement;
public partial class PlayerWalkControllerComplex : Component
{
[Property, Group( "Body" )] public GameObject Body { get; set; }
[Property, Group( "Body" )] public SkinnedModelRenderer BodyModelRenderer { get; set; }
[RequireComponent] public CitizenAnimationHelper AnimationHelper { get; set; }
protected void SetupBody()
{
if ( !Body.IsValid() )
{
Body = Scene.CreateObject();
Body.SetParent( GameObject );
Body.LocalPosition = Vector3.Zero;
Body.Name = "Body";
}
if ( !BodyModelRenderer.IsValid() )
{
BodyModelRenderer = Body.AddComponent<SkinnedModelRenderer>();
BodyModelRenderer.Model = Model.Load( "models/citizen/citizen.vmdl" );
AnimationHelper.Target = BodyModelRenderer;
}
}
[Property, Group( "Animator" )] public float RotationAngleLimit { get; set; } = 45.0f;
[Property, Group( "Animator" )] public float RotationSpeed { get; set; } = 1.0f;
[Property, Group( "Animator" )] public bool RotationFaceLadders { get; set; } = true;
float _animRotationSpeed;
TimeSince timeSinceRotationSpeedUpdate;
public virtual void RotateBody()
{
if ( IsTouchingLadder && RotationFaceLadders )
{
Body.WorldRotation = Rotation.Lerp( Body.WorldRotation, Rotation.LookAt( LadderNormal * -1 ), Time.Delta * 5.0f );
return;
}
var targetAngle = new Angles( 0, EyeAngles.yaw, 0 ).ToRotation();
var velocity = Controller.WishVelocity.WithZ( 0 );
float rotateDifference = BodyModelRenderer.WorldRotation.Distance( targetAngle );
// We're over the limit - snap it
if ( rotateDifference > RotationAngleLimit )
{
var delta = 0.999f - (RotationAngleLimit / rotateDifference);
var newRotation = Rotation.Lerp( BodyModelRenderer.WorldRotation, targetAngle, delta );
var a = newRotation.Angles();
var b = BodyModelRenderer.WorldRotation.Angles();
var yaw = MathX.DeltaDegrees( a.yaw, b.yaw );
_animRotationSpeed += yaw;
_animRotationSpeed = _animRotationSpeed.Clamp( -90, 90 );
BodyModelRenderer.WorldRotation = newRotation;
}
if ( velocity.Length > 10 )
{
var newRotation = Rotation.Slerp( BodyModelRenderer.WorldRotation, targetAngle, Time.Delta * 2.0f * RotationSpeed * velocity.Length.Remap( 0, 100 ) );
var a = newRotation.Angles();
var b = BodyModelRenderer.WorldRotation.Angles();
var yaw = MathX.DeltaDegrees( a.yaw, b.yaw );
_animRotationSpeed += yaw;
_animRotationSpeed = _animRotationSpeed.Clamp( -90, 90 );
BodyModelRenderer.WorldRotation = newRotation;
}
}
public virtual void Animate()
{
AnimationHelper.WithWishVelocity( Controller.WishVelocity );
AnimationHelper.WithVelocity( Controller.Velocity );
// skid, this isn't in AnimationHelper yet it seems? ok nvm it's absolutely FUCKED
/*{
var dir = Controller.Velocity.SubtractDirection( Controller.WishVelocity.Normal );
if ( dir.IsNearlyZero( 1.0f ) ) dir = 0;
var forward = BodyModelRenderer.WorldRotation.Forward.Dot( dir );
var sideward = BodyModelRenderer.WorldRotation.Right.Dot( dir );
BodyModelRenderer.Set( "skid_x", forward );
BodyModelRenderer.Set( "skid_y", sideward );
var skidAmount = (Controller.Velocity.Length - Controller.WishVelocity.Length).Clamp( 0, 10 ).Remap( 0, 10, 0, 0.5f );
BodyModelRenderer.Set( "skid", skidAmount );
}*/
AnimationHelper.WithLook( EyeAngles.Forward * 100, 1, 1, 1.0f );
AnimationHelper.DuckLevel = IsCrouching ? 100 : 0;
AnimationHelper.IsGrounded = Controller.IsOnGround || IsTouchingLadder;
AnimationHelper.IsClimbing = IsTouchingLadder;
AnimationHelper.IsSwimming = IsSwimming;
AnimationHelper.IsNoclipping = IsNoclipping;
if ( timeSinceRotationSpeedUpdate > 0.1f )
{
timeSinceRotationSpeedUpdate = 0;
AnimationHelper.MoveRotationSpeed = _animRotationSpeed * 5;
_animRotationSpeed = 0;
}
RotateBody();
}
}