Npcs/Roller/Tasks/RollerLeapTask.cs
using Sandbox.Npcs.Roller;
namespace Sandbox.Npcs.Roller.Tasks;
/// <summary>
/// Leaps at the current target with a clean impulse (velocity zeroed first),
/// then waits for cooldown before handing back to the roll task.
/// </summary>
public sealed class RollerLeapTask : TaskBase
{
private const float LeapCooldown = 1.2f;
private TimeUntil _cooldown;
protected override void OnStart()
{
var rollermine = Npc as RollerNpc;
if ( rollermine is null ) return;
var rb = rollermine.Rigidbody;
if ( !rb.IsValid() ) return;
var target = Npc.Senses.GetNearestVisible();
if ( !target.IsValid() ) return;
var dir = (target.WorldPosition - Npc.WorldPosition).Normal;
var leapDir = (dir + Vector3.Up * rollermine.LeapUpwardBias).Normal;
// Zero existing velocity so the leap feels snappy rather than additive
rb.Velocity = Vector3.Zero;
rb.AngularVelocity = Vector3.Zero;
rb.ApplyImpulse( leapDir * rollermine.LeapForce );
rollermine.BroadcastLeapEffect();
_cooldown = LeapCooldown;
}
protected override TaskStatus OnUpdate()
{
return _cooldown ? TaskStatus.Success : TaskStatus.Running;
}
}