Player/PlayerController.cs
using System;
using Sandbox;
using Sandbox.Citizen;
using System.Drawing;
using System.Runtime;
using Clover.Carriable;
using Clover.Components;
using Clover.Player;
[Category( "Clover/Player" )]
public class PlayerController : Component, IEquipChanged
{
[RequireComponent] public PlayerCharacter Player { get; set; }
[RequireComponent] public CharacterController CharacterController { get; set; }
[Property] public SkinnedModelRenderer Model { get; set; }
[Property] public CitizenAnimationHelper AnimationHelper { get; set; }
[Property] public Vector3 Gravity { get; set; } = new Vector3( 0, 0, 800 );
[Property] public float WalkSpeed { get; set; } = 110.0f;
[Property] public float RunSpeed { get; set; } = 180.0f;
[Property] public float SneakSpeed { get; set; } = 60.0f;
public Vector3 WishVelocity { get; private set; }
[Sync] public float Yaw { get; set; }
[Sync] public bool IsRunning { get; set; }
protected override void OnEnabled()
{
base.OnEnabled();
if ( IsProxy )
return;
/*var cam = Scene.GetAllComponents<CameraComponent>().FirstOrDefault();
if ( cam.IsValid() )
{
var ee = cam.WorldRotation.Angles();
ee.roll = 0;
EyeAngles = ee;
}*/
}
protected override void OnUpdate()
{
if ( Player.Model.IsValid() )
{
Player.Model.WorldRotation = Rotation.Lerp( Player.Model.WorldRotation, Rotation.From( 0, Yaw, 0 ),
Time.Delta * 10.0f );
}
// Eye input
if ( !IsProxy )
{
/*var ee = EyeAngles;
ee += Input.AnalogLook * 0.5f;
ee.roll = 0;
EyeAngles = ee;
var cam = Scene.GetAllComponents<CameraComponent>().FirstOrDefault();
var lookDir = EyeAngles.ToRotation();
if ( FirstPerson )
{
cam.Transform.Position = Eye.Transform.Position;
cam.WorldRotation = lookDir;
}
else
{
cam.Transform.Position = Transform.Position + lookDir.Backward * 300 + Vector3.Up * 75.0f;
cam.WorldRotation = lookDir;
}*/
IsRunning = Input.Down( "Run" );
}
/*var cc = GameObject.Components.Get<CharacterController>();
if ( !cc.IsValid() ) return;
float moveRotationSpeed = 0;
// rotate body to look angles
if ( Model.IsValid() )
{
var targetAngle = new Angles( 0, 0, 0 ).ToRotation();
var v = cc.Velocity.WithZ( 0 );
if ( v.Length > 10.0f )
{
targetAngle = Rotation.LookAt( v, Vector3.Up );
}
float rotateDifference = Model.WorldRotation.Distance( targetAngle );
if ( rotateDifference > 50.0f || cc.Velocity.Length > 10.0f )
{
var newRotation = Rotation.Lerp( Model.WorldRotation, targetAngle, Time.Delta * 2.0f );
// We won't end up actually moving to the targetAngle, so calculate how much we're actually moving
var angleDiff = Model.WorldRotation.Angles() - newRotation.Angles(); // Rotation.Distance is unsigned
moveRotationSpeed = angleDiff.yaw / Time.Delta;
Model.WorldRotation = newRotation;
}
}*/
var speed = CharacterController.Velocity.Length * 2.54f;
Model.Set( "move_speed", speed );
Model.Set( "running", IsRunning );
// Model.Set( "holding", true );
// Gizmo.Draw.Text( $"Speed: {speed}", new Transform( Player.WorldPosition + Vector3.Up * 32 ) );
if ( AnimationHelper.IsValid() )
{
AnimationHelper.WithVelocity( CharacterController.Velocity );
AnimationHelper.WithWishVelocity( WishVelocity );
AnimationHelper.IsGrounded = CharacterController.IsOnGround;
AnimationHelper.MoveRotationSpeed = 1f;
// AnimationHelper.WithLook( EyeAngles.Forward, 1, 1, 1.0f );
AnimationHelper.MoveStyle =
IsRunning ? CitizenAnimationHelper.MoveStyles.Run : CitizenAnimationHelper.MoveStyles.Walk;
}
}
/*[Broadcast]
public void OnJump( float floatValue, string dataString, object[] objects, Vector3 position )
{
AnimationHelper?.TriggerJump();
}*/
float fJumps;
protected override void OnFixedUpdate()
{
Model.LocalPosition = Vector3.Zero;
if ( IsProxy )
{
Model.Set( "holding",
Player.Equips.EquippedSlots.TryGetValue( Equips.EquipSlot.Tool, out var state ) && state );
return;
}
if ( Player.InCutscene )
{
if ( Player.CutsceneTarget.HasValue )
{
var target = Player.CutsceneTarget.Value;
var direction = (target - Player.WorldPosition).Normal;
CharacterController.Velocity = direction * 100.0f;
Player.ModelLookAt( target );
// Gizmo.Draw.LineSphere( target, 10.0f );
// Gizmo.Draw.Arrow( Player.WorldPosition, target );
if ( (target - Player.WorldPosition).Length < 10.0f )
{
// Player.CutsceneTarget = null;
CharacterController.Velocity = Vector3.Zero;
// Log.Info( "Cutscene target reached" );
}
CharacterController.Move();
}
return;
}
if ( !Player.ShouldMove() )
{
CharacterController.Velocity = Vector3.Zero;
return;
}
BuildWishVelocity();
var cc = GameObject.Components.Get<CharacterController>();
if ( !cc.IsValid() )
{
// Log.Error( "CharacterController is not valid" );
return;
}
if ( JumpEnabled && cc.IsOnGround && Input.Down( "Jump" ) )
{
float flGroundFactor = 1.0f;
float flMul = 268.3281572999747f * 1.2f;
//if ( Duck.IsActive )
// flMul *= 0.8f;
cc.Punch( Vector3.Up * flMul * flGroundFactor );
// cc.IsOnGround = false;
// OnJump( fJumps, "Hello", new object[] { Time.Now.ToString(), 43.0f }, Vector3.Random );
fJumps += 1.0f;
}
if ( cc.IsOnGround )
{
cc.Velocity = cc.Velocity.WithZ( 0 );
cc.Accelerate( WishVelocity );
cc.ApplyFriction( 4.0f );
}
else
{
cc.Velocity -= Gravity * Time.Delta * 0.5f;
cc.Accelerate( WishVelocity.ClampLength( 50 ) );
cc.ApplyFriction( 0.1f );
}
cc.Move();
if ( !cc.IsOnGround )
{
cc.Velocity -= Gravity * Time.Delta * 0.5f;
}
else
{
cc.Velocity = cc.Velocity.WithZ( 0 );
}
}
[ConVar( "clover_player_jump_enabled" )]
public static bool JumpEnabled { get; set; }
public void BuildWishVelocity()
{
var input = Input.AnalogMove;
if ( input.Length > 0 /*&& !Player.ShouldDisableMovement()*/ )
{
// Player.Model.WorldRotation = Rotation.Lerp( Player.Model.WorldRotation, Rotation.LookAt( input, Vector3.Up ),
// Time.Delta * 10.0f );
if ( !Player.Model.IsValid() )
{
Log.Error( "Player.Model is not valid" );
return;
}
// move relative to camera
// TODO: normalise properly
var camera = Scene.Camera;
var cameraRotation = camera.WorldRotation.Angles().WithPitch( 0f ).ToRotation();
var cameraForward = cameraRotation.Forward;
var cameraRight = cameraRotation.Right;
var move = (cameraForward * input.x) + (cameraRight * -input.y);
WishVelocity = move.ClampLength( 1f );
// player facing angle
Yaw = Yaw.LerpDegreesTo( move.EulerAngles.yaw, Time.Delta * 7.0f );
}
else
{
WishVelocity = Vector3.Zero;
}
if ( Input.Down( "Run" ) )
{
WishVelocity *= RunSpeed;
}
else if ( Input.Down( "Walk" ) )
{
WishVelocity *= SneakSpeed;
}
else
{
WishVelocity *= WalkSpeed;
}
if ( Player.Equips.TryGetEquippedItem<BaseCarriable>( Equips.EquipSlot.Tool, out var tool ) )
{
WishVelocity *= tool.CustomPlayerSpeed();
}
}
public void OnEquippedItemChanged( GameObject owner, Equips.EquipSlot slot, GameObject item )
{
Log.Info( $"OnEquippedItemChanged: {owner} {slot} {item}" );
if ( owner != GameObject ) return;
Model.Set( "holding", item.IsValid() );
}
public void OnEquippedItemRemoved( GameObject owner, Equips.EquipSlot slot )
{
Log.Info( $"OnEquippedItemRemoved: {owner} {slot}" );
if ( owner != GameObject ) return;
Model.Set( "holding", false );
}
}