void UGameplayDebuggingControllerComponent::EnableActiveView(EAIDebugDrawDataView::Type View, bool bEnable)
{
	bEnable ? GameplayDebuggerSettings(GetDebuggingReplicator()).SetFlag(View) : GameplayDebuggerSettings(GetDebuggingReplicator()).ClearFlag(View);

	if (GetDebuggingReplicator())
	{
		GetDebuggingReplicator()->ServerReplicateMessage(DebugAITargetActor, bEnable ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, View);
#if WITH_EQS
		if (GetDebuggingReplicator()->GetDebugComponent() && View == EAIDebugDrawDataView::EQS)
		{
			GetDebuggingReplicator()->GetDebugComponent()->EnableClientEQSSceneProxy(IsViewActive(EAIDebugDrawDataView::EQS));
		}
#endif // WITH_EQS
	}
}
void UGameplayDebuggingControllerComponent::ToggleAIDebugView_SetView0()
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	APawn* Pawn = PlayerOwner.IsValid() ? PlayerOwner->GetPawn() : NULL;

	if (PlayerOwner.IsValid() && Pawn && bToolActivated && GetDebuggingReplicator())
	{
		if (UGameplayDebuggingComponent* OwnerComp = GetDebuggingReplicator() ? GetDebuggingReplicator()->GetDebugComponent() : NULL)
		{
			GameplayDebuggerSettings(GetDebuggingReplicator()).DebuggerShowFlags ^= 1 << EAIDebugDrawDataView::NavMesh;

			if (IsViewActive(EAIDebugDrawDataView::NavMesh))
			{
				GetWorld()->GetTimerManager().SetTimer(TimerHandle_UpdateNavMeshTimer, this, &UGameplayDebuggingControllerComponent::UpdateNavMeshTimer, 5.0f, true);
				UpdateNavMeshTimer();

				GetDebuggingReplicator()->ServerReplicateMessage(Pawn, EDebugComponentMessage::ActivateDataView, EAIDebugDrawDataView::NavMesh);
				OwnerComp->MarkRenderStateDirty();
			}
			else
			{
				GetWorld()->GetTimerManager().ClearTimer(TimerHandle_UpdateNavMeshTimer);

				GetDebuggingReplicator()->ServerReplicateMessage(Pawn, EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::NavMesh);
				OwnerComp->ServerDiscardNavmeshData();
				OwnerComp->MarkRenderStateDirty();
			}
		}
	}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void UGameplayDebuggingControllerComponent::OnRegister()
{
	Super::OnRegister();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	BindActivationKeys();
	SetActiveViews(GameplayDebuggerSettings().DebuggerShowFlags);
#endif
}
void UGameplayDebuggingControllerComponent::SetActiveViews(uint32 InActiveViews)
{
	GameplayDebuggerSettings(GetDebuggingReplicator()).DebuggerShowFlags = InActiveViews;

	if (GetDebuggingReplicator())
	{
		for (uint32 Index = 0; Index < EAIDebugDrawDataView::MAX; ++Index)
		{
			EAIDebugDrawDataView::Type CurrentView = (EAIDebugDrawDataView::Type)Index;
			EnableActiveView(CurrentView, IsViewActive(CurrentView));
		}
	}
}
void AGameplayDebuggingReplicator::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (!PropertyChangedEvent.Property)
	{
		return;
	}

	FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);

#define CHECK_AND_UPDATE_FLAGS(__FlagName_) \
	if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, __FlagName_)) \
	{ \
		__FlagName_ ? Settings.SetFlag(EAIDebugDrawDataView::__FlagName_) : Settings.ClearFlag(EAIDebugDrawDataView::__FlagName_); \
		GetDebugComponent()->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::__FlagName_) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::__FlagName_); \
	}else

	CHECK_AND_UPDATE_FLAGS(OverHead)
	CHECK_AND_UPDATE_FLAGS(Basic)
	CHECK_AND_UPDATE_FLAGS(BehaviorTree)
	CHECK_AND_UPDATE_FLAGS(EQS)
	CHECK_AND_UPDATE_FLAGS(Perception)
	CHECK_AND_UPDATE_FLAGS(GameView1)
	CHECK_AND_UPDATE_FLAGS(GameView2)
	CHECK_AND_UPDATE_FLAGS(GameView3)
	CHECK_AND_UPDATE_FLAGS(GameView4)
	CHECK_AND_UPDATE_FLAGS(GameView5) {}

