Exemplo n.º 1
0
/**
 * Transition from destroying a session to returning to the main menu
 *
 * @param SessionName name of session recently destroyed
 * @param bWasSuccessful was the destroy attempt successful
 */
void UOnlineSessionClient::OnDestroyForMainMenuComplete(FName SessionName, bool bWasSuccessful)
{
	UE_LOG(LogOnline, Verbose, TEXT("OnDestroyForMainMenuComplete %s bSuccess: %d"), *SessionName.ToString(), bWasSuccessful);
	if (SessionInt.IsValid())
	{
		SessionInt->ClearOnDestroySessionCompleteDelegate(OnDestroyForMainMenuCompleteDelegate);
	}	

	APlayerController* PC = GetPlayerController();
	if (PC)
	{
		// Call disconnect to force us back to the menu level
		GEngine->HandleDisconnect(PC->GetWorld(), PC->GetWorld()->GetNetDriver());
	}

	bHandlingDisconnect = false;
}
void AGameplayDebuggerReplicator::SelectTargetToDebug()
{
#if ENABLED_GAMEPLAY_DEBUGGER
	APlayerController* MyPC = DebugCameraController.IsValid() ? DebugCameraController.Get() : GetLocalPlayerOwner();

	if (MyPC)
	{
		float bestAim = 0;
		FVector CamLocation;
		FRotator CamRotation;
		check(MyPC->PlayerCameraManager != nullptr);
		MyPC->PlayerCameraManager->GetCameraViewPoint(CamLocation, CamRotation);
		FVector FireDir = CamRotation.Vector();
		UWorld* World = MyPC->GetWorld();
		check(World);

		APawn* PossibleTarget = nullptr;
		for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator)
		{
			APawn* NewTarget = *Iterator;
			if (NewTarget == nullptr || NewTarget == MyPC->GetPawn()
				|| (NewTarget->PlayerState != nullptr && NewTarget->PlayerState->bIsABot == false)
				|| NewTarget->GetActorEnableCollision() == false)
			{
				continue;
			}

			if (NewTarget != MyPC->GetPawn())
			{
				// look for best controlled pawn target
				const FVector AimDir = NewTarget->GetActorLocation() - CamLocation;
				float FireDist = AimDir.SizeSquared();
				// only find targets which are < 25000 units away
				if (FireDist < 625000000.f)
				{
					FireDist = FMath::Sqrt(FireDist);
					float newAim = FVector::DotProduct(FireDir, AimDir);
					newAim = newAim / FireDist;
					if (newAim > bestAim)
					{
						PossibleTarget = NewTarget;
						bestAim = newAim;
					}
				}
			}
		}

		if (PossibleTarget != nullptr && PossibleTarget != LastSelectedActorToDebug)
		{
			ServerSetActorToDebug(Cast<AActor>(PossibleTarget));
		}
	}
