public static IEnumerator UpdateGoToActionNode(Motile m, MotileAction action) { if (action.HasLiveTarget) { //m.rvoController.usePath = (action.Method == MotileGoToMethod.Pathfinding); m.GoalObject.position = action.LiveTarget.Position; ActionNode node = null; if (action.LiveTarget.IOIType == ItemOfInterestType.ActionNode) //see if we're there yet { node = action.LiveTarget.node; float distanceFromTarget = Vector3.Distance(m.worlditem.Position, m.GoalObject.position); //use the range variable for our distance check if (distanceFromTarget <= action.Range) { m.TargetMovementSpeed = m.State.MotileProps.SpeedWalk; //can we occupy this thing? if (node.CanOccupy(m.worlditem)) //hooray! we can occupy it { if (node.TryToOccupyNode(m.worlditem)) //we've occupied it, huzzah { m.LastOccupiedNode = node; m.TargetMovementSpeed = 0.0f; FinishAction(m, action); yield break; } //if we didn't occupy it, it might mean we're not close enough //because our range may be larger than the node range //so try again next frame } else //whoops, node is inaccessible //set to error { action.State = MotileActionState.Error; action.Error = MotileActionError.TargetInaccessible; } } else if (distanceFromTarget <= action.Range * 1.5) { //don't stop, but do slow down a bit m.TargetMovementSpeed = m.State.MotileProps.SpeedWalk; } else { //run and catch up! m.TargetMovementSpeed = m.State.MotileProps.SpeedRun; } } else //weird, it got unloaded for some reason { action.State = MotileActionState.Error; action.Error = MotileActionError.TargetNotLoaded; } } else //weird, live target is gone for some reason //try to get it again //(not implemented) { action.State = MotileActionState.Error; action.Error = MotileActionError.TargetNotLoaded; } //otherwise get live target yield return(null); yield break; }
public static bool FinishAction(Motile m, MotileAction action) { //Debug.Log("Finishing action " + action.Name); if (action.BaseAction) { return(false); } m.AvoidingObstacle = false; action.State = MotileActionState.Finishing; bool finished = false; switch (action.Type) { case MotileActionType.FocusOnTarget: finished = true; break; case MotileActionType.FollowGoal: finished = true; break; case MotileActionType.FollowRoutine: finished = true; break; case MotileActionType.WanderIdly: finished = true; break; case MotileActionType.FollowTargetHolder: m.GoalHolder = null; //move goal to group transform //this will stop the target holder from using it finished = true; break; case MotileActionType.GoToActionNode: //if we're at the action node, vacate the node //if we're not at the action node, do nothing if (m.LastOccupiedNode == null && action.HasLiveTarget && action.LiveTarget.IOIType == ItemOfInterestType.ActionNode) //if we actually have a live target { ActionNode node = action.LiveTarget.node; if (!node.IsOccupant(m.worlditem)) //try to occupy it one last time { node.TryToOccupyNode(m.worlditem); //if we don't make it oh well } } finished = true; break; case MotileActionType.Wait: default: finished = true; break; } if (finished) { if (action.State != MotileActionState.Error) //preserve the error { action.State = MotileActionState.Finished; } action.UpdateCoroutine = null; //reset this action.WTFinished = WorldClock.AdjustedRealTime; m.LastFinishedAction = action; //send final messages and whatnot action.OnFinishAction.SafeInvoke(); action.OnFinishAction = null; if (m != null && m.GoalObject != null) { m.GoalObject.parent = m.worlditem.Group.transform; } } //wait for finish to end (not implemented) //force refresh hud //m.rvoController.PositionLocked = false; //m.rvoController.RotationLocked = false; if (m != null) { m.worlditem.RefreshHud(); } //action state is finsihed return(finished); }