Compare commits

..

No commits in common. "33b3723b820c20ea3bb610f1d90261e5dcd41bc1" and "22aee515edbf55c67c658a7cb3e76d339c2d0fdf" have entirely different histories.

32 changed files with 104 additions and 525 deletions

Binary file not shown.

View File

@ -1,16 +0,0 @@
[/Script/GameplayTags.GameplayTagsSettings]
ImportTagsFromConfig=True
WarnOnInvalidTags=True
ClearInvalidTags=False
AllowEditorTagUnloading=True
AllowGameTagUnloading=False
FastReplication=False
InvalidTagCharacters="\"\',"
+GameplayTagTableList=/Game/Core/DT_PrimaryAttributes.DT_PrimaryAttributes
NumBitsForContainerSize=6
NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="Attributes.Vital.Health",DevComment="")
+GameplayTagList=(Tag="Attributes.Vital.Mana",DevComment="")
+GameplayTagList=(Tag="Attributes.Vital.MaxHealth",DevComment="")
+GameplayTagList=(Tag="Attributes.Vital.MaxMana",DevComment="")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Project/Content/Core/CT_Potion.uasset (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Project/Content/Core/Pickups/BP_HealthCrystal.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
Project/Content/Core/Pickups/BP_HealthPotion.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Project/Content/Core/Pickups/BP_ManaCrystal.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
Project/Content/Levels/StartupMap.umap (Stored with Git LFS)

Binary file not shown.

View File

@ -1,7 +0,0 @@
{
"ColumnWidths":
{
"DevComment": 405,
"Tag": 381
}
}

View File

@ -1,38 +0,0 @@
#include "EffectProperties.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "GameplayEffect.h"
#include "GameplayEffectExtension.h"
#include "GameFramework/Pawn.h"
#include "GameFramework/PlayerController.h"
void FEffectProperties::Populate(FGameplayEffectModCallbackData const& Data)
{
Context = Data.EffectSpec.GetContext();
SourceAbilitySystem = Context.GetOriginalInstigatorAbilitySystemComponent();
if (IsValid(SourceAbilitySystem)
&& SourceAbilitySystem->AbilityActorInfo.IsValid()
&& SourceAbilitySystem->AbilityActorInfo->AvatarActor.IsValid())
{
FGameplayAbilityActorInfo* AbilityInfo = SourceAbilitySystem->AbilityActorInfo.Get();
SourceAvatar = AbilityInfo->AvatarActor.Get();
SourceController = AbilityInfo->PlayerController.Get();
if (SourceController == nullptr && SourceAvatar)
{
APawn* Pawn = Cast<APawn>(SourceAvatar);
if (Pawn)
SourceController = Pawn->GetController();
}
}
if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
{
FGameplayAbilityActorInfo* AbilityInfo = Data.Target.AbilityActorInfo.Get();
TargetAvatar = AbilityInfo->AvatarActor.Get();
TargetController = AbilityInfo->PlayerController.Get();
TargetAbilitySystem = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(TargetAvatar);
}
}

View File

@ -1,34 +0,0 @@
#pragma once
#include "GameplayEffectTypes.h"
#include "GasaCommon.h"
#include "EffectProperties.generated.h"
USTRUCT()
struct GASA_API FEffectProperties
{
GENERATED_BODY()
FGameplayEffectContextHandle Context;
UPROPERTY(VisibleAnywhere)
UAbilitySystemComponent* SourceAbilitySystem;
UPROPERTY(VisibleAnywhere)
AActor* SourceAvatar;
UPROPERTY(VisibleAnywhere)
AController* SourceController;
UPROPERTY(VisibleAnywhere)
UAbilitySystemComponent* TargetAbilitySystem;
UPROPERTY(VisibleAnywhere)
AActor* TargetAvatar;
UPROPERTY(VisibleAnywhere)
APlayerController* TargetController;
void Populate(FGameplayEffectModCallbackData const& Data);
};

View File

@ -18,7 +18,7 @@ namespace Gasa
// From: UAbilitySystemGlobals::GetAbilitySystemComponentFromActor // From: UAbilitySystemGlobals::GetAbilitySystemComponentFromActor
inline inline
UGasaAbilitySystemComp* GetAbilitySystem(AActor* Actor, bool LookForComponent = true) UGasaAbilitySystemComp* GetAbilitySystem(AActor* Actor, bool LookForComponent = false)
{ {
if (Actor == nullptr) if (Actor == nullptr)
return nullptr; return nullptr;

View File

@ -1,7 +1,6 @@
// Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp // Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp
#include "GasaAttributeSet.h" #include "GasaAttributeSet.h"
#include "GasaAttributeSet_Inlines.h" #include "GasaAttributeSet_Inlines.h"
#include "EffectProperties.h"
#include "AbilitySystemComponent.h" #include "AbilitySystemComponent.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
@ -9,9 +8,9 @@
UGasaAttributeSet::UGasaAttributeSet() UGasaAttributeSet::UGasaAttributeSet()
{ {
InitHealth( 100.f ); InitHealth( 50.f );
InitMaxHealth( 100.f ); InitMaxHealth( 100.f );
InitMana( 50.f ); InitMana( 25.f );
InitMaxMana( 50.f ); InitMaxMana( 50.f );
} }
@ -42,35 +41,6 @@ void UGasaAttributeSet::Client_OnRep_MaxMana( FGameplayAttributeData& PrevMaxMan
} }
#pragma endregion Rep Notifies #pragma endregion Rep Notifies
void UGasaAttributeSet::PostGameplayEffectExecute( FGameplayEffectModCallbackData const& Data )
{
Super::PostGameplayEffectExecute( Data );
FEffectProperties Props;
Props.Populate( Data );
}
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<FLifetimeProperty>& OutLifetimeProps ) const void UGasaAttributeSet::GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const
{ {
Super::GetLifetimeReplicatedProps( OutLifetimeProps ); Super::GetLifetimeReplicatedProps( OutLifetimeProps );

View File

@ -9,17 +9,21 @@ class GASA_API UGasaAttributeSet : public UAttributeSet
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UGasaAttributeSet();
UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) UPROPERTY( ReplicatedUsing = Client_OnRep_Health, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData Health; FGameplayAttributeData Health;
UPROPERTY( ReplicatedUsing = Client_OnRep_MaxHealth, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) UPROPERTY( ReplicatedUsing = Client_OnRep_MaxHealth, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData MaxHealth; FGameplayAttributeData MaxHealth;
UPROPERTY( ReplicatedUsing = Client_OnRep_Mana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) UPROPERTY( ReplicatedUsing = Client_OnRep_Mana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData Mana; FGameplayAttributeData Mana;
UPROPERTY( ReplicatedUsing = Client_OnRep_MaxMana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" ) UPROPERTY( ReplicatedUsing = Client_OnRep_MaxMana, EditAnywhere, BlueprintReadWrite, Category = "Attributes" )
FGameplayAttributeData MaxMana; FGameplayAttributeData MaxMana;
UGasaAttributeSet();
UFUNCTION() UFUNCTION()
void Client_OnRep_Health( FGameplayAttributeData& PrevHealth ); void Client_OnRep_Health( FGameplayAttributeData& PrevHealth );
UFUNCTION() UFUNCTION()
@ -86,12 +90,6 @@ public:
} }
#pragma endregion Setters #pragma endregion Setters
#pragma region AttributeSet
void
PreAttributeChange( const FGameplayAttribute& Attribute, float& NewValue ) override;
void PostGameplayEffectExecute( FGameplayEffectModCallbackData const& Data ) override;
#pragma endregion AttributeSet
#pragma region UObject #pragma region UObject
void void
GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const override; GetLifetimeReplicatedProps( TArray<FLifetimeProperty>& OutLifetimeProps ) const override;

View File

@ -1,7 +1,6 @@
#include "GasaEffectActor.h" #include "GasaEffectActor.h"
#include "GasaAbilitySystemComponent_Inlines.h" #include "GasaAbilitySystemComponent_Inlines.h"
#include "GasaContainers.h"
using namespace Gasa; using namespace Gasa;
AGasaEffectActor::AGasaEffectActor() AGasaEffectActor::AGasaEffectActor()
@ -9,118 +8,16 @@ AGasaEffectActor::AGasaEffectActor()
PrimaryActorTick.bCanEverTick = false; PrimaryActorTick.bCanEverTick = false;
RootComponent = CreateDefaultSubobject<USceneComponent>("Root"); RootComponent = CreateDefaultSubobject<USceneComponent>("Root");
Level = 1.f;
InstantEffectUsage = EInstantEffectUsagePolicy::DoNotApply;
DurationEffectUsage = DefaultEffectUsagePolicy;
InfiniteEffectUsage = DefaultEffectUsagePolicy;
bDestroyOnEffectRemoval = false;
} }
void AGasaEffectActor::ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass, bool bRemoveOnEndOverlap) void AGasaEffectActor::ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass)
{ {
UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true); UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true);
FGameplayEffectContextHandle FGameplayEffectContextHandle
Context = AS->MakeEffectContext(); Context = AS->MakeEffectContext();
Context.AddSourceObject(Actor); Context.AddSourceObject(Actor);
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( EffectClass, Level, Context ); FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( EffectClass, 1.0f, Context );
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
if (bRemoveOnEndOverlap)
ActiveEffectsToRemove.Add(ActiveEffect, AS);
}
void AGasaEffectActor::OnOverlap(AActor* Actor)
{
UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true);
FGameplayEffectContextHandle
Context = AS->MakeEffectContext();
Context.AddSourceObject(Actor);
if (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnOverlap)
{
FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, Level, Context );
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data ); AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
} }
if (DurationEffectClass)
{
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnOverlap))
{
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( DurationEffectClass, Level, Context );
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap))
ActiveDuration = ActiveEffect;
}
if (ActiveDuration.IsValid() && Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
AS->RemoveActiveGameplayEffect(ActiveDuration);
}
if (InfiniteEffectClass)
{
bool bApplyOnOverlap = Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::ApplyOnOverlap);
if (bApplyOnOverlap)
{
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InfiniteEffectClass, Level, Context );
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
if (Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap))
ActiveInfinite = ActiveEffect;
}
if (ActiveInfinite.IsValid() && Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
{
if (ActiveInfinite.IsValid())
AS->RemoveActiveGameplayEffect(ActiveInfinite);
}
}
}
void AGasaEffectActor::OnEndOverlap(AActor* Actor)
{
UGasaAbilitySystemComp* AS = GetAbilitySystem(Actor, true);
FGameplayEffectContextHandle
Context = AS->MakeEffectContext();
Context.AddSourceObject(Actor);
if (InstantEffectClass && InstantEffectUsage == EInstantEffectUsagePolicy::ApplyOnEndOverlap)
{
FGameplayEffectSpecHandle Spec= AS->MakeOutgoingSpec( InstantEffectClass, Level, Context );
AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
}
if (DurationEffectClass)
{
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap))
{
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( DurationEffectClass, Level, Context );
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
if (Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
ActiveDuration = ActiveEffect;
}
if (ActiveDuration.IsValid() && Bitfield_IsSet(DurationEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap))
AS->RemoveActiveGameplayEffect(ActiveDuration);
}
if (InfiniteEffectClass)
{
if (Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::ApplyOnEndOverlap))
{
FGameplayEffectSpecHandle Spec = AS->MakeOutgoingSpec( InfiniteEffectClass, Level, Context );
FActiveGameplayEffectHandle ActiveEffect = AS->ApplyGameplayEffectSpecToSelf( * Spec.Data );
if (Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnOverlap))
ActiveInfinite = ActiveEffect;
}
if (ActiveInfinite.IsValid() && Bitfield_IsSet(InfiniteEffectUsage, EEffectUsagePolicy::RemoveOnEndOverlap))
{
if (ActiveInfinite.IsValid())
AS->RemoveActiveGameplayEffect(ActiveInfinite);
}
}
TArray<FActiveGameplayEffectHandle> EffectsRemoved;
for (ActiveEffectEntry ActiveEffect : ActiveEffectsToRemove)
{
if (ActiveEffect.Value != AS)
continue;
AS->RemoveActiveGameplayEffect(ActiveEffect.Key, 1);
EffectsRemoved.Add(ActiveEffect.Key);
}
RemoveKeys(ActiveEffectsToRemove, EffectsRemoved);
}

