// using this namespace is necessary for Utility AI Tasks
//
// The game adds UAI.UAITask to the class name for discovery.
namespace UAI
{
///
/// Guards a position. If the entity is not at its guard position, it will path its way back to it.
/// The guard position must already be set, for example from .
///
///
///
/// <task class="Guard, SCore" />
///
///
///
public class UAITaskGuard : UAITaskBase
{
private float _timeOut = 100f;
private float _currentTimeout;
public override void Start(Context _context)
{
base.Start(_context);
_currentTimeout = _timeOut;
// Clear out any pathing on the target that was set by other tasks.
var entityAlive = UAIUtils.ConvertToEntityAlive(_context.ActionData.Target);
if (entityAlive is IEntityOrderReceiverSDX)
{
entityAlive.moveHelper.Stop();
entityAlive.navigator.clearPath();
}
}
public override void Update(Context _context)
{
var entityAlive = UAIUtils.ConvertToEntityAlive(_context.ActionData.Target);
if (!(entityAlive is IEntityOrderReceiverSDX entityOrderReceiver))
{
Stop(_context);
return;
}
base.Update(_context);
// Don't do anything until the entity touches the ground; avoid the free in mid-air scenario.
if (!entityAlive.onGround) return;
// If we don't have a path, then either we started this task away from the guard
// position and need to find our way back, or we are already there.
if (entityAlive.navigator.noPathAndNotPlanningOne())
{
// Compare the block centers of the current position and guard position to avoid
// repathing for tiny position changes.
var entityPosition = EntityUtilities.CenterPosition(entityOrderReceiver.Position);
var guardPosition = EntityUtilities.CenterPosition(entityOrderReceiver.GuardPosition);
if (guardPosition != entityPosition)
{
// Even if NPCs can't break blocks, setting this to false results in weird pathing.
var canBreakBlocks = true;
entityAlive.moveHelper.SetMoveTo(entityOrderReceiver.GuardPosition, canBreakBlocks);
entityAlive.FindPath(
entityOrderReceiver.GuardPosition,
entityAlive.GetMoveSpeedPanic(),
canBreakBlocks,
null);
return;
}
else
{
// Turn around and face the same way as when the order was given.
entityAlive.SetLookPosition(entityOrderReceiver.GuardLookPosition);
entityAlive.RotateTo(
entityOrderReceiver.GuardLookPosition.x,
entityOrderReceiver.GuardLookPosition.y,
entityOrderReceiver.GuardLookPosition.z,
30f,
30f);
}
}
// Check if a player is in your bounds, and face them if they are.
var leader = EntityUtilities.GetLeaderOrOwner(_context.Self.entityId) as EntityAlive;
SCoreUtils.TurnToFaceEntity(_context, leader);
_currentTimeout--;
if (_currentTimeout < 0) Stop(_context);
}
}
}