#endif //ENABLED_GAMEPLAY_DEBUGGER
}
void FGameplayDebugger::OnLevelActorAdded(AActor* InActor)
{
	// This function doesn't help much, because it's only called in EDITOR!
	// We need a function that is called in the game!  So instead of creating it automatically, I'm leaving it
	// to be created explicitly by any player controller that needs to create it.
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	APlayerController* PC = Cast<APlayerController>(InActor);
	if (PC && PC->GetNetMode() < ENetMode::NM_Client)
	{
		UWorld* PCWorld = PC->GetWorld();
		if (PCWorld && PCWorld->IsGameWorld())
		{
			CreateGameplayDebuggerForPlayerController(PC);
		}
	}
#endif
}
AVisualLoggerCameraController* AVisualLoggerCameraController::EnableCamera(UWorld* InWorld)
{
	APlayerController* PC = UGameplayStatics::GetPlayerController(InWorld, 0);
	if (PC == NULL || PC->Player == NULL || PC->IsLocalPlayerController() == false
		|| PC->GetWorld() == NULL)
	{
		return NULL;
	}
	
	if (Instance.IsValid() == false)
	{
		// spawn if necessary
		// and ungly @HACK to be able to spawn camera in game world rathen then
		// in editor world (if running PIE). Hate it, but it works, and 
		// this is a debugging tool		
		FActorSpawnParameters SpawnInfo;
		SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
		SpawnInfo.Owner = PC->GetWorldSettings();
		SpawnInfo.Instigator = PC->Instigator;
		Instance = InWorld->SpawnActor<AVisualLoggerCameraController>( SpawnInfo );
		Instance->Player = PC->Player;
	}
	
	if (Instance.IsValid())
	{
		if (Instance.Get() != PC)
		{
			// set up new controller
			Instance->OnActivate(PC);

			// then switch to it
			PC->Player->SwitchController( Instance.Get() );

			Instance->ChangeState(NAME_Default);
			Instance->ChangeState(NAME_Spectating);
		}

		return Instance.Get();
	}

	return NULL;
}
Exemplo n.º 5
0
bool UOnlineSessionClient::HandleDisconnectInternal(UWorld* World, UNetDriver* NetDriver)
{
	APlayerController* PC = GetPlayerController();
	if (PC)
	{
		// This was a disconnect for our active world, we will handle it
		if (PC->GetWorld() == World)
		{
			// Prevent multiple calls to this async flow
			if (!bHandlingDisconnect)
			{
				bHandlingDisconnect = true;
				DestroyExistingSession(GameSessionName, OnDestroyForMainMenuCompleteDelegate);
			}

			return true;
		}
	}

	return false;
}
bool FGameplayDebugger::Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	bool bHandled = false;

	if (FParse::Command(&Cmd, TEXT("RunEQS")) && InWorld)
	{
		APlayerController* MyPC = InWorld->GetGameInstance() ? InWorld->GetGameInstance()->GetFirstLocalPlayerController() : nullptr;
		UAISystem* AISys = UAISystem::GetCurrent(*InWorld);

		UEnvQueryManager* EQS = AISys ? AISys->GetEnvironmentQueryManager() : NULL;
		if (MyPC && EQS)
		{
			AGameplayDebuggingReplicator* DebuggingReplicator = NULL;
			for (TActorIterator<AGameplayDebuggingReplicator> It(InWorld); It; ++It)
			{
				AGameplayDebuggingReplicator* A = *It;
				if (!A->IsPendingKill())
				{
					DebuggingReplicator = A;
					if (!DebuggingReplicator->IsGlobalInWorld() && DebuggingReplicator->GetLocalPlayerOwner() == MyPC)
					{
						break;
					}
				}
			}

			UObject* Target = DebuggingReplicator != NULL ? DebuggingReplicator->GetSelectedActorToDebug() : NULL;
			FString QueryName = FParse::Token(Cmd, 0);
			if (Target)
			{
				AISys->RunEQS(QueryName, Target);
			}
			else
			{
				MyPC->ClientMessage(TEXT("No debugging target to run EQS"));
			}
		}

		return true;
	}


	if (FParse::Command(&Cmd, TEXT("EnableGDT")) == false)
	{
		return false;
	}

	FString UniquePlayerId = FParse::Token(Cmd, 0);
	APlayerController* LocalPC = NULL;
	UWorld* MyWorld = InWorld;

	if (MyWorld == nullptr)
	{
		if (UniquePlayerId.Len() > 0)
		{
			// let's find correct world based on Player Id
			const TIndirectArray<FWorldContext> WorldContexts = GEngine->GetWorldContexts();
			for (auto& Context : WorldContexts)
			{
				if (Context.WorldType != EWorldType::Game && Context.WorldType != EWorldType::PIE)
				{
					continue;
				}

				UWorld *CurrentWorld = Context.World();
				for (FConstPlayerControllerIterator Iterator = CurrentWorld->GetPlayerControllerIterator(); Iterator; ++Iterator)
				{
					APlayerController* PC = *Iterator;
					if (PC && PC->PlayerState->UniqueId.ToString() == UniquePlayerId)
					{
						LocalPC = PC;
						MyWorld = PC->GetWorld();
						break;
					}
				}

				if (LocalPC && MyWorld)
				{
					break;
				}
			}
		}
	}

	if (MyWorld == nullptr)
	{
		return false;
	}

	if (LocalPC == nullptr)
	{
		if (UniquePlayerId.Len() > 0)
		{
			for (FConstPlayerControllerIterator Iterator = MyWorld->GetPlayerControllerIterator(); Iterator; ++Iterator)
			{
				APlayerController* PlayerController = *Iterator;
				UE_LOG(LogGameplayDebugger, Log, TEXT("- Client: %s"), *PlayerController->PlayerState->UniqueId.ToString());
				if (PlayerController && PlayerController->PlayerState->UniqueId.ToString() == UniquePlayerId)
				{
					LocalPC = PlayerController;
					break;
				}
			}
		}

		if (!LocalPC && MyWorld->GetNetMode() != NM_DedicatedServer)
		{
			LocalPC = MyWorld->GetGameInstance() ? MyWorld->GetGameInstance()->GetFirstLocalPlayerController() : nullptr;
		}
	}

	if (LocalPC == nullptr)
	{
		return false;
	}

	if (MyWorld->GetNetMode() == NM_Client)
	{
		AGameplayDebuggingReplicator* Replicator = NULL;
		for (TActorIterator<AGameplayDebuggingReplicator> It(MyWorld); It; ++It)
		{
			Replicator = *It;
			if (Replicator && !Replicator->IsPendingKill())
			{
				APlayerController* PCOwner = Replicator->GetLocalPlayerOwner();
				if (LocalPC == PCOwner)
				{
					break;
				}
			}
			Replicator = NULL;
		}

		if (!Replicator)
		{
			LocalPC->ClientMessage(TEXT("Enabling GameplayDebugger on server, please wait for replicated data..."));
			if (LocalPC->PlayerState)
			{
				const FString ServerCheatString = FString::Printf(TEXT("cheat EnableGDT %s"), *LocalPC->PlayerState->UniqueId.ToString());
				UE_LOG(LogGameplayDebugger, Warning, TEXT("Sending to Server: %s"), *ServerCheatString);
				LocalPC->ConsoleCommand(*ServerCheatString);
				bHandled = true;
			}
		}
		else
		{
			if (Replicator->IsToolCreated() == false)
			{
				Replicator->CreateTool();
			}
			Replicator->EnableTool();
			bHandled = true;
		}
	}
	else
	{
		UE_LOG(LogGameplayDebugger, Warning, TEXT("Got from client: EnableGDT %s"), *UniquePlayerId);
		{
			AGameplayDebuggingReplicator* Replicator = NULL;
			for (TActorIterator<AGameplayDebuggingReplicator> It(MyWorld); It; ++It)
			{
				Replicator = *It;
				if (Replicator && !Replicator->IsPendingKill())
				{
					APlayerController* PCOwner = Replicator->GetLocalPlayerOwner();
					if (LocalPC == PCOwner)
					{
						break;
					}
				}
				Replicator = NULL;
			}

			if (!Replicator)
			{
				CreateGameplayDebuggerForPlayerController(LocalPC);
				for (TActorIterator<AGameplayDebuggingReplicator> It(MyWorld); It; ++It)
				{
					Replicator = *It;
					if (Replicator && !Replicator->IsPendingKill())
					{
						APlayerController* PCOwner = Replicator->GetLocalPlayerOwner();
						if (LocalPC == PCOwner)
						{
							break;
						}
					}
					Replicator = NULL;
				}
			}

			if (MyWorld->GetNetMode() != NM_DedicatedServer)
			{
				if (Replicator && !Replicator->IsToolCreated())
				{
					Replicator->CreateTool();
					Replicator->EnableTool();
					bHandled = true;
				}
			}
			else
			{
				if (Replicator)
				{
					Replicator->ClientAutoActivate();
					bHandled = true;
				}
			}
		}
	}

	return bHandled;