View File

@ -2,77 +2,25 @@
#include "GasaCommon.h" #include "GasaCommon.h"
#include "Actors/GasaActor.h" #include "Actors/GasaActor.h"
#include "ActiveGameplayEffectHandle.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "GasaEffectActor.generated.h" #include "GasaEffectActor.generated.h"
struct FActiveGameplayEffectHandle;
UENUM(BlueprintType)
enum class EInstantEffectUsagePolicy : uint8
{
DoNotApply,
ApplyOnOverlap,
ApplyOnEndOverlap,
};
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EEffectUsagePolicy : uint8
{
None = 0 UMETA(Hidden),
ApplyOnOverlap = bit(0),
ApplyOnEndOverlap = bit(1),
RemoveOnOverlap = bit(2),
RemoveOnEndOverlap = bit(3),
};
constexpr int32 DefaultEffectUsagePolicy = (int32(EEffectUsagePolicy::RemoveOnEndOverlap));
UCLASS() UCLASS()
class GASA_API AGasaEffectActor : public AGasaActor class GASA_API AGasaEffectActor : public AGasaActor
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
AGasaEffectActor();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
float Level;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
TSubclassOf<UGameplayEffect> InstantEffectClass; TSubclassOf<UGameplayEffect> InstantEffectClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
EInstantEffectUsagePolicy InstantEffectUsage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
TSubclassOf<UGameplayEffect> DurationEffectClass; TSubclassOf<UGameplayEffect> DurationEffectClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EEffectUsagePolicy")) AGasaEffectActor();
int32 DurationEffectUsage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
TSubclassOf<UGameplayEffect> InfiniteEffectClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EEffectUsagePolicy"))
int32 InfiniteEffectUsage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay Effects")
bool bDestroyOnEffectRemoval;
TMap<FActiveGameplayEffectHandle, UAbilitySystemComponent*> ActiveEffectsToRemove;
using ActiveEffectEntry = TTuple<FActiveGameplayEffectHandle, UAbilitySystemComponent*>;
FActiveGameplayEffectHandle ActiveDuration;
FActiveGameplayEffectHandle ActiveInfinite;
UFUNCTION(BlueprintCallable, Category = "Gameplay Effects") UFUNCTION(BlueprintCallable, Category = "Gameplay Effects")
void ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass, bool bRemoveOnEndOverlap = false); void ApplyEffectToActor(AActor* Actor, TSubclassOf<UGameplayEffect> EffectClass );
UFUNCTION(BlueprintCallable)
void OnOverlap(AActor* Actor);
UFUNCTION(BlueprintCallable)
void OnEndOverlap(AActor* Actor);
}; };

