void AGameplayDebuggingReplicator::DebugNextPawn(UClass* CompareClass, APawn* CurrentPawn)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	APawn* LastSeen = nullptr;
	APawn* FirstSeen = nullptr;
	// Search through the list looking for the next one of this type
	for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++)
	{
		APawn* IterPawn = *It;
		if (IterPawn->IsA(CompareClass))
		{
			if (LastSeen == CurrentPawn)
			{
				ServerSetActorToDebug(IterPawn);
				return;
			}
			LastSeen = IterPawn;
			if (FirstSeen == nullptr)
			{
				FirstSeen = IterPawn;
			}
		}
	}
	// See if we need to wrap around the list
	if (FirstSeen != nullptr)
	{
		ServerSetActorToDebug(FirstSeen);
	}
#endif
}
void AGameplayDebuggerReplicator::DrawDebugDataDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if ENABLED_GAMEPLAY_DEBUGGER
	if (GetWorld() == nullptr || IsPendingKill() || Canvas == nullptr || Canvas->IsPendingKill())
	{
		return;
	}

	if (!LocalPlayerOwner || !IsActorTickEnabled())
	{
		return;
	}

	if (Canvas->SceneView != nullptr && !Canvas->SceneView->bIsGameView)
	{
		return;
	}

	if (GetWorld()->bPlayersOnly && Role == ROLE_Authority)
	{
		for (FConstPawnIterator Iterator = GetWorld()->GetPawnIterator(); Iterator; ++Iterator)
		{
			AActor* NewTarget = Cast<AActor>(*Iterator);
			if (NewTarget->IsSelected() && GetSelectedActorToDebug() != NewTarget)
			{
				ServerSetActorToDebug(NewTarget);
			}
		}
	}
	DrawDebugData(Canvas, PC);
#endif
}
void AGameplayDebuggerReplicator::OnDebugAIDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if WITH_EDITOR && ENABLED_GAMEPLAY_DEBUGGER
	if (!GIsEditor)
	{
		return;
	}

	if (!LocalPlayerOwner)
	{
		return;
	}

	UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
	if (!EEngine || !EEngine->bIsSimulatingInEditor)
	{
		return;
	}

	if (!Canvas || !Canvas->SceneView || Canvas->SceneView->bIsGameView == false)
	{
		return;
	}

	FEngineShowFlags EngineShowFlags = Canvas && Canvas->SceneView && Canvas->SceneView->Family ? Canvas->SceneView->Family->EngineShowFlags : FEngineShowFlags(GIsEditor ? EShowFlagInitMode::ESFIM_Editor : EShowFlagInitMode::ESFIM_Game);
	if (!EngineShowFlags.DebugAI)
	{
		return;
	}

	EnableDraw(true);
	UWorld* World = GetWorld();
	if (World && Role == ROLE_Authority)
	{
		if (IsActorTickEnabled() == false)
		{
			SetActorTickEnabled(true);
		}

		// looks like Simulate in UE4 Editor - let's find selected Pawn to debug
		AActor* SelectedActor = nullptr;
		for (FSelectionIterator It = EEngine->GetSelectedActorIterator(); It; ++It)
		{
			SelectedActor = Cast<APawn>(*It); //we only work with pawns for now
			if (SelectedActor)
			{
				break;
			}
		}

		if (LastSelectedActorToDebug != SelectedActor)
		{
			MarkComponentsRenderStateDirty();
		}

		ServerSetActorToDebug(SelectedActor);
		DrawDebugData(Canvas, PC, true);
	}
#endif
}
void AGameplayDebuggingReplicator::DebugPrevPawn(UClass* CompareClass, APawn* CurrentPawn)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	APawn* LastSeen = nullptr;
	APawn* PrevSeen = nullptr;
	APawn* FirstSeen = nullptr;
	// Search through the list looking for the prev one of this type
	for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; It++)
	{
		APawn* IterPawn = *It;
		if (IterPawn->IsA(CompareClass))
		{
			if (LastSeen == CurrentPawn && FirstSeen != CurrentPawn)
			{
				ServerSetActorToDebug(PrevSeen);
				return;
			}
			PrevSeen = LastSeen;
			LastSeen = IterPawn;
			if (FirstSeen == nullptr)
			{
				FirstSeen = IterPawn;
				if (CurrentPawn == nullptr)
				{
					ServerSetActorToDebug(FirstSeen);
					return;
				}
			}
		}
	}
	// Wrap from the beginning to the end
	if (FirstSeen == CurrentPawn)
	{
		ServerSetActorToDebug(LastSeen);
	}
	// Handle getting the previous to the end
	else if (LastSeen == CurrentPawn)
	{
		ServerSetActorToDebug(PrevSeen);
	}
