Refactor and remove gameplay ability system, replace with own one

This commit is contained in:
2026-07-16 22:24:27 +02:00
parent da0a0b643f
commit 5d6377b082
44 changed files with 170 additions and 478 deletions

View File

@@ -192,4 +192,5 @@ CameraZoomLevels=(((TagName="Camera.BoomOffset.Default"), (X=-1200.000000,Y=0.00
+ProfessionExpArray=208000.000000 +ProfessionExpArray=208000.000000
+ProfessionExpArray=240000.000000 +ProfessionExpArray=240000.000000
ExpIncreaseEffectClass=/Script/Engine.BlueprintGeneratedClass'/Game/Blueprints/GameEffects/GSE_AddExp_Template.GSE_AddExp_Template_C' ExpIncreaseEffectClass=/Script/Engine.BlueprintGeneratedClass'/Game/Blueprints/GameEffects/GSE_AddExp_Template.GSE_AddExp_Template_C'
GlobalSettingsDataSheet=/Game/GameData/CSV/GlobalKeyValueSettings.GlobalKeyValueSettings

View File

@@ -0,0 +1,6 @@
Name,Value
AlchemyEnergyCost,1
FoodEnergyRestore,20
HarvestingEnergyCost,1
PlantingEnergyCost,1
SleepEnergyRestore,70
1 Name Value
2 AlchemyEnergyCost 1
3 FoodEnergyRestore 20
4 HarvestingEnergyCost 1
5 PlantingEnergyCost 1
6 SleepEnergyRestore 70

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -236,6 +236,24 @@ bool UStatForgeComponent::RemoveGameplayStatEffect(FGuid EffectId)
return false; return false;
} }
void UStatForgeComponent::RemoveAllGameplayStatEffects()
{
ActiveEffectsArray.Empty();
}
void UStatForgeComponent::ModifyGeDuration(FGuid EffectId, float NewRemainingDuration, float NewNextTickDuration)
{
for (int32 i = ActiveEffectsArray.Num() - 1; i >= 0; --i)
{
if (ActiveEffectsArray[i].Handle == EffectId)
{
ActiveEffectsArray[i].RemainingDuration = NewRemainingDuration;
ActiveEffectsArray[i].NextTickDuration = NewNextTickDuration;
break;
}
}
}
bool UStatForgeComponent::HasStat(const FName& StatName) const bool UStatForgeComponent::HasStat(const FName& StatName) const
{ {
for (const FStatRuntimeDef& Stat : StatArray) for (const FStatRuntimeDef& Stat : StatArray)

View File

@@ -123,6 +123,12 @@ protected:
bool CanApplyEffect(const UGameplayStatEffect* StatEffect) const; bool CanApplyEffect(const UGameplayStatEffect* StatEffect) const;
bool CanTickEffect(const UGameplayStatEffect* StatEffect) const; bool CanTickEffect(const UGameplayStatEffect* StatEffect) const;
// CAUTION, only to be used inside AEleriGameState to load game
void RemoveAllGameplayStatEffects();
void ModifyGeDuration(FGuid EffectId, float NewRemainingDuration, float NewNextTickDuration);
const TArray<FStatRuntimeDef>& GetStatArray() { return StatArray; }
const TArray<FActiveGameplayStatEffect>& GetActiveEffectsArray() { return ActiveEffectsArray; }
UPROPERTY() UPROPERTY()
TArray<FStatRuntimeDef> StatArray; TArray<FStatRuntimeDef> StatArray;
@@ -136,4 +142,7 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Tags") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stat Forge|Tags")
FGameplayTagContainer CharacterGameplayTags; FGameplayTagContainer CharacterGameplayTags;
friend class AEleriGameState;
friend struct FSaveData;
}; };

View File