View File

@ -45,7 +45,7 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework")
EGameFrameworkState GameFrameworkState; EGameFrameworkState GameFrameworkState;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework", meta=(Bitmask, BitmaskEnum = "/Script/Gasa.EGameFrameworkClassFlag")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GameFramework", meta=(Bitmask, BitmaskEnum = EGameFrameworkClassFlag))
int32 GameFrameworkClassesState; int32 GameFrameworkClassesState;
UFUNCTION(BlueprintCallable, Category="GameFramework") UFUNCTION(BlueprintCallable, Category="GameFramework")

View File

@ -13,16 +13,12 @@
#define rcast( Type, Value ) reinterpret_cast<Type>( Value ) #define rcast( Type, Value ) reinterpret_cast<Type>( Value )
#define scast( Type, Value ) static_cast<Type>( Value ) #define scast( Type, Value ) static_cast<Type>( Value )
#define bit(position) (1 << position)
#pragma region Math #pragma region Math
#define m_pow2( value ) (value * value) #define m_pow2( value ) (value * value)
#pragma endregion Math #pragma endregion Math
#pragma region Engine Forwards #pragma region Engine Forwards
struct FInputActionValue; struct FInputActionValue;
struct FGameplayEffectContextHandle;
struct FGameplayEffectModCallbackData;
struct FOnAttributeChangeData; struct FOnAttributeChangeData;
struct FReplicationFlags; struct FReplicationFlags;
@ -82,30 +78,13 @@ namespace Gasa
{ {
inline inline
bool Bitfield_IsSet(int32 Bitfield, int32 Bitmask) { bool Bitfield_IsSet(int32 Bitfield, int32 Bitmask) {
bool Result = Bitmask == (Bitfield & Bitmask); int32 Result = Bitmask == (Bitfield & Bitmask);
return Result; return scast(bool, Result);
}
inline
bool Bitfield_IsSetExactly(int32 Bitfield, int32 Bitmask)
{
bool Result = Bitfield == (Bitfield & Bitmask);
return Result;
} }
inline void Bitfield_Set ( int32& Bitfield, int32 BitsToAdd ) { Bitfield |= BitsToAdd; } inline void Bitfield_Set ( int32& Bitfield, int32 BitsToAdd ) { Bitfield |= BitsToAdd; }
inline void Bitfield_Remove( int32& Bitfield, int32 BitsToRemove ) { Bitfield &= (! BitsToRemove); } inline void Bitfield_Remove( int32& Bitfield, int32 BitsToRemove ) { Bitfield &= (! BitsToRemove); }
inline void Bitfield_Toggle( int32& Bitfield, int32 Bitmask ) { Bitfield ^= Bitmask; } inline void Bitfield_Toggle( int32& Bitfield, int32 Bitmask ) { Bitfield ^= Bitmask; }
template<typename EnumType>
inline
bool Bitfield_IsSet(int32 Bitfield, EnumType Mask)
{
bool Result = int32(Mask) == (Bitfield & int32(Mask));
return Result;
}
template<typename EnumType> inline void Bitfield_Set ( int32& Bitfield, EnumType BitToAdd ) { Bitfield |= int32(BitToAdd); }
template<typename EnumType> inline void Bitfield_Remove( int32& Bitfield, EnumType BitToRemove ) { Bitfield &= (! int32(BitToRemove)); }
template<typename EnumType> inline void Bitfield_Toggle( int32& Bitfield, EnumType BitToToggle ) { Bitfield ^= int32(BitToToggle); }
} }
#pragma endregion Bitfields #pragma endregion Bitfields

