Skip to content

Commit d9cb06f

Browse files
committed
Optimized Modifier & Attribute networking, Improved Modifier UX, Improved API
1 parent 9356675 commit d9cb06f

19 files changed

Lines changed: 623 additions & 177 deletions

AttributesExtension.uplugin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"FileVersion": 3,
33
"Version": 3,
4-
"VersionName": "1.2",
4+
"VersionName": "1.3",
55
"FriendlyName": "Attributes Extension",
66
"Description": "A lightweight attributes system for Unreal Engine 4",
77
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/1f0ba37099a14e228a1ce5e4891ed70a",

Source/Attributes/Private/AttrModifier.cpp

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,76 @@
44
#include "FloatAttr.h"
55

66

7+
FAttrModifier::FAttrModifier(EModifierMask Mode, float Value)
8+
: Guid(FGuid::NewGuid())
9+
{
10+
switch (Mode)
11+
{
12+
case EModifierMask::Increment:
13+
Increment = Value;
14+
break;
15+
case EModifierMask::LastMultiplier:
16+
LastMultiplier = Value;
17+
break;
18+
case EModifierMask::BaseMultiplier:
19+
BaseMultiplier = Value;
20+
break;
21+
}
22+
}
23+
24+
FAttrModifier::FAttrModifier(float Increment, float LastValueMultiplier, float BaseValueMultiplier)
25+
: Guid(FGuid::NewGuid())
26+
, Increment(Increment)
27+
, LastMultiplier(LastValueMultiplier)
28+
, BaseMultiplier(BaseValueMultiplier)
29+
{
30+
}
31+
732
void FAttrModifier::Apply(float& Value, float BaseValue) const
833
{
9-
if (!FMath::IsNearlyZero(LastValueMultiplier))
34+
if (!FMath::IsNearlyZero(LastMultiplier))
1035
{
11-
Value *= 1.0f + LastValueMultiplier;
36+
Value *= 1.0f + LastMultiplier;
1237
}
13-
if (!FMath::IsNearlyZero(BaseValueMultiplier))
38+
if (!FMath::IsNearlyZero(BaseMultiplier))
1439
{
15-
Value += BaseValueMultiplier * BaseValue;
40+
Value += BaseMultiplier * BaseValue;
1641
}
1742
Value += Increment;
1843
}
1944

2045
void FAttrModifier::Apply(double& Value, int32 BaseValue) const
2146
{
22-
if (!FMath::IsNearlyZero(LastValueMultiplier))
47+
if (!FMath::IsNearlyZero(LastMultiplier))
2348
{
24-
Value *= 1.0 + LastValueMultiplier;
49+
Value *= 1.0 + LastMultiplier;
2550
}
26-
if (!FMath::IsNearlyZero(BaseValueMultiplier))
51+
if (!FMath::IsNearlyZero(BaseMultiplier))
2752
{
28-
Value += BaseValueMultiplier * BaseValue;
53+
Value += BaseMultiplier * BaseValue;
2954
}
3055
Value += Increment;
3156
}
3257

3358
void FAttrModifier::StackMods(const TArray<FAttrModifier>& OtherMods)
3459
{
60+
for (const auto& Mod : OtherMods)
61+
{
62+
StackMod(Mod);
63+
}
3564
}
3665

3766
void FAttrModifier::StackMod(const FAttrModifier& OtherMod)
3867
{
39-
if (!FMath::IsNearlyZero(OtherMod.LastValueMultiplier))
68+
if (!FMath::IsNearlyZero(OtherMod.LastMultiplier))
4069
{
4170
// Stack % value
42-
LastValueMultiplier = (1.f + LastValueMultiplier) * (1.f + OtherMod.LastValueMultiplier) - 1.0f;
71+
LastMultiplier = (1.f + LastMultiplier) * (1.f + OtherMod.LastMultiplier) - 1.0f;
4372
}
44-
if (!FMath::IsNearlyZero(OtherMod.BaseValueMultiplier))
73+
if (!FMath::IsNearlyZero(OtherMod.BaseMultiplier))
4574
{
4675
// Stack % base value
47-
BaseValueMultiplier = (1.f + BaseValueMultiplier) * (1.f + OtherMod.BaseValueMultiplier) - 1.0f;
76+
BaseMultiplier = (1.f + BaseMultiplier) * (1.f + OtherMod.BaseMultiplier) - 1.0f;
4877
}
4978
Increment += OtherMod.Increment;
5079
}

Source/Attributes/Private/AttributesSettings.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,27 @@
44
#include "AttributesModule.h"
55

66

7+
FAttributeReplicationConfig UAttributesSettings::Replication{};
8+
9+
710
UAttributesSettings::UAttributesSettings()
811
: Super()
912
{
1013
Categories.Add(TEXT("Buff"));
1114
Categories.Add(TEXT("Aura"));
1215

13-
FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UAttributesSettings::OnWorldInitialization);
16+
FWorldDelegates::OnPreWorldInitialization.AddUObject(this, &UAttributesSettings::OnWorldInitialization);
1417
}
1518