@@ -112,10 +112,6 @@
"Enabled": true, "Enabled": true,
"MarketplaceURL": "https://unrealengineresources.com/plugins" "MarketplaceURL": "https://unrealengineresources.com/plugins"
}, },
{
"Name": "GameplayAbilities",
"Enabled": true
},
{ {
"Name": "UniversalCameraPlugin", "Name": "UniversalCameraPlugin",
"Enabled": true, "Enabled": true,

View File

@@ -0,0 +1,16 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "EleriGlobalKeyValueStruct.generated.h"
USTRUCT(BlueprintType)
struct FEleriGlobalKeyValueStruct : public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Value;
};

View File

@@ -1,72 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PrimaryAttributeSet.h"
UPrimaryAttributeSet::UPrimaryAttributeSet()
: Energy(100.f)
, HungerSatiation(0.f)
, GatherDoubleDropChance(0.f)
, GatherHqDropChance(0.f)
, FriendPointsMultiplier(1.f)
, AlchemyMultiplier(1.f)
, BazarCustomerSpawnRate(6.f)
, BazarCustomerWill(0.33f)
, AlchemyExp(0.f)
, BotanyExp(0.f)
, GatheringExp(0.f)
, FlyingExp(0.f)
, BargainingExp(0.f)
{}
void UPrimaryAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) {
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetGatherDoubleDropChanceAttribute()) {
NewValue = FMath::Clamp(NewValue, 0.f, 100.f);
}
if (Attribute == GetGatherHqDropChanceAttribute()) {
NewValue = FMath::Clamp(NewValue, 0.f, 100.f);
}
if (Attribute == GetBazarCustomerSpawnRateAttribute())
{
NewValue = FMath::Clamp(NewValue, 3.f, 6.f);
}
if (Attribute == GetBazarCustomerWillAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.f, 1.f);
}
if (IsExpAttribute(Attribute)) {
NewValue = FMath::Max(NewValue, 0.f);
}
}
void UPrimaryAttributeSet::PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const {
Super::PreAttributeBaseChange(Attribute, NewValue);
if (Attribute == GetGatherDoubleDropChanceAttribute()) {
NewValue = FMath::Clamp(NewValue, 0.f, 100.f);
}
if (Attribute == GetGatherHqDropChanceAttribute()) {
NewValue = FMath::Clamp(NewValue, 0.f, 100.f);
}
if (Attribute == GetBazarCustomerSpawnRateAttribute())
{
NewValue = FMath::Clamp(NewValue, 3.f, 6.f);
}
if (Attribute == GetBazarCustomerWillAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.f, 1.f);
}
if (IsExpAttribute(Attribute)) {
NewValue = FMath::Max(NewValue, 0.f);
}
}

View File

@@ -1,94 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "PrimaryAttributeSet.generated.h"
// Uses macros from AttributeSet.h
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
*
*/
UCLASS()
class PROJECTELERI_API UPrimaryAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPrimaryAttributeSet();
public:
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData Energy;
ATTRIBUTE_ACCESSORS(ThisClass, Energy)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData HungerSatiation;
ATTRIBUTE_ACCESSORS(ThisClass, HungerSatiation)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData GatherDoubleDropChance;
ATTRIBUTE_ACCESSORS(ThisClass, GatherDoubleDropChance)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData GatherHqDropChance;
ATTRIBUTE_ACCESSORS(ThisClass, GatherHqDropChance)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData FriendPointsMultiplier;
ATTRIBUTE_ACCESSORS(ThisClass, FriendPointsMultiplier)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData AlchemyMultiplier;
ATTRIBUTE_ACCESSORS(ThisClass, AlchemyMultiplier)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData BazarCustomerSpawnRate;
ATTRIBUTE_ACCESSORS(ThisClass, BazarCustomerSpawnRate)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData BazarCustomerWill;
ATTRIBUTE_ACCESSORS(ThisClass, BazarCustomerWill)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData AlchemyExp;
ATTRIBUTE_ACCESSORS(ThisClass, AlchemyExp)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData BotanyExp;
ATTRIBUTE_ACCESSORS(ThisClass, BotanyExp)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData GatheringExp;
ATTRIBUTE_ACCESSORS(ThisClass, GatheringExp)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData FlyingExp;
ATTRIBUTE_ACCESSORS(ThisClass, FlyingExp)
UPROPERTY(BlueprintReadOnly, SaveGame)
FGameplayAttributeData BargainingExp;
ATTRIBUTE_ACCESSORS(ThisClass, BargainingExp)
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
virtual void PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const override;
public:
static bool IsExpAttribute(const FGameplayAttribute& Attribute) {
return
Attribute == GetAlchemyExpAttribute() ||
Attribute == GetBotanyExpAttribute() ||
Attribute == GetGatheringExpAttribute() ||
Attribute == GetFlyingExpAttribute() ||
Attribute == GetBargainingExpAttribute();
}
};

View File

