GASATHON/Project/Source/GasaGen/GasaGen_UGasaAttributeSet.cpp

422 lines
14 KiB
C++
Raw Normal View History

// Used in the GasaGen.cpp translation unit
#if GASA_INTELLISENSE_DIRECTIVES
#pragma once
#define GEN_EXPOSE_BACKEND
#include "gen.hpp"
#include "gen.builder.hpp"
#include "GasaGenCommon.cpp"
#endif
2024-04-24 15:18:26 -07:00
struct GAS_AttributeEntry
{
StringCached Name;
StringCached MinName;
StringCached MaxName;
float Min;
float Max;
};
void def_attribute_properties ( CodeBody body, Array<GAS_AttributeEntry> properties );
void def_attribute_field_on_reps ( CodeBody body, Array<GAS_AttributeEntry> properties );
void def_attribute_field_property_getters ( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties );
void def_attribute_field_value_getters ( CodeBody body, Array<GAS_AttributeEntry> properties );
void def_attribute_field_value_setters ( CodeBody body, Array<GAS_AttributeEntry> properties );
void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties );
void def_attribute_field_initers ( CodeBody body, Array<GAS_AttributeEntry> properties );
void impl_attribute_fields ( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties );
Array<GAS_AttributeEntry> get_gasa_attribute_fields()
2024-04-21 21:30:29 -07:00
{
local_persist
2024-04-24 15:18:26 -07:00
Array<GAS_AttributeEntry> attribute_fields = Array<GAS_AttributeEntry>::init_reserve(GlobalAllocator, 64);
2024-04-21 21:30:29 -07:00
for (local_persist s32 do_once = 0; do_once == 0; ++ do_once) {
2024-04-24 15:18:26 -07:00
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);
2024-04-21 21:30:29 -07:00
}
return attribute_fields;
}
void gen_UGasaAttributeSet()
{
CodeType type_UAttributeSet = def_type( txt("UAttributeSet") );
2024-04-21 15:56:57 -07:00
CodeComment generation_notice = def_comment(txt("Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp"));
2024-04-24 15:18:26 -07:00
Array<GAS_AttributeEntry> attribute_fields = get_gasa_attribute_fields();
StrC class_name = txt("UGasaAttributeSet");
Builder header = Builder::open( path_gasa_ability_system "GasaAttributeSet.h");
{
header.print(generation_notice);
2024-04-21 15:56:57 -07:00
header.print(pragma_once);
header.print(fmt_newline);
{
CodeInclude Include_AttributeSet = def_include(txt("AttributeSet.h"));
CodeInclude Include_GasaAttributeSet_Generated = def_include(txt("GasaAttributeSet.generated.h"));
CodeAttributes api_attribute= def_attributes( UModule_GASA_API->Name);
CodeClass GasaAttributeSet = {};
{
CodeBody body = def_body( CodeT::Class_Body );
{
body.append( UHT_GENERATED_BODY);
body.append( access_public );
body.append( def_constructor() );
body.append(fmt_newline);
2024-04-24 15:18:26 -07:00
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 );
2024-04-24 15:18:26 -07:00
body.append( def_pragma(txt( "region Getters" )));
def_attribute_field_property_getters( body, class_name, attribute_fields );
2024-04-21 15:56:57 -07:00
body.append( fmt_newline );
def_attribute_field_value_getters( body, attribute_fields );
2024-04-24 15:18:26 -07:00
body.append( def_pragma(txt( "endregion Getters" )));
body.append( fmt_newline );
2024-04-24 15:18:26 -07:00
body.append( def_pragma(txt( "region Setters" )));
def_attribute_field_value_setters( body, attribute_fields );
2024-04-21 15:56:57 -07:00
body.append( fmt_newline );
body.append( fmt_newline );
def_attribute_field_initers( body, attribute_fields );
2024-04-24 15:18:26 -07:00
body.append( def_pragma(txt( "endregion Setters" )));
body.append( fmt_newline );
2024-04-24 15:18:26 -07:00
body.append( def_pragma( txt("region AttributeSet")));
body.append( code_str(
void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
2024-04-24 17:18:38 -07:00
void PostGameplayEffectExecute(FGameplayEffectModCallbackData const& Data) override;
2024-04-24 15:18:26 -07:00
));
body.append( def_pragma( txt("endregion AttributeSet")));
body.append(fmt_newline);
body.append( def_pragma( txt("region UObject")));
2024-04-16 14:18:06 -07:00
CodeFn GetLifetimeOfReplicatedProps = parse_function( code(
void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
2024-04-16 14:18:06 -07:00
));
body.append( GetLifetimeOfReplicatedProps );
body.append( def_pragma( txt("endregion UObject")));
}
GasaAttributeSet = def_class( class_name, body
, type_UAttributeSet, AccessSpec::Public
, api_attribute
);
}
header.print( Include_AttributeSet);
header.print( Include_GasaAttributeSet_Generated);
header.print( fmt_newline);
header.print( UHT_UCLASS );
header.print(GasaAttributeSet);
}
header.write();
format_file(path_gasa_ability_system "GasaAttributeSet.h");
}
2024-04-21 15:56:57 -07:00
Builder inlines = Builder::open( path_gasa_ability_system "GasaAttributeSet_Inlines.h");
{
inlines.print(generation_notice);
inlines.print(pragma_once);
inlines.print(fmt_newline);
inlines.print( def_include( txt("GasaAttributeSet.h")));
inlines.print( def_include(txt("AbilitySystemComponent.h")));
inlines.print(fmt_newline);
CodeBody body = def_body(CodeT::Global_Body);
{
def_attribute_field_property_setter_inlines( body, class_name, attribute_fields );
}
inlines.print(body);
inlines.print(fmt_newline);
CodeNS ns_gasa = parse_namespace( code(
namespace Gasa
{
inline
UGasaAttributeSet const* GetAttributeSet( UAbilitySystemComponent* ASC )
{
return Cast<UGasaAttributeSet>(ASC->GetAttributeSet( UGasaAttributeSet::StaticClass() ));
}
}
));
inlines.print(ns_gasa);
inlines.write();
format_file(path_gasa_ability_system "GasaAttributeSet_Inlines.h");
}
Builder source = Builder::open( path_gasa_ability_system "GasaAttributeSet.cpp" );
{
source.print(generation_notice);
header.print(fmt_newline);
source.print( def_include( txt("GasaAttributeSet.h")));
2024-04-21 15:56:57 -07:00
source.print( def_include( txt("GasaAttributeSet_Inlines.h")));
2024-04-24 17:18:38 -07:00
source.print( def_include( txt("EffectProperties.h")));
source.print(fmt_newline);
source.print( def_include( txt("AbilitySystemComponent.h")));
source.print( def_include( txt("Net/UnrealNetwork.h")));
source.print( def_include( txt("Networking/GasaNetLibrary.h")));
{
CodeBody body = def_body( CodeT::Global_Body );
body.append(fmt_newline);
CodeConstructor constructor_for_UGasaAttributeSet = parse_constructor( code(
UGasaAttributeSet::UGasaAttributeSet()
{
InitHealth( 100.f );
InitMaxHealth( 100.f );
2024-04-15 20:09:46 -07:00
InitMana( 50.f );
InitMaxMana( 50.f );
}
));
body.append(constructor_for_UGasaAttributeSet );
impl_attribute_fields( body, class_name, attribute_fields);
2024-04-24 17:18:38 -07:00
Code PostGameplayEffectExecute = parse_function( code(
void UGasaAttributeSet::PostGameplayEffectExecute(FGameplayEffectModCallbackData const& Data)
{
Super::PostGameplayEffectExecute(Data);
FEffectProperties Props;
Props.Populate(Data);
}
));
body.append(PostGameplayEffectExecute);
body.append(fmt_newline);
2024-04-24 15:18:26 -07:00
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<MinName>()"));
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<MaxName>()"));
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 == Get<field>Attribute())
{
NewValue = FMath::Clamp(NewValue, <clamp_min>, <clamp_max>);
}
)));
}
2024-04-24 17:18:38 -07:00
attribute_clamps.append(fmt_newline);
attribute_clamps.append(fmt_newline);
2024-04-24 15:18:26 -07:00
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);
<attribute_clamps>
}
)));
}
body.append(PreAttributeChange);
2024-04-24 17:18:38 -07:00
body.append(fmt_newline);
2024-04-24 15:18:26 -07:00
CodeFn GetLifetimeOfReplicatedProps;
{
CodeBody field_lifetimes = def_body( CodeT::Function_Body);
field_lifetimes.append(fmt_newline);
field_lifetimes.append(fmt_newline);
2024-04-24 15:18:26 -07:00
for (GAS_AttributeEntry field : attribute_fields)
{
2024-04-24 15:18:26 -07:00
field_lifetimes.append( code_fmt( "field", (StrC)field.Name, stringize(
DOREPLIFETIME_DEFAULT_GAS(UGasaAttributeSet, <field>);
)));
}
GetLifetimeOfReplicatedProps = parse_function( token_fmt( "field_lifetimes", (StrC)(field_lifetimes.to_string()), stringize(
void UGasaAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
<field_lifetimes>
}
)));
}
body.append(GetLifetimeOfReplicatedProps);
source.print(body);
}
source.write();
format_file(path_gasa_ability_system "GasaAttributeSet.cpp");
}
}
2024-04-24 15:18:26 -07:00
void def_attribute_properties( CodeBody body, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
2024-04-24 15:18:26 -07:00
Code field_uproperty = code_fmt( "property", (StrC)property.Name, stringize(
UPROPERTY(ReplicatedUsing=Client_OnRep_<property>, EditAnywhere, BlueprintReadWrite, Category="Attributes")
2024-04-24 15:18:26 -07:00
FGameplayAttributeData <property>;
));
2024-04-24 15:18:26 -07:00
body.append(field_uproperty);
}
}
2024-04-24 15:18:26 -07:00
void def_attribute_field_on_reps( CodeBody body, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
Code umeta_UFUNCTION = code_str( UFUNCTION() );
body.append(fmt_newline);
body.append( umeta_UFUNCTION );
body.append(fmt_newline);
2024-04-24 15:18:26 -07:00
body.append( code_fmt( "property", (StrC)property.Name, stringize(
void Client_OnRep_<property>(FGameplayAttributeData& Prev<property>);
)));
}
}
2024-04-24 15:18:26 -07:00
void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
CodeFn generated_get_attribute = parse_function(
2024-04-24 15:18:26 -07:00
token_fmt( "class_name", class_name, "property", (StrC)property.Name,
stringize(
static FGameplayAttribute Get<property>Attribute()
{
static FProperty* Prop = FindFieldChecked<FProperty>(<class_name>::StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property>));
return Prop;
}
)));
body.append( generated_get_attribute );
}
}
#pragma push_macro("FORCEINLINE")
#undef FORCEINLINE
2024-04-24 15:18:26 -07:00
void def_attribute_field_value_getters( CodeBody body, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
2024-04-24 15:18:26 -07:00
body.append( code_fmt( "property", (StrC)property.Name,
stringize(
FORCEINLINE float Get<property>() const
{
return <property>.GetCurrentValue();
}
)));
}
}
2024-04-24 15:18:26 -07:00
void def_attribute_field_value_setters( CodeBody body, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
2024-04-24 15:18:26 -07:00
body.append( code_fmt( "property", (StrC)property.Name,
stringize(
2024-04-21 15:56:57 -07:00
FORCEINLINE void Set<property>(float NewVal);
)));
}
}
2024-04-24 15:18:26 -07:00
void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties )
2024-04-21 15:56:57 -07:00
{
body.append(def_pragma( txt("region Attribute Setters")));
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
2024-04-21 15:56:57 -07:00
{
CodeFn generated_get_attribute = parse_function(
2024-04-24 15:18:26 -07:00
token_fmt( "class_name", class_name, "property", (StrC)property.Name,
2024-04-21 15:56:57 -07:00
stringize(
FORCEINLINE void <class_name>::Set<property>(float NewVal)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
if (ensure(AbilityComp))
{
AbilityComp->SetNumericAttributeBase(Get<property>Attribute(), NewVal);
};
}
)));
body.append( generated_get_attribute );
}
body.append(def_pragma( txt("endregion Attribute Setters")));
2024-04-21 15:56:57 -07:00
}
2024-04-24 15:18:26 -07:00
void def_attribute_field_initers ( CodeBody body, Array<GAS_AttributeEntry> properties )
{
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
2024-04-24 15:18:26 -07:00
body.append( code_fmt( "property", (StrC)property.Name,
stringize(
FORCEINLINE void Init<property>(float NewVal)
{
<property>.SetBaseValue(NewVal);
<property>.SetCurrentValue(NewVal);
}
)));
}
}
2024-04-24 15:18:26 -07:00
void impl_attribute_fields( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties )
{
body.append(fmt_newline);
2024-04-22 09:01:30 -07:00
body.append(def_pragma( txt("region Rep Notifies")));
2024-04-24 15:18:26 -07:00
for ( GAS_AttributeEntry property : properties )
{
2024-04-22 09:01:30 -07:00
CodeFn field_impl = parse_function( token_fmt(
2024-04-24 15:18:26 -07:00
"class_name", class_name, "property", (StrC)property.Name, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"),
stringize(
void <class_name>::Client_OnRep_<property>(FGameplayAttributeData& Prev<property>)
{
2024-04-22 09:01:30 -07:00
<from_notice>
static FProperty* <class_name>Property = FindFieldChecked<FProperty>( StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property>));
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication(FGameplayAttribute(<class_name>Property), <property>, Prev<property>);
}
)));
body.append( field_impl );
}
2024-04-22 09:01:30 -07:00
body.append( def_pragma( txt("endregion Rep Notifies")));
body.append(fmt_newline);
2024-04-22 09:01:30 -07:00
}
inline
Code gen_GAMEPLAYATTRIBUTE_REPNOTIFY(StrC class_name, StrC property_name, StrC old_value)
{
Code rep_notify = code_fmt(
"class_name", class_name
, "property_name", property_name
, "old_value", old_value,
stringize(
static FProperty* <class_name>Property = FindFieldChecked<FProperty>(<class_name>::StaticClass(), GET_MEMBER_NAME_CHECKED(<class_name>, <property_name>));
GetOwningAbilitySystemComponentChecked()->SetBaseAttributeValueFromReplication(FGameplayAttribute(<class_name>Property), <property_name>, <old_value>);
));
}
#pragma pop_macro("FORCEINLINE")