1619
void UAttributesSettings::BeginDestroy()
1720
{
18-
FWorldDelegates::OnPostWorldInitialization.RemoveAll(this);
21+
FWorldDelegates::OnPreWorldInitialization.RemoveAll(this);
1922

2023
Super::BeginDestroy();
2124
}
2225

2326
void UAttributesSettings::OnWorldInitialization(UWorld* World, const UWorld::InitializationValues IVS)
2427
{
25-
//Initialize manager
26-
//FAttributesModule::GetAttributesManager();
28+
// Update replication settings
29+
Replication = { bReplicateBaseValue, bReplicateAttributeModifiers };
2730
}

Source/Attributes/Private/FloatAttr.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ void FFloatAttr::SetBaseValue(float NewValue)
1616
}
1717
}
1818

19-
void FFloatAttr::PostSerialize(const FArchive & Ar)
19+
void FFloatAttr::PostScriptConstruct()
2020
{
21-
if (Ar.IsSaving())
22-
{
23-
RefreshValue();
24-
}
21+
RefreshValue();
2522
}
2623

2724
void FFloatAttr::RefreshValue()

Source/Attributes/Private/Int32Attr.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ void FInt32Attr::SetBaseValue(int32 NewValue)
1616
}
1717
}
1818

19-
void FInt32Attr::PostSerialize(const FArchive & Ar)
19+
void FInt32Attr::PostScriptConstruct()
2020
{
21-
if (Ar.IsSaving())
22-
{
23-
RefreshValue();
24-
}
21+
RefreshValue();
2522
}
2623

2724
void FInt32Attr::RefreshValue()

Source/Attributes/Public/AttrModifier.h

Lines changed: 122 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,75 @@
88

99
struct FFloatAttr;
1010

11-
/**
12-
*
13-
*/
11+
/* Masks modifier effects in editor. */
12+
UENUM(BlueprintType)
13+
enum class EModifierMask : uint8
14+
{
15+
Increment, // X += Value | Sums a value to the attribute
16+
LastMultiplier, // X += X * Cof | Adds the incremental coefficient of the last modified value.
17+
BaseMultiplier // X += Base * Cof | Adds the incremental coefficient of the base value of the attribute.
18+
};
19+
20+
21+
/** Contains modifier values to be applied to an attribute. 32B */
1422
USTRUCT(BlueprintType)
1523
struct ATTRIBUTES_API FAttrModifier
1624
{
1725
GENERATED_BODY()
1826

19-
FAttrModifier()
20-
: Guid(FGuid::NewGuid())
21-
, Increment(0.f)
22-
, LastValueMultiplier(0.f)
23-
, BaseValueMultiplier(0.f)
24-
{}
27+
/************************************************************************/
28+
/* PROPERTIES */
29+
/************************************************************************/
30+
protected:
2531

26-
FAttrModifier(float BaseValueMultiplier, float LastValueMultiplier = 0.f, float Increment = 0.f)
27-
: Guid(FGuid::NewGuid())
28-
, Increment(Increment)
29-
, LastValueMultiplier(LastValueMultiplier)
30-
, BaseValueMultiplier(BaseValueMultiplier)
31-
{}
32+
UPROPERTY(BlueprintReadOnly, Category = Modifier)
33+
FGuid Guid;
34+
35+
// We use 4 bytes of alignment for Dirty flags
36+
UPROPERTY(Transient)
37+
bool bNetDirty_Guid = true;
3238

3339
public:
3440

35-
UPROPERTY(BlueprintReadOnly, Category = Modifier)
36-
FGuid Guid;
41+
// X += Value | Sums a value to the attribute
42+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier, meta = (ColumnWidth = "70", Delta = "0.01"))
43+
float Increment = 0.f;
3744

38-
/* Sums an amount to the attribute */
39-
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier)
40-
float Increment;
45+
// X += X * Cof | Adds the incremental coefficient of the last modified value.
46+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier, meta = (ColumnWidth = "70", UIMin = "-1.0", UIMax = "1.0", Delta="0.05", Units = "x"))
47+
float LastMultiplier = 0.f;
4148

42-
/* Adds the incremental coefficient of the last attribute value. E.g: +5% health
43-
* X += X * Cof
44-
*/
45-
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier, meta = (UIMin = "-1.0", UIMax = "1.0"))
46-
float LastValueMultiplier;
49+
// X += Base * Cof | Adds the incremental coefficient of the base value of the attribute.
50+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier, meta = (UIMin = "-1.0", UIMax = "1.0", Delta = "0.05", Units = "x"))
51+
float BaseMultiplier = 0.f;
4752

48-
/* Adds the incremental coefficient of Base. E.g: +5% damage
49-
* X += Base * Cof
50-
*/
51-
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Modifier, meta = (UIMin = "-1.0", UIMax = "1.0"))
52-
float BaseValueMultiplier;
5353

