/** Change the Pawn's base. */ void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, bool bNotifyPawn ) { if (NewBaseComponent != MovementBase) { // Verify no recursion. APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL); for( ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) ) { if( Loop == this ) { UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName()); return; } } // Set base. MovementBase = NewBaseComponent; if (Role == ROLE_Authority) { // Update replicated value UE_LOG(LogCharacter, Verbose, TEXT("Setting base on server for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); RelativeMovement.MovementBase = NewBaseComponent; RelativeMovement.bServerHasBaseComponent = (NewBaseComponent != NULL); // Flag whether the server had a non-null base. } else { UE_LOG(LogCharacter, Verbose, TEXT("Setting base on CLIENT for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } // Update relative location/rotation if ( Role == ROLE_Authority || Role == ROLE_AutonomousProxy ) { if (MovementBaseUtility::UseRelativePosition(MovementBase)) { RelativeMovement.Location = GetActorLocation() - MovementBase->GetComponentLocation(); RelativeMovement.Rotation = (FRotationMatrix(GetActorRotation()) * FRotationMatrix(MovementBase->GetComponentRotation()).GetTransposed()).Rotator(); } } // Notify this actor of his new floor. if ( bNotifyPawn ) { BaseChange(); } if (MovementBase && CharacterMovement) { // Update OldBaseLocation/Rotation as those were referring to a different base CharacterMovement->OldBaseLocation = MovementBase->GetComponentLocation(); CharacterMovement->OldBaseRotation = MovementBase->GetComponentRotation(); } } }
void AAIController::SetFocalPoint( FVector FP, bool bOffsetFromBase, uint8 InPriority) { if (InPriority >= FocusInformation.Priorities.Num()) { FocusInformation.Priorities.SetNum(InPriority+1); } FFocusKnowledge::FFocusItem& Focusitem = FocusInformation.Priorities[InPriority]; { AActor* FocalActor = NULL; if (bOffsetFromBase) { APawn *Pawn = GetPawn(); if (Pawn && Pawn->GetMovementBase()) { FocalActor = Pawn->GetMovementBase()->GetOwner(); } } Focusitem.Position.Set( FocalActor, FP ); } Focusitem.Actor = NULL; }
/** Change the Pawn's base. */ void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, const FName InBoneName, bool bNotifyPawn ) { // If NewBaseComponent is null, ignore bone name. const FName BoneName = (NewBaseComponent ? InBoneName : NAME_None); // See what changed. const bool bBaseChanged = (NewBaseComponent != BasedMovement.MovementBase); const bool bBoneChanged = (BoneName != BasedMovement.BoneName); if (bBaseChanged || bBoneChanged) { // Verify no recursion. APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL); for( ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) ) { if( Loop == this ) { UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName()); return; } } // Set base. UPrimitiveComponent* OldBase = BasedMovement.MovementBase; BasedMovement.MovementBase = NewBaseComponent; BasedMovement.BoneName = BoneName; if (CharacterMovement) { if (bBaseChanged) { MovementBaseUtility::RemoveTickDependency(CharacterMovement->PrimaryComponentTick, OldBase); MovementBaseUtility::AddTickDependency(CharacterMovement->PrimaryComponentTick, NewBaseComponent); } if (NewBaseComponent) { // Update OldBaseLocation/Rotation as those were referring to a different base // ... but not when handling replication for proxies (since they are going to copy this data from the replicated values anyway) if (!bInBaseReplication) { CharacterMovement->SaveBaseLocation(); } // Enable pre-cloth tick if we are standing on a physics object, as we need to to use post-physics transforms CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(NewBaseComponent->IsSimulatingPhysics()); } else { BasedMovement.BoneName = NAME_None; // None, regardless of whether user tried to set a bone name, since we have no base component. BasedMovement.bRelativeRotation = false; CharacterMovement->CurrentFloor.Clear(); CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(false); } if (Role == ROLE_Authority || Role == ROLE_AutonomousProxy) { BasedMovement.bServerHasBaseComponent = (BasedMovement.MovementBase != NULL); // Also set on proxies for nicer debugging. UE_LOG(LogCharacter, Verbose, TEXT("Setting base on %s for '%s' to '%s'"), Role == ROLE_Authority ? TEXT("Server") : TEXT("AutoProxy"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } else { UE_LOG(LogCharacter, Verbose, TEXT("Setting base on Client for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } } // Notify this actor of his new floor. if ( bNotifyPawn ) { BaseChange(); } } }
void FGameplayDebuggerCategory_AI::CollectData(APlayerController* OwnerPC, AActor* DebugActor) { APawn* MyPawn = Cast<APawn>(DebugActor); ACharacter* MyChar = Cast<ACharacter>(MyPawn); DataPack.PawnName = MyPawn ? MyPawn->GetHumanReadableName() : FString(TEXT("{red}No selected pawn.")); DataPack.bIsUsingCharacter = (MyChar != nullptr); AAIController* MyController = MyPawn ? Cast<AAIController>(MyPawn->Controller) : nullptr; DataPack.bHasController = (MyController != nullptr); if (MyController) { if (MyController->IsPendingKill() == false) { DataPack.ControllerName = MyController->GetName(); } else { DataPack.ControllerName = TEXT("Controller PENDING KILL"); } } else { DataPack.ControllerName = TEXT("No Controller"); } if (MyPawn && !MyPawn->IsPendingKill()) { UCharacterMovementComponent* CharMovementComp = MyChar ? MyChar->GetCharacterMovement() : nullptr; if (CharMovementComp) { UPrimitiveComponent* FloorComponent = MyPawn->GetMovementBase(); AActor* FloorActor = FloorComponent ? FloorComponent->GetOwner() : nullptr; DataPack.MovementBaseInfo = FloorComponent ? FString::Printf(TEXT("%s.%s"), *GetNameSafe(FloorActor), *FloorComponent->GetName()) : FString(TEXT("None")); DataPack.MovementModeInfo = CharMovementComp->GetMovementName(); } UBehaviorTreeComponent* BehaviorComp = MyController ? Cast<UBehaviorTreeComponent>(MyController->BrainComponent) : nullptr; DataPack.bIsUsingBehaviorTree = (BehaviorComp != nullptr); if (BehaviorComp) { DataPack.CurrentAITask = BehaviorComp->DescribeActiveTasks(); DataPack.CurrentAIState = BehaviorComp->IsRunning() ? TEXT("Running") : BehaviorComp->IsPaused() ? TEXT("Paused") : TEXT("Inactive"); DataPack.CurrentAIAssets = BehaviorComp->DescribeActiveTrees(); } UGameplayTasksComponent* TasksComponent = MyController ? MyController->GetGameplayTasksComponent() : nullptr; DataPack.bIsUsingGameplayTasks = (TasksComponent != nullptr); if (TasksComponent) { for (FConstGameplayTaskIterator It = TasksComponent->GetTickingTaskIterator(); It; ++It) { const UGameplayTask* TaskOb = *It; if (TaskOb) { DataPack.TickingTaskInfo += DescribeTaskHelper(*TaskOb); DataPack.NumTickingTasks++; } } for (FConstGameplayTaskIterator It = TasksComponent->GetPriorityQueueIterator(); It; ++It) { const UGameplayTask* TaskOb = *It; if (TaskOb) { DataPack.TaskQueueInfo += DescribeTaskHelper(*TaskOb); DataPack.NumTasksInQueue++; } } } DataPack.MontageInfo = MyChar ? GetNameSafe(MyChar->GetCurrentMontage()) : FString(); UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(MyPawn->GetWorld()); const ANavigationData* NavData = MyController && NavSys ? NavSys->GetNavDataForProps(MyController->GetNavAgentPropertiesRef()) : nullptr; DataPack.NavDataInfo = NavData ? NavData->GetConfig().Name.ToString() : FString(); CollectPathData(MyController); } else { PathDataPack.PathCorridor.Reset(); PathDataPack.PathPoints.Reset(); } }