114 lines
3.8 KiB
C#
114 lines
3.8 KiB
C#
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
using VOID.Generic.Objects.Abstract;
|
|
using VOID.Generic.Objects.Unit.Actions.Exceptions;
|
|
using VOID.Generic.Objects.Unit.Events;
|
|
using VOID.Generic.Util;
|
|
|
|
namespace VOID.Generic.Objects.Unit.Actions
|
|
{
|
|
public class MoveAction : AbstractAction
|
|
{
|
|
private readonly UnitObject _unit;
|
|
private readonly Vector3 _targetPosition;
|
|
private readonly AbstractObject _targetObject;
|
|
private readonly float _untilInRange;
|
|
|
|
public MoveAction(UnitObject unit, Vector3 targetPosition, float untilInRange = 0f)
|
|
{
|
|
_unit = unit;
|
|
_targetPosition = targetPosition;
|
|
_untilInRange = untilInRange;
|
|
}
|
|
|
|
public MoveAction(UnitObject unit, AbstractObject targetObject, float untilInRange = 0f)
|
|
: this(unit, targetObject.transform.position, untilInRange + targetObject.basicData.radius)
|
|
{
|
|
_targetObject = targetObject;
|
|
}
|
|
|
|
public override bool IsInRange()
|
|
{
|
|
// Dont let player ordering move too far away
|
|
var distanceBetween = Vector3.Distance(_unit.transform.position, _targetPosition);
|
|
return distanceBetween < 100f;
|
|
}
|
|
|
|
public override bool CanBeStopped()
|
|
{
|
|
return !_unit.unitState.isTraversing;
|
|
}
|
|
|
|
protected override void OnEndIt()
|
|
{
|
|
_unit.unitEvents.onMoveEnd.RemoveListener(OnMoveEnd);
|
|
}
|
|
|
|
protected override void OnCancelIt()
|
|
{
|
|
_unit.unitEvents.onMoveEnd.RemoveListener(OnMoveEnd);
|
|
_unit.unitNavAgent.Stop();
|
|
}
|
|
|
|
public override void CanDoIt()
|
|
{
|
|
Check(
|
|
_unit.unitData.canMove,
|
|
UnitActionErrorType.ThisUnitCantMove);
|
|
Check(
|
|
state == ActionState.Ready,
|
|
UnitActionErrorType.ActionStateIsNotReady);
|
|
Check(
|
|
!_unit.unitState.isCasting,
|
|
UnitActionErrorType.ThisUnitIsCasting);
|
|
if (_unit.basicState.turnManager)
|
|
{
|
|
Check(
|
|
_unit.unitState.isSelfTurn,
|
|
UnitActionErrorType.UnitSelfTurnNotActive);
|
|
Check(
|
|
_unit.unitData.currentResources.movePoints > 0.1f,
|
|
UnitActionErrorType.UnitNotEnoughMovePoints);
|
|
}
|
|
Check(
|
|
_unit.unitState.isControllable,
|
|
UnitActionErrorType.UnitStateIsNotControllable);
|
|
Check(
|
|
IsInRange(),
|
|
UnitActionErrorType.NotInRange);
|
|
_unit.unitNavAgent.CalculatePathTo(_targetPosition, _untilInRange);
|
|
Check(
|
|
_unit.unitNavAgent.GetPath().status is not NavMeshPathStatus.PathInvalid,
|
|
UnitActionErrorType.NoPathToTarget);
|
|
}
|
|
|
|
protected override void OnDoIt()
|
|
{
|
|
var isInRange = _targetObject
|
|
? RangeUtil.IsInRange(_unit, _targetObject, _untilInRange, false)
|
|
: RangeUtil.IsInRange(_unit, _targetPosition, _untilInRange, false);
|
|
|
|
if (isInRange)
|
|
{
|
|
EndIt();
|
|
return;
|
|
}
|
|
|
|
BeforePerform();
|
|
|
|
_unit.unitEvents.onMoveEnd.AddListener(OnMoveEnd);
|
|
var moveStarted = _targetObject
|
|
? _unit.unitNavAgent.Move(_targetObject, _untilInRange)
|
|
: _unit.unitNavAgent.Move(_targetPosition, _untilInRange);
|
|
|
|
// Unit didn't move for some reason (usually path is impossible or already at path destination)
|
|
if (!moveStarted) EndIt();
|
|
}
|
|
|
|
private void OnMoveEnd(MoveEvent moveEvent)
|
|
{
|
|
AfterPerform();
|
|
EndIt();
|
|
}
|
|
}
|
|
} |