#else
	return false;
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
Exemplo n.º 7
0
/** This will set the StreamingLevels TMap with the current Streaming Level Status and also set which level the player is in **/
void GetLevelStreamingStatus( UWorld* World, TMap<FName,int32>& StreamingLevels, FString& LevelPlayerIsInName )
{
	FWorldContext &Context = GEngine->WorldContextFromWorld(World);

	// Iterate over the world info's level streaming objects to find and see whether levels are loaded, visible or neither.
	for( int32 LevelIndex=0; LevelIndex<World->StreamingLevels.Num(); LevelIndex++ )
	{
		ULevelStreaming* LevelStreaming = World->StreamingLevels[LevelIndex];

		if( LevelStreaming 
			&&  LevelStreaming->PackageName != NAME_None 
			&&	LevelStreaming->PackageName != World->GetOutermost()->GetFName() )
		{
			ULevel* Level = LevelStreaming->GetLoadedLevel();
			if( Level != NULL )
			{
				if( World->ContainsLevel( Level ) == true )
				{
					if( World->CurrentLevelPendingVisibility == Level )
					{
						StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_MakingVisible );
					}
					else
					{
						StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_Visible );
					}
				}
				else
				{
					StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_Loaded );
				}
			}
			else
			{
				// See whether the level's world object is still around.
				UPackage* LevelPackage	= Cast<UPackage>(StaticFindObjectFast( UPackage::StaticClass(), NULL, LevelStreaming->PackageName ));
				UWorld*	  LevelWorld	= NULL;
				if( LevelPackage )
				{
					LevelWorld = UWorld::FindWorldInPackage(LevelPackage);
				}

				if( LevelWorld )
				{
					StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_UnloadedButStillAround );
				}
				else if( GetAsyncLoadPercentage( *LevelStreaming->PackageName.ToString() ) >= 0 )
				{
					StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_Loading );
				}
				else
				{
					StreamingLevels.Add( LevelStreaming->PackageName, LEVEL_Unloaded );
				}
			}
		}
	}

	
	// toss in the levels being loaded by PrepareMapChange
	for( int32 LevelIndex=0; LevelIndex < Context.LevelsToLoadForPendingMapChange.Num(); LevelIndex++ )
	{
		const FName LevelName = Context.LevelsToLoadForPendingMapChange[LevelIndex];
		StreamingLevels.Add(LevelName, LEVEL_Preloading);
	}


	ULevel* LevelPlayerIsIn = NULL;

	for( FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator )
	{
		APlayerController* PlayerController = *Iterator;

		if( PlayerController->GetPawn() != NULL )
		{
			// need to do a trace down here
			//TraceActor = Trace( out_HitLocation, out_HitNormal, TraceDest, TraceStart, false, TraceExtent, HitInfo, true );
			FHitResult Hit(1.f);

			// this will not work for flying around :-(
			static FName NAME_FindLevel = FName(TEXT("FindLevel"), true);			
			PlayerController->GetWorld()->LineTraceSingle(Hit,PlayerController->GetPawn()->GetActorLocation(), (PlayerController->GetPawn()->GetActorLocation()-FVector(0.f, 0.f, 256.f)), FCollisionQueryParams(NAME_FindLevel, true, PlayerController->GetPawn()), FCollisionObjectQueryParams(ECC_WorldStatic));

			/** @todo UE4 FIXME
			if( Hit.Level != NULL )
			{
				LevelPlayerIsIn = Hit.Level;
			}
			else 
			*/
			if( Hit.GetActor() != NULL )
			{
				LevelPlayerIsIn = Hit.GetActor()->GetLevel();
			}
			else if( Hit.Component != NULL && Hit.Component->GetOwner() != NULL )
			{
				AActor* Owner = Hit.Component->GetOwner();
				if (Owner)
				{
					LevelPlayerIsIn = Owner->GetLevel();
				}
				else
				{
					// This happens for BSP where the ModelComponent's outer is the level
					LevelPlayerIsIn = Hit.Component->GetTypedOuter<ULevel>();
				}
			}
		}
	}

	// this no longer seems to be getting the correct level name :-(
	LevelPlayerIsInName = LevelPlayerIsIn != NULL ? LevelPlayerIsIn->GetOutermost()->GetName() : TEXT("None");
}
Exemplo n.º 8
0
/**
 * Exec handler, parsing the passed in command
 *
 * @param InWorld World Context
 * @param Cmd	Command to parse
 * @param Ar	output device used for logging
 */
