Replace CogAbilityCheat window with CogEngineCheat window

CogEngineCheat window relies on an Execution to execute the cheat which can be extended. One implementation is implemented in CogAbility which applies an effect on the selected target (same logic as the previous CogAbilityCheat window)
This commit is contained in:
Arnaud Jamin
2025-01-13 03:06:41 -05:00
parent c3100d59b5
commit a05d8cc9a4
14 changed files with 828 additions and 4 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
#include "CogEngineDataAsset.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogEngineCheat_Execution::Execute_Implementation(const AActor* Instigator, const TArray<AActor*>& Targets) const
{
}
//--------------------------------------------------------------------------------------------------------------------------
ECogEngineCheat_ActiveState UCogEngineCheat_Execution::IsActiveOnTargets_Implementation(const TArray<AActor*>& Targets) const
{
return ECogEngineCheat_ActiveState::Inactive;
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogEngineCheat_Execution::GetColor(const FCogWindow& InCallingWindow, FLinearColor& OutColor) const
{
return false;
}
@@ -220,3 +220,26 @@ void ACogEngineReplicator::Server_DeleteActor_Implementation(AActor* Actor)
#endif // !UE_BUILD_SHIPPING
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogEngineReplicator::Server_ApplyCheat_Implementation(const AActor* CheatInstigator, const TArray<AActor*>& Targets, const FCogEngineCheat& Cheat) const
{
if (Cheat.Execution == nullptr)
{
return;
}
Cheat.Execution->Execute(CheatInstigator, Targets);
}
//--------------------------------------------------------------------------------------------------------------------------
ECogEngineCheat_ActiveState ACogEngineReplicator::IsCheatActiveOnTargets(const TArray<AActor*>& Targets, const FCogEngineCheat& Cheat)
{
if (Cheat.Execution == nullptr)
{
return ECogEngineCheat_ActiveState::Inactive;
}
return Cheat.Execution->IsActiveOnTargets(Targets);
}
@@ -0,0 +1,485 @@
#include "CogEngineWindow_Cheats.h"
#include "CogEngineDataAsset.h"
#include "CogEngineReplicator.h"
#include "CogCommonAllegianceActorInterface.h"
#include "CogImguiHelper.h"
#include "CogWindowConsoleCommandManager.h"
#include "CogWindowWidgets.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
#include "imgui.h"
#include "imgui_internal.h"
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::RenderHelp()
{
ImGui::Text(
"This window can be used to apply cheats to the selected actor (by default). "
"The cheats can be configured in the '%s' data asset. "
"When clicking a cheat button, press:\n"
" [CTRL] to apply the cheat to controlled actor\n"
" [ALT] to apply the cheat to the allies of the selected actor\n"
" [SHIFT] to apply the cheat to the enemies of the selected actor\n"
, TCHAR_TO_ANSI(*GetNameSafe(Asset.Get()))
);
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::Initialize()
{
Super::Initialize();
bHasMenu = true;
Asset = GetAsset<UCogEngineDataAsset>();
Config = GetConfig<UCogEngineConfig_Cheats>();
FCogWindowConsoleCommandManager::RegisterWorldConsoleCommand(
TEXT("Cog.Cheat"),
TEXT("Apply a cheat to the selection. Cog.Cheat <CheatName> -Allies -Enemies -Controlled"),
GetWorld(),
FCogWindowConsoleCommandDelegate::CreateLambda([this](const TArray<FString>& InArgs, UWorld* InWorld)
{
if (InArgs.Num() > 0)
{
if (const FCogEngineCheat* cheat = FindCheatByName(InArgs[0], false))
{
const bool ApplyToEnemies = InArgs.Contains("-Enemies");
const bool ApplyToAllies = InArgs.Contains("-Allies");
const bool ApplyToControlled = InArgs.Contains("-Controlled");
RequestCheat(GetLocalPlayerPawn(), GetSelection(), *cheat, ApplyToEnemies, ApplyToAllies, ApplyToControlled);
}
else
{
UE_LOG(LogCogImGui, Warning, TEXT("Cog.Cheat %s | Cheat not found"), *InArgs[0]);
}
}
}));
for (const FCogEngineCheatCategory& CheatCategory : Asset->CheatCategories)
{
for (const FCogEngineCheat& Cheat : CheatCategory.PersistentEffects)
{
UpdateCheatColor(Cheat);
}
for (const FCogEngineCheat& Cheat : CheatCategory.InstantEffects)
{
UpdateCheatColor(Cheat);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::UpdateCheatColor(const FCogEngineCheat& Cheat) const
{
FLinearColor CustomColor;
if (Cheat.Execution != nullptr && Cheat.Execution->GetColor(*this, CustomColor))
{
Cheat.CustomColor = CustomColor;
}
else
{
Cheat.CustomColor = Cheat.Color;
}
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::ResetConfig()
{
Super::ResetConfig();
Config->Reset();
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::GameTick(float DeltaTime)
{
Super::GameTick(DeltaTime);
TryReapplyCheats();
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::TryReapplyCheats()
{
if (Config == nullptr)
{ return; }
if (bHasReappliedCheats)
{ return; }
if (Config->bReapplyCheatsBetweenPlays == false)
{ return; }
static int32 IsFirstLaunch = true;
if (IsFirstLaunch && Config->bReapplyCheatsBetweenLaunches == false)
{ return; }
IsFirstLaunch = false;
if (Asset == nullptr)
{ return; }
APawn* ControlledActor = GetLocalPlayerPawn();
if (ControlledActor == nullptr)
{ return; }
const ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*GetWorld());
if (Replicator == nullptr)
{ return; }
TArray<AActor*> Targets { ControlledActor };
for (int32 i = Config->AppliedCheats.Num() - 1; i >= 0; i--)
{
if (const FCogEngineCheat* Cheat = FindCheatByName(Config->AppliedCheats[i], true))
{
Replicator->Server_ApplyCheat(ControlledActor, Targets, *Cheat);
}
else
{
//-----------------------------------------------------
// This cheat doesn't exist anymore. We can remove it.
//-----------------------------------------------------
Config->AppliedCheats.RemoveAt(i);
}
}
bHasReappliedCheats = true;
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogEngineWindow_Cheats::DrawTable()
{
const bool Open = ImGui::BeginTable("Cheats", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_NoBordersInBodyUntilResize);
ImGui::TableSetupColumn("Toggle", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Instant", ImGuiTableColumnFlags_WidthStretch);
return Open;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::RenderContent()
{
Super::RenderContent();
if (Config == nullptr)
{
ImGui::TextDisabled("Invalid Config");
return;
}
AActor* SelectedActor = GetSelection();
if (SelectedActor == nullptr)
{
ImGui::TextDisabled("Invalid Selection");
return;
}
if (Asset == nullptr)
{
ImGui::TextDisabled("Invalid Asset");
return;
}
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
ImGui::Checkbox("Group By Category", &Config->bGroupByCategories);
ImGui::Checkbox("Use Two Columns", &Config->bUseTwoColumns);
ImGui::Separator();
ImGui::Checkbox("Reapply Cheats Between Plays", &Config->bReapplyCheatsBetweenPlays);
if (Config->bReapplyCheatsBetweenPlays == false)
{
ImGui::BeginDisabled();
}
ImGui::Checkbox("Reapply Cheats Between Launches", &Config->bReapplyCheatsBetweenLaunches);
if (Config->bReapplyCheatsBetweenPlays == false)
{
ImGui::EndDisabled();
}
ImGui::Separator();
if (ImGui::MenuItem("Reset Settings"))
{
ResetConfig();
}
ImGui::EndMenu();
}
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 7);
FString CategoryPreview;
if (Config->SelectedCategories.Num() == 0)
{
CategoryPreview = "None";
}
else if (Config->SelectedCategories.Num() == 1)
{
CategoryPreview = *Config->SelectedCategories.CreateIterator();
}
else
{
CategoryPreview = "Multiple";
}
const auto CategoryPreviewStr = StringCast<ANSICHAR>(*CategoryPreview);
if (ImGui::BeginCombo("##Categories", CategoryPreviewStr.Get()))
{
for (const FCogEngineCheatCategory& CheatCategory : Asset->CheatCategories)
{
const auto CategoryStr = StringCast<ANSICHAR>(*CheatCategory.Name);
bool IsSelected = Config->SelectedCategories.Contains(CheatCategory.Name);
if (ImGui::Checkbox(CategoryStr.Get(), &IsSelected))
{
if (IsSelected)
{
Config->SelectedCategories.Add(CheatCategory.Name);
}
else
{
Config->SelectedCategories.Remove(CheatCategory.Name);
}
}
}
ImGui::EndCombo();
}
FCogWindowWidgets::SearchBar(Filter);
ImGui::EndMenuBar();
}
APawn* ControlledActor = GetLocalPlayerPawn();
bool OpenTable = false;
if (Config->bGroupByCategories == false && Config->bUseTwoColumns)
{
OpenTable = DrawTable();
}
for (const FCogEngineCheatCategory& CheatCategory : Asset->CheatCategories)
{
const auto CategoryStr = StringCast<ANSICHAR>(*CheatCategory.Name);
if (Config->SelectedCategories.Num() != 0 && Config->SelectedCategories.Contains(CheatCategory.Name) == false)
{ continue; }
bool Open = true;
if (Config->bGroupByCategories)
{
ImGui::PushStyleColor(ImGuiCol_Header, IM_COL32(66, 66, 66, 79));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, IM_COL32(62, 62, 62, 204));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, IM_COL32(86, 86, 86, 255));
Open = ImGui::CollapsingHeader(CategoryStr.Get(), ImGuiTreeNodeFlags_DefaultOpen);
ImGui::PopStyleColor(3);
if (Open && Config->bUseTwoColumns)
{
DrawTable();
}
}
if (Open)
{
if (Config->bUseTwoColumns)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
}
int Index = 0;
for (const FCogEngineCheat& Cheat : CheatCategory.PersistentEffects)
{
AddCheat(Index, ControlledActor, SelectedActor, Cheat, true);
Index++;
}
//----------------------------------------------------------------------------
// Update the config of applied cheat to reapply them on the next launch.
// We do not update them only when the user input is pressed because
// the state of the cheat is lagging when connected to a server.
// So we check if the array should be updated all the time.
//----------------------------------------------------------------------------
if (SelectedActor == ControlledActor)
{
for (const FCogEngineCheat& Cheat : CheatCategory.PersistentEffects)
{
TArray<AActor*> Targets = { SelectedActor };
if (ACogEngineReplicator::IsCheatActiveOnTargets(Targets, Cheat) == ECogEngineCheat_ActiveState::Active)
{
Config->AppliedCheats.AddUnique(Cheat.Name);
}
else
{
Config->AppliedCheats.Remove(Cheat.Name);
}
}
}
ImGui::TableNextColumn();
Index = 0;
for (const FCogEngineCheat& Cheat : CheatCategory.InstantEffects)
{
AddCheat(Index, ControlledActor, SelectedActor, Cheat, false);
Index++;
}
if (Config->bGroupByCategories && Config->bUseTwoColumns)
{
ImGui::EndTable();
}
}
}
if (OpenTable)
{
ImGui::EndTable();
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool FCogEngineWindow_Cheats::AddCheat(const int32 Index, AActor* ControlledActor, AActor* SelectedActor, const FCogEngineCheat& Cheat, bool IsPersistent)
{
const auto CheatName = StringCast<ANSICHAR>(*Cheat.Name);
if (Filter.PassFilter(CheatName.Get()) == false)
{ return false; }
ImGui::PushID(Index);
FCogWindowWidgets::PushBackColor(FCogImguiHelper::ToImVec4(Cheat.CustomColor));
const bool IsShiftDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Shift) != 0;
const bool IsAltDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Alt) != 0;
const bool IsControlDown = (ImGui::GetCurrentContext()->IO.KeyMods & ImGuiMod_Ctrl) != 0;
bool bIsPressed = false;
if (IsPersistent)
{
TArray<AActor*> Targets = { SelectedActor };
bool isEnabled = ACogEngineReplicator::IsCheatActiveOnTargets(Targets, Cheat) == ECogEngineCheat_ActiveState::Active;
if (ImGui::Checkbox(CheatName.Get(), &isEnabled))
{
RequestCheat(ControlledActor, SelectedActor, Cheat, IsShiftDown, IsAltDown, IsControlDown);
bIsPressed = true;
}
}
else
{
if (ImGui::Button(CheatName.Get(), ImVec2(-1, 0)))
{
RequestCheat(ControlledActor, SelectedActor, Cheat, IsShiftDown, IsAltDown, IsControlDown);
bIsPressed = true;
}
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsShiftDown || IsAltDown || IsControlDown ? 0.5f : 1.0f), "On Selection");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsShiftDown ? 1.0f : 0.5f), "On Enemies [SHIFT]");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsAltDown ? 1.0f : 0.5f), "On Allies [ALT]");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, IsControlDown ? 1.0f : 0.5f), "On Controlled [CTRL]");
ImGui::EndTooltip();
}
FCogWindowWidgets::PopBackColor();
ImGui::PopID();
return bIsPressed;
}
//--------------------------------------------------------------------------------------------------------------------------
void FCogEngineWindow_Cheats::RequestCheat(AActor* ControlledActor, AActor* SelectedActor, const FCogEngineCheat& Cheat, bool ApplyToEnemies, bool ApplyToAllies, bool ApplyToControlled)
{
TArray<AActor*> Actors;
if (ApplyToControlled)
{
Actors.Add(ControlledActor);
}
if (ApplyToEnemies || ApplyToAllies)
{
for (TActorIterator<ACharacter> It(GetWorld(), ACharacter::StaticClass()); It; ++It)
{
if (AActor* OtherActor = *It)
{
ECogCommonAllegiance Allegiance = ECogCommonAllegiance::Enemy;
if (ICogCommonAllegianceActorInterface* AllegianceInterface = Cast<ICogCommonAllegianceActorInterface>(OtherActor))
{
Allegiance = AllegianceInterface->GetAllegianceWithOtherActor(ControlledActor);
}
if ((ApplyToEnemies && (Allegiance == ECogCommonAllegiance::Enemy))
|| (ApplyToAllies && (Allegiance == ECogCommonAllegiance::Friendly)))
{
Actors.Add(OtherActor);
}
}
}
}
if ((ApplyToControlled || ApplyToEnemies || ApplyToAllies) == false)
{
Actors.Add(SelectedActor);
}
if (ACogEngineReplicator* Replicator = ACogEngineReplicator::GetLocalReplicator(*GetWorld()))
{
Replicator->Server_ApplyCheat(ControlledActor, Actors, Cheat);
}
else
{
UE_LOG(LogCogImGui, Warning, TEXT("FCogAbilityWindow_Cheats::RequestCheat | Replicator not found"));
}
}
//--------------------------------------------------------------------------------------------------------------------------
const FCogEngineCheat* FCogEngineWindow_Cheats::FindCheatByName(const FString& CheatName, const bool OnlyPersistentCheats)
{
for (const FCogEngineCheatCategory& CheatCategory : Asset->CheatCategories)
{
for (const FCogEngineCheat& Cheat : CheatCategory.PersistentEffects)
{
if (Cheat.Name == CheatName)
{
return &Cheat;
}
}
if (OnlyPersistentCheats)
{
continue;
}
for (const FCogEngineCheat& Cheat : CheatCategory.InstantEffects)
{
if (Cheat.Name == CheatName)
{
return &Cheat;
}
}
}
return nullptr;
}
@@ -5,6 +5,68 @@
#include "Engine/EngineTypes.h"
#include "CogEngineDataAsset.generated.h"
class FCogWindow;
//--------------------------------------------------------------------------------------------------------------------------
UENUM(BlueprintType)
enum class ECogEngineCheat_ActiveState : uint8
{
Inactive,
Partial,
Active,
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(BlueprintType, Abstract, Const, DefaultToInstanced, EditInlineNew, CollapseCategories)
class COGENGINE_API UCogEngineCheat_Execution
: public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent)
void Execute(const AActor* Instigator, const TArray<AActor*>& Targets) const;
UFUNCTION(BlueprintNativeEvent)
ECogEngineCheat_ActiveState IsActiveOnTargets(const TArray<AActor*>& Targets) const;
virtual bool GetColor(const FCogWindow& InCallingWindow, FLinearColor& OutColor) const;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGENGINE_API FCogEngineCheat
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
FString Name;
UPROPERTY(EditAnywhere, Instanced)
TObjectPtr<UCogEngineCheat_Execution> Execution;
UPROPERTY(EditAnywhere)
FLinearColor Color = FLinearColor::White;
mutable FLinearColor CustomColor = FLinearColor::White;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGENGINE_API FCogEngineCheatCategory
{
GENERATED_BODY()
UPROPERTY(Category = "Cheats", EditAnywhere)
FString Name;
UPROPERTY(Category = "Cheats", EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogEngineCheat> PersistentEffects;
UPROPERTY(Category = "Cheats", EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogEngineCheat> InstantEffects;
};
//--------------------------------------------------------------------------------------------------------------------------
USTRUCT()
struct COGENGINE_API FCogEngineSpawnEntry
@@ -44,6 +106,9 @@ public:
UCogEngineDataAsset() {}
UPROPERTY(Category = "Cheats", EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogEngineCheatCategory> CheatCategories;
UPROPERTY(Category = "Spawns", EditAnywhere, meta = (TitleProperty = "Name"))
TArray<FCogEngineSpawnGroup> SpawnGroups;
};
@@ -1,6 +1,7 @@
#pragma once
#include "CoreMinimal.h"
#include "CogEngineDataAsset.h"
#include "GameFramework/Actor.h"
#include "UObject/Class.h"
#include "UObject/ObjectMacros.h"
@@ -50,6 +51,11 @@ public:
UFUNCTION(Server, Reliable)
void Server_DeleteActor(AActor* Actor);
UFUNCTION(Reliable, Server)
void Server_ApplyCheat(const AActor* CheatInstigator, const TArray<AActor*>& TargetActors, const FCogEngineCheat& Cheat) const;
static ECogEngineCheat_ActiveState IsCheatActiveOnTargets(const TArray<AActor*>& Targets, const FCogEngineCheat& Cheat);
protected:
UFUNCTION(Server, Reliable)
@@ -0,0 +1,90 @@
#pragma once
#include "CoreMinimal.h"
#include "CogCommonConfig.h"
#include "CogWindow.h"
#include "CogEngineWindow_Cheats.generated.h"
class AActor;
class UCogEngineConfig_Cheats;
class UCogEngineDataAsset;
struct FCogEngineCheat;
//--------------------------------------------------------------------------------------------------------------------------
class COGENGINE_API FCogEngineWindow_Cheats : public FCogWindow
{
typedef FCogWindow Super;
public:
virtual void Initialize() override;
protected:
virtual void GameTick(float DeltaTime) override;
virtual void ResetConfig() override;
virtual void RenderHelp() override;
virtual void RenderContent() override;
virtual void TryReapplyCheats();
virtual bool AddCheat(const int32 Index, AActor* ControlledActor, AActor* TargetActor, const FCogEngineCheat& CheatEffect, bool IsPersistent);
virtual void RequestCheat(AActor* ControlledActor, AActor* SelectedActor, const FCogEngineCheat& Cheat, bool ApplyToEnemies, bool ApplyToAllies, bool ApplyToControlled);
virtual const FCogEngineCheat* FindCheatByName(const FString& CheatName, const bool OnlyPersistentCheats);
static bool DrawTable();
void UpdateCheatColor(const FCogEngineCheat& Cheat) const;
TObjectPtr<const UCogEngineDataAsset> Asset = nullptr;
TObjectPtr<UCogEngineConfig_Cheats> Config = nullptr;
bool bHasReappliedCheats = false;
ImGuiTextFilter Filter;
TArray<FCogEngineCheat> AllCheats;
};
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(Config = Cog)
class UCogEngineConfig_Cheats : public UCogCommonConfig
{
GENERATED_BODY()
public:
UPROPERTY(Config)
bool bGroupByCategories = true;
UPROPERTY(Config)
bool bReapplyCheatsBetweenPlays = true;
UPROPERTY(Config)
bool bReapplyCheatsBetweenLaunches = true;
UPROPERTY(Config)
bool bUseTwoColumns = true;
UPROPERTY(Config)
TArray<FString> AppliedCheats;
UPROPERTY(Config)
TSet<FString> SelectedCategories;
virtual void Reset() override
{
Super::Reset();
bReapplyCheatsBetweenPlays = true;
bReapplyCheatsBetweenLaunches = true;
AppliedCheats.Empty();
SelectedCategories.Empty();
}
};
@@ -1,5 +1,4 @@
using UnrealBuildTool;
using UnrealBuildTool.Rules;
public class CogAbility : ModuleRules
{
@@ -26,10 +25,11 @@ public class CogAbility : ModuleRules
"CogImgui",
"CogCommon",
"CogDebug",
"CogEngine",
"CogWindow",
"GameplayAbilities",
"GameplayTags",
"NetCore",
"NetCore",
}
);
@@ -0,0 +1,111 @@
#include "CogAbilityCheat_Execution_ApplyEffect.h"
#include "CogAbilityDataAsset.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "CogAbilityConfig_Alignment.h"
#include "CogImguiHelper.h"
#include "CogWindow.h"
//--------------------------------------------------------------------------------------------------------------------------
void UCogAbilityCheat_Execution_ApplyEffect::Execute_Implementation(const AActor* Instigator, const TArray<AActor*>& Targets) const
{
UAbilitySystemComponent* DefaultInstigatorAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Instigator, true);
for (AActor* Target : Targets)
{
UAbilitySystemComponent* TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target, true);
if (TargetAbilitySystem == nullptr)
{
UE_LOG(LogCogImGui, Warning, TEXT("ACogAbilityReplicator::Server_ApplyCheat_Implementation | Target:%s | Invalid Target AbilitySystem"), *GetNameSafe(Target));
continue;
}
if (TargetAbilitySystem->GetGameplayEffectCount(Effect, nullptr) > 0)
{
TargetAbilitySystem->RemoveActiveGameplayEffectBySourceEffect(Effect, nullptr);
}
else
{
//-----------------------------------------------------------------------------------
// When executing a cheat directly on the game server, there is not an obvious
// local player to use as the instigator. Instead, we use the target ability system.
//-----------------------------------------------------------------------------------
UAbilitySystemComponent* InstigatorAbilitySystem = (DefaultInstigatorAbilitySystem != nullptr) ? DefaultInstigatorAbilitySystem : TargetAbilitySystem;
FGameplayEffectContextHandle ContextHandle = InstigatorAbilitySystem->MakeEffectContext();
ContextHandle.AddSourceObject(InstigatorAbilitySystem);
FGameplayEffectSpecHandle SpecHandle = InstigatorAbilitySystem->MakeOutgoingSpec(Effect, 1, ContextHandle);
if (const FGameplayEffectSpec* EffectSpec = SpecHandle.Data.Get())
{
FHitResult HitResult;
HitResult.HitObjectHandle = FActorInstanceHandle(Target);
HitResult.Normal = FVector::ForwardVector;
HitResult.ImpactNormal = FVector::ForwardVector;
HitResult.Location = Target->GetActorLocation();
HitResult.ImpactPoint = Target->GetActorLocation();
HitResult.PhysMaterial = nullptr;
ContextHandle.AddHitResult(HitResult, true);
InstigatorAbilitySystem->ApplyGameplayEffectSpecToTarget(*EffectSpec, TargetAbilitySystem);
}
}
}
}
//--------------------------------------------------------------------------------------------------------------------------
ECogEngineCheat_ActiveState UCogAbilityCheat_Execution_ApplyEffect::IsActiveOnTargets_Implementation(const TArray<AActor*>& Targets) const
{
if (Effect == nullptr)
{
return ECogEngineCheat_ActiveState::Inactive;
}
int32 NumWithEffect = 0;
for (const AActor* Target : Targets)
{
const UAbilitySystemComponent* AbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target, true);
if (AbilitySystem == nullptr)
{
continue;
}
const int32 Count = AbilitySystem->GetGameplayEffectCount(Effect, nullptr);
if (Count > 0)
{
NumWithEffect++;
}
}
if (NumWithEffect == 0)
{
return ECogEngineCheat_ActiveState::Inactive;
}
if (NumWithEffect == Targets.Num())
{
return ECogEngineCheat_ActiveState::Active;
}
return ECogEngineCheat_ActiveState::Partial;
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogAbilityCheat_Execution_ApplyEffect::GetColor(const FCogWindow& InCallingWindow, FLinearColor& OutColor) const
{
if (Effect == nullptr)
{ return false; }
const UGameplayEffect* GameplayEffect = Effect->GetDefaultObject<UGameplayEffect>();
if (GameplayEffect == nullptr)
{ return false; }
const UCogAbilityConfig_Alignment* Config = InCallingWindow.GetConfig<UCogAbilityConfig_Alignment>();
const UCogAbilityDataAsset* Asset = InCallingWindow.GetAsset<UCogAbilityDataAsset>();
OutColor = Config->GetEffectColor(Asset, *GameplayEffect);
return true;
}
@@ -0,0 +1,24 @@
#pragma once
#include "CoreMinimal.h"
#include "CogEngineDataAsset.h"
#include "GameplayEffect.h"
#include "CogAbilityCheat_Execution_ApplyEffect.generated.h"
//--------------------------------------------------------------------------------------------------------------------------
UCLASS(DisplayName = "Apply Effect")
class COGABILITY_API UCogAbilityCheat_Execution_ApplyEffect
: public UCogEngineCheat_Execution
{
GENERATED_BODY()
public:
void Execute_Implementation(const AActor* Instigator, const TArray<AActor*>& Targets) const override;
ECogEngineCheat_ActiveState IsActiveOnTargets_Implementation(const TArray<AActor*>& Targets) const override;
virtual bool GetColor(const FCogWindow& InCallingWindow, FLinearColor& OutColor) const override;
UPROPERTY(EditAnywhere)
TSubclassOf<UGameplayEffect> Effect;
};
@@ -2,7 +2,6 @@
#include "CogAbilityWindow_Abilities.h"
#include "CogAbilityWindow_Attributes.h"
#include "CogAbilityWindow_Cheats.h"
#include "CogAbilityWindow_Effects.h"
#include "CogAbilityWindow_Pools.h"
#include "CogAbilityWindow_Tags.h"
@@ -10,6 +9,7 @@
#include "CogAbilityWindow_Tweaks.h"
#include "CogAIWindow_BehaviorTree.h"
#include "CogAIWindow_Blackboard.h"
#include "CogEngineWindow_Cheats.h"
#include "CogEngineWindow_CollisionTester.h"
#include "CogEngineWindow_CollisionViewer.h"
#include "CogEngineWindow_CommandBindings.h"
@@ -103,7 +103,9 @@ void Cog::AddAllWindows(UCogWindowManager& CogWindowManager)
CogWindowManager.AddWindow<FCogAbilityWindow_BlockedTags>("Gameplay.Blocking Tags");
CogWindowManager.AddWindow<FCogAbilityWindow_Cheats>("Gameplay.Cheats");
//CogWindowManager.AddWindow<FCogEngineWindow_Cheats>("Gameplay.Cheats");
CogWindowManager.AddWindow<FCogEngineWindow_Cheats>("Gameplay.Cheats");
CogWindowManager.AddWindow<FCogAbilityWindow_Effects>("Gameplay.Effects");