void FPawnActionStack::PopAction(UPawnAction& ActionToPop) { // first check if it's there UPawnAction* CutPoint = TopAction; while (CutPoint != NULL && CutPoint != &ActionToPop) { CutPoint = CutPoint->ParentAction; } if (CutPoint == &ActionToPop) { UPawnAction* ActionBeingRemoved = TopAction; // note StopAction can be null UPawnAction* StopAction = ActionToPop.ParentAction; while (ActionBeingRemoved != StopAction) { UPawnAction* NextAction = ActionBeingRemoved->ParentAction; if (ActionBeingRemoved->IsBeingAborted() == false && ActionBeingRemoved->IsFinished() == false) { // forcing abort to make sure it happens instantly. We don't have time for delayed finish here. ActionBeingRemoved->Abort(EAIForceParam::Force); } ActionBeingRemoved->OnPopped(); if (ActionBeingRemoved->ParentAction) { ActionBeingRemoved->ParentAction->OnChildFinished(*ActionBeingRemoved, ActionBeingRemoved->FinishResult); } ActionBeingRemoved = NextAction; } TopAction = StopAction; } }
bool UPawnActionsComponent::HasActiveActionOfType(EAIRequestPriority::Type Priority, TSubclassOf<UPawnAction> PawnActionClass) const { TArray<UPawnAction*> ActionsToTest; ActionsToTest.Add(GetActiveAction(Priority)); while (ActionsToTest.Num() > 0) { UPawnAction* ActiveActionIter = ActionsToTest[0]; if (ActiveActionIter) { if (ActiveActionIter->GetClass()->IsChildOf(*PawnActionClass)) { return true; } else { UPawnAction_Sequence* PawnActionSequence = Cast<UPawnAction_Sequence>(ActiveActionIter); if (PawnActionSequence) { for (int32 PawnActionSequenceCount = 0; PawnActionSequenceCount < PawnActionSequence->ActionSequence.Num(); ++PawnActionSequenceCount) { ActionsToTest.Add(PawnActionSequence->ActionSequence[PawnActionSequenceCount]); } } } } ActionsToTest.RemoveAt(0); } // Didn't find one. return false; }
bool UPawnActionsComponent::OnEvent(UPawnAction& Action, EPawnActionEventType::Type Event) { bool bResult = false; const FPawnActionEvent ActionEvent(Action, Event, ActionEventIndex++); if (Event != EPawnActionEventType::Invalid && ActionEvents.Find(ActionEvent) == INDEX_NONE) { ActionEvents.Add(ActionEvent); // if it's a first even enable tick if (ActionEvents.Num() == 1) { SetComponentTickEnabled(true); } bResult = true; } else if (Event == EPawnActionEventType::Invalid) { // ignore UE_VLOG(ControlledPawn, LogPawnAction, Warning, TEXT("Ignoring Action Event: Action %s Event %s") , *Action.GetName(), *GetEventName(Event)); } else { UE_VLOG(ControlledPawn, LogPawnAction, Warning, TEXT("Ignoring duplicate Action Event: Action %s Event %s") , *Action.GetName(), *GetEventName(Event)); } return bResult; }
uint32 UPawnActionsComponent::AbortActionsInstigatedBy(UObject* const Instigator, EAIRequestPriority::Type Priority) { uint32 AbortedActionsCount = 0; if (Priority == EAIRequestPriority::MAX) { // call for every regular priority for (int32 PriorityIndex = 0; PriorityIndex < EAIRequestPriority::MAX; ++PriorityIndex) { AbortedActionsCount += AbortActionsInstigatedBy(Instigator, EAIRequestPriority::Type(PriorityIndex)); } } else { UPawnAction* Action = ActionStacks[Priority].GetTop(); while (Action) { if (Action->GetInstigator() == Instigator) { OnEvent(*Action, EPawnActionEventType::InstantAbort); ++AbortedActionsCount; } Action = Action->ParentAction; } } return AbortedActionsCount; }
bool UPawnActionsComponent::PushAction(UPawnAction& NewAction, EAIRequestPriority::Type Priority, UObject* Instigator) { if (NewAction.HasBeenStarted() == false || NewAction.IsFinished() == true) { NewAction.ExecutionPriority = Priority; NewAction.SetOwnerComponent(this); NewAction.SetInstigator(Instigator); return OnEvent(NewAction, EPawnActionEventType::Push); } return false; }
void UPawnActionsComponent::OnUnregister() { if ((ControlledPawn != nullptr) && !ControlledPawn->IsPendingKillPending()) { // call for every regular priority for (int32 PriorityIndex = 0; PriorityIndex < EAIRequestPriority::MAX; ++PriorityIndex) { UPawnAction* Action = ActionStacks[PriorityIndex].GetTop(); while (Action) { Action->Abort(EAIForceParam::Force); Action = Action->ParentAction; } } } Super::OnUnregister(); }
void UPawnAction::OnChildFinished(UPawnAction& Action, EPawnActionResult::Type WithResult) { UE_VLOG(GetPawn(), LogPawnAction, Log, TEXT("%s> Child \'%s\' finished with result %s") , *GetName(), *Action.GetName(), *GetActionResultName(WithResult)); ensure(Action.ParentAction == this); ensure(ChildAction == &Action); Action.ParentAction = NULL; ChildAction = NULL; }
bool UPawnAction::PushChildAction(UPawnAction& Action) { bool bResult = false; if (OwnerComponent != NULL) { UE_CVLOG( ChildAction != NULL , GetPawn(), LogPawnAction, Log, TEXT("%s> Pushing child action %s while already having ChildAction set to %s") , *GetName(), *Action.GetName(), *ChildAction->GetName()); // copy runtime data // note that priority and instigator will get assigned as part of PushAction. bResult = OwnerComponent->PushAction(Action, GetPriority(), Instigator); // adding a check to make sure important data has been set ensure(Action.GetPriority() == GetPriority() && Action.GetInstigator() == GetInstigator()); } return bResult; }
EPawnActionAbortState::Type UPawnActionsComponent::AbortAction(UPawnAction& ActionToAbort) { const EPawnActionAbortState::Type AbortState = ActionToAbort.Abort(EAIForceParam::DoNotForce); if (AbortState == EPawnActionAbortState::NeverStarted) { // this is a special case. It's possible someone tried to abort an action that // has just requested to be pushes and the push event has not been processed yet. // in such a case we'll look through the awaiting action events and remove a push event // for given ActionToAbort RemoveEventsForAction(ActionToAbort); } return AbortState; }
void FPawnActionStack::PushAction(UPawnAction& NewTopAction) { if (TopAction != NULL) { if (TopAction->IsPaused() == false && TopAction->HasBeenStarted() == true) { TopAction->Pause(&NewTopAction); } ensure(TopAction->ChildAction == NULL); TopAction->ChildAction = &NewTopAction; NewTopAction.ParentAction = TopAction; } TopAction = &NewTopAction; NewTopAction.OnPushed(); }
FPawnActionEvent::FPawnActionEvent(UPawnAction& InAction, EPawnActionEventType::Type InEventType, uint32 InIndex) : Action(&InAction), EventType(InEventType), Index(InIndex) { Priority = InAction.GetPriority(); }
EPawnActionAbortState::Type UPawnActionsComponent::ForceAbortAction(UPawnAction& ActionToAbort) { return ActionToAbort.Abort(EAIForceParam::Force); }