#if WITH_EQS
	if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, EQS))
	{
		GetDebugComponent()->EnableClientEQSSceneProxy(EQS);
		GetDebugComponent()->SetEQSIndex(ActiveEQSIndex);
		GetDebugComponent()->MarkRenderStateDirty();
	}

	if (PropertyChangedEvent.Property->GetFName() == GET_MEMBER_NAME_CHECKED(AGameplayDebuggingReplicator, ActiveEQSIndex))
	{
		GetDebugComponent()->SetEQSIndex(ActiveEQSIndex);
	}
#endif // WITH_EQS
#undef CHECK_AND_UPDATE_FLAGS

#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void AGameplayDebuggingReplicator::EnableDraw(bool bEnable)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	bEnabledDraw = bEnable;

	if (AHUD* const GameHUD = LocalPlayerOwner ? LocalPlayerOwner->GetHUD() : NULL)
	{
		GameHUD->bShowHUD = bEnable ? false : true;
	}
	GEngine->bEnableOnScreenDebugMessages = bEnable ? false : true;

	if (DebugComponent)
	{
		const bool bEnabledEQSView = GameplayDebuggerSettings(this).CheckFlag(EAIDebugDrawDataView::EQS);
		DebugComponent->EnableClientEQSSceneProxy(bEnable && bEnabledEQSView ? true : false);
		DebugComponent->MarkRenderStateDirty();
	}
#endif
}
uint32 UGameplayDebuggingControllerComponent::GetActiveViews()
{
	return GameplayDebuggerSettings(GetDebuggingReplicator()).DebuggerShowFlags;
}
bool UGameplayDebuggingControllerComponent::IsViewActive(EAIDebugDrawDataView::Type View) const
{
	return GameplayDebuggerSettings(GetDebuggingReplicator()).CheckFlag(View);
}
void UGameplayDebuggingControllerComponent::OnRegister()
{
	Super::OnRegister();
	BindActivationKeys();
	SetActiveViews(GameplayDebuggerSettings().DebuggerShowFlags);
}
void AGameplayDebuggingHUDComponent::DrawDebugComponentData(APlayerController* MyPC, class UGameplayDebuggingComponent *DebugComponent)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	AActor* SelectedActor = DebugComponent->GetSelectedActor();
	const bool bDrawFullData = GetDebuggingReplicator()->GetSelectedActorToDebug() == SelectedActor;
	const FVector ScreenLoc = SelectedActor ? ProjectLocation(DefaultContext, SelectedActor->GetActorLocation() + FVector(0.f, 0.f, SelectedActor->GetSimpleCollisionHalfHeight())) : FVector::ZeroVector;

	OverHeadContext = FPrintContext(GEngine->GetSmallFont(), Canvas, ScreenLoc.X, ScreenLoc.Y);
	//DefaultContext.CursorY += 20;
	BlackboardFinishY = 0.0f;

	FGameplayDebuggerSettings DebuggerSettings = GameplayDebuggerSettings(GetDebuggingReplicator());
	bool bForceOverhead = false;
#if !WITH_EDITOR
	bForceOverhead = bDrawFullData;
