Entities/WalkingCat.cs
using CatHarvest;
using CatHarvest.Util.Particles;
namespace Sandbox.Entities;
public class WalkingCat : Component
{
[Property] private CharacterController _characterController { get; set; }
private readonly Vector3 minBounds = new Vector3( -800, -770, 0 );
private readonly Vector3 maxBounds = new Vector3( 750, 790, 0 );
[Property] public bool IsDying { get; set; } = false;
[Property] public bool Aggressive { get; set; } = false;
[Property] public bool Passive { get; set; } = false;
[Property] public HarvestPlayer Victim { get; set; }
protected override void OnStart()
{
base.OnStart();
Tags.Add( "cat" );
}
RealTimeSince frameTime = 0f;
float lastDistance = 0f;
float nextFrame = 0f;
float nextMove = 0f;
[Property] public bool IsSecret;
protected override void OnFixedUpdate()
{
if ( !GameObject.IsValid() || GameObject.IsDestroyed ) return;
var traceGround = Scene.Trace.Ray( WorldPosition + Vector3.Up * 16, WorldPosition + Vector3.Down * 32f )
.IgnoreGameObjectHierarchy( this.GameObject.Root )
.WithoutTags( "Player" )
.WithoutTags( "Cat" )
.Run();
if ( IsProxy )
{
float frameDelta = 1f / 24f;
float minFps = 1f;
float minDistanceFalloff = 300f;
float maxDistanceFalloff = 2000f;
if ( frameTime >= nextFrame )
{
lastDistance = Math.Max( Scene.Camera.WorldPosition.Distance( WorldPosition ) - minDistanceFalloff,
1f );
nextFrame = frameDelta.LerpTo( minFps, lastDistance / maxDistanceFalloff );
frameTime = 0f;
}
return;
}
if ( nextMove <= Time.Now )
{
if ( !Passive )
{
if ( WorldPosition.x <= minBounds.x || WorldPosition.x >= maxBounds.x ||
WorldPosition.y <= minBounds.y || WorldPosition.y >= maxBounds.y )
{
_characterController.Velocity = (Vector3.Zero - WorldPosition).Normal * (IsSecret ? 1.5f : 4);
}
else
{
if ( Aggressive )
{
if ( Victim.IsValid() )
{
_characterController.Velocity =
((Victim.WorldPosition + new Vector3( Game.Random.Float( 30f ) - 15f,
Game.Random.Float( 30f ) - 15f, 0 )) - WorldPosition).Normal * 2;
}
Sound.Play( $"angry{Game.Random.Int( 1 )}", WorldPosition );
}
else
{
_characterController.Velocity =
new Vector3( Game.Random.Float( 2f ) - 1f, Game.Random.Float( 2f ) - 1f, 0f ).Normal *
(IsSecret ? 0.3f : 2);
var meow = Sound.Play( $"meow{Game.Random.Int( 10 )}", WorldPosition );
meow.Volume = IsSecret ? 0.3f : 0.15f;
if ( IsSecret )
{
meow.Pitch = 2f;
}
}
}
nextMove = Time.Now + Game.Random.Float( 2f ) + (Aggressive ? 0f : 6f);
}
else
{
_characterController.Velocity = new Vector3( 0f, 4f, 0f );
}
}
_characterController.Move();
if ( traceGround.Hit )
{
WorldPosition = traceGround.EndPosition;
WorldPosition += WorldRotation.Forward * 8 * _characterController.Velocity.Length * Time.Delta;
Rotation rotation = _characterController.Velocity.EulerAngles.ToRotation();
WorldRotation = Rotation.Slerp( WorldRotation, rotation, 2 * Time.Delta );
}
if ( IsDying )
{
Log.Info( "test" );
GetComponent<SkinnedModelRenderer>().Tint = Color.FromBytes( 255, 255, 255, (int)(hourOfDeath - Time.Now) * 5 );
if ( hourOfDeath <= 0 )
{
Destroy();
}
}
}
TimeUntil hourOfDeath = 0f;
public void Snap()
{
var particle = LegacyParticle.Create( "particles/ashes.vpcf", WorldPosition );
particle.GameObject.DestroyAsync( 3 );
hourOfDeath = 0.2f;
IsDying = true;
HarvestGame.The.AllCats.Remove( this.GameObject );
}
}