From ef002ccf53ba6035ed0855d6fcf512649a043dbd Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 24 Apr 2024 18:18:26 -0400 Subject: [PATCH] 45. PreAttributeChange --- .../Core/AbilitySystem/GE_AreaFire.uasset | 2 +- .../Gasa/AbilitySystem/GasaAttributeSet.cpp | 25 ++- .../Gasa/AbilitySystem/GasaAttributeSet.h | 30 ++- Project/Source/GasaGen/GasaGenCommon.cpp | 3 + .../GasaGen/GasaGen_HostWidgetController.cpp | 19 +- .../GasaGen/GasaGen_UGasaAttributeSet.cpp | 171 ++++++++++++------ scripts/gencpp.natvis | 15 ++ 7 files changed, 182 insertions(+), 83 deletions(-) diff --git a/Project/Content/Core/AbilitySystem/GE_AreaFire.uasset b/Project/Content/Core/AbilitySystem/GE_AreaFire.uasset index 22c7b5c..b1979ce 100644 --- a/Project/Content/Core/AbilitySystem/GE_AreaFire.uasset +++ b/Project/Content/Core/AbilitySystem/GE_AreaFire.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a83a98fac27c1e831ed8437aea996a15c9de3eaf25233f6307c4ad8766b61bf4 +oid sha256:c6ce2ba41b64462c280fc8c683ea2b425daba0dbf3098c18d8d62fd0e2bced2a size 13946 diff --git a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp index d8588df..ff24001 100644 --- a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp +++ b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.cpp @@ -8,9 +8,9 @@ UGasaAttributeSet::UGasaAttributeSet() { - InitHealth( 50.f ); + InitHealth( 100.f ); InitMaxHealth( 100.f ); - InitMana( 25.f ); + InitMana( 50.f ); InitMaxMana( 50.f ); } @@ -41,6 +41,27 @@ void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMan } #pragma endregion Rep Notifies +void UGasaAttributeSet::PreAttributeChange( FGameplayAttribute const& Attribute, float& NewValue ) +{ + Super::PreAttributeChange( Attribute, NewValue ); + + if ( Attribute == GetHealthAttribute() ) + { + NewValue = FMath::Clamp( NewValue, 0, GetMaxHealth() ); + } + if ( Attribute == GetMaxHealthAttribute() ) + { + NewValue = FMath::Clamp( NewValue, 0, 99999.000000 ); + } + if ( Attribute == GetManaAttribute() ) + { + NewValue = FMath::Clamp( NewValue, 0, GetMaxMana() ); + } + if ( Attribute == GetMaxManaAttribute() ) + { + NewValue = FMath::Clamp( NewValue, 0, 99999.000000 ); + } +} void UGasaAttributeSet::GetLifetimeReplicatedProps( TArray& OutLifetimeProps ) const { Super::GetLifetimeReplicatedProps( OutLifetimeProps ); diff --git a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h index 6d4cd2a..4a83286 100644 --- a/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h +++ b/Project/Source/Gasa/AbilitySystem/GasaAttributeSet.h @@ -9,20 +9,16 @@ class GASA_API UGasaAttributeSet : public UAttributeSet { GENERATED_BODY() public: - UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) - FGameplayAttributeData Health; - - UPROPERTY( ReplicatedUsing = Client_OnRep_MaxHealth, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) - FGameplayAttributeData MaxHealth; - - UPROPERTY( ReplicatedUsing = Client_OnRep_Mana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) - FGameplayAttributeData Mana; - - UPROPERTY( ReplicatedUsing = Client_OnRep_MaxMana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) - FGameplayAttributeData MaxMana; - UGasaAttributeSet(); + UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) + FGameplayAttributeData Health; + UPROPERTY( ReplicatedUsing = Client_OnRep_MaxHealth, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) + FGameplayAttributeData MaxHealth; + UPROPERTY( ReplicatedUsing = Client_OnRep_Mana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) + FGameplayAttributeData Mana; + UPROPERTY( ReplicatedUsing = Client_OnRep_MaxMana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) + FGameplayAttributeData MaxMana; UFUNCTION() void Client_OnRep_Health( FGameplayAttributeData& PrevHealth ); @@ -62,8 +58,7 @@ public: #pragma endregion Getters #pragma region Setters - FORCEINLINE void - SetHealth( float NewVal ); + FORCEINLINE void SetHealth( float NewVal ); FORCEINLINE void SetMaxHealth( float NewVal ); FORCEINLINE void SetMana( float NewVal ); FORCEINLINE void SetMaxMana( float NewVal ); @@ -90,8 +85,11 @@ public: } #pragma endregion Setters +#pragma region AttributeSet + void PreAttributeChange( const FGameplayAttribute& Attribute, float& NewValue ) override; +#pragma endregion AttributeSet + #pragma region UObject - void - GetLifetimeReplicatedProps( TArray& OutLifetimeProps ) const override; + void GetLifetimeReplicatedProps( TArray& OutLifetimeProps ) const override; #pragma endregion UObject }; diff --git a/Project/Source/GasaGen/GasaGenCommon.cpp b/Project/Source/GasaGen/GasaGenCommon.cpp index 1f1e09f..b2e8d3a 100644 --- a/Project/Source/GasaGen/GasaGenCommon.cpp +++ b/Project/Source/GasaGen/GasaGenCommon.cpp @@ -77,6 +77,9 @@ CodeBody parse_file( char const* path ) { return code; } +// inline +// CodeConstructor find_constructor( StrC parent_name, ) + inline void format_file( char const* path ) { diff --git a/Project/Source/GasaGen/GasaGen_HostWidgetController.cpp b/Project/Source/GasaGen/GasaGen_HostWidgetController.cpp index b922d59..f24cc5e 100644 --- a/Project/Source/GasaGen/GasaGen_HostWidgetController.cpp +++ b/Project/Source/GasaGen/GasaGen_HostWidgetController.cpp @@ -4,11 +4,12 @@ #include "gen.hpp" #include "gen.builder.hpp" #include "GasaGenCommon.cpp" +#include "GasaGen_UGasaAttributeSet.cpp" #endif void gen_UHostWidgetController() { - Array attribute_fields = get_gasa_attribute_fields(); + Array attribute_fields = get_gasa_attribute_fields(); CodeBody ori_HostWidgetController_header = parse_file(path_gasa_ui "HostWidgetController.h"); { @@ -64,21 +65,21 @@ void gen_UHostWidgetController() for ( s32 id = 0; id < attribute_fields.num(); ++id ) { - StringCached attribute_field = attribute_fields[id]; + GAS_AttributeEntry attribute_field = attribute_fields[id]; attribute_events.append( code_str( UPROPERTY(BlueprintAssignable, Category = "Attributes") )); attribute_events.append(fmt_newline); attribute_events.append( parse_variable( - token_fmt( "field", (StrC) attribute_field, stringize( FAttributeFloatChangedSig Event_OnChanged; )) + token_fmt( "field", (StrC) attribute_field.Name, stringize( FAttributeFloatChangedSig Event_OnChanged; )) )); attribute_events.append(fmt_newline); } for ( s32 id = 0; id < attribute_fields.num(); ++id ) { - StringCached attribute_field = attribute_fields[id]; + StringCached attribute_field = attribute_fields[id].Name; attribute_events.append( parse_function( token_fmt( "field", (StrC) attribute_field, stringize( void Changed(FOnAttributeChangeData const& Data); )) @@ -154,9 +155,9 @@ void gen_UHostWidgetController() CodeFn BroadcastInitialValues = NoCode; { CodeBody broadcast_calls = def_body(ECode::Function_Body); - for (StringCached field : attribute_fields) + for (GAS_AttributeEntry field : attribute_fields) { - broadcast_calls.append( code_fmt( "field", (StrC)field, + broadcast_calls.append( code_fmt( "field", (StrC)field.Name, stringize( Event_OnChanged.Broadcast( GasaAttribs->Get() ); ) )); } @@ -185,9 +186,9 @@ void gen_UHostWidgetController() CodeBody bindings = def_body(ECode::Function_Body); bindings.append(fmt_newline); bindings.append(fmt_newline); - for (StringCached field : attribute_fields) + for (GAS_AttributeEntry field : attribute_fields) { - bindings.append( code_fmt( "field", (StrC)field, + bindings.append( code_fmt( "field", (StrC)field.Name, stringize( FOnGameplayAttributeValueChange& AttributeChangedDelegate = AbilitySystem->GetGameplayAttributeValueChangeDelegate(GasaAttribs->GetAttribute()); AttributeChangedDelegate.AddUObject(this, &ThisClass::Changed); @@ -219,7 +220,7 @@ void gen_UHostWidgetController() for ( s32 id = 0; id < attribute_fields.num(); ) { - StringCached attribute_field = attribute_fields[id]; + StringCached attribute_field = attribute_fields[id].Name; attribute_callbacks.append( parse_function( token_fmt( "field", (StrC) attribute_field, diff --git a/Project/Source/GasaGen/GasaGen_UGasaAttributeSet.cpp b/Project/Source/GasaGen/GasaGen_UGasaAttributeSet.cpp index 88c2a6d..2c591d8 100644 --- a/Project/Source/GasaGen/GasaGen_UGasaAttributeSet.cpp +++ b/Project/Source/GasaGen/GasaGen_UGasaAttributeSet.cpp @@ -7,25 +7,44 @@ #include "GasaGenCommon.cpp" #endif -void def_attribute_properties ( CodeBody body, Array properties ); -void def_attribute_field_on_reps ( CodeBody body, Array properties ); -void def_attribute_field_property_getters ( CodeBody body, StrC class_name, Array properties ); -void def_attribute_field_value_getters ( CodeBody body, Array properties ); -void def_attribute_field_value_setters ( CodeBody body, Array properties ); -void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array properties ); -void def_attribute_field_initers ( CodeBody body, Array properties ); -void impl_attribute_fields ( CodeBody body, StrC class_name, Array properties ); +struct GAS_AttributeEntry +{ + StringCached Name; + StringCached MinName; + StringCached MaxName; + float Min; + float Max; +}; -Array get_gasa_attribute_fields() +void def_attribute_properties ( CodeBody body, Array properties ); +void def_attribute_field_on_reps ( CodeBody body, Array properties ); +void def_attribute_field_property_getters ( CodeBody body, StrC class_name, Array properties ); +void def_attribute_field_value_getters ( CodeBody body, Array properties ); +void def_attribute_field_value_setters ( CodeBody body, Array properties ); +void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array properties ); +void def_attribute_field_initers ( CodeBody body, Array properties ); +void impl_attribute_fields ( CodeBody body, StrC class_name, Array properties ); + +Array get_gasa_attribute_fields() { local_persist - Array attribute_fields = Array::init_reserve(GlobalAllocator, 64); + Array attribute_fields = Array::init_reserve(GlobalAllocator, 64); for (local_persist s32 do_once = 0; do_once == 0; ++ do_once) { - attribute_fields.append( get_cached_string(txt("Health"))); - attribute_fields.append( get_cached_string(txt("MaxHealth"))); - attribute_fields.append( get_cached_string(txt("Mana"))); - attribute_fields.append( get_cached_string(txt("MaxMana"))); + StringCached str_Health = get_cached_string(txt("Health")); + StringCached str_MaxHealth = get_cached_string(txt("MaxHealth")); + StringCached str_Mana = get_cached_string(txt("Mana")); + StringCached str_MaxMana = get_cached_string(txt("MaxMana")); + + GAS_AttributeEntry Health = { str_Health, {nullptr}, str_MaxHealth, 0, 100.f }; + GAS_AttributeEntry MaxHealth = { str_MaxHealth, {nullptr}, {nullptr}, 0, 99999.f }; + GAS_AttributeEntry Mana = { str_Mana, {nullptr}, str_MaxMana, 0, 50.f }; + GAS_AttributeEntry MaxMana = { str_MaxMana, {nullptr}, {nullptr}, 0, 99999.f }; + + attribute_fields.append(Health); + attribute_fields.append(MaxHealth); + attribute_fields.append(Mana); + attribute_fields.append(MaxMana); } return attribute_fields; } @@ -35,7 +54,7 @@ void gen_UGasaAttributeSet() CodeType type_UAttributeSet = def_type( txt("UAttributeSet") ); CodeComment generation_notice = def_comment(txt("Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp")); - Array attribute_fields = get_gasa_attribute_fields(); + Array attribute_fields = get_gasa_attribute_fields(); StrC class_name = txt("UGasaAttributeSet"); @@ -57,32 +76,39 @@ void gen_UGasaAttributeSet() body.append( UHT_GENERATED_BODY); body.append( access_public ); - def_attribute_properties( body, attribute_fields); - - body.append(fmt_newline); body.append( def_constructor() ); body.append(fmt_newline); + def_attribute_properties( body, attribute_fields); + body.append(fmt_newline); def_attribute_field_on_reps( body, attribute_fields); body.append(fmt_newline); body.append( fmt_newline ); - body.append( def_pragma(code( region Getters ))); + body.append( def_pragma(txt( "region Getters" ))); def_attribute_field_property_getters( body, class_name, attribute_fields ); body.append( fmt_newline ); def_attribute_field_value_getters( body, attribute_fields ); - body.append( def_pragma(code( endregion Getters ))); + body.append( def_pragma(txt( "endregion Getters" ))); body.append( fmt_newline ); - body.append( def_pragma(code( region Setters ))); + body.append( def_pragma(txt( "region Setters" ))); def_attribute_field_value_setters( body, attribute_fields ); body.append( fmt_newline ); body.append( fmt_newline ); def_attribute_field_initers( body, attribute_fields ); - body.append( def_pragma(code( endregion Setters ))); + body.append( def_pragma(txt( "endregion Setters" ))); body.append( fmt_newline ); + body.append( def_pragma( txt("region AttributeSet"))); + body.append( code_str( + void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override; + // void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override; + )); + body.append( def_pragma( txt("endregion AttributeSet"))); + body.append(fmt_newline); + body.append( def_pragma( txt("region UObject"))); CodeFn GetLifetimeOfReplicatedProps = parse_function( code( void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; @@ -165,14 +191,54 @@ void gen_UGasaAttributeSet() impl_attribute_fields( body, class_name, attribute_fields); + CodeFn PreAttributeChange; + { + CodeBody attribute_clamps = def_body( CodeT::Function_Body ); + attribute_clamps.append(fmt_newline); + attribute_clamps.append(fmt_newline); + for (GAS_AttributeEntry field : attribute_fields) + { + String clamp_min; + if (field.MinName.Data) + clamp_min = get_cached_string(token_fmt( "MinName", (StrC)field.MinName, "Get()")); + else + clamp_min = String::fmt_buf(GlobalAllocator, "%f", field.Min); + + String clamp_max; + if (field.MaxName.Data) + clamp_max = get_cached_string(token_fmt( "MaxName", (StrC)field.MaxName, "Get()")); + else + clamp_max = String::fmt_buf(GlobalAllocator, "%f", field.Max); + + attribute_clamps.append( code_fmt( + "field", (StrC)field.Name, + "clamp_min", (StrC)clamp_min, + "clamp_max", (StrC)clamp_max, + stringize( + if (Attribute == GetAttribute()) + { + NewValue = FMath::Clamp(NewValue, , ); + } + ))); + } + PreAttributeChange = parse_function( token_fmt( "attribute_clamps", (StrC)attribute_clamps.to_string(), stringize( + void UGasaAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) + { + Super::PreAttributeChange(Attribute, NewValue); + + } + ))); + } + body.append(PreAttributeChange); + CodeFn GetLifetimeOfReplicatedProps; { CodeBody field_lifetimes = def_body( CodeT::Function_Body); field_lifetimes.append(fmt_newline); field_lifetimes.append(fmt_newline); - for (StringCached field : attribute_fields) + for (GAS_AttributeEntry field : attribute_fields) { - field_lifetimes.append( code_fmt( "field", (StrC)field, stringize( + field_lifetimes.append( code_fmt( "field", (StrC)field.Name, stringize( DOREPLIFETIME_DEFAULT_GAS(UGasaAttributeSet, ); ))); } @@ -194,44 +260,39 @@ void gen_UGasaAttributeSet() } } -void def_attribute_properties( CodeBody body, Array properties ) +void def_attribute_properties( CodeBody body, Array properties ) { - for ( StringCached property : properties ) + for ( GAS_AttributeEntry property : properties ) { - Code field_uproperty = code_fmt( "property", (StrC)property, stringize( + Code field_uproperty = code_fmt( "property", (StrC)property.Name, stringize( UPROPERTY(ReplicatedUsing=Client_OnRep_, EditAnywhere, BlueprintReadWrite, Category="Attributes") + FGameplayAttributeData ; )); - - CodeType type_FGameplayAttributeData = def_type( txt("FGameplayAttributeData")); - - body.append(fmt_newline); - body.append( field_uproperty ); - body.append(fmt_newline); - body.append( def_variable( type_FGameplayAttributeData, StrC(property)) ); + body.append(field_uproperty); } } -void def_attribute_field_on_reps( CodeBody body, Array properties ) +void def_attribute_field_on_reps( CodeBody body, Array properties ) { - for ( StringCached property : properties ) + for ( GAS_AttributeEntry property : properties ) { Code umeta_UFUNCTION = code_str( UFUNCTION() ); body.append(fmt_newline); body.append( umeta_UFUNCTION ); body.append(fmt_newline); - body.append( code_fmt( "property", (StrC)property, stringize( + body.append( code_fmt( "property", (StrC)property.Name, stringize( void Client_OnRep_(FGameplayAttributeData& Prev); ))); } } -void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array properties ) +void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array properties ) { - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { CodeFn generated_get_attribute = parse_function( - token_fmt( "class_name", class_name, "property", (StrC)property, + token_fmt( "class_name", class_name, "property", (StrC)property.Name, stringize( static FGameplayAttribute GetAttribute() { @@ -245,11 +306,11 @@ void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array #pragma push_macro("FORCEINLINE") #undef FORCEINLINE -void def_attribute_field_value_getters( CodeBody body, Array properties ) +void def_attribute_field_value_getters( CodeBody body, Array properties ) { - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { - body.append( code_fmt( "property", (StrC)property, + body.append( code_fmt( "property", (StrC)property.Name, stringize( FORCEINLINE float Get() const { @@ -259,24 +320,24 @@ void def_attribute_field_value_getters( CodeBody body, Array prope } } -void def_attribute_field_value_setters( CodeBody body, Array properties ) +void def_attribute_field_value_setters( CodeBody body, Array properties ) { - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { - body.append( code_fmt( "property", (StrC)property, + body.append( code_fmt( "property", (StrC)property.Name, stringize( FORCEINLINE void Set(float NewVal); ))); } } -void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array properties ) +void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array properties ) { body.append(def_pragma( txt("region Attribute Setters"))); - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { CodeFn generated_get_attribute = parse_function( - token_fmt( "class_name", class_name, "property", (StrC)property, + token_fmt( "class_name", class_name, "property", (StrC)property.Name, stringize( FORCEINLINE void ::Set(float NewVal) { @@ -292,11 +353,11 @@ void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name body.append(def_pragma( txt("endregion Attribute Setters"))); } -void def_attribute_field_initers ( CodeBody body, Array properties ) +void def_attribute_field_initers ( CodeBody body, Array properties ) { - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { - body.append( code_fmt( "property", (StrC)property, + body.append( code_fmt( "property", (StrC)property.Name, stringize( FORCEINLINE void Init(float NewVal) { @@ -307,14 +368,14 @@ void def_attribute_field_initers ( CodeBody body, Array properties } } -void impl_attribute_fields( CodeBody body, StrC class_name, Array properties ) +void impl_attribute_fields( CodeBody body, StrC class_name, Array properties ) { body.append(fmt_newline); body.append(def_pragma( txt("region Rep Notifies"))); - for ( String property : properties ) + for ( GAS_AttributeEntry property : properties ) { CodeFn field_impl = parse_function( token_fmt( - "class_name", class_name, "property", (StrC)property, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"), + "class_name", class_name, "property", (StrC)property.Name, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"), stringize( void ::Client_OnRep_(FGameplayAttributeData& Prev) { diff --git a/scripts/gencpp.natvis b/scripts/gencpp.natvis index 7b94b25..88b26f8 100644 --- a/scripts/gencpp.natvis +++ b/scripts/gencpp.natvis @@ -55,6 +55,21 @@ + + null + {Data,na} + + + {(Header*)((char*)Data - sizeof(Header))} + + ((Header*)((char*)Data - sizeof(Header)))->Allocator + ((Header*)((char*)Data - sizeof(Header)))->Capacity + ((Header*)((char*)Data - sizeof(Header)))->Length + + + + + Length: {Length}, Capacity: {Capacity}