View File

@ -1,14 +0,0 @@
#pragma once
#include "GasaCommon.h"
template<typename KeyType, typename ValueType>
inline
void RemoveKeys(TMap<KeyType, ValueType> Map, TArray<KeyType> Keys)
{
for (KeyType& Key : Keys )
{
Map.Remove(Key);
}
}

View File

@ -77,9 +77,6 @@ CodeBody parse_file( char const* path ) {
return code; return code;
} }
// inline
// CodeConstructor find_constructor( StrC parent_name, )
inline inline
void format_file( char const* path ) void format_file( char const* path )
{ {

View File

@ -4,12 +4,11 @@
#include "gen.hpp" #include "gen.hpp"
#include "gen.builder.hpp" #include "gen.builder.hpp"
#include "GasaGenCommon.cpp" #include "GasaGenCommon.cpp"
#include "GasaGen_UGasaAttributeSet.cpp"
#endif #endif
void gen_UHostWidgetController() void gen_UHostWidgetController()
{ {
Array<GAS_AttributeEntry> attribute_fields = get_gasa_attribute_fields(); Array<StringCached> attribute_fields = get_gasa_attribute_fields();
CodeBody ori_HostWidgetController_header = parse_file(path_gasa_ui "HostWidgetController.h"); CodeBody ori_HostWidgetController_header = parse_file(path_gasa_ui "HostWidgetController.h");
{ {
@ -65,21 +64,21 @@ void gen_UHostWidgetController()
for ( s32 id = 0; id < attribute_fields.num(); ++id ) for ( s32 id = 0; id < attribute_fields.num(); ++id )
{ {
GAS_AttributeEntry attribute_field = attribute_fields[id]; StringCached attribute_field = attribute_fields[id];
attribute_events.append( code_str( attribute_events.append( code_str(
UPROPERTY(BlueprintAssignable, Category = "Attributes") UPROPERTY(BlueprintAssignable, Category = "Attributes")
)); ));
attribute_events.append(fmt_newline); attribute_events.append(fmt_newline);
attribute_events.append( parse_variable( attribute_events.append( parse_variable(
token_fmt( "field", (StrC) attribute_field.Name, stringize( FAttributeFloatChangedSig Event_On<field>Changed; )) token_fmt( "field", (StrC) attribute_field, stringize( FAttributeFloatChangedSig Event_On<field>Changed; ))
)); ));
attribute_events.append(fmt_newline); attribute_events.append(fmt_newline);
} }
for ( s32 id = 0; id < attribute_fields.num(); ++id ) for ( s32 id = 0; id < attribute_fields.num(); ++id )
{ {
StringCached attribute_field = attribute_fields[id].Name; StringCached attribute_field = attribute_fields[id];
attribute_events.append( parse_function( attribute_events.append( parse_function(
token_fmt( "field", (StrC) attribute_field, stringize( void <field>Changed(FOnAttributeChangeData const& Data); )) token_fmt( "field", (StrC) attribute_field, stringize( void <field>Changed(FOnAttributeChangeData const& Data); ))
@ -155,9 +154,9 @@ void gen_UHostWidgetController()
CodeFn BroadcastInitialValues = NoCode; CodeFn BroadcastInitialValues = NoCode;
{ {
CodeBody broadcast_calls = def_body(ECode::Function_Body); CodeBody broadcast_calls = def_body(ECode::Function_Body);
for (GAS_AttributeEntry field : attribute_fields) for (StringCached field : attribute_fields)
{ {
broadcast_calls.append( code_fmt( "field", (StrC)field.Name, broadcast_calls.append( code_fmt( "field", (StrC)field,
stringize( Event_On<field>Changed.Broadcast( GasaAttribs->Get<field>() ); ) stringize( Event_On<field>Changed.Broadcast( GasaAttribs->Get<field>() ); )
)); ));
} }
@ -186,9 +185,9 @@ void gen_UHostWidgetController()
CodeBody bindings = def_body(ECode::Function_Body); CodeBody bindings = def_body(ECode::Function_Body);
bindings.append(fmt_newline); bindings.append(fmt_newline);
bindings.append(fmt_newline); bindings.append(fmt_newline);
for (GAS_AttributeEntry field : attribute_fields) for (StringCached field : attribute_fields)
{ {
bindings.append( code_fmt( "field", (StrC)field.Name, bindings.append( code_fmt( "field", (StrC)field,
stringize( stringize(
FOnGameplayAttributeValueChange& <field>AttributeChangedDelegate = AbilitySystem->GetGameplayAttributeValueChangeDelegate(GasaAttribs->Get<field>Attribute()); FOnGameplayAttributeValueChange& <field>AttributeChangedDelegate = AbilitySystem->GetGameplayAttributeValueChangeDelegate(GasaAttribs->Get<field>Attribute());
<field>AttributeChangedDelegate.AddUObject(this, &ThisClass::<field>Changed); <field>AttributeChangedDelegate.AddUObject(this, &ThisClass::<field>Changed);
@ -220,7 +219,7 @@ void gen_UHostWidgetController()
for ( s32 id = 0; id < attribute_fields.num(); ) for ( s32 id = 0; id < attribute_fields.num(); )
{ {
StringCached attribute_field = attribute_fields[id].Name; StringCached attribute_field = attribute_fields[id];
attribute_callbacks.append( parse_function( token_fmt( attribute_callbacks.append( parse_function( token_fmt(
"field", (StrC) attribute_field, "field", (StrC) attribute_field,

View File

@ -7,44 +7,25 @@
#include "GasaGenCommon.cpp" #include "GasaGenCommon.cpp"
#endif #endif
struct GAS_AttributeEntry void def_attribute_properties ( CodeBody body, Array<StringCached> properties );
{ void def_attribute_field_on_reps ( CodeBody body, Array<StringCached> properties );
StringCached Name; void def_attribute_field_property_getters ( CodeBody body, StrC class_name, Array<StringCached> properties );
StringCached MinName; void def_attribute_field_value_getters ( CodeBody body, Array<StringCached> properties );
StringCached MaxName; void def_attribute_field_value_setters ( CodeBody body, Array<StringCached> properties );
float Min; void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<StringCached> properties );
float Max; void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties );
}; void impl_attribute_fields ( CodeBody body, StrC class_name, Array<StringCached> properties );
void def_attribute_properties ( CodeBody body, Array<GAS_AttributeEntry> properties ); Array<StringCached> get_gasa_attribute_fields()
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()
{ {
local_persist local_persist
Array<GAS_AttributeEntry> attribute_fields = Array<GAS_AttributeEntry>::init_reserve(GlobalAllocator, 64); Array<StringCached> attribute_fields = Array<StringCached>::init_reserve(GlobalAllocator, 64);
for (local_persist s32 do_once = 0; do_once == 0; ++ do_once) { for (local_persist s32 do_once = 0; do_once == 0; ++ do_once) {
StringCached str_Health = get_cached_string(txt("Health")); attribute_fields.append( get_cached_string(txt("Health")));
StringCached str_MaxHealth = get_cached_string(txt("MaxHealth")); attribute_fields.append( get_cached_string(txt("MaxHealth")));
StringCached str_Mana = get_cached_string(txt("Mana")); attribute_fields.append( get_cached_string(txt("Mana")));
StringCached str_MaxMana = get_cached_string(txt("MaxMana")); attribute_fields.append( 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; return attribute_fields;
} }
@ -54,7 +35,7 @@ void gen_UGasaAttributeSet()
CodeType type_UAttributeSet = def_type( txt("UAttributeSet") ); CodeType type_UAttributeSet = def_type( txt("UAttributeSet") );
CodeComment generation_notice = def_comment(txt("Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp")); CodeComment generation_notice = def_comment(txt("Generated by GasaGen/GasaGen_UGasaAttributeSet.cpp"));
Array<GAS_AttributeEntry> attribute_fields = get_gasa_attribute_fields(); Array<StringCached> attribute_fields = get_gasa_attribute_fields();
StrC class_name = txt("UGasaAttributeSet"); StrC class_name = txt("UGasaAttributeSet");
@ -76,37 +57,30 @@ void gen_UGasaAttributeSet()
body.append( UHT_GENERATED_BODY); body.append( UHT_GENERATED_BODY);
body.append( access_public ); body.append( access_public );
def_attribute_properties( body, attribute_fields);
body.append(fmt_newline);
body.append( def_constructor() ); body.append( def_constructor() );
body.append(fmt_newline); body.append(fmt_newline);
def_attribute_properties( body, attribute_fields);
body.append(fmt_newline);
def_attribute_field_on_reps( body, attribute_fields); def_attribute_field_on_reps( body, attribute_fields);
body.append(fmt_newline); body.append(fmt_newline);
body.append( fmt_newline ); body.append( fmt_newline );
body.append( def_pragma(txt( "region Getters" ))); body.append( def_pragma(code( region Getters )));
def_attribute_field_property_getters( body, class_name, attribute_fields ); def_attribute_field_property_getters( body, class_name, attribute_fields );
body.append( fmt_newline ); body.append( fmt_newline );
def_attribute_field_value_getters( body, attribute_fields ); def_attribute_field_value_getters( body, attribute_fields );
body.append( def_pragma(txt( "endregion Getters" ))); body.append( def_pragma(code( endregion Getters )));
body.append( fmt_newline ); body.append( fmt_newline );
body.append( def_pragma(txt( "region Setters" ))); body.append( def_pragma(code( region Setters )));
def_attribute_field_value_setters( body, attribute_fields ); def_attribute_field_value_setters( body, attribute_fields );
body.append( fmt_newline ); body.append( fmt_newline );
body.append( fmt_newline ); body.append( fmt_newline );
def_attribute_field_initers( body, attribute_fields ); def_attribute_field_initers( body, attribute_fields );
body.append( def_pragma(txt( "endregion Setters" ))); body.append( def_pragma(code( 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 PostGameplayEffectExecute(FGameplayEffectModCallbackData const& Data) override;
));
body.append( def_pragma( txt("endregion AttributeSet")));
body.append( fmt_newline ); body.append( fmt_newline );
body.append( def_pragma( txt("region UObject"))); body.append( def_pragma( txt("region UObject")));
@ -170,7 +144,6 @@ void gen_UGasaAttributeSet()
header.print(fmt_newline); header.print(fmt_newline);
source.print( def_include( txt("GasaAttributeSet.h"))); source.print( def_include( txt("GasaAttributeSet.h")));
source.print( def_include( txt("GasaAttributeSet_Inlines.h"))); source.print( def_include( txt("GasaAttributeSet_Inlines.h")));
source.print( def_include( txt("EffectProperties.h")));
source.print(fmt_newline); source.print(fmt_newline);
source.print( def_include( txt("AbilitySystemComponent.h"))); source.print( def_include( txt("AbilitySystemComponent.h")));
source.print( def_include( txt("Net/UnrealNetwork.h"))); source.print( def_include( txt("Net/UnrealNetwork.h")));
@ -192,68 +165,14 @@ void gen_UGasaAttributeSet()
impl_attribute_fields( body, class_name, attribute_fields); impl_attribute_fields( body, class_name, attribute_fields);
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);
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>);
}
)));
}
attribute_clamps.append(fmt_newline);
attribute_clamps.append(fmt_newline);
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);
body.append(fmt_newline);
CodeFn GetLifetimeOfReplicatedProps; CodeFn GetLifetimeOfReplicatedProps;
{ {
CodeBody field_lifetimes = def_body( CodeT::Function_Body); CodeBody field_lifetimes = def_body( CodeT::Function_Body);
field_lifetimes.append(fmt_newline); field_lifetimes.append(fmt_newline);
field_lifetimes.append(fmt_newline); field_lifetimes.append(fmt_newline);
for (GAS_AttributeEntry field : attribute_fields) for (StringCached field : attribute_fields)
{ {
field_lifetimes.append( code_fmt( "field", (StrC)field.Name, stringize( field_lifetimes.append( code_fmt( "field", (StrC)field, stringize(
DOREPLIFETIME_DEFAULT_GAS(UGasaAttributeSet, <field>); DOREPLIFETIME_DEFAULT_GAS(UGasaAttributeSet, <field>);
))); )));
} }
@ -275,39 +194,44 @@ void gen_UGasaAttributeSet()
} }
} }
void def_attribute_properties( CodeBody body, Array<GAS_AttributeEntry> properties ) void def_attribute_properties( CodeBody body, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( StringCached property : properties )
{ {
Code field_uproperty = code_fmt( "property", (StrC)property.Name, stringize( Code field_uproperty = code_fmt( "property", (StrC)property, stringize(
UPROPERTY(ReplicatedUsing=Client_OnRep_<property>, EditAnywhere, BlueprintReadWrite, Category="Attributes") UPROPERTY(ReplicatedUsing=Client_OnRep_<property>, EditAnywhere, BlueprintReadWrite, Category="Attributes")
FGameplayAttributeData <property>;
)); ));
CodeType type_FGameplayAttributeData = def_type( txt("FGameplayAttributeData"));
body.append(fmt_newline);
body.append( field_uproperty ); body.append( field_uproperty );
body.append(fmt_newline);
body.append( def_variable( type_FGameplayAttributeData, StrC(property)) );
} }
} }
void def_attribute_field_on_reps( CodeBody body, Array<GAS_AttributeEntry> properties ) void def_attribute_field_on_reps( CodeBody body, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( StringCached property : properties )
{ {
Code umeta_UFUNCTION = code_str( UFUNCTION() ); Code umeta_UFUNCTION = code_str( UFUNCTION() );
body.append(fmt_newline); body.append(fmt_newline);
body.append( umeta_UFUNCTION ); body.append( umeta_UFUNCTION );
body.append(fmt_newline); body.append(fmt_newline);
body.append( code_fmt( "property", (StrC)property.Name, stringize( body.append( code_fmt( "property", (StrC)property, stringize(
void Client_OnRep_<property>(FGameplayAttributeData& Prev<property>); void Client_OnRep_<property>(FGameplayAttributeData& Prev<property>);
))); )));
} }
} }
void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties ) void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
CodeFn generated_get_attribute = parse_function( CodeFn generated_get_attribute = parse_function(
token_fmt( "class_name", class_name, "property", (StrC)property.Name, token_fmt( "class_name", class_name, "property", (StrC)property,
stringize( stringize(
static FGameplayAttribute Get<property>Attribute() static FGameplayAttribute Get<property>Attribute()
{ {
@ -321,11 +245,11 @@ void def_attribute_field_property_getters( CodeBody body, StrC class_name, Array
#pragma push_macro("FORCEINLINE") #pragma push_macro("FORCEINLINE")
#undef FORCEINLINE #undef FORCEINLINE
void def_attribute_field_value_getters( CodeBody body, Array<GAS_AttributeEntry> properties ) void def_attribute_field_value_getters( CodeBody body, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
body.append( code_fmt( "property", (StrC)property.Name, body.append( code_fmt( "property", (StrC)property,
stringize( stringize(
FORCEINLINE float Get<property>() const FORCEINLINE float Get<property>() const
{ {
@ -335,24 +259,24 @@ void def_attribute_field_value_getters( CodeBody body, Array<GAS_AttributeEntry>
} }
} }
void def_attribute_field_value_setters( CodeBody body, Array<GAS_AttributeEntry> properties ) void def_attribute_field_value_setters( CodeBody body, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
body.append( code_fmt( "property", (StrC)property.Name, body.append( code_fmt( "property", (StrC)property,
stringize( stringize(
FORCEINLINE void Set<property>(float NewVal); FORCEINLINE void Set<property>(float NewVal);
))); )));
} }
} }
void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties ) void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name, Array<StringCached> properties )
{ {
body.append(def_pragma( txt("region Attribute Setters"))); body.append(def_pragma( txt("region Attribute Setters")));
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
CodeFn generated_get_attribute = parse_function( CodeFn generated_get_attribute = parse_function(
token_fmt( "class_name", class_name, "property", (StrC)property.Name, token_fmt( "class_name", class_name, "property", (StrC)property,
stringize( stringize(
FORCEINLINE void <class_name>::Set<property>(float NewVal) FORCEINLINE void <class_name>::Set<property>(float NewVal)
{ {
@ -368,11 +292,11 @@ void def_attribute_field_property_setter_inlines( CodeBody body, StrC class_name
body.append(def_pragma( txt("endregion Attribute Setters"))); body.append(def_pragma( txt("endregion Attribute Setters")));
} }
void def_attribute_field_initers ( CodeBody body, Array<GAS_AttributeEntry> properties ) void def_attribute_field_initers ( CodeBody body, Array<StringCached> properties )
{ {
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
body.append( code_fmt( "property", (StrC)property.Name, body.append( code_fmt( "property", (StrC)property,
stringize( stringize(
FORCEINLINE void Init<property>(float NewVal) FORCEINLINE void Init<property>(float NewVal)
{ {
@ -383,14 +307,14 @@ void def_attribute_field_initers ( CodeBody body, Array<GAS_AttributeEntry> prop
} }
} }
void impl_attribute_fields( CodeBody body, StrC class_name, Array<GAS_AttributeEntry> properties ) void impl_attribute_fields( CodeBody body, StrC class_name, Array<StringCached> properties )
{ {
body.append(fmt_newline); body.append(fmt_newline);
body.append(def_pragma( txt("region Rep Notifies"))); body.append(def_pragma( txt("region Rep Notifies")));
for ( GAS_AttributeEntry property : properties ) for ( String property : properties )
{ {
CodeFn field_impl = parse_function( token_fmt( CodeFn field_impl = parse_function( token_fmt(
"class_name", class_name, "property", (StrC)property.Name, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"), "class_name", class_name, "property", (StrC)property, "from_notice", txt("\n// From GAMEPLAYATTRIBUTE_REPNOTIFY\n"),
stringize( stringize(
void <class_name>::Client_OnRep_<property>(FGameplayAttributeData& Prev<property>) void <class_name>::Client_OnRep_<property>(FGameplayAttributeData& Prev<property>)
{ {

View File

@ -55,21 +55,6 @@
</Expand> </Expand>
</Type> </Type>
<Type Name="gen::StringCached">
<DisplayString Condition="Data == nullptr">null</DisplayString>
<DisplayString>{Data,na}</DisplayString>
<Expand>
<Synthetic Name="Header">
<DisplayString>{(Header*)((char*)Data - sizeof(Header))}</DisplayString>
<Expand>
<Item Name="Allocator">((Header*)((char*)Data - sizeof(Header)))->Allocator</Item>
<Item Name="Capacity">((Header*)((char*)Data - sizeof(Header)))->Capacity</Item>
<Item Name="Length">((Header*)((char*)Data - sizeof(Header)))->Length</Item>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="gen::String::Header"> <Type Name="gen::String::Header">
<DisplayString>Length: {Length}, Capacity: {Capacity}</DisplayString> <DisplayString>Length: {Length}, Capacity: {Capacity}</DisplayString>
<Expand> <Expand>