@@ -1,83 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "EleriAbilitySystemComponent.h"
#include "GameplayEffect.h"
#include "Attributes/PrimaryAttributeSet.h"
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
#include "ProjectEleri/Settings/EleriGameSettings.h"
void UEleriAbilitySystemComponent::AddExp(UObject* WorldContextObject, FGameplayAttribute GameplayAttribute, float Amount) {
}
void UEleriAbilitySystemComponent::AddProfessionExp(UObject* WorldContextObject, EProfessionType Profession, float Amount) {
AddExp(WorldContextObject, GetGameplayAttributeForProfession(Profession), Amount);
if (UEleriAbilitySystemComponent* ASC = UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(WorldContextObject)) {
if (FActiveGameplayEffectHandle* ActiveEffectHandle = ASC->ProfessionModifierEffectsContainer.Find(Profession)) {
ASC->SetActiveGameplayEffectLevel(*ActiveEffectHandle, GetProfessionLevel(WorldContextObject, Profession));
}
}
}
int32 UEleriAbilitySystemComponent::GetProfessionLevel(UObject* WorldContextObject, EProfessionType Profession) {
if (UEleriAbilitySystemComponent* ASC = UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(WorldContextObject)) {
if (const UEleriGameSettings* GameSettings = GetDefault<UEleriGameSettings>()) {
switch (Profession) {
case EProfessionType::ALCHEMY:
return GameSettings->GetProfessionLevelForExp(ASC->GetNumericAttribute(UPrimaryAttributeSet::GetAlchemyExpAttribute()));
case EProfessionType::BOTANY:
return GameSettings->GetProfessionLevelForExp(ASC->GetNumericAttribute(UPrimaryAttributeSet::GetBotanyExpAttribute()));
case EProfessionType::GATHERING:
return GameSettings->GetProfessionLevelForExp(ASC->GetNumericAttribute(UPrimaryAttributeSet::GetGatheringExpAttribute()));
case EProfessionType::FLYING:
return GameSettings->GetProfessionLevelForExp(ASC->GetNumericAttribute(UPrimaryAttributeSet::GetFlyingExpAttribute()));
default:
break;
}
}
}
return 0;
}
void UEleriAbilitySystemComponent::BeginPlay() {
Super::BeginPlay();
GetGameplayAttributeValueChangeDelegate(UPrimaryAttributeSet::GetEnergyAttribute()).AddUObject(this, &UEleriAbilitySystemComponent::AttributeChanged);
GetGameplayAttributeValueChangeDelegate(UPrimaryAttributeSet::GetHungerSatiationAttribute()).AddUObject(this, &UEleriAbilitySystemComponent::AttributeChanged);
GetGameplayAttributeValueChangeDelegate(UPrimaryAttributeSet::GetGatherDoubleDropChanceAttribute()).AddUObject(this, &UEleriAbilitySystemComponent::AttributeChanged);
GetGameplayAttributeValueChangeDelegate(UPrimaryAttributeSet::GetGatherHqDropChanceAttribute()).AddUObject(this, &UEleriAbilitySystemComponent::AttributeChanged);
GetGameplayAttributeValueChangeDelegate(UPrimaryAttributeSet::GetFriendPointsMultiplierAttribute()).AddUObject(this, &UEleriAbilitySystemComponent::AttributeChanged);
for (auto Effect : InitialEffects) {
BP_ApplyGameplayEffectToSelf(Effect, 1.f, MakeEffectContext());
}
for (auto ProfModEffect : ProfessionModifierEffects) {
FActiveGameplayEffectHandle EffectHandle = BP_ApplyGameplayEffectToSelf(ProfModEffect.Value, 1.f, MakeEffectContext());
ProfessionModifierEffectsContainer.Add(ProfModEffect.Key, EffectHandle);
}
}
void UEleriAbilitySystemComponent::AttributeChanged(const FOnAttributeChangeData& AttributeChangeData) {
OnAttributeChange.Broadcast(AttributeChangeData.Attribute, AttributeChangeData.NewValue, AttributeChangeData.OldValue);
}
FGameplayAttribute UEleriAbilitySystemComponent::GetGameplayAttributeForProfession(EProfessionType Profession) {
switch (Profession) {
case EProfessionType::ALCHEMY:
return UPrimaryAttributeSet::GetAlchemyExpAttribute();
case EProfessionType::BOTANY:
return UPrimaryAttributeSet::GetBotanyExpAttribute();
case EProfessionType::GATHERING:
return UPrimaryAttributeSet::GetGatheringExpAttribute();
case EProfessionType::FLYING:
return UPrimaryAttributeSet::GetFlyingExpAttribute();
default:
break;
}
return FGameplayAttribute();
}

View File

@@ -1,59 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "EleriAbilitySystemComponent.generated.h"
class UGameplayEffect;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnAttributeChange, FGameplayAttribute, GameplayAttribute, float, NewValue, float, OldValue);
UENUM(BlueprintType)
enum class EProfessionType : uint8 {
ALCHEMY UMETA(DisplayName="Alchemy"),
BOTANY UMETA(DisplayName = "Botany"),
GATHERING UMETA(DisplayName = "Gathering"),
FLYING UMETA(DisplayName = "Flying"),
MAX UMETA(Hidden)
};
/**
*
*/
UCLASS()
class PROJECTELERI_API UEleriAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TArray<TSubclassOf<UGameplayEffect>> InitialEffects;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TMap<EProfessionType, TSubclassOf<UGameplayEffect>> ProfessionModifierEffects;
UPROPERTY(BlueprintAssignable)
FOnAttributeChange OnAttributeChange;
UFUNCTION(BlueprintCallable, Category = "Eleri Ability System", meta = (WorldContext = "WorldContextObject"))
static void AddExp(UObject* WorldContextObject, FGameplayAttribute GameplayAttribute, float Amount);
UFUNCTION(BlueprintCallable, Category = "Eleri Ability System", meta = (WorldContext = "WorldContextObject"))
static void AddProfessionExp(UObject* WorldContextObject, EProfessionType Profession, float Amount);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri Ability System", meta = (WorldContext = "WorldContextObject"))
static int32 GetProfessionLevel(UObject* WorldContextObject, EProfessionType Profession);
protected:
UPROPERTY()
TMap<EProfessionType, FActiveGameplayEffectHandle> ProfessionModifierEffectsContainer;
virtual void BeginPlay() override;
void AttributeChanged(const FOnAttributeChangeData& AttributeChangeData);
static FGameplayAttribute GetGameplayAttributeForProfession(EProfessionType Profession);
};