bool FDebugToolExec::Exec( UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar )
{
	// these commands are only allowed in standalone games
#if UE_BUILD_SHIPPING || UE_BUILD_TEST
	if (GEngine->GetNetMode(InWorld) != NM_Standalone || (GEngine->GetWorldContextFromWorldChecked(InWorld).PendingNetGame != NULL))
	{
		return 0;
	}
	// Edits the class defaults.
	else
#endif
	if( FParse::Command(&Cmd,TEXT("EDITDEFAULT")) )
	{
		// not allowed in the editor as this command can have far reaching effects such as impacting serialization
		if (!GIsEditor)
		{
			UClass* Class = NULL;
			if( ParseObject<UClass>( Cmd, TEXT("CLASS="), Class, ANY_PACKAGE ) == false )
			{
				TCHAR ClassName[256];
				if ( FParse::Token(Cmd,ClassName,ARRAY_COUNT(ClassName), 1) )
				{
					Class = FindObject<UClass>( ANY_PACKAGE, ClassName);
				}
			}

			if (Class)
			{
				EditObject(Class->GetDefaultObject(), true);
			}
			else
			{
				Ar.Logf( TEXT("Missing class") );
			}
		}
		return 1;
	}
	else if (FParse::Command(&Cmd,TEXT("EDITOBJECT")))
	{
		UClass* searchClass = NULL;
		UObject* foundObj = NULL;
		// Search by class.
		if (ParseObject<UClass>(Cmd, TEXT("CLASS="), searchClass, ANY_PACKAGE))
		{
			// pick the first valid object
			for (FObjectIterator It(searchClass); It && foundObj == NULL; ++It) 
			{
				if (!It->IsPendingKill() && !It->IsTemplate())
				{
					foundObj = *It;
				}
			}
		}
		// Search by name.
		else
		{
			FName searchName;
			FString SearchPathName;
			if ( FParse::Value(Cmd, TEXT("NAME="), searchName) )
			{
				// Look for actor by name.
				for( TObjectIterator<UObject> It; It && foundObj == NULL; ++It )
				{
					if (It->GetFName() == searchName) 
					{
						foundObj = *It;
					}
				}
			}
			else if ( FParse::Token(Cmd,SearchPathName, true) )
			{
				foundObj = FindObject<UObject>(ANY_PACKAGE,*SearchPathName);
			}
		}

		// Bring up an property editing window for the found object.
		if (foundObj != NULL)
		{
			// not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization
			if (!GIsEditor || ((!foundObj->IsTemplate() && (foundObj->GetOutermost()->PackageFlags & PKG_PlayInEditor))))
			{
				EditObject(foundObj, true);
			}
		}
		else
		{
			Ar.Logf(TEXT("Target not found"));
		}
		return 1;
	}
	else if (FParse::Command(&Cmd,TEXT("EDITARCHETYPE")))
	{
		UObject* foundObj = NULL;
		// require fully qualified path name
		FString SearchPathName;
		if (FParse::Token(Cmd, SearchPathName, true))
		{
			foundObj = FindObject<UObject>(ANY_PACKAGE,*SearchPathName);
		}

		// Bring up an property editing window for the found object.
		if (foundObj != NULL)
		{
			// not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization
			if (!GIsEditor || ((!foundObj->IsTemplate() && (foundObj->GetOutermost()->PackageFlags & PKG_PlayInEditor))))
			{
				EditObject(foundObj, false);
			}
		}
		else
		{
			Ar.Logf(TEXT("Target not found"));
		}
		return 1;
	}
	// Edits an objects properties or copies them to the clipboard.
	else if( FParse::Command(&Cmd,TEXT("EDITACTOR")) )
	{
		UClass*		Class = NULL;
		AActor*		Found = NULL;

		if (FParse::Command(&Cmd, TEXT("TRACE")))
		{
			APlayerController* PlayerController = InWorld->GetFirstPlayerController();
			if (PlayerController != NULL)
			{
				// Do a trace in the player's facing direction and edit anything that's hit.
				FVector PlayerLocation;
				FRotator PlayerRotation;
				PlayerController->GetPlayerViewPoint(PlayerLocation, PlayerRotation);
				FHitResult Hit(1.0f);
				PlayerController->GetWorld()->LineTraceSingle(Hit, PlayerLocation, PlayerLocation + PlayerRotation.Vector() * 10000.f, ECC_Pawn, FCollisionQueryParams(NAME_None, true, PlayerController->GetPawn()));
				Found = Hit.GetActor();
			}
		}
		// Search by class.
		else if( ParseObject<UClass>( Cmd, TEXT("CLASS="), Class, ANY_PACKAGE ) && Class->IsChildOf(AActor::StaticClass()) )
		{
			UGameEngine* GameEngine = Cast<UGameEngine>(GEngine);
			
			// Look for the closest actor of this class to the player.
			FVector PlayerLocation(0.0f);
			APlayerController* PlayerController = InWorld->GetFirstPlayerController();
			if (PlayerController != NULL)
			{
				FRotator DummyRotation;
				PlayerController->GetPlayerViewPoint(PlayerLocation, DummyRotation);
			}

			float   MinDist = FLT_MAX;
			for( TActorIterator<AActor> It(InWorld, Class); It; ++It )
			{
				if ( !It->IsPendingKill() )
				{
					float const Dist = (PlayerController && It->GetRootComponent()) ? FVector::Dist(It->GetActorLocation(), PlayerLocation) : 0.f;
					if (Dist < MinDist)
					{
						MinDist = Dist;
						Found   = *It;
					}
				}
			}
		}
		// Search by name.
		else
		{
			FName ActorName;
			if( FParse::Value( Cmd, TEXT("NAME="), ActorName ) )
			{
				// Look for actor by name.
				for( FActorIterator It(InWorld); It; ++It )
				{
					if( It->GetFName() == ActorName )
					{
						Found = *It;
						break;
					}
				}
			}
		}

		// Bring up an property editing window for the found object.
		if( Found )
		{
			// not allowed in the editor unless it is a PIE object as this command can have far reaching effects such as impacting serialization
			if (!GIsEditor || ((!Found->IsTemplate() && (Found->GetOutermost()->PackageFlags & PKG_PlayInEditor))))
			{
				EditObject(Found, true);
			}
		}
		else
		{
			Ar.Logf( TEXT("Target not found") );
		}

		return 1;
	}
	else
	{
		return 0;
	}
}
void UGameplayDebuggingComponent::SelectTargetToDebug()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
    AGameplayDebuggingReplicator* Replicator = Cast<AGameplayDebuggingReplicator>(GetOwner());
    APlayerController* MyPC = Replicator->GetLocalPlayerOwner();

    if (MyPC )
    {
        APawn* BestTarget = NULL;
        if (MyPC->GetViewTarget() != NULL && MyPC->GetViewTarget() != MyPC->GetPawn())
        {
            BestTarget = Cast<APawn>(MyPC->GetViewTarget());
            if (BestTarget && ((BestTarget->PlayerState != NULL && BestTarget->PlayerState->bIsABot == false) || BestTarget->GetActorEnableCollision() == false))
            {
                BestTarget = NULL;
            }
        }

        float bestAim = 0.f;
        FVector CamLocation;
        FRotator CamRotation;
        check(MyPC->PlayerCameraManager != NULL);
        MyPC->PlayerCameraManager->GetCameraViewPoint(CamLocation, CamRotation);
        FVector FireDir = CamRotation.Vector();
        UWorld* World = MyPC->GetWorld();
        check( World );

        APawn* PossibleTarget = NULL;
        for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator )
        {
            APawn* NewTarget = *Iterator;
            if (NewTarget == NULL || NewTarget == MyPC->GetPawn()
                    || (NewTarget->PlayerState != NULL && NewTarget->PlayerState->bIsABot == false)
                    || NewTarget->GetActorEnableCollision() == false)
            {
                continue;
            }

            if (BestTarget == NULL && (NewTarget != MyPC->GetPawn()))
            {
                // look for best controlled pawn target
                const FVector AimDir = NewTarget->GetActorLocation() - CamLocation;
                float FireDist = AimDir.SizeSquared();
                // only find targets which are < 25000 units away
                if (FireDist < 625000000.f)
                {
                    FireDist = FMath::Sqrt(FireDist);
                    float newAim = FireDir | AimDir;
                    newAim = newAim/FireDist;
                    if (newAim > bestAim)
                    {
                        PossibleTarget = NewTarget;
                        bestAim = newAim;
                    }
                }
            }
        }

        BestTarget = BestTarget == NULL ? PossibleTarget : BestTarget;
        if (BestTarget != NULL && BestTarget != GetSelectedActor())
        {
            if (AGameplayDebuggingReplicator* Replicator = Cast<AGameplayDebuggingReplicator>(GetOwner()))
            {
                Replicator->SetActorToDebug(Cast<AActor>(BestTarget));
            }

            //always update component for best target
            SetActorToDebug(Cast<AActor>(BestTarget));
            ServerReplicateData(EDebugComponentMessage::ActivateReplication, EAIDebugDrawDataView::Empty);
        }
    }
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}