Add new plugins, refactor exp, introduce stat forge to replace GAS
This commit is contained in:
BIN
Plugins/StatForge/Resources/Icon128.png
LFS
Normal file
BIN
Plugins/StatForge/Resources/Icon128.png
LFS
Normal file
Binary file not shown.
@@ -0,0 +1,381 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Components/StatForgeComponent.h"
|
||||
#include "Config/StatForgeDeveloperSettings.h"
|
||||
#include "Data/GameplayStatEffect.h"
|
||||
|
||||
|
||||
FActiveGameplayStatEffect FActiveGameplayStatEffect::CreateNew(UObject* SourceObject, UGameplayStatEffect* Effect, int32 Stacks)
|
||||
{
|
||||
if (!Effect || !SourceObject) return FActiveGameplayStatEffect();
|
||||
|
||||
FActiveGameplayStatEffect ActiveEffect;
|
||||
ActiveEffect.SourceObject = SourceObject;
|
||||
ActiveEffect.GameplayEffectClass = Effect->GetClass();
|
||||
ActiveEffect.StackCount = Stacks;
|
||||
ActiveEffect.GameplayEffectInstance = Effect;
|
||||
ActiveEffect.RemainingDuration = Effect->Duration;
|
||||
ActiveEffect.NextTickDuration = Effect->TickPeriod;
|
||||
ActiveEffect.bIsTicking = ActiveEffect.NextTickDuration > 0.f;
|
||||
ActiveEffect.Handle = FGuid::NewGuid();
|
||||
|
||||
return ActiveEffect;
|
||||
}
|
||||
|
||||
UStatForgeComponent::UStatForgeComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
float UStatForgeComponent::GetStatValue(const FName StatName) const
|
||||
{
|
||||
for (const FStatRuntimeDef& Def : StatArray)
|
||||
{
|
||||
if (Def.StatDef.StatName == StatName)
|
||||
{
|
||||
return Def.CurrentValue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
void UStatForgeComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
TMap<FName, float> DataValueMap;
|
||||
|
||||
if (const UStatForgeDeveloperSettings* DeveloperSettings = GetDefault<UStatForgeDeveloperSettings>())
|
||||
{
|
||||
for (const auto& StatPair : InitialStatValueArray)
|
||||
{
|
||||
FStatDef Def = DeveloperSettings->GetStatByName(StatPair.Key);
|
||||
if (Def.IsValid())
|
||||
{
|
||||
StatArray.Add(FStatRuntimeDef(Def));
|
||||
FGameplayStatEffectMod Mod;
|
||||
Mod.AffectedStat = StatPair.Key;
|
||||
Mod.ModOperation = EModOperation::Override;
|
||||
Mod.CalculationType = EGameplayStatEffectModCalculation::Flat;
|
||||
Mod.FlatValue = StatPair.Value;
|
||||
ApplyModToStat(Mod, DataValueMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const TSubclassOf<UGameplayStatEffect>& Effect : InitialEffectArray)
|
||||
{
|
||||
ApplyGameplayStatEffect(Effect, DataValueMap);
|
||||
}
|
||||
}
|
||||
|
||||
void UStatForgeComponent::TickComponent(float DeltaTime, enum ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
TickEffects(DeltaTime);
|
||||
}
|
||||
|
||||
void UStatForgeComponent::IsStat(FName StatName, FName CheckedName, EIsStatResult& Result)
|
||||
{
|
||||
Result = StatName.IsEqual(CheckedName)? EIsStatResult::Yes : EIsStatResult::No;
|
||||
}
|
||||
|
||||
void UStatForgeComponent::Internal_ApplyGameplayStatEffect(UGameplayStatEffect* Effect)
|
||||
{
|
||||
if (!CanApplyEffect(Effect)) return;
|
||||
|
||||
PreGameplayEffectExecute(Effect);
|
||||
for (const FGameplayStatEffectMod& Modifier : Effect->Modifiers)
|
||||
{
|
||||
ApplyModToStat(Modifier, Effect->GetDataValueMap());
|
||||
}
|
||||
PostGameplayEffectExecute(Effect);
|
||||
}
|
||||
|
||||
void UStatForgeComponent::ApplyModToStat(const FGameplayStatEffectMod& Mod, const TMap<FName, float> DataValueMap)
|
||||
{
|
||||
FStatRuntimeDef* StatDef = GetStatRef(Mod.AffectedStat);
|
||||
if (!StatDef) return;
|
||||
|
||||
PreStatModify(StatDef->StatDef.StatName);
|
||||
const float OldValue = StatDef->BaseValue;
|
||||
const float ModValue = Mod.GetModValue(this, DataValueMap);
|
||||
switch (Mod.ModOperation)
|
||||
{
|
||||
case EModOperation::Add:
|
||||
StatDef->BaseValue += ModValue;
|
||||
break;
|
||||
case EModOperation::MultiplyAdditive:
|
||||
case EModOperation::MultiplyCompound:
|
||||
StatDef->BaseValue *= ModValue;
|
||||
break;
|
||||
case EModOperation::Override:
|
||||
StatDef->BaseValue = ModValue;
|
||||
break;
|
||||
}
|
||||
RecalculateStatCurrentValue(Mod.AffectedStat, OldValue);
|
||||
}
|
||||
|
||||
void UStatForgeComponent::RecalculateStatCurrentValue(const FName StatName, const float OldValue)
|
||||
{
|
||||
FStatRuntimeDef* StatDef = GetStatRef(StatName);
|
||||
if (!StatDef) return;
|
||||
|
||||
const float BaseValue = StatDef->BaseValue;
|
||||
float AdditiveSum = 0.f;
|
||||
float MultiAddSum = 0.f;
|
||||
float MultiCompound = 1.f;
|
||||
bool bHasOverride = false;
|
||||
float OverrideValue = 0.f;
|
||||
for (FActiveGameplayStatEffect& Effect : ActiveEffectsArray)
|
||||
{
|
||||
if (Effect.bIsTicking) continue;
|
||||
|
||||
for (auto Mod : Effect.GameplayEffectInstance->Modifiers)
|
||||
{
|
||||
if (Mod.AffectedStat != StatName) continue;
|
||||
|
||||
const float StackCount = Effect.StackCount;
|
||||
const float ModValue = Mod.GetModValue(this, Effect.GameplayEffectInstance->GetDataValueMap());
|
||||
switch (Mod.ModOperation) {
|
||||
case EModOperation::Add:
|
||||
{
|
||||
AdditiveSum += (ModValue * StackCount);
|
||||
break;
|
||||
}
|
||||
case EModOperation::MultiplyAdditive:
|
||||
{
|
||||
MultiAddSum += (ModValue * StackCount);
|
||||
break;
|
||||
}
|
||||
case EModOperation::MultiplyCompound:
|
||||
{
|
||||
MultiCompound *= (ModValue * StackCount);
|
||||
break;
|
||||
}
|
||||
case EModOperation::Override:
|
||||
{
|
||||
bHasOverride = true;
|
||||
OverrideValue = ModValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bHasOverride)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float Result = (BaseValue + AdditiveSum) * (1.f + MultiAddSum) * MultiCompound;
|
||||
if (bHasOverride)
|
||||
{
|
||||
Result = OverrideValue;
|
||||
}
|
||||
|
||||
StatDef->CurrentValue = Result;
|
||||
PostStatModify(StatName);
|
||||
OnStatChanged.Broadcast(StatName, OldValue, StatDef->CurrentValue);
|
||||
}
|
||||
|
||||
FGuid UStatForgeComponent::ApplyGameplayStatEffect(const TSubclassOf<UGameplayStatEffect> EffectClass, TMap<FName, float> DataValueMap, int32 Stacks)
|
||||
{
|
||||
if (!EffectClass) return FGuid();
|
||||
|
||||
UGameplayStatEffect* Effect = NewObject<UGameplayStatEffect>(this, EffectClass);
|
||||
check(Effect);
|
||||
|
||||
Effect->AppendDataValueMap(DataValueMap);
|
||||
FGuid GuidToReturn;
|
||||
|
||||
if (Effect->Duration == GameplayStatEffectDuration_Instant)
|
||||
{
|
||||
Internal_ApplyGameplayStatEffect(Effect);
|
||||
}
|
||||
else
|
||||
{
|
||||
FActiveGameplayStatEffect ActiveEffect = FActiveGameplayStatEffect::CreateNew(this, Effect, Stacks);
|
||||
GuidToReturn = ActiveEffect.Handle;
|
||||
ActiveEffectsArray.Add(ActiveEffect);
|
||||
AddGameplayTags(Effect->CharacterTags);
|
||||
|
||||
for (const FName StatName : GetAffectedStatsFromEffect(ActiveEffect.GameplayEffectInstance))
|
||||
{
|
||||
const float OldValue = GetStatValue(StatName);
|
||||
RecalculateStatCurrentValue(StatName, OldValue);
|
||||
}
|
||||
}
|
||||
|
||||
return GuidToReturn;
|
||||
}
|
||||
|
||||
bool UStatForgeComponent::RemoveGameplayStatEffect(FGuid EffectId)
|
||||
{
|
||||
for (int32 i = ActiveEffectsArray.Num() - 1; i >= 0; --i)
|
||||
{
|
||||
if (ActiveEffectsArray[i].Handle == EffectId)
|
||||
{
|
||||
RemoveGameplayTags(ActiveEffectsArray[i].GameplayEffectInstance->CharacterTags);
|
||||
TArray<FName> AffectedStats = GetAffectedStatsFromEffect(ActiveEffectsArray[i].GameplayEffectInstance.Get());
|
||||
ActiveEffectsArray.RemoveAt(i);
|
||||
|
||||
for (const FName& Stat : AffectedStats)
|
||||
{
|
||||
const float OldValue = GetStatValue(Stat);
|
||||
RecalculateStatCurrentValue(Stat, OldValue);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UStatForgeComponent::HasStat(const FName& StatName) const
|
||||
{
|
||||
for (const FStatRuntimeDef& Stat : StatArray)
|
||||
{
|
||||
if (Stat.StatDef.StatName == StatName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UStatForgeComponent::AddGameplayTag(const FGameplayTag& NewTag)
|
||||
{
|
||||
if (NewTag.IsValid())
|
||||
{
|
||||
CharacterGameplayTags.AddTag(NewTag);
|
||||
NotifyGameplayTagsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UStatForgeComponent::AddGameplayTags(const FGameplayTagContainer& NewTags)
|
||||
{
|
||||
if(NewTags.Num() > 0)
|
||||
{
|
||||
CharacterGameplayTags.AppendTags(NewTags);
|
||||
NotifyGameplayTagsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool UStatForgeComponent::RemoveGameplayTag(const FGameplayTag& NewTag)
|
||||
{
|
||||
if (NewTag.IsValid())
|
||||
{
|
||||
CharacterGameplayTags.RemoveTag(NewTag);
|
||||
NotifyGameplayTagsChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UStatForgeComponent::RemoveGameplayTags(const FGameplayTagContainer& NewTags)
|
||||
{
|
||||
if(NewTags.Num() > 0)
|
||||
{
|
||||
CharacterGameplayTags.RemoveTags(NewTags);
|
||||
NotifyGameplayTagsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UStatForgeComponent::NotifyGameplayTagsChanged() const
|
||||
{
|
||||
OnTagsChanged.Broadcast();
|
||||
}
|
||||
|
||||
TArray<FName> UStatForgeComponent::GetAffectedStatsFromEffect(UGameplayStatEffect* Effect)
|
||||
{
|
||||
TArray<FName> ChangedStats;
|
||||
for (auto Mod : Effect->Modifiers)
|
||||
{
|
||||
ChangedStats.AddUnique(Mod.AffectedStat);
|
||||
}
|
||||
|
||||
return ChangedStats;
|
||||
}
|
||||
|
||||
FStatRuntimeDef* UStatForgeComponent::GetStatRef(const FName StatName)
|
||||
{
|
||||
for (FStatRuntimeDef& Def : StatArray)
|
||||
{
|
||||
if (Def.StatDef.StatName == StatName)
|
||||
{
|
||||
return &Def;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UStatForgeComponent::TickEffects(float DeltaTime)
|
||||
{
|
||||
TArray<FName> StatNames;
|
||||
for (int32 i = ActiveEffectsArray.Num() - 1; i >= 0; --i)
|
||||
{
|
||||
StatNames.Append(GetAffectedStatsFromEffect(ActiveEffectsArray[i].GameplayEffectInstance));
|
||||
|
||||
if (!CanTickEffect(ActiveEffectsArray[i].GameplayEffectInstance.Get()))
|
||||
{
|
||||
ActiveEffectsArray[i].RemainingDuration = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActiveEffectsArray[i].RemainingDuration -= DeltaTime;
|
||||
}
|
||||
|
||||
if (ActiveEffectsArray[i].RemainingDuration <= 0.f)
|
||||
{
|
||||
RemoveGameplayStatEffect(ActiveEffectsArray[i].Handle);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ActiveEffectsArray[i].GameplayEffectInstance->TickPeriod > 0.f)
|
||||
{
|
||||
ActiveEffectsArray[i].NextTickDuration -= DeltaTime;
|
||||
if (ActiveEffectsArray[i].NextTickDuration <= 0)
|
||||
{
|
||||
ActiveEffectsArray[i].NextTickDuration = ActiveEffectsArray[i].GameplayEffectInstance->TickPeriod;
|
||||
Internal_ApplyGameplayStatEffect(ActiveEffectsArray[i].GameplayEffectInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const FName StatName : StatNames)
|
||||
{
|
||||
const float OldValue = GetStatValue(StatName);
|
||||
RecalculateStatCurrentValue(StatName, OldValue);
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
for (const auto& Stat : StatArray)
|
||||
{
|
||||
StatValuesPreview.Add(Stat.StatDef.StatName, GetStatValue(Stat.StatDef.StatName));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UStatForgeComponent::CanApplyEffect(const UGameplayStatEffect* StatEffect) const
|
||||
{
|
||||
if (!StatEffect) return false;
|
||||
|
||||
return GetGameplayTags().HasAll(StatEffect->TagsRequiredToApply);
|
||||
}
|
||||
|
||||
bool UStatForgeComponent::CanTickEffect(const UGameplayStatEffect* StatEffect) const
|
||||
{
|
||||
if (!StatEffect) return false;
|
||||
|
||||
return GetGameplayTags().HasAll(StatEffect->TagsRequiredToTick);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Config/StatForgeDeveloperSettings.h"
|
||||
#include "Data/StatForgeRegistry.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UStatForgeDeveloperSettings::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UStatForgeDeveloperSettings, StatMap))
|
||||
{
|
||||
TSet<FName> Seen;
|
||||
for (int32 i = StatMap.Num() - 1; i >= 0; i--)
|
||||
{
|
||||
if (StatMap[i].StatName.IsNone())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Seen.Contains(StatMap[i].StatName))
|
||||
{
|
||||
FMessageDialog::Open(EAppMsgType::Ok,
|
||||
FText::Format(INVTEXT("StatForge: Duplicate stat name '{0}' removed."),FText::FromName(StatMap[i].StatName)));
|
||||
StatMap.RemoveAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
Seen.Add(StatMap[i].StatName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UStatForgeDeveloperSettings::PostReloadConfig(class FProperty* PropertyThatWasLoaded)
|
||||
{
|
||||
Super::PostReloadConfig(PropertyThatWasLoaded);
|
||||
MergeRegistryIntoStatMap();
|
||||
}
|
||||
#endif
|
||||
|
||||
FStatDef UStatForgeDeveloperSettings::GetStatByName(FName StatName) const
|
||||
{
|
||||
for (const FStatDef Def : StatMap)
|
||||
{
|
||||
if (Def.StatName == StatName)
|
||||
{
|
||||
return Def;
|
||||
}
|
||||
}
|
||||
|
||||
return FStatDef();
|
||||
}
|
||||
|
||||
TArray<FName> UStatForgeDeveloperSettings::GetStatNames()
|
||||
{
|
||||
TArray<FName> Names;
|
||||
|
||||
if (const UStatForgeDeveloperSettings* Settings = GetDefault<UStatForgeDeveloperSettings>())
|
||||
{
|
||||
for (const FStatDef Def : Settings->StatMap)
|
||||
{
|
||||
Names.Add(Def.StatName);
|
||||
}
|
||||
}
|
||||
|
||||
return Names;
|
||||
}
|
||||
|
||||
const FStatDef* UStatForgeDeveloperSettings::FindStat(const FName& StatName) const
|
||||
{
|
||||
return StatMap.FindByPredicate([&](const FStatDef& Def)
|
||||
{
|
||||
return Def.StatName == StatName;
|
||||
});
|
||||
}
|
||||
|
||||
void UStatForgeDeveloperSettings::PostInitProperties()
|
||||
{
|
||||
Super::PostInitProperties();
|
||||
MergeRegistryIntoStatMap();
|
||||
}
|
||||
|
||||
void UStatForgeDeveloperSettings::MergeRegistryIntoStatMap()
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("StatForge: Merging, registry has %d stats"), FStatForgeRegistry::Get().Num());
|
||||
|
||||
for (const FStatDef& Registered : FStatForgeRegistry::Get())
|
||||
{
|
||||
const bool bExists = StatMap.ContainsByPredicate([&](const FStatDef& Def)
|
||||
{
|
||||
return Def.StatName == Registered.StatName;
|
||||
});
|
||||
|
||||
if (!bExists)
|
||||
{
|
||||
StatMap.Add(Registered);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Data/GameplayStatEffect.h"
|
||||
#include "Components/StatForgeComponent.h"
|
||||
|
||||
float FGameplayStatEffectMod::GetModValue(UStatForgeComponent* StatComponent, const TMap<FName, float>& DataValueMap) const
|
||||
{
|
||||
switch (CalculationType) {
|
||||
case EGameplayStatEffectModCalculation::Flat:
|
||||
return FlatValue;
|
||||
case EGameplayStatEffectModCalculation::CalculationClass:
|
||||
{
|
||||
if (!StatCalculationClass) return 0.f;
|
||||
|
||||
UStatEffectModCalculation* Calc = NewObject<UStatEffectModCalculation>(StatComponent, StatCalculationClass);
|
||||
return Calc->GetValue(StatComponent);
|
||||
}
|
||||
case EGameplayStatEffectModCalculation::DataValue:
|
||||
{
|
||||
if (const float* Value = DataValueMap.Find(DataValueName))
|
||||
{
|
||||
return *Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
#include "Data/StatForgeDefs.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Helpers/StatEffectModCalculation.h"
|
||||
@@ -0,0 +1,27 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Helpers/StatForgeFunctionLibrary.h"
|
||||
|
||||
#include "Components/StatForgeComponent.h"
|
||||
|
||||
float UStatForgeFunctionLibrary::GetStatValue(const FName StatName, AActor* Actor)
|
||||
{
|
||||
if (!Actor || StatName.IsNone()) return 0.f;
|
||||
|
||||
UStatForgeComponent* StatForgeComponent = Actor->GetComponentByClass<UStatForgeComponent>();
|
||||
if(!StatForgeComponent) return 0.f;
|
||||
|
||||
return StatForgeComponent->GetStatValue(StatName);
|
||||
}
|
||||
|
||||
FGuid UStatForgeFunctionLibrary::ApplyGameplayStatEffect(const TSubclassOf<UGameplayStatEffect> EffectClass,
|
||||
TMap<FName, float> DataValueMap, AActor* Actor, int32 Stacks)
|
||||
{
|
||||
if (!EffectClass || !Actor) return FGuid();
|
||||
|
||||
UStatForgeComponent* StatForgeComponent = Actor->GetComponentByClass<UStatForgeComponent>();
|
||||
if(!StatForgeComponent) return FGuid();
|
||||
|
||||
return StatForgeComponent->ApplyGameplayStatEffect(EffectClass, DataValueMap, Stacks);
|
||||
}
|
||||
26
Plugins/StatForge/Source/StatForge/Private/StatForge.cpp
Normal file
26
Plugins/StatForge/Source/StatForge/Private/StatForge.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "StatForge.h"
|
||||
|
||||
#include "Config/StatForgeDeveloperSettings.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FStatForgeModule"
|
||||
|
||||
void FStatForgeModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
if (UStatForgeDeveloperSettings* Settings = GetMutableDefault<UStatForgeDeveloperSettings>())
|
||||
{
|
||||
Settings->EnsureRegistryMerged();
|
||||
}
|
||||
}
|
||||
|
||||
void FStatForgeModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FStatForgeModule, StatForge)
|
||||
@@ -0,0 +1,139 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Data/GameplayStatEffect.h"
|
||||
#include "Data/StatForgeDefs.h"
|
||||
#include "StatForgeComponent.generated.h"
|
||||
|
||||
struct FGameplayStatEffectMod;
|
||||
|
||||
USTRUCT()
|
||||
struct FActiveGameplayStatEffect
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY()
|
||||
FGuid Handle;
|
||||
|
||||
UPROPERTY()
|
||||
TSubclassOf<UGameplayStatEffect> GameplayEffectClass;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UGameplayStatEffect> GameplayEffectInstance;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UObject> SourceObject = nullptr;
|
||||
|
||||
UPROPERTY()
|
||||
int32 StackCount = 1;
|
||||
|
||||
UPROPERTY()
|
||||
float RemainingDuration = -1.f;
|
||||
|
||||
UPROPERTY()
|
||||
float NextTickDuration = -1.f;
|
||||
|
||||
UPROPERTY()
|
||||
bool bIsTicking = false;
|
||||
|
||||
static FActiveGameplayStatEffect CreateNew(UObject* SourceObject, UGameplayStatEffect* Effect, int32 Stacks = 1);
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum class EIsStatResult : uint8
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnStatChanged, FName, StatName, float, OldValue, float, NewValue);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameplayTagsChangedDelegate);
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType, ClassGroup=(StatForge), meta=(BlueprintSpawnableComponent))
|
||||
class STATFORGE_API UStatForgeComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UStatForgeComponent();
|
||||
virtual void BeginPlay() override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge", meta = (ExpandEnumAsExecs = "Result"))
|
||||
static void IsStat(FName StatName, UPARAM(meta = (GetOptions = "StatForgeDeveloperSettings.GetStatNames")) FName CheckedName, EIsStatResult& Result);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Stat Forge")
|
||||
float GetStatValue(UPARAM(meta = (GetOptions = "StatForgeDeveloperSettings.GetStatNames")) const FName StatName) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge", meta = (AutoCreateRefTerm = "DataValueMap"))
|
||||
FGuid ApplyGameplayStatEffect(const TSubclassOf<UGameplayStatEffect> EffectClass, TMap<FName, float> DataValueMap, int32 Stacks = 1);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge")
|
||||
bool RemoveGameplayStatEffect(FGuid EffectId);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Stat Forge")
|
||||
bool HasStat(const FName& StatName) const;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Stat Forge|Stats", meta = (GetOptions = "StatForgeDeveloperSettings.GetStatNames"))
|
||||
TMap<FName, float> InitialStatValueArray;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
TArray<TSubclassOf<UGameplayStatEffect>> InitialEffectArray;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Stat Forge|Events")
|
||||
FOnStatChanged OnStatChanged;
|
||||
|
||||
/** Begin TAGS */
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = Buffs)
|
||||
FOnGameplayTagsChangedDelegate OnTagsChanged;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge|Tags")
|
||||
void AddGameplayTag(const FGameplayTag& NewTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge|Tags")
|
||||
void AddGameplayTags(const FGameplayTagContainer& NewTags);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge|Tags")
|
||||
bool RemoveGameplayTag(const FGameplayTag& NewTag);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge|Tags")
|
||||
void RemoveGameplayTags(const FGameplayTagContainer& NewTags);
|
||||
|
||||
const FGameplayTagContainer& GetGameplayTags() const { return CharacterGameplayTags; }
|
||||
|
||||
protected:
|
||||
|
||||
void NotifyGameplayTagsChanged() const;
|
||||
/** End TAGS */
|
||||
|
||||
virtual void PreGameplayEffectExecute(UGameplayStatEffect* Effect) {}
|
||||
virtual void PostGameplayEffectExecute(UGameplayStatEffect* Effect) {}
|
||||
virtual void PreStatModify(const FName StatName) {}
|
||||
virtual void PostStatModify(const FName StatName) {}
|
||||
void Internal_ApplyGameplayStatEffect(UGameplayStatEffect* Effect);
|
||||
virtual void ApplyModToStat(const FGameplayStatEffectMod& Mod, const TMap<FName, float> DataValueMap);
|
||||
virtual void RecalculateStatCurrentValue(const FName StatName, const float OldValue);
|
||||
static TArray<FName> GetAffectedStatsFromEffect(UGameplayStatEffect* Effect);
|
||||
FStatRuntimeDef* GetStatRef(const FName StatName);
|
||||
void TickEffects(float DeltaTime);
|
||||
bool CanApplyEffect(const UGameplayStatEffect* StatEffect) const;
|
||||
bool CanTickEffect(const UGameplayStatEffect* StatEffect) const;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FStatRuntimeDef> StatArray;
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
TMap<FName, float> StatValuesPreview;
|
||||
#endif
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FActiveGameplayStatEffect> ActiveEffectsArray;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Tags")
|
||||
FGameplayTagContainer CharacterGameplayTags;
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Data/StatForgeDefs.h"
|
||||
#include "Engine/DeveloperSettings.h"
|
||||
#include "StatForgeDeveloperSettings.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Config = Game, defaultconfig, meta = (DisplayName = "Stat Forge Settings"))
|
||||
class STATFORGE_API UStatForgeDeveloperSettings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "Setup")
|
||||
TArray<FStatDef> StatMap;
|
||||
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
virtual void PostReloadConfig(class FProperty* PropertyThatWasLoaded) override;
|
||||
#endif
|
||||
|
||||
FStatDef GetStatByName(FName StatName) const;
|
||||
|
||||
UFUNCTION()
|
||||
static TArray<FName> GetStatNames();
|
||||
const FStatDef* FindStat(const FName& StatName) const;
|
||||
void EnsureRegistryMerged() { MergeRegistryIntoStatMap(); }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void PostInitProperties() override;
|
||||
|
||||
private:
|
||||
void MergeRegistryIntoStatMap();
|
||||
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "StatForgeDefs.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "GameplayStatEffect.generated.h"
|
||||
|
||||
class UGameplayStatEffect;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EModOperation : uint8
|
||||
{
|
||||
Add,
|
||||
MultiplyAdditive UMETA(DisplayName = "Multiply Additive"),
|
||||
MultiplyCompound UMETA(DisplayName = "Multiply Compound"),
|
||||
Override
|
||||
};
|
||||
|
||||
static constexpr float GameplayStatEffectDuration_Instant = 0.f;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EGameplayStatEffectModCalculation : uint8
|
||||
{
|
||||
Flat,
|
||||
CalculationClass,
|
||||
DataValue
|
||||
};
|
||||
|
||||
USTRUCT(BLueprintType)
|
||||
struct STATFORGE_API FGameplayStatEffectMod
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats", meta = (GetOptions = "StatForgeDeveloperSettings.GetStatNames"))
|
||||
FName AffectedStat;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
EModOperation ModOperation;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
EGameplayStatEffectModCalculation CalculationType;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats", meta = (EditCondition = "CalculationType==EGameplayStatEffectModCalculation::Flat", EditConditionHides))
|
||||
float FlatValue = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Stat Forge|Stats", meta = (EditCondition = "CalculationType==EGameplayStatEffectModCalculation::CalculationClass", EditConditionHides, BlueprintBaseOnly, ShowTreeView))
|
||||
TSubclassOf<class UStatEffectModCalculation> StatCalculationClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats", meta = (EditCondition = "CalculationType==EGameplayStatEffectModCalculation::DataValue", EditConditionHides))
|
||||
FName DataValueName;
|
||||
|
||||
float GetModValue(UStatForgeComponent* StatComponent, const TMap<FName, float>& DataValueMap) const;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class STATFORGE_API UGameplayStatEffect : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Duration")
|
||||
float Duration = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Duration")
|
||||
float TickPeriod = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Modifiers")
|
||||
TArray<FGameplayStatEffectMod> Modifiers;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tags")
|
||||
FGameplayTagContainer EffectTags;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tags")
|
||||
FGameplayTagContainer CharacterTags;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tags|Requirements", meta = (EditCondition = "Duration==0"))
|
||||
FGameplayTagContainer TagsRequiredToApply;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tags|Requirements", meta = (EditCondition = "Duration!=0"))
|
||||
FGameplayTagContainer TagsRequiredToTick;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge|Effect")
|
||||
void AppendDataValueMap(TMap<FName, float> InDataValueMap) { DataValueMap.Append(InDataValueMap); }
|
||||
|
||||
const TMap<FName, float>& GetDataValueMap() { return DataValueMap; }
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY()
|
||||
TMap<FName, float> DataValueMap;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StatForgeRegistry.h"
|
||||
|
||||
// -Flat Stats-
|
||||
// MAKE_STAT(Health)
|
||||
|
||||
// -Grouped Stats-
|
||||
// MAKE_STAT_NS(Combat, AttackSpeed)
|
||||
// MAKE_STAT_NS(Locomotion, MovementSpeed)
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Helpers/StatEffectModCalculation.h"
|
||||
#include "StatForgeDefs.generated.h"
|
||||
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EStatDefClampMode : uint8
|
||||
{
|
||||
None,
|
||||
FlatValue,
|
||||
Stat
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct STATFORGE_API FStatDefClampMode
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
EStatDefClampMode ClampMode = EStatDefClampMode::None;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName = "Value", Category = "Stat Forge|Stats", meta = (EditCondition = "ClampMode==EStatDefClampMode::FlatValue", EditConditionHides))
|
||||
float ClampModeFlatValue = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName = "Stat Reference", Category = "Stat Forge|Stats", meta = (EditCondition = "ClampMode==EStatDefClampMode::Stat", EditConditionHides, GetOptions = "StatForgeDeveloperSettings.GetStatNames"))
|
||||
FName ClampModeStatValue;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct STATFORGE_API FStatDef
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
FName StatName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
FText StatDescriptiveName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat Forge|Stats")
|
||||
FStatDefClampMode ClampMode;
|
||||
|
||||
bool IsValid() const { return !StatName.IsNone(); }
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct STATFORGE_API FStatRuntimeDef
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
FStatRuntimeDef() { StatDef = FStatDef(); }
|
||||
explicit FStatRuntimeDef(const FStatDef& Def)
|
||||
{
|
||||
StatDef = Def;
|
||||
}
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Stats")
|
||||
FStatDef StatDef;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Stats")
|
||||
float BaseValue = 0.f;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Stats")
|
||||
float CurrentValue = 0.f;
|
||||
|
||||
float GetBaseValue() const { return BaseValue; }
|
||||
float GetCurrentValue() const { return CurrentValue; }
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "StatForgeDefs.h"
|
||||
|
||||
class STATFORGE_API FStatForgeRegistry
|
||||
{
|
||||
public:
|
||||
|
||||
static TArray<FStatDef>& Get()
|
||||
{
|
||||
static TArray<FStatDef> Registry;
|
||||
return Registry;
|
||||
}
|
||||
|
||||
static void RegisterStat(const FName& StatName)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("StatForge: Registering %s"), *StatName.ToString());
|
||||
|
||||
const bool bAlreadyRegistered = Get().ContainsByPredicate([&](const FStatDef& Def)
|
||||
{
|
||||
return Def.StatName == StatName;
|
||||
});
|
||||
|
||||
if (!bAlreadyRegistered)
|
||||
{
|
||||
FStatDef StatDef;
|
||||
StatDef.StatName = StatName;
|
||||
Get().Add(StatDef);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define STATFORGE_DECLARE_STAT(StatName)\
|
||||
namespace FStat\
|
||||
{\
|
||||
extern const FName StatName;\
|
||||
}\
|
||||
|
||||
#define STATFORGE_DECLARE_STAT_NS(Group, StatName)\
|
||||
namespace FStat\
|
||||
{\
|
||||
namespace Group\
|
||||
{\
|
||||
extern const FName StatName;\
|
||||
}\
|
||||
}\
|
||||
|
||||
|
||||
#define STATFORGE_MAKE_STAT(StatName)\
|
||||
namespace FStat\
|
||||
{\
|
||||
const FName StatName = FName(#StatName);\
|
||||
namespace Detail\
|
||||
{\
|
||||
struct FAutoRegister_##StatName\
|
||||
{\
|
||||
FAutoRegister_##StatName() { FStatForgeRegistry::RegisterStat(FName(#StatName)); }\
|
||||
};\
|
||||
FAutoRegister_##StatName AutoRegister_##StatName;\
|
||||
}\
|
||||
}\
|
||||
|
||||
#define STATFORGE_MAKE_STAT_NS(Group, StatName)\
|
||||
namespace FStat\
|
||||
{\
|
||||
namespace Group\
|
||||
{\
|
||||
const FName StatName = FName(#Group "." #StatName);\
|
||||
namespace Detail\
|
||||
{\
|
||||
struct FAutoRegister_##Group##_##StatName\
|
||||
{\
|
||||
FAutoRegister_##Group##_##StatName()\
|
||||
{ FStatForgeRegistry::RegisterStat(FName(#Group "." #StatName)); }\
|
||||
};\
|
||||
FAutoRegister_##Group##_##StatName AutoRegister_##Group##_##StatName;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
@@ -0,0 +1,22 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "StatEffectModCalculation.generated.h"
|
||||
|
||||
class UStatForgeComponent;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class STATFORGE_API UStatEffectModCalculation : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintNativeEvent, Category = "Stat Forge")
|
||||
float GetValue(UStatForgeComponent* StatForgeComponent);
|
||||
virtual float GetValue_Implementation(UStatForgeComponent* StatForgeComponent) { return 0.f; }
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "StatForgeFunctionLibrary.generated.h"
|
||||
|
||||
class UGameplayStatEffect;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class STATFORGE_API UStatForgeFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Stat Forge")
|
||||
static float GetStatValue(UPARAM(meta = (GetOptions = "StatForgeDeveloperSettings.GetStatNames")) const FName StatName, AActor* Actor);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Stat Forge", meta = (AutoCreateRefTerm = "DataValueMap"))
|
||||
static FGuid ApplyGameplayStatEffect(const TSubclassOf<UGameplayStatEffect> EffectClass, TMap<FName, float> DataValueMap, AActor* Actor, int32 Stacks = 1);
|
||||
|
||||
};
|
||||
14
Plugins/StatForge/Source/StatForge/Public/StatForge.h
Normal file
14
Plugins/StatForge/Source/StatForge/Public/StatForge.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FStatForgeModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
||||
54
Plugins/StatForge/Source/StatForge/StatForge.Build.cs
Normal file
54
Plugins/StatForge/Source/StatForge/StatForge.Build.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class StatForge : ModuleRules
|
||||
{
|
||||
public StatForge(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"GameplayTags",
|
||||
"DeveloperSettings"
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add any modules that your module loads dynamically here ...
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
24
Plugins/StatForge/StatForge.uplugin
Normal file
24
Plugins/StatForge/StatForge.uplugin
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "StatForge",
|
||||
"Description": "",
|
||||
"Category": "Gameplay",
|
||||
"CreatedBy": "",
|
||||
"CreatedByURL": "",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "",
|
||||
"CanContainContent": true,
|
||||
"IsBetaVersion": false,
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "StatForge",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user