#endif
}
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 AGameplayDebuggerReplicator::OnSelectPlayer()
{
#if ENABLED_GAMEPLAY_DEBUGGER
	APlayerController* MyPC = DebugCameraController.IsValid() ? DebugCameraController.Get() : GetLocalPlayerOwner();
	APawn* MyPawn = MyPC ? MyPC->GetPawnOrSpectator() : nullptr;
	if (MyPawn)
	{
		ServerSetActorToDebug(MyPawn);
	}
#endif
}
void AGameplayDebuggingReplicator::ServerReplicateMessage_Implementation(class  AActor* Actor, uint32 InMessage, uint32 DataView)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if ((EDebugComponentMessage::Type)InMessage == EDebugComponentMessage::DeactivateReplilcation)
	{
		ServerSetActorToDebug(NULL);
		MarkComponentsRenderStateDirty();
	}

	if (GetDebugComponent())
	{
		GetDebugComponent()->ServerReplicateData((EDebugComponentMessage::Type)InMessage, (EAIDebugDrawDataView::Type)DataView);
	}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void AGameplayDebuggingReplicator::DrawDebugDataDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (GetWorld() == NULL || IsPendingKill() || Canvas == NULL || Canvas->IsPendingKill())
	{
		return;
	}

	if (!LocalPlayerOwner || IsGlobalInWorld() || !IsDrawEnabled())
	{
		return;
	}

	if (Canvas->SceneView != NULL && !Canvas->SceneView->bIsGameView)
	{
		return;
	}

	if (GFrameNumber == LastDrawAtFrame)
	{
		return;
	}
	LastDrawAtFrame = GFrameNumber;

	const UGameplayDebuggingControllerComponent*  GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
	if (!GDC)
	{
		return;
	}

	if (GetWorld()->bPlayersOnly && Role == ROLE_Authority)
	{
		for (FConstPawnIterator Iterator = GetWorld()->GetPawnIterator(); Iterator; ++Iterator)
		{
			AActor* NewTarget = Cast<AActor>(*Iterator);
			if (NewTarget->IsSelected() && GetSelectedActorToDebug() != NewTarget)
			{
				ServerSetActorToDebug(NewTarget);
			}

			GetDebugComponent()->SetActorToDebug(NewTarget);
			GetDebugComponent()->CollectDataToReplicate(true);
		}
	}

	DrawDebugData(Canvas, PC);
#endif
}
void AGameplayDebuggingReplicator::OnDebugAIDelegate(class UCanvas* Canvas, class APlayerController* PC)
{
#if WITH_EDITOR && !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (!GIsEditor)
	{
		return;
	}

	if (!LocalPlayerOwner || IsGlobalInWorld())
	{
		return;
	}

	UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
	if (GFrameNumber == LastDrawAtFrame || !EEngine || !EEngine->bIsSimulatingInEditor)
	{
		return;
	}

	if (!Canvas || !Canvas->SceneView || Canvas->SceneView->bIsGameView == false)
	{
		return;
	}
	LastDrawAtFrame = GFrameNumber;

	FEngineShowFlags EngineShowFlags = Canvas && Canvas->SceneView && Canvas->SceneView->Family ? Canvas->SceneView->Family->EngineShowFlags : FEngineShowFlags(GIsEditor ? EShowFlagInitMode::ESFIM_Editor : EShowFlagInitMode::ESFIM_Game);
	if (!EngineShowFlags.DebugAI)
	{
		return;
	}

	EnableDraw(true);
	UWorld* World = GetWorld();
	UGameplayDebuggingComponent* DebuggingComponent = GetDebugComponent();
	if (World && DebuggingComponent && DebuggingComponent->GetOwnerRole() == ROLE_Authority)
	{
		UGameplayDebuggingControllerComponent*  GDC = FindComponentByClass<UGameplayDebuggingControllerComponent>();
		TArray<int32> OryginalReplicateViewDataCounters;

		OryginalReplicateViewDataCounters = DebuggingComponent->ReplicateViewDataCounters;
		for (uint32 Index = 0; Index < EAIDebugDrawDataView::MAX; ++Index)
		{
			DebuggingComponent->ReplicateViewDataCounters[Index] = GameplayDebuggerSettings(this).CheckFlag((EAIDebugDrawDataView::Type)Index) ? 1 : 0;
		}

		// looks like Simulate in UE4 Editor - let's find selected Pawn to debug
		AActor* FullSelectedTarget = NULL;
		for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator)
		{
			AActor* NewTarget = Cast<AActor>(*Iterator);

			if (NewTarget->IsSelected() && !FullSelectedTarget)
			{
				FullSelectedTarget = NewTarget;
				continue;
			}

			//We needs to collect data manually in Simulate
			DebuggingComponent->SetActorToDebug(NewTarget);
			DebuggingComponent->CollectDataToReplicate(NewTarget->IsSelected());
			DrawDebugData(Canvas, PC);
		}

		const AActor* OldActor = LastSelectedActorToDebug;
		ServerSetActorToDebug(FullSelectedTarget);
		if (FullSelectedTarget)
		{
			DebuggingComponent->CollectDataToReplicate(true);
			DebuggingComponent->SetEQSIndex(ActiveEQSIndex);
			DrawDebugData(Canvas, PC);
		}

		if (GetSelectedActorToDebug() != OldActor)
		{
			DebuggingComponent->MarkRenderStateDirty();
		}

		DebuggingComponent->ReplicateViewDataCounters = OryginalReplicateViewDataCounters;

	}
#endif
}