54+
/************************************************************************/
55+
/* METHODS */
56+
/************************************************************************/
57+
58+
FAttrModifier() : Guid(FGuid::NewGuid()) {}
59+
60+
FAttrModifier(EModifierMask Mode, float Value = 0.f);
61+
62+
FAttrModifier(float Increment, float LastValueMultiplier = 0.f, float BaseValueMultiplier = 0.f);
63+
64+
FAttrModifier(FAttrModifier&& Other) : Guid(Other.Guid) { SetValues(Other); }
65+
FAttrModifier(const FAttrModifier& Other) : Guid(Other.Guid) { SetValues(Other); }
66+
FAttrModifier& operator=(FAttrModifier&& Other)
67+
{
68+
Guid = Other.Guid;
69+
bNetDirty_Guid = true;
70+
SetValues(Other);
71+
return *this;
72+
}
73+
FAttrModifier& operator=(const FAttrModifier& Other)
74+
{
75+
Guid = Other.Guid;
76+
bNetDirty_Guid = true;
77+
SetValues(Other);
78+
return *this;
79+
}
5480

5581
/** Apply changes to the value */
5682
void Apply(float& Value, float BaseValue) const;
@@ -73,4 +99,70 @@ struct ATTRIBUTES_API FAttrModifier
7399
{
74100
return Guid == Other.Guid;
75101
}
102+
FORCEINLINE bool operator!=(const FAttrModifier& Other) const { return !(*this == Other); }
103+
104+
void SetValues(FAttrModifier&& Other)
105+
{
106+
Increment = Other.Increment;
107+
LastMultiplier = Other.LastMultiplier;
108+
BaseMultiplier = Other.BaseMultiplier;
109+
}
110+
111+
void SetValues(const FAttrModifier& Other)
112+
{
113+
Increment = Other.Increment;
114+
LastMultiplier = Other.LastMultiplier;
115+
BaseMultiplier = Other.BaseMultiplier;
116+
}
117+
118+
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess);
76119
};
120+
121+
template<>
122+
struct TStructOpsTypeTraits<FAttrModifier> : public TStructOpsTypeTraitsBase2<FAttrModifier>
123+
{
124+
enum
125+
{
126+
WithCopy = true,
127+
WithNetSerializer = true,
128+
WithNetSharedSerialization = true,
129+
//WithIdenticalViaEquality = true
130+
};
131+
};
132+
133+
134+
inline bool FAttrModifier::NetSerialize(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess)
135+
{
136+
// Only replicate non-zero values
137+
uint8 Flags = (bNetDirty_Guid << 0)
138+
| (!FMath::IsNearlyZero(Increment) << 1)
139+
| (!FMath::IsNearlyZero(LastMultiplier) << 2)
140+
| (!FMath::IsNearlyZero(BaseMultiplier) << 3);
141+
142+
Ar.SerializeBits(&Flags, 4);
143+
144+
bNetDirty_Guid = Flags & 1 << 0;
145+
if (bNetDirty_Guid)
146+
{
147+
Ar << Guid;
148+
bNetDirty_Guid = false;
149+
}
150+
151+
if (Flags & 1 << 1)
152+
Ar << Increment;
153+
else
154+
Increment = 0.f;
155+
156+
if (Flags & 1 << 2)
157+
Ar << LastMultiplier;
158+
else
159+
LastMultiplier = 0.f;
160+
161+
if (Flags & 1 << 3)
162+
Ar << BaseMultiplier;
163+
else
164+
BaseMultiplier = 0.f;
165+
166+
bOutSuccess = true;
167+
return true;
168+
}

Source/Attributes/Public/AttributesSettings.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
#include "AttributesSettings.generated.h"
99

10+
struct FAttributeReplicationConfig
11+
{
12+
bool bReplicateBaseValue = true;
13+
14+
bool bReplicateAttributeModifiers = false;
15+
};
16+
1017

1118
/**
1219
*
@@ -22,6 +29,14 @@ class ATTRIBUTES_API UAttributesSettings : public UObject
2229
UPROPERTY(config, EditAnywhere, Category = Modifiers, SaveGame)
2330
TSet<FName> Categories;
2431

32+
UPROPERTY(config, EditAnywhere, Category = Replication, SaveGame)
33+
bool bReplicateBaseValue = true;
34+
35+
UPROPERTY(config, VisibleAnywhere, Category = Replication, SaveGame)
36+
bool bReplicateAttributeModifiers = false;
37+
38+
// We keep a global instance of the replication settings for efficiency
39+
static FAttributeReplicationConfig Replication;
2540

2641
public:
2742

@@ -37,4 +52,8 @@ class ATTRIBUTES_API UAttributesSettings : public UObject
3752
virtual void BeginDestroy() override;
3853

3954
void OnWorldInitialization(UWorld* World, const UWorld::InitializationValues IVS);
55+
56+
public:
57+
58+
static const FAttributeReplicationConfig& GetReplication() { return Replication; }
4059
};

0 commit comments

Comments
 (0)