44#include " ComponentDynamicAttributes.h"
55
66void UActorCDA::InitializeAttributes ()
7+ {
8+ // Rebuild runtime attributes from configured assets/collections.
9+ RebuildAttributesFromAssets ();
10+ }
11+
12+ void UActorCDA::AddAttributeDefinition (const FAttributeDefinitionCDA& Definition)
13+ {
14+ if (!Definition.AttributeTag .IsValid ())
15+ {
16+ UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::AddAttributeDefinition - Invalid GameplayTag." ));
17+ return ;
18+ }
19+ // Delegate to the unified registration pipeline. Do not manipulate runtime arrays here.
20+ FAttributeRuntimeDataCDA RuntimeData;
21+ RuntimeData.BaseValue = Definition.BaseValue ;
22+ RuntimeData.MinValue = Definition.MinValue ;
23+ RuntimeData.MaxValue = Definition.MaxValue ;
24+ RuntimeData.CachedMaxValue = FMath::Clamp (Definition.BaseValue , Definition.MinValue , Definition.MaxValue );
25+ RuntimeData.CurrentValue = RuntimeData.CachedMaxValue ;
26+ RuntimeData.Modifiers .Reset ();
27+ RuntimeData.bNeedsRecalculation = false ;
28+
29+ if (!RegisterAttributeInternal (Definition.AttributeTag , RuntimeData, Definition, false ))
30+ {
31+ UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::AddAttributeDefinition - Duplicate GameplayTag found: %s. Skipping." ), *Definition.AttributeTag .ToString ());
32+ }
33+ }
34+
35+ void UActorCDA::RebuildAttributesFromAssets ()
736{
837 AttributeIndex.Reset ();
938 Attributes.Reset ();
1039 AttributeDefinitions.Reset ();
1140
12- if (RegisteredAttributeAssets.IsEmpty ())
41+ // Count total definitions to reserve arrays
42+ int32 TotalDefinitions = 0 ;
43+
44+ for (const TObjectPtr<UAttributesCollectionDataAssetCDA>& Collection : RegisteredAttributeCollections)
1345 {
14- return ;
46+ if (!IsValid (Collection))
47+ {
48+ continue ;
49+ }
50+
51+ for (const TObjectPtr<UAttributesDataAssetCDA>& Asset : Collection->AttributeAssets )
52+ {
53+ if (IsValid (Asset))
54+ {
55+ TotalDefinitions += Asset->Attributes .Num ();
56+ }
57+ }
1558 }
1659
17- int32 TotalDefinitions = 0 ;
1860 for (const TObjectPtr<UAttributesDataAssetCDA>& DataAsset : RegisteredAttributeAssets)
1961 {
2062 if (IsValid (DataAsset))
@@ -26,50 +68,66 @@ void UActorCDA::InitializeAttributes()
2668 Attributes.Reserve (TotalDefinitions);
2769 AttributeDefinitions.Reserve (TotalDefinitions);
2870
29- for (const TObjectPtr<UAttributesDataAssetCDA>& DataAsset : RegisteredAttributeAssets)
71+ // Register collections first
72+ for (const TObjectPtr<UAttributesCollectionDataAssetCDA>& Collection : RegisteredAttributeCollections)
3073 {
31- if (!IsValid (DataAsset ))
74+ if (!IsValid (Collection ))
3275 {
33- UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::InitializeAttributes - Invalid AttributesDataAsset." ));
3476 continue ;
3577 }
3678
37- if (DataAsset->Attributes .IsEmpty ())
79+ RegisterAttributesFromCollection (Collection, false );
80+ }
81+
82+ // Then register single assets
83+ for (const TObjectPtr<UAttributesDataAssetCDA>& DataAsset : RegisteredAttributeAssets)
84+ {
85+ if (!IsValid (DataAsset))
3886 {
87+ UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::RebuildAttributesFromAssets - Invalid AttributesDataAsset." ));
3988 continue ;
4089 }
4190
42- for (const FAttributeDefinitionCDA& Definition : DataAsset->Attributes )
43- {
44- AddAttributeDefinition (Definition);
45- }
91+ RegisterAttributesFromDataAsset (DataAsset, false );
4692 }
4793}
4894
49- void UActorCDA::AddAttributeDefinition ( const FAttributeDefinitionCDA& Definition )
95+ void UActorCDA::RegisterAttributesFromDataAsset (UAttributesDataAssetCDA* DataAsset, bool bOverrideExisting )
5096{
51- if (!Definition. AttributeTag . IsValid ())
97+ if (!IsValid (DataAsset ))
5298 {
53- UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::AddAttributeDefinition - Invalid GameplayTag." ));
5499 return ;
55100 }
56101
57- if (AttributeIndex.Contains (Definition.AttributeTag ))
102+ for (const FAttributeDefinitionCDA& Definition : DataAsset->Attributes )
103+ {
104+ FAttributeRuntimeDataCDA RuntimeData;
105+
106+ RuntimeData.BaseValue = Definition.BaseValue ;
107+ RuntimeData.MinValue = Definition.MinValue ;
108+ RuntimeData.MaxValue = Definition.MaxValue ;
109+
110+ RuntimeData.CachedMaxValue = FMath::Clamp (Definition.BaseValue , Definition.MinValue , Definition.MaxValue );
111+ RuntimeData.CurrentValue = RuntimeData.CachedMaxValue ;
112+
113+ RegisterAttributeInternal (Definition.AttributeTag , RuntimeData, Definition, bOverrideExisting);
114+ }
115+ }
116+
117+ void UActorCDA::RegisterAttributesFromCollection (UAttributesCollectionDataAssetCDA* Collection, bool bOverrideExisting)
118+ {
119+ if (!IsValid (Collection))
58120 {
59- UE_LOG (LogComponentDynamicAttributes, Warning, TEXT (" ActorCDA::AddAttributeDefinition - Duplicate GameplayTag found: %s. Skipping." ), *Definition.AttributeTag .ToString ());
60121 return ;
61122 }
62123
63- const int32 NewIndex = Attributes.AddDefaulted ();
64- AttributeIndex.Add (Definition.AttributeTag , NewIndex);
65- AttributeDefinitions.Add (Definition);
124+ for (const TObjectPtr<UAttributesDataAssetCDA>& Asset : Collection->AttributeAssets )
125+ {
126+ if (!IsValid (Asset))
127+ {
128+ continue ;
129+ }
66130
67- FAttributeRuntimeDataCDA& RuntimeData = Attributes[NewIndex];
68- RuntimeData.BaseValue = Definition.BaseValue ;
69- RuntimeData.MinValue = Definition.MinValue ;
70- RuntimeData.MaxValue = Definition.MaxValue ;
71- RuntimeData.CachedMaxValue = FMath::Clamp (Definition.BaseValue , Definition.MinValue , Definition.MaxValue );
72- RuntimeData.CurrentValue = RuntimeData.CachedMaxValue ;
73- RuntimeData.Modifiers .Reset ();
74- RuntimeData.bNeedsRecalculation = false ;
131+ RegisterAttributesFromDataAsset (Asset.Get (), bOverrideExisting);
132+ }
75133}
0 commit comments