#endif

	if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::OverHead) || bForceOverhead)
	{
		DrawOverHeadInformation(MyPC, DebugComponent);
	}

	if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::NavMesh))
	{
		DrawNavMeshSnapshot(MyPC, DebugComponent);
	}

	if (SelectedActor && bDrawFullData)
	{
		if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::Basic) /*|| EngineShowFlags.DebugAI*/)
		{
			DrawBasicData(MyPC, DebugComponent);
		}

		if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::BehaviorTree))
		{
			DrawBehaviorTreeData(MyPC, DebugComponent);
		}

		if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::EQS))
		{
			bool bEnabledEnvironmentQueryEd = true;
			if (GConfig)
			{
				GConfig->GetBool(TEXT("EnvironmentQueryEd"), TEXT("EnableEnvironmentQueryEd"), bEnabledEnvironmentQueryEd, GEngineIni);
			}
			if (bEnabledEnvironmentQueryEd)
			{
				DrawEQSData(MyPC, DebugComponent);
			}
		}

		if (DebuggerSettings.CheckFlag(EAIDebugDrawDataView::Perception) /*|| EngineShowFlags.DebugAI*/)
		{
			DrawPerception(MyPC, DebugComponent);
		}
	}

	DrawGameSpecificView(MyPC, DebugComponent);
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void AGameplayDebuggingHUDComponent::DrawMenu(const float X, const float Y, class UGameplayDebuggingComponent* DebugComponent)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	const float OldX = DefaultContext.CursorX;
	const float OldY = DefaultContext.CursorY;

	UGameplayDebuggingControllerComponent*  GDC = GetDebuggingReplicator()->FindComponentByClass<UGameplayDebuggingControllerComponent>();
	if (DefaultContext.Canvas != NULL)
	{
		TArray<FDebugCategoryView> Categories;
		GetKeyboardDesc(Categories);

		UFont* OldFont = DefaultContext.Font;
		DefaultContext.Font = GEngine->GetMediumFont();

		TArray<float> CategoriesWidth;
		CategoriesWidth.AddZeroed(Categories.Num());
		float TotalWidth = 0.0f, MaxHeight = 0.0f;

		FString ActivationKeyDisplayName = TEXT("'");
		FString ActivationKeyName = TEXT("Apostrophe");

		APlayerController* const MyPC = Cast<APlayerController>(PlayerOwner);
		if (GDC)
		{
			ActivationKeyDisplayName = GDC->GetActivationKey().Key.GetDisplayName().ToString();
			ActivationKeyName = GDC->GetActivationKey().Key.GetFName().ToString();
		}

		const FString KeyDesc = ActivationKeyName != ActivationKeyDisplayName ? FString::Printf(TEXT("(%s key)"), *ActivationKeyName) : TEXT("");
		FString HeaderDesc = FString::Printf(TEXT("Tap %s %s to close, use Numpad numbers to toggle categories"), *ActivationKeyDisplayName, *KeyDesc);

		float HeaderWidth = 0.0f;
		CalulateStringSize(DefaultContext, DefaultContext.Font, HeaderDesc, HeaderWidth, MaxHeight);

		for (int32 i = 0; i < Categories.Num(); i++)
		{
			Categories[i].Desc = FString::Printf(TEXT("%d:%s "), i, *Categories[i].Desc);

			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[i].Desc, CategoriesWidth[i], StrHeight);
			TotalWidth += CategoriesWidth[i];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}

		{
			static FString KeyShortcut = GDC->DebugCameraBind.GetInputText().ToString();
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GDC && GDC->GetDebugCameraController().IsValid() ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("Debug Camera"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}
		{
			static FString KeyShortcut = GDC->OnScreenDebugMessagesBind.GetInputText().ToString();
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GEngine && GEngine->bEnableOnScreenDebugMessages ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("DebugMessages"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}
		{
			static FString KeyShortcut = GDC->GameHUDBind.GetInputText().ToString();
			const AHUD* GameHUD = MyPC ? MyPC->GetHUD() : NULL;
			const int32 DebugCameraIndex = Categories.Add(FDebugCategoryView());
			CategoriesWidth.AddZeroed(1);
			Categories[DebugCameraIndex].Desc = FString::Printf(TEXT(" %s[%s]: %s  "), GameHUD && GameHUD->bShowHUD ? TEXT("{Green}") : TEXT("{White}"), *KeyShortcut, TEXT("GameHUD"));
			float StrHeight = 0.0f;
			CalulateStringSize(DefaultContext, DefaultContext.Font, Categories[DebugCameraIndex].Desc, CategoriesWidth[DebugCameraIndex], StrHeight);
			TotalWidth += CategoriesWidth[DebugCameraIndex];
			MaxHeight = FMath::Max(MaxHeight, StrHeight);
		}


		TotalWidth = FMath::Max(TotalWidth, HeaderWidth);

		FCanvasTileItem TileItem(FVector2D(10, 10), GWhiteTexture, FVector2D(TotalWidth + 20, MaxHeight + 20), FColor(0, 0, 0, 20));
		TileItem.BlendMode = SE_BLEND_Translucent;
		DrawItem(DefaultContext, TileItem, MenuStartX, MenuStartY);

		PrintString(DefaultContext, FColorList::LightBlue, HeaderDesc, MenuStartX + 2.f, MenuStartY + 2.f);

		float XPos = MenuStartX + 20.f;
		for (int32 i = 0; i < Categories.Num(); i++)
		{
			const bool bIsActive = GameplayDebuggerSettings(GetDebuggingReplicator()).CheckFlag(Categories[i].View) ? true : false;
			const bool bIsDisabled = Categories[i].View == EAIDebugDrawDataView::NavMesh ? false : (DebugComponent && DebugComponent->GetSelectedActor() ? false: true);

			PrintString(DefaultContext, bIsDisabled ? (bIsActive ? FColorList::DarkGreen  : FColorList::LightGrey) : (bIsActive ? FColorList::Green : FColorList::White), Categories[i].Desc, XPos, MenuStartY + MaxHeight + 2.f);
			XPos += CategoriesWidth[i];
		}
		DefaultContext.Font = OldFont;
	}

	if ((!DebugComponent || !DebugComponent->GetSelectedActor()) && GetWorld()->GetNetMode() == NM_Client)
	{
		PrintString(DefaultContext, "\n{red}No Pawn selected - waiting for data to replicate from server. {green}Press and hold ' to select Pawn \n");
	}

	if (GDC && GDC->GetDebugCameraController().IsValid())
	{
		ADebugCameraController* DebugCamController = GDC->GetDebugCameraController().Get();
		if (DebugCamController != NULL)
		{
			FVector const CamLoc = DebugCamController->PlayerCameraManager->GetCameraLocation();
			FRotator const CamRot = DebugCamController->PlayerCameraManager->GetCameraRotation();

			FString HitString;
			FCollisionQueryParams TraceParams(NAME_None, true, this);
			FHitResult Hit;
			bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, CamLoc, CamRot.Vector() * 100000.f + CamLoc, ECC_Pawn, TraceParams);
			if (bHit && Hit.GetActor() != nullptr)
			{
				HitString = FString::Printf(TEXT("{white}Under cursor: {yellow}'%s'"), *Hit.GetActor()->GetName());
				DrawDebugLine(GetWorld(), Hit.Location, Hit.Location + Hit.Normal*30.f, FColor::White);
			}
			else
			{
				HitString = FString::Printf(TEXT("Not actor under cursor"));
			}

			PrintString(DefaultContext, FColor::White, HitString, MenuStartX, MenuStartY + 40);
		}
	}


	DefaultContext.CursorX = OldX;
	DefaultContext.CursorY = OldY;
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
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
}
AGameplayDebuggingReplicator::AGameplayDebuggingReplicator(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
	, MaxEQSQueries(5)
	, bIsGlobalInWorld(true)
	, LastDrawAtFrame(0)
	, PlayerControllersUpdateDelay(0)
{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		ConstructorHelpers::FObjectFinderOptional<UTexture2D> RedIcon;
		ConstructorHelpers::FObjectFinderOptional<UTexture2D> GreenIcon;

		// both icons are needed to debug AI
		FConstructorStatics()
			: RedIcon(TEXT("/Engine/EngineResources/AICON-Red.AICON-Red"))
			, GreenIcon(TEXT("/Engine/EngineResources/AICON-Green.AICON-Green"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;

	DefaultTexture_Red = ConstructorStatics.RedIcon.Get();
	DefaultTexture_Green = ConstructorStatics.GreenIcon.Get();

	PrimaryActorTick.bCanEverTick = true;
	PrimaryActorTick.bStartWithTickEnabled = false;
	
	USceneComponent* SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
	RootComponent = SceneComponent;

#if WITH_EDITOR
	SetIsTemporarilyHiddenInEditor(true);
#endif
#if WITH_EDITORONLY_DATA
	SetTickableWhenPaused(true);
	SetActorHiddenInGame(false);
	bHiddenEdLevel = true;
	bHiddenEdLayer = true;
	bHiddenEd = true;
	bEditable = false;
#endif

	DebuggerShowFlags =  GameplayDebuggerSettings().DebuggerShowFlags;

	FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);
#define UPDATE_VIEW_PROPS(__FlagName__)  __FlagName__ = Settings.CheckFlag(EAIDebugDrawDataView::__FlagName__);
	UPDATE_VIEW_PROPS(OverHead);
	UPDATE_VIEW_PROPS(Basic);
	UPDATE_VIEW_PROPS(BehaviorTree);
	UPDATE_VIEW_PROPS(EQS);
	UPDATE_VIEW_PROPS(Perception);
	UPDATE_VIEW_PROPS(GameView1);
	UPDATE_VIEW_PROPS(GameView2);
	UPDATE_VIEW_PROPS(GameView3);
	UPDATE_VIEW_PROPS(GameView4);
	UPDATE_VIEW_PROPS(GameView5);
#undef UPDATE_VIEW_PROPS

	EnableEQSOnHUD = true;

	if (!HasAnyFlags(RF_ClassDefaultObject))
	{
		SetActorTickEnabled(true);

		bReplicates = false;
		SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
		SetReplicates(true);

		AGameplayDebuggingReplicator::OnSelectionChangedDelegate.AddUObject(this, &AGameplayDebuggingReplicator::ServerSetActorToDebug);
	}
#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}
void AGameplayDebuggingReplicator::BeginPlay()
{
	Super::BeginPlay();

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if (Role == ROLE_Authority)
	{
		bReplicates = false;
		SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
		SetReplicates(true);

		if (!DebugComponentClass.IsValid() && GetWorld() && GetNetMode() < ENetMode::NM_Client)
		{
			DebugComponentClass = StaticLoadClass(UGameplayDebuggingComponent::StaticClass(), NULL, *DebugComponentClassName, NULL, LOAD_None, NULL);
			if (!DebugComponentClass.IsValid())
			{
				DebugComponentClass = UGameplayDebuggingComponent::StaticClass();
			}
		}
		GetDebugComponent();
	}

	if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
	{
		if (GIsEditor)
		{
			UDebugDrawService::Register(TEXT("DebugAI"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::OnDebugAIDelegate));
		}
		UDebugDrawService::Register(TEXT("Game"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::DrawDebugDataDelegate));

		if (!DebugComponentHUDClass.IsValid())
		{
			DebugComponentHUDClass = StaticLoadClass(AGameplayDebuggingHUDComponent::StaticClass(), NULL, *DebugComponentHUDClassName, NULL, LOAD_None, NULL);
			if (!DebugComponentHUDClass.IsValid())
			{
				DebugComponentHUDClass = AGameplayDebuggingHUDComponent::StaticClass();
			}
		}
	}

#if WITH_EDITOR
	const UEditorEngine* EEngine = Cast<UEditorEngine>(GEngine);
	if (EEngine && (EEngine->bIsSimulatingInEditor || EEngine->EditorWorld) && GetWorld() != EEngine->EditorWorld && !IsGlobalInWorld() && GCurrentLevelEditingViewportClient && GCurrentLevelEditingViewportClient->EngineShowFlags.DebugAI)
	{
		SetIsTemporarilyHiddenInEditor(false);
		SetActorHiddenInGame(false);
		bHiddenEdLevel = false;
		bHiddenEdLayer = false;
		bHiddenEd = false;
		bEditable = true;

		if (DebugComponent)
		{
			DebugComponent->ServerReplicateData(EDebugComponentMessage::ActivateReplication, EAIDebugDrawDataView::Empty);

			FGameplayDebuggerSettings Settings = GameplayDebuggerSettings(this);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::OverHead) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::OverHead);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::Basic) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Basic);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::BehaviorTree) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::BehaviorTree);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::EQS) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::EQS);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::Perception) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Perception);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView1) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView1);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView2) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView2);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView3) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView3);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView4) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView4);
			DebugComponent->ServerReplicateData(Settings.CheckFlag(EAIDebugDrawDataView::GameView5) ? EDebugComponentMessage::ActivateDataView : EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::GameView5);
		}
	}
	else
	{
		SetTickableWhenPaused(true);
		SetIsTemporarilyHiddenInEditor(true);
		SetActorHiddenInGame(false);
		bHiddenEdLevel = true;
		bHiddenEdLayer = true;
		bHiddenEd = true;
		bEditable = false;
		if (DebugComponent)
		{
			DebugComponent->ServerReplicateData(EDebugComponentMessage::DeactivateDataView, EAIDebugDrawDataView::Empty);
		}
	}
#endif

	if (GetWorld() && GetNetMode() != ENetMode::NM_DedicatedServer)
	{
		if (GIsEditor)
		{
			UDebugDrawService::Register(TEXT("DebugAI"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::OnDebugAIDelegate));
		}
		UDebugDrawService::Register(TEXT("Game"), FDebugDrawDelegate::CreateUObject(this, &AGameplayDebuggingReplicator::DrawDebugDataDelegate));

		if (!DebugComponentHUDClass.IsValid())
		{
			DebugComponentHUDClass = StaticLoadClass(AGameplayDebuggingHUDComponent::StaticClass(), NULL, *DebugComponentHUDClassName, NULL, LOAD_None, NULL);
			if (!DebugComponentHUDClass.IsValid())
			{
				DebugComponentHUDClass = AGameplayDebuggingHUDComponent::StaticClass();
			}
		}
	}

	if (bAutoActivate)
	{
		OnRep_AutoActivate();
	}

#endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST)
}