View File

@@ -6,6 +6,8 @@
#include "EleriPlayerController.h" #include "EleriPlayerController.h"
#include "EnhancedInputComponent.h" #include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "Components/StatForgeComponent.h"
#include "ProjectEleri/Data/StatDefinitions.h"
#include "ProjectEleri/Public/InventoryComponent.h" #include "ProjectEleri/Public/InventoryComponent.h"
#include "ProjectEleri/Items/DataAssets/ItemDataAsset.h" #include "ProjectEleri/Items/DataAssets/ItemDataAsset.h"
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h" #include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
@@ -34,10 +36,10 @@ void AAlchemyManager::CalculateRewardStack() {
} }
void AAlchemyManager::CalculateFinalMultiplier() { void AAlchemyManager::CalculateFinalMultiplier() {
UEleriAbilitySystemComponent* ASC = UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(this); UStatForgeComponent* StatForgeComponent = UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(this);
check(ASC); check(StatForgeComponent);
FinalHqMultiplier = ASC->GetNumericAttribute(UPrimaryAttributeSet::GetAlchemyMultiplierAttribute()); FinalHqMultiplier = StatForgeComponent->GetStatValue(FStat::AlchemyMultiplier);
if(FinalHqMultiplier <= 0.f) if(FinalHqMultiplier <= 0.f)
FinalHqMultiplier = 1.f; FinalHqMultiplier = 1.f;

View File

@@ -6,6 +6,7 @@
#include "MyCharacter.h" #include "MyCharacter.h"
#include "../System/Subsystem/ObjectPersistenceSubsystem.h" #include "../System/Subsystem/ObjectPersistenceSubsystem.h"
#include "EngineUtils.h" #include "EngineUtils.h"
#include "Components/StatForgeComponent.h"
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h" #include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
#include "ProjectEleri/GameObjects/EleriBaseActor.h" #include "ProjectEleri/GameObjects/EleriBaseActor.h"
@@ -127,23 +128,23 @@ void AEleriGameState::PropagateSaveData(UEleriSaveGame* InSaveData) {
//Load player data //Load player data
PlayerCharacter->SetActorTransform(SaveData.PlayerTransform); PlayerCharacter->SetActorTransform(SaveData.PlayerTransform);
if (UEleriAbilitySystemComponent* ASC = UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(GetWorld())) { if (UStatForgeComponent* StatForgeComponent = UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(GetWorld())) {
TArray<FActiveGameplayEffectHandle> CollectedEffects = ASC->GetActiveEffects(FGameplayEffectQuery::MakeQuery_MatchNoEffectTags(FGameplayTagContainer())); StatForgeComponent->RemoveAllGameplayStatEffects();
for (int32 i = CollectedEffects.Num() - 1; i >= 0; --i) {
ASC->RemoveActiveGameplayEffect(CollectedEffects[i], -9999); for (const FStatRuntimeDef& Stat : SaveData.StatData) {
FGameplayStatEffectMod Mod;
Mod.AffectedStat = Stat.StatDef.StatName;
Mod.CalculationType = EGameplayStatEffectModCalculation::Flat;
Mod.FlatValue = Stat.BaseValue;
Mod.ModOperation = EModOperation::Override;
TMap<FName, float> DataValueMap;
StatForgeComponent->ApplyModToStat(Mod, DataValueMap);
} }
for (auto Attr : SaveData.GameplayAttributes) { for (const FActiveGameplayStatEffect_SerializedData& SavedGe : SaveData.GameEffects)
ASC->SetNumericAttributeBase(Attr.Attribute, Attr.BaseValue); {
} const FGuid Id = StatForgeComponent->ApplyGameplayStatEffect(SavedGe.GameplayEffectClass, SavedGe.DataValueMap, SavedGe.StackCount);
StatForgeComponent->ModifyGeDuration(Id, SavedGe.RemainingDuration, SavedGe.NextTickDuration);
for (auto SavedGe : SaveData.GameplayEffects) {
FGameplayEffectSpecHandle GeHandle = ASC->MakeOutgoingSpec(SavedGe.EffectClass, 1.f, ASC->MakeEffectContext());
if (!SavedGe.bIsInfinite) {
GeHandle.Data->SetDuration(SavedGe.RemainingTime, false);
}
GeHandle.Data->SetStackCount(SavedGe.StackCount);
ASC->ApplyGameplayEffectSpecToSelf(*GeHandle.Data.Get());
} }
} }
} }

View File

@@ -5,8 +5,8 @@
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "EngineUtils.h" #include "EngineUtils.h"
#include "Components/StatForgeComponent.h"
#include "ProjectEleri/System/MainBlueprintFunctionLibrary.h" #include "ProjectEleri/System/MainBlueprintFunctionLibrary.h"
#include "ProjectEleri/GameplayAbilities/EleriAbilitySystemComponent.h"
#include "ProjectEleri/GameObjects/EleriBaseActor.h" #include "ProjectEleri/GameObjects/EleriBaseActor.h"
void FSaveData::Initialize() void FSaveData::Initialize()
@@ -18,8 +18,8 @@ void FSaveData::Initialize()
PlacedActors.Empty(); PlacedActors.Empty();
ActorSaveData.Empty(); ActorSaveData.Empty();
EventDataMap.Empty(); EventDataMap.Empty();
GameplayAttributes.Empty(); StatData.Empty();
GameplayEffects.Empty(); GameEffects.Empty();
} }
void FSaveData::SaveQuests(const TArray<FQuestItem>& Quests) { void FSaveData::SaveQuests(const TArray<FQuestItem>& Quests) {
@@ -93,35 +93,22 @@ void FSaveData::SetPlayerData(const UWorld* World) {
void FSaveData::SetAbilitySystemData(const UWorld* World) { void FSaveData::SetAbilitySystemData(const UWorld* World) {
if (!World) return; if (!World) return;
UEleriAbilitySystemComponent* ASC = UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(World); UStatForgeComponent* StatForgeComponent = UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(World);
if (!ASC) return; if (!StatForgeComponent) return;
for (auto Attr : ASC->GetSpawnedAttributes()) { for (const FStatRuntimeDef& StatRuntimeDef : StatForgeComponent->GetStatArray())
for (TFieldIterator<FProperty> Prop(Attr->GetClass()); Prop; ++Prop) { {
if (FGameplayAttribute AttrData = FGameplayAttribute(*Prop); AttrData.IsValid()) { StatData.Add(StatRuntimeDef);
FAbilitySystemSerializedData_Attribute AttrSaveDat;
AttrSaveDat.Attribute = AttrData;
AttrSaveDat.BaseValue = ASC->GetNumericAttributeBase(AttrData);
GameplayAttributes.Add(AttrSaveDat);
}
}
} }
TArray<FActiveGameplayEffectHandle> CollectedEffects = ASC->GetActiveEffects(FGameplayEffectQuery::MakeQuery_MatchNoEffectTags(FGameplayTagContainer())); for (const FActiveGameplayStatEffect& ActiveEffect : StatForgeComponent->GetActiveEffectsArray())
for (auto Eff : CollectedEffects) { {
const FActiveGameplayEffect* Effect = ASC->GetActiveGameplayEffect(Eff); FActiveGameplayStatEffect_SerializedData SerializedData;
if (!Effect) continue; SerializedData.GameplayEffectClass = ActiveEffect.GameplayEffectClass;
SerializedData.StackCount = ActiveEffect.StackCount;
FAbilitySystemSerializedData_Effect EffData; SerializedData.DataValueMap = ActiveEffect.GameplayEffectInstance->GetDataValueMap();
EffData.EffectClass = Effect->Spec.Def->GetClass(); SerializedData.RemainingDuration = ActiveEffect.RemainingDuration;
EffData.bIsInfinite = Effect->Spec.Duration == FGameplayEffectConstants::INFINITE_DURATION; SerializedData.NextTickDuration = ActiveEffect.NextTickDuration;
EffData.StackCount = Effect->Spec.GetStackCount(); GameEffects.Add(SerializedData);
if (!EffData.bIsInfinite) {
EffData.RemainingTime = Effect->GetTimeRemaining(World->GetWorld()->GetTimeSeconds());
}
GameplayEffects.Add(EffData);
} }
} }

View File

@@ -49,8 +49,6 @@ AMyCharacter::AMyCharacter()
InteractableOverlapMesh->SetRelativeScale3D(FVector(2.0f, 2.0f, 4.0f)); InteractableOverlapMesh->SetRelativeScale3D(FVector(2.0f, 2.0f, 4.0f));
InteractableOverlapMesh->SetGenerateOverlapEvents(true); InteractableOverlapMesh->SetGenerateOverlapEvents(true);
EleriAbilitySystemComponent = CreateDefaultSubobject<UEleriAbilitySystemComponent>(TEXT("EleriAbilitySystemComponent"));
PrimaryAttributeSet = CreateDefaultSubobject<UPrimaryAttributeSet>(TEXT("PrimaryAttributeSet"));
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>(TEXT("StatForgeComponent")); StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>(TEXT("StatForgeComponent"));
} }

View File

@@ -25,7 +25,6 @@ public class ProjectEleri : ModuleRules
"HTTP", "HTTP",
"Json", "Json",
"JsonUtilities", "JsonUtilities",
"GameplayAbilities",
"GameplayTasks", "GameplayTasks",
"UniversalCameraPlugin", "UniversalCameraPlugin",
"StateTreeModule", "StateTreeModule",

View File

@@ -13,31 +13,30 @@
#include "ProjectEleri/GameEventSystem/GameEventSubsystem.h" #include "ProjectEleri/GameEventSystem/GameEventSubsystem.h"
#include "AttributeSet.h" #include "AttributeSet.h"
#include "GameplayEffect.h" #include "GameplayEffect.h"
#include "Data/GameplayStatEffect.h"
#include "Data/StatForgeDefs.h"
#include "ProjectEleri/System/TimeOfDayStruct.h" #include "ProjectEleri/System/TimeOfDayStruct.h"
#include "EleriSaveGame.generated.h" #include "EleriSaveGame.generated.h"
USTRUCT() USTRUCT()
struct FAbilitySystemSerializedData_Attribute { struct FActiveGameplayStatEffect_SerializedData {
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY()
FGameplayAttribute Attribute;
UPROPERTY()
float BaseValue = 0;
};
USTRUCT()
struct FAbilitySystemSerializedData_Effect {
GENERATED_BODY()
public:
UPROPERTY() UPROPERTY()
TSubclassOf<UGameplayEffect> EffectClass; TSubclassOf<UGameplayStatEffect> GameplayEffectClass;
UPROPERTY() UPROPERTY()
float RemainingTime = 0; TMap<FName, float> DataValueMap;
UPROPERTY() UPROPERTY()
int32 StackCount = 1; int32 StackCount = 1;
UPROPERTY() UPROPERTY()
bool bIsInfinite = false; float RemainingDuration = -1.f;
UPROPERTY()
float NextTickDuration = -1.f;
}; };
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
@@ -70,10 +69,11 @@ struct FSaveData {
UPROPERTY() UPROPERTY()
FTransform PlayerTransform; FTransform PlayerTransform;
UPROPERTY() UPROPERTY()
TArray<FAbilitySystemSerializedData_Attribute> GameplayAttributes; TArray<FActiveGameplayStatEffect_SerializedData> GameEffects;
UPROPERTY() UPROPERTY()
TArray<FAbilitySystemSerializedData_Effect> GameplayEffects; TArray<FStatRuntimeDef> StatData;
void Initialize(); void Initialize();

View File

@@ -10,11 +10,8 @@
#include "Components/BoxComponent.h" #include "Components/BoxComponent.h"
#include "GlobalEnums.h" #include "GlobalEnums.h"
#include "Camera/CameraComponent.h" #include "Camera/CameraComponent.h"
#include "Components/ChildActorComponent.h"
#include "Delegates/Delegate.h" #include "Delegates/Delegate.h"
#include "AbilitySystemInterface.h" #include "AbilitySystemInterface.h"
#include "ProjectEleri/GameplayAbilities/EleriAbilitySystemComponent.h"
#include "ProjectEleri/GameplayAbilities/Attributes/PrimaryAttributeSet.h"
#include "ProjectEleri/Public/Interface/SaveableObjectInterface.h" #include "ProjectEleri/Public/Interface/SaveableObjectInterface.h"
#include "MyCharacter.generated.h" #include "MyCharacter.generated.h"
@@ -34,7 +31,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnInteractExit);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnBookRenderTexUpdate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnBookRenderTexUpdate);
UCLASS() UCLASS()
class PROJECTELERI_API AMyCharacter : public ACharacter, public IAbilitySystemInterface, public ISaveableObjectInterface class PROJECTELERI_API AMyCharacter : public ACharacter, public ISaveableObjectInterface
{ {
GENERATED_BODY() GENERATED_BODY()
@@ -74,15 +71,9 @@ protected:
UPROPERTY() UPROPERTY()
float CachedHalfHeight; float CachedHalfHeight;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
UEleriAbilitySystemComponent* EleriAbilitySystemComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
UStatForgeComponent* StatForgeComponent; UStatForgeComponent* StatForgeComponent;
UPROPERTY()
UPrimaryAttributeSet* PrimaryAttributeSet;
UPROPERTY() UPROPERTY()
TObjectPtr<AUniversalCamera> CameraRef; TObjectPtr<AUniversalCamera> CameraRef;
@@ -108,11 +99,6 @@ public:
virtual FActorSaveData RequestSave() override; virtual FActorSaveData RequestSave() override;
virtual void RequestLoad(FActorSaveData& Data) override; virtual void RequestLoad(FActorSaveData& Data) override;
UFUNCTION(BlueprintCallable, BlueprintPure)
virtual class UAbilitySystemComponent* GetAbilitySystemComponent() const override { return EleriAbilitySystemComponent; }
UFUNCTION(BlueprintCallable, BlueprintPure)
UPrimaryAttributeSet* GetPrimaryAttributeSet() { return PrimaryAttributeSet; }
UFUNCTION(BlueprintCallable, BlueprintPure) UFUNCTION(BlueprintCallable, BlueprintPure)
UStatForgeComponent* GetStatForgeComponent() const { return StatForgeComponent; } UStatForgeComponent* GetStatForgeComponent() const { return StatForgeComponent; }

View File

@@ -5,6 +5,7 @@
#include "ProjectEleri/Items/DataAssets/ItemDataAsset.h" #include "ProjectEleri/Items/DataAssets/ItemDataAsset.h"
#include "ProjectEleri/Items/ItemDatabase.h" #include "ProjectEleri/Items/ItemDatabase.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "ProjectEleri/Data/EleriGlobalKeyValueStruct.h"
bool UEleriGameSettings::GetCameraZoom(FGameplayTag Tag, FVector& OutBoomLength) { bool UEleriGameSettings::GetCameraZoom(FGameplayTag Tag, FVector& OutBoomLength) {
if (const UEleriGameSettings* Settings = GetDefault<UEleriGameSettings>()) { if (const UEleriGameSettings* Settings = GetDefault<UEleriGameSettings>()) {
@@ -55,3 +56,18 @@ int32 UEleriGameSettings::GetProfessionLevelForExp(float Exp) {
return 0; return 0;
} }
float UEleriGameSettings::GetGlobalKeyValue(const FName& Key)
{
if (!GetEleriGameSettings()->GlobalSettingsDataSheet.IsValid())
{
GetEleriGameSettings()->GlobalSettingsDataSheet.LoadSynchronous();
}
if (const FEleriGlobalKeyValueStruct* RowPtr = GetEleriGameSettings()->GlobalSettingsDataSheet->FindRow<FEleriGlobalKeyValueStruct>(Key, TEXT("")))
{
return RowPtr->Value;
}
return -1.f;
}

View File

@@ -6,9 +6,12 @@
#include "Engine/DeveloperSettings.h" #include "Engine/DeveloperSettings.h"
#include "GameplayTagContainer.h" #include "GameplayTagContainer.h"
#include "Data/GameplayStatEffect.h" #include "Data/GameplayStatEffect.h"
#include "Templates/SubclassOf.h"
#include "UObject/SoftObjectPtr.h"
#include "EleriGameSettings.generated.h" #include "EleriGameSettings.generated.h"
class UDataTable;
class UNpcDataAsset; class UNpcDataAsset;
class UNpcScheduleAsset; class UNpcScheduleAsset;
class UItemDataAsset; class UItemDataAsset;
@@ -38,6 +41,9 @@ public:
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ai") UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ai")
TArray<TSoftObjectPtr<UNpcDataAsset>> NpcDataAssets; TArray<TSoftObjectPtr<UNpcDataAsset>> NpcDataAssets;
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ability System|Settings")
TSoftObjectPtr<UDataTable> GlobalSettingsDataSheet;
public: public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri Game Settingss") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri Game Settingss")
@@ -57,4 +63,7 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Ability System|Professions") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Ability System|Professions")
static int32 GetProfessionLevelForExp(float Exp); static int32 GetProfessionLevelForExp(float Exp);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri Game Settingss", meta = (AutoCreateRefTerm = "Key"))
static float GetGlobalKeyValue(const FName& Key);
}; };

View File

@@ -44,12 +44,6 @@ public:
UFUNCTION(BlueprintCallable, Category = "Eleri", meta=(WorldContext="WorldContextObject")) UFUNCTION(BlueprintCallable, Category = "Eleri", meta=(WorldContext="WorldContextObject"))
static UMainGameWidget* GetMainGameWidget(UObject* WorldContextObject); static UMainGameWidget* GetMainGameWidget(UObject* WorldContextObject);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri", meta = (WorldContext = "WorldContextObject"))
static UEleriAbilitySystemComponent* GetAbilitySystemComponentFromActor(const AActor* Actor);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri", meta = (WorldContext = "WorldContextObject"))
static UEleriAbilitySystemComponent* GetAbilitySystemComponentFromPlayer(const UObject* WorldContextObject);
UFUNCTION(BlueprintCallable, Category = "Eleri") UFUNCTION(BlueprintCallable, Category = "Eleri")
static ARemovableStaticMeshActor* SpawnPlaceable(UWorld* World, UClass* Class, FTransform Transform, FVector ScaleOverride); static ARemovableStaticMeshActor* SpawnPlaceable(UWorld* World, UClass* Class, FTransform Transform, FVector ScaleOverride);
@@ -79,8 +73,16 @@ public:
// STATS // STATS
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri|Stats") UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri|Stats")
static UStatForgeComponent* GetStatForgeComponentFromActor(AActor* Actor); static UStatForgeComponent* GetStatForgeComponentFromActor(const AActor* Actor);
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri|Stats", meta = (WorldContext = "WorldContext"))
static UStatForgeComponent* GetStatForgeComponentFromPlayer(const UObject* WorldContext);
UFUNCTION(BlueprintCallable, Category = "Eleri|Stats", meta = (WorldContext = "WorldContext")) UFUNCTION(BlueprintCallable, Category = "Eleri|Stats", meta = (WorldContext = "WorldContext"))
static void ModifyExp(const UObject* WorldContext, const EExpType ExpType, const float Amount); static void ModifyExp(const UObject* WorldContext, const EExpType ExpType, const float Amount);
// MATH
UFUNCTION(BlueprintPure, Category = "Eleri|Math")
static float NegateFloat(const float& Value) { return Value * -1.f; }
}; };

View File

@@ -15,7 +15,6 @@
#include "ProjectEleri/GameObjects/BaseCharacter.h" #include "ProjectEleri/GameObjects/BaseCharacter.h"
#include "Runtime/Online/HTTP/Public/HttpModule.h" #include "Runtime/Online/HTTP/Public/HttpModule.h"
#include "ProjectEleri/Settings/EleriGameSettings.h" #include "ProjectEleri/Settings/EleriGameSettings.h"
#include "ProjectEleri/GameplayAbilities/EleriAbilitySystemComponent.h"
void UMainBlueprintFunctionLibrary::PostFeedback(const FString& Message) { void UMainBlueprintFunctionLibrary::PostFeedback(const FString& Message) {
auto request = FHttpModule::Get().CreateRequest(); auto request = FHttpModule::Get().CreateRequest();
@@ -54,22 +53,6 @@ UMainGameWidget* UMainBlueprintFunctionLibrary::GetMainGameWidget(UObject* World
return nullptr; return nullptr;
} }
UEleriAbilitySystemComponent* UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromActor(const AActor* Actor) {
if (!IsValid(Actor) || !Actor->GetWorld())
return nullptr;
return Actor->GetComponentByClass<UEleriAbilitySystemComponent>();
}
UEleriAbilitySystemComponent* UMainBlueprintFunctionLibrary::GetAbilitySystemComponentFromPlayer(const UObject* WorldContextObject) {
if (!WorldContextObject || !WorldContextObject->GetWorld())
return nullptr;
if (ACharacter* PlayerChar = UGameplayStatics::GetPlayerCharacter(WorldContextObject, 0)) {
return PlayerChar->GetComponentByClass<UEleriAbilitySystemComponent>();
}
return nullptr;
}
ARemovableStaticMeshActor* UMainBlueprintFunctionLibrary::SpawnPlaceable(UWorld* World, UClass* Class, FTransform Transform, FVector ScaleOverride) { ARemovableStaticMeshActor* UMainBlueprintFunctionLibrary::SpawnPlaceable(UWorld* World, UClass* Class, FTransform Transform, FVector ScaleOverride) {
Transform.SetScale3D(FVector::OneVector); Transform.SetScale3D(FVector::OneVector);
return World->SpawnActor<ARemovableStaticMeshActor>(Class, Transform, FActorSpawnParameters()); return World->SpawnActor<ARemovableStaticMeshActor>(Class, Transform, FActorSpawnParameters());
@@ -168,11 +151,18 @@ float UMainBlueprintFunctionLibrary::GetCharacterHeight(const UObject* WorldCont
return 0.f; return 0.f;
} }
UStatForgeComponent* UMainBlueprintFunctionLibrary::GetStatForgeComponentFromActor(AActor* Actor) UStatForgeComponent* UMainBlueprintFunctionLibrary::GetStatForgeComponentFromActor(const AActor* Actor)
{ {
if (!Actor) return nullptr; if (!Actor) return nullptr;
if (const AMyCharacter* MyCharacter = Cast<AMyCharacter>(Actor)) return Actor->GetComponentByClass<UStatForgeComponent>();
}
UStatForgeComponent* UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(const UObject* WorldContext)
{
if (!WorldContext) return nullptr;
if (const AMyCharacter* MyCharacter = Cast<AMyCharacter>(UGameplayStatics::GetPlayerCharacter(WorldContext, 0)))
{ {
return MyCharacter->GetStatForgeComponent(); return MyCharacter->GetStatForgeComponent();
} }
@@ -184,7 +174,7 @@ void UMainBlueprintFunctionLibrary::ModifyExp(const UObject* WorldContext, const
{ {
if (!WorldContext || !WorldContext->GetWorld()) return; if (!WorldContext || !WorldContext->GetWorld()) return;
UStatForgeComponent* StatForgeComponent = GetStatForgeComponentFromActor(UGameplayStatics::GetPlayerCharacter(WorldContext, 0)); UStatForgeComponent* StatForgeComponent = GetStatForgeComponentFromPlayer(WorldContext);
if (!StatForgeComponent) return; if (!StatForgeComponent) return;
const UEleriGameSettings* GameSettings = UEleriGameSettings::GetEleriGameSettings(); const UEleriGameSettings* GameSettings = UEleriGameSettings::GetEleriGameSettings();