using MLAPI; using UnityEngine; namespace BossRoom.Server { public class ChaseAction : Action { private NetworkedObject m_Target; private ServerCharacterMovement m_Movement; private Vector3 m_CurrentTargetPos; public ChaseAction(ServerCharacter parent, ref ActionRequestData data, int level) : base(parent, ref data, level) { } /// /// Called when the Action starts actually playing (which may be after it is created, because of queueing). /// /// false if the action decided it doesn't want to run after all, true otherwise. public override bool Start() { if (!HasValidTarget()) { Debug.Log("Failed to start ChaseAction. The target entity wasn't submitted or doesn't exist anymore"); return false; } m_Target = MLAPI.Spawning.SpawnManager.SpawnedObjects[m_Data.TargetIds[0]]; m_Movement = m_Parent.GetComponent(); m_CurrentTargetPos = m_Target.transform.position; if (StopIfDone()) { m_Parent.transform.LookAt(m_CurrentTargetPos); //even if we didn't move, snap to face the target! return false; } m_Movement.SetMovementTarget(m_Target.transform.position); return true; } /// /// Returns true if our ActionRequestData came with a valid target. For the ChaseAction, this is pretty liberal (could be friend or foe, could be /// dead or alive--just needs to be present). /// private bool HasValidTarget() { return m_Data.TargetIds != null && m_Data.TargetIds.Length > 0 && MLAPI.Spawning.SpawnManager.SpawnedObjects.ContainsKey(m_Data.TargetIds[0]); } /// /// Tests to see if we've reached our target. Returns true if we've reached our target, false otherwise (in which case it also stops our movement). /// private bool StopIfDone() { float distToTarget2 = (m_Parent.transform.position - m_Target.transform.position).sqrMagnitude; if ((m_Data.Amount * m_Data.Amount) > distToTarget2) { //we made it! we're done. Cancel(); return true; } return false; } /// /// Called each frame while the action is running. /// /// true to keep running, false to stop. The Action will stop by default when its duration expires, if it has a duration set. public override bool Update() { if (StopIfDone()) { return false; } float targetMoved2 = (m_Target.transform.position - m_CurrentTargetPos).sqrMagnitude; if ((m_Data.Amount * m_Data.Amount) < targetMoved2) { //target has moved past our range tolerance. Must repath. this.m_Movement.SetMovementTarget(m_Target.transform.position); m_CurrentTargetPos = m_Target.transform.position; } return true; } public override void Cancel() { m_Movement?.CancelMove(); } } }