SupaLidlGame/State/Thinker/IdleState.cs

92 lines
2.3 KiB
C#

using Godot;
using GodotUtilities;
namespace SupaLidlGame.State.Thinker;
public partial class IdleState : ThinkerState
{
[Export]
public ThinkerState PursueState { get; set; }
[Export]
public float MinTargetDistance { get; set; }
[ExportGroup("Line of Sight")]
[Export]
public bool PursueOnLineOfSight { get; set; }
[Export]
public float MinLineOfSightDistance { get; set; }
[ExportGroup("Returning")]
[Export]
public bool ShouldReturnToOriginalPosition { get; set; } = true;
[Export]
public NavigationAgent2D NavigationAgent { get; set; }
protected Vector2 _originalPosition;
protected bool _isReturning;
public override void _Ready()
{
_originalPosition = NPC.GlobalPosition;
base._Ready();
}
public override ThinkerState Think()
{
var bestTarget = NPC.FindBestTarget();
if (bestTarget is not null)
{
var pos = bestTarget.GlobalPosition;
var dist = NPC.GlobalPosition.DistanceTo(pos);
if (dist < MinTargetDistance)
{
return PursueState;
}
else if (PursueOnLineOfSight && NPC.HasLineOfSight(bestTarget))
{
if (dist < MinLineOfSightDistance)
{
return PursueState;
}
}
_isReturning = false;
}
if (ShouldReturnToOriginalPosition)
{
if (NavigationAgent is not null)
{
// if we're less than 8 units away then we don't move
var pos = NPC.GlobalPosition;
if (!pos.IsWithinDistanceSquared(_originalPosition, 64))
{
NavigationAgent.TargetPosition = _originalPosition;
}
}
_isReturning = true;
}
return base.Think();
}
public override ThinkerState PhysicsProcess(double delta)
{
if (_isReturning && NavigationAgent.IsTargetReachable())
{
var navPos = NavigationAgent.GetNextPathPosition();
NPC.Direction = NPC.GlobalPosition.DirectionTo(navPos);
}
if (NavigationAgent.IsTargetReached())
{
NPC.Direction = Vector2.Zero;
}
return base.PhysicsProcess(delta);
}
}