Player/Player.Animation.cs

Player partial implementing animation updates for a skinned body model. It computes movement parameters from velocity and rotation, sets animgraph variables on a SkinnedModelRenderer, updates look direction, and applies a custom movement-state parameter and tint.

Native Interop
using System;
using Sandbox;

namespace BrickJam;

public sealed partial class Player
{
	/// <summary>
	/// The skinned body model. Set on the player prefab. Replaces the legacy
	/// <c>AnimatedEntity</c> self-model.
	/// </summary>
	[Property] public SkinnedModelRenderer Body { get; set; }

	private void UpdateAnimation()
	{
		if ( !Body.IsValid() )
			return;

		// Citizen animgraph parameters, set directly on the renderer (mirrors what
		// CitizenAnimationHelper.WithVelocity does, without depending on the base addon's
		// Sandbox.Citizen namespace which isn't available here).
		var velocity = Velocity;
		var rotation = Body.WorldRotation;
		var forward = rotation.Forward.Dot( velocity );
		var sideward = rotation.Right.Dot( velocity );
		var moveAngle = MathF.Atan2( sideward, forward ).RadianToDegree().NormalizeDegrees();

		Body.Set( "move_direction", moveAngle );
		Body.Set( "move_speed", velocity.Length );
		Body.Set( "move_groundspeed", velocity.WithZ( 0 ).Length );
		Body.Set( "move_y", sideward );
		Body.Set( "move_x", forward );
		Body.Set( "move_z", velocity.z );

		Body.Set( "duck", IsCrouching ? 1f : 0f );
		Body.Set( "b_grounded", IsOnGround );
		Body.SetLookDirection( "aim_eyes", InputRotation.Forward );

		// Custom parameters specific to this game's citizen animgraph.
		Body.Set( "special_movement_states", IsStunned ? 1 : (IsTripping ? 2 : (IsSlipping ? 3 : 0)) );
		Body.Set( "speed_scale", velocity.WithZ( 0 ).Length / 150f );

		ApplyMaskTint();
	}
}