void SmartAI::UpdatePath(const uint32 diff) { if (!HasEscortState(SMART_ESCORT_ESCORTING)) return; if (mEscortInvokerCheckTimer < diff) { if (!IsEscortInvokerInRange()) { StopPath(0, mEscortQuestID, true); // allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me); me->DespawnOrUnsummon(1); return; } mEscortInvokerCheckTimer = 1000; } else mEscortInvokerCheckTimer -= diff; // handle pause if (HasEscortState(SMART_ESCORT_PAUSED)) { if (mWPPauseTimer <= diff) { if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mForcedPaused)) { ResumePath(); } } else mWPPauseTimer -= diff; } else if (m_Ended) // end path { m_Ended = false; StopPath(); return; } if (HasEscortState(SMART_ESCORT_RETURNING)) { if (mOOCReached)//reached OOC WP { mOOCReached = false; RemoveEscortState(SMART_ESCORT_RETURNING); if (!HasEscortState(SMART_ESCORT_PAUSED)) ResumePath(); } } }
bool UNavigationComponent::FindSimplePathToActor(const AActor* NewGoalActor, float RepathDistance) { bool bPathGenerationSucceeded = false; if (bIsPaused && NewGoalActor != NULL && GoalActor == NewGoalActor && Path.IsValid() && Path->IsValid() && Path->GetOwner() == NULL) { RepathDistanceSq = FMath::Square(RepathDistance); OriginalGoalActorLocation = GetCurrentMoveGoal(NewGoalActor, GetOwner()); bPathGenerationSucceeded = ResumePath(); } else { if (NewGoalActor != NULL) { const FVector NewGoalActorLocation = GetCurrentMoveGoal(NewGoalActor, GetOwner()); bPathGenerationSucceeded = GenerateSimplePath(NewGoalActorLocation); if (bPathGenerationSucceeded) { GoalActor = NewGoalActor; RepathDistanceSq = FMath::Square(RepathDistance); OriginalGoalActorLocation = NewGoalActorLocation; bUseSimplePath = true; // if doing sync pathfinding enabling component's ticking needs to be done now SetComponentTickEnabledAsync(true); } } if (!bPathGenerationSucceeded) { UE_VLOG(GetOwner(), LogNavigation, Warning, TEXT("Failed to generate simple path to %s"), *GetNameSafe(NewGoalActor)); } } if (bPathGenerationSucceeded == false) { ResetTransientData(); } return bPathGenerationSucceeded; }
void SmartAI::MovepointReached(uint32 id) { // override the id, path can be resumed any time and counter will reset // mCurrentWPID holds proper id // xinef: both point movement and escort generator can enter this function if (id == SMART_ESCORT_LAST_OOC_POINT) { mOOCReached = true; return; } mWPReached = true; GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_REACHED, NULL, mCurrentWPID); if (mLastWP) { me->SetPosition(mLastWP->x, mLastWP->y, mLastWP->z, me->GetOrientation()); me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); } if (HasEscortState(SMART_ESCORT_PAUSED)) { if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == ESCORT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); me->StopMovingOnCurrentPos(); me->GetMotionMaster()->MoveIdle(); } // Xinef: Can be unset in ProcessEvents else if (HasEscortState(SMART_ESCORT_ESCORTING) && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == ESCORT_MOTION_TYPE) { mWPReached = false; if (mCurrentWPID == GetWPCount()) EndPath(); else if (GetNextWayPoint()) { SetRun(mRun); // xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one if (me->movespline->Finalized()) ResumePath(); } } }
bool UNavigationComponent::FindSimplePathToLocation(const FVector& DestLocation) { bool bPathGenerationSucceeded = false; if (bIsPaused && Path.IsValid() && Path->IsValid() && Path->GetOwner() == NULL && FVector::DistSquared(CurrentGoal, DestLocation) < SMALL_NUMBER) { bPathGenerationSucceeded = ResumePath(); } if (bPathGenerationSucceeded == false) { ResetTransientData(); bPathGenerationSucceeded = GenerateSimplePath(DestLocation); } return bPathGenerationSucceeded; }
bool UNavigationComponent::FindPathToLocation(const FVector& DestLocation, TSharedPtr<const FNavigationQueryFilter> QueryFilter) { bool bPathGenerationSucceeded = false; if (bIsPaused == true && Path.IsValid() && Path->IsValid() && FVector::DistSquared(CurrentGoal, DestLocation) < SMALL_NUMBER) { // path to destination already generated. Use it. if (bDoAsyncPathfinding == true) { FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateUObject(this, &UNavigationComponent::DeferredResumePath) , TEXT("Deferred resume path") , NULL , ENamedThreads::GameThread ); bPathGenerationSucceeded = true; } else { bPathGenerationSucceeded = ResumePath(); } } if (bPathGenerationSucceeded == false) { ResetTransientData(); if (bDoAsyncPathfinding == true) { bPathGenerationSucceeded = AsyncGeneratePathTo(DestLocation, QueryFilter); } else { bPathGenerationSucceeded = GeneratePathTo(DestLocation, QueryFilter); } } return bPathGenerationSucceeded; }
void SmartAI::UpdatePath(const uint32 diff) { if (!HasEscortState(SMART_ESCORT_ESCORTING)) return; if (mEscortInvokerCheckTimer < diff) { if (!IsEscortInvokerInRange()) { StopPath(mDespawnTime, mEscortQuestID, true); } mEscortInvokerCheckTimer = 1000; } else mEscortInvokerCheckTimer -= diff; // handle pause if (HasEscortState(SMART_ESCORT_PAUSED)) { if (mWPPauseTimer < diff) { if (!me->isInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT || mForcedPaused)) { GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, NULL, mLastWP->id, GetScript()->GetPathId()); RemoveEscortState(SMART_ESCORT_PAUSED); if (mForcedPaused)// if paused between 2 wps resend movement { ResumePath(); mWPReached = false; mForcedPaused = false; } if (mLastWPIDReached == SMART_ESCORT_LAST_OOC_POINT) mWPReached = true; } mWPPauseTimer = 0; } else { mWPPauseTimer -= diff; } } if (HasEscortState(SMART_ESCORT_RETURNING)) { if (mWPReached)//reached OOC WP { RemoveEscortState(SMART_ESCORT_RETURNING); if (!HasEscortState(SMART_ESCORT_PAUSED)) ResumePath(); mWPReached = false; } } if (me->isInCombat() || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING)) return; // handle next wp if (mWPReached)//reached WP { mWPReached = false; if (mCurrentWPID == GetWPCount()) { EndPath(); } else { WayPoint* wp = GetNextWayPoint(); if (wp) { SetRun(mRun); me->GetMotionMaster()->MovePoint(wp->id, wp->x, wp->y, wp->z); } } } }
void SmartAI::UpdatePath(const uint32 diff) { if (!HasEscortState(SMART_ESCORT_ESCORTING)) return; if (mEscortInvokerCheckTimer < diff) { // Xinef: Escort failed - no players in range // Xinef: Despawn immediately if (!IsEscortInvokerInRange()) { StopPath(0, mEscortQuestID, true); // Xinef: allow to properly hook out of range despawn action, which in most cases should perform the same operation as dying GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, me); me->DespawnOrUnsummon(1); return; } mEscortInvokerCheckTimer = 1000; } else mEscortInvokerCheckTimer -= diff; // handle pause if (HasEscortState(SMART_ESCORT_PAUSED)) { if (mWPPauseTimer < diff) { if (!me->IsInCombat() && !HasEscortState(SMART_ESCORT_RETURNING) && (mWPReached || mForcedPaused)) { GetScript()->ProcessEventsFor(SMART_EVENT_WAYPOINT_RESUMED, NULL, mCurrentWPID, GetScript()->GetPathId()); RemoveEscortState(SMART_ESCORT_PAUSED); if (mForcedPaused)// if paused between 2 wps resend movement { mWPReached = false; mForcedPaused = false; ResumePath(); } mWPPauseTimer = 0; } } else mWPPauseTimer -= diff; } if (HasEscortState(SMART_ESCORT_RETURNING)) { if (mOOCReached)//reached OOC WP { mOOCReached = false; RemoveEscortState(SMART_ESCORT_RETURNING); if (!HasEscortState(SMART_ESCORT_PAUSED)) ResumePath(); } } if ((me->GetVictim() && me->IsInCombat()) || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING)) return; // handle next wp if (!me->HasUnitState(UNIT_STATE_NOT_MOVE) && me->movespline->Finalized())//reached WP { if (!mWPReached) { ResumePath(); return; } mWPReached = false; if (mCurrentWPID == GetWPCount()) EndPath(); else if (GetNextWayPoint()) { SetRun(mRun); // xinef: if we have reached waypoint, and there is no working spline movement it means our splitted array has ended, make new one if (me->movespline->Finalized()) ResumePath(); } } }
bool UNavigationComponent::FindPathToActor(const AActor* NewGoalActor, TSharedPtr<const FNavigationQueryFilter> QueryFilter, float RepathDistance) { bool bPathGenerationSucceeded = false; if (bIsPaused && NewGoalActor != NULL && GoalActor == NewGoalActor && Path.IsValid() && Path->IsValid()) { RepathDistanceSq = FMath::Square(RepathDistance); OriginalGoalActorLocation = GetCurrentMoveGoal(NewGoalActor, GetOwner()); if (bDoAsyncPathfinding == true) { FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateUObject(this, &UNavigationComponent::DeferredResumePath) , TEXT("Deferred resume path") , NULL , ENamedThreads::GameThread ); bPathGenerationSucceeded = true; } else { bPathGenerationSucceeded = ResumePath(); } } else { if (NewGoalActor != NULL) { const FVector NewGoalActorLocation = GetCurrentMoveGoal(NewGoalActor, GetOwner()); if (bDoAsyncPathfinding == true) { bPathGenerationSucceeded = AsyncGeneratePathTo(NewGoalActorLocation, QueryFilter); } else { bPathGenerationSucceeded = GeneratePathTo(NewGoalActorLocation, QueryFilter); } if (bPathGenerationSucceeded) { // if there's a specific query filter store it StoredQueryFilter = QueryFilter; GoalActor = NewGoalActor; RepathDistanceSq = FMath::Square(RepathDistance); OriginalGoalActorLocation = NewGoalActorLocation; bUseSimplePath = false; if (bDoAsyncPathfinding == false) { // if doing sync pathfinding enabling component's ticking needs to be done now SetComponentTickEnabledAsync(true); } } } if (!bPathGenerationSucceeded) { UE_VLOG(GetOwner(), LogNavigation, Log, TEXT("%s failed to generate path to %s"), *GetNameSafe(GetOwner()), *GetNameSafe(NewGoalActor)); } } if (bPathGenerationSucceeded == false) { ResetTransientData(); } return bPathGenerationSucceeded; }
void UNavigationComponent::DeferredResumePath() { ResumePath(); }