Merge pull request #52 from TheRiverNyx/main

bunch o' fixes(not done)
This commit is contained in:
Lore Natusol
2025-10-06 20:14:55 -06:00
committed by GitHub
35 changed files with 782 additions and 286 deletions

View File

@@ -32,6 +32,9 @@ r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8
r.VirtualTextures=True r.VirtualTextures=True
r.VirtualTexturedLightmaps=True r.VirtualTexturedLightmaps=True
r.VT.AnisotropicFiltering=True r.VT.AnisotropicFiltering=True
r.Substrate=True
r.Substrate.OpaqueMaterialRoughRefraction=True
r.Substrate.Debug.AdvancedVisualizationShaders=False
[/Script/WindowsTargetPlatform.WindowsTargetSettings] [/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 DefaultGraphicsRHI=DefaultGraphicsRHI_DX12
@@ -170,4 +173,5 @@ EndpointSettings=(bEnableLogging=False,PurgeProcessedMessageDelaySeconds=30,Remo
[CoreRedirects] [CoreRedirects]
+ClassRedirects=(OldName="/Script/Elistria_Calling.MagickPlayerState",NewName="/Script/Elistria_Calling.MagickPlayerState") +ClassRedirects=(OldName="/Script/Elistria_Calling.MagickPlayerState",NewName="/Script/Elistria_Calling.MagickPlayerState")
+FunctionRedirects=(OldName="/Script/Elistria_Calling.PlayerGameplayAbilitiesDataAsset.GetAllMapings",NewName="/Script/Elistria_Calling.PlayerGameplayAbilitiesDataAsset.GetAllMappings")

View File

@@ -1,6 +1,6 @@
[/Script/EngineSettings.GeneralProjectSettings] [/Script/EngineSettings.GeneralProjectSettings]
ProjectID=34F4655F445E2B07E97EE9BB8110A0B8 ProjectID=36220C6945401B1B4EE12D8C5C8FBF0C
ProjectName=Third Person BP Game Template ProjectName=Elistria Calling
[StartupActions] [StartupActions]
bAddPacks=True bAddPacks=True
@@ -25,3 +25,8 @@ bShouldAcquireMissingChunksOnLoad=False
bShouldWarnAboutInvalidAssets=True bShouldWarnAboutInvalidAssets=True
MetaDataTagsForAssetRegistry=() MetaDataTagsForAssetRegistry=()
[/Script/GameplayAbilitiesEditor.GameplayEffectCreationMenu]
[/Script/CommonInput.CommonInputSettings]
bEnableEnhancedInputSupport=True

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64b8cb2d0256d3c6932480de5d06f2a5db803cb779fbd761955166227c217ecc
size 20676

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5fbb7205f5b42be72c79b2ad0a7b5c07a1eec2db75ba696e89e33e5cbfbef51b oid sha256:e6499614f53125133cc54f123b53b6bc095ddf1bae8cedbc398cdb3b76077f6d
size 51057 size 135350

View File

@@ -1,5 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
using System.IO;
using UnrealBuildTool; using UnrealBuildTool;
public class Elistria_Calling : ModuleRules public class Elistria_Calling : ModuleRules
@@ -18,6 +19,10 @@ public class Elistria_Calling : ModuleRules
// Uncomment if you are using online features // Uncomment if you are using online features
PrivateDependencyModuleNames.Add("OnlineSubsystem"); PrivateDependencyModuleNames.Add("OnlineSubsystem");
PublicIncludePaths.AddRange(new string[]{Path.Combine(ModuleDirectory, "Public")});
PrivateIncludePaths.AddRange(new string[]{Path.Combine(ModuleDirectory, "Private")});
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
} }
} }

View File

@@ -0,0 +1,68 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attributes/HealthAttributeSet.h"
UHealthAttributeSet::UHealthAttributeSet()
{
InitHealth(100.0f);
InitMaxHealth(100.0f);
}
void UHealthAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UHealthAttributeSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UHealthAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
}
void UHealthAttributeSet::OnRep_Health(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UHealthAttributeSet, Health, OldValue);
const float OldHealth = OldValue.GetCurrentValue();
const float NewHealth = GetHealth();
OnHealthChanged.Broadcast(this, OldHealth, NewHealth);
}
void UHealthAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UHealthAttributeSet, MaxHealth, OldValue);
const float OldMaxHealth = OldValue.GetCurrentValue();
const float NewMaxHealth = GetMaxHealth();
OnMaxHealthChanged.Broadcast(this, OldMaxHealth, NewMaxHealth);
}
void UHealthAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.0f, GetMaxHealth()));
}
if (Data.EvaluatedData.Attribute == GetDamageAttribute())
{
const float DamageValue = GetDamage();
const float OldHealth = GetHealth();
const float HealthMax = GetMaxHealth();
const float NewHealth = FMath::Clamp(OldHealth-DamageValue,0.0f, HealthMax);
if (OldHealth!=NewHealth)
{
SetHealth(NewHealth);
}
SetDamage(0.0f);
}
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
const float HealValue = GetHeal();
const float OldHealth = GetHealth();
const float HealthMax = GetMaxHealth();
const float NewHealth = FMath::Clamp(OldHealth+HealValue,0.0f, HealthMax);
if (OldHealth!=NewHealth)
{
SetHealth(NewHealth);
}
SetHeal(0.0f);
}
}

View File

@@ -0,0 +1,112 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attributes/LevelAttributeSet.h"
ULevelAttributeSet::ULevelAttributeSet()
{
InitLevel(1.0f);
InitXP(0.0f);
InitXPToNextLevel(ComputeXPForLevel(1));
}
void ULevelAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(ULevelAttributeSet, Level, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ULevelAttributeSet, XP, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ULevelAttributeSet, XPToNextLevel, COND_None, REPNOTIFY_Always);
}
float ULevelAttributeSet::ComputeXPForLevel(int32 InLevel) const
{
return 100.f + 50.f * FMath::Max(0, InLevel - 1);
}
void ULevelAttributeSet::OnRep_Level(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULevelAttributeSet, Level, OldValue);
UE_LOG(LogTemp, Log, TEXT("Level changed from %f to %f"), OldValue.GetCurrentValue(), Level.GetCurrentValue());
OnLevelChanged.Broadcast(this, OldValue.GetCurrentValue(), Level.GetCurrentValue());
}
void ULevelAttributeSet::OnRep_XP(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULevelAttributeSet, XP, OldValue);
UE_LOG( LogTemp, Log, TEXT("XP changed from %f to %f"), OldValue.GetCurrentValue(), XP.GetCurrentValue());
OnXPChanged.Broadcast(this, OldValue.GetCurrentValue(), XP.GetCurrentValue());
}
void ULevelAttributeSet::OnRep_XPToNextLevel(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULevelAttributeSet, XPToNextLevel, OldValue);
OnXPToNextLevelChanged.Broadcast(this, OldValue.GetCurrentValue(), XPToNextLevel.GetCurrentValue());
}
void ULevelAttributeSet::ConsumeXPGain()
{
const float Gain = GetXPGain();
if (Gain > 0.0f)
{
SetXP(GetXP() + Gain);
SetXPGain(0.0f);
}
}
void ULevelAttributeSet::TryProcessLevelUp()
{
bool Leveled = false;
int32 LevelsGained = 0;
float CurrentXP = GetXP();
float Needed = GetXPToNextLevel();
int32 CurrentLevelInt = FMath::FloorToInt(GetLevel());
while (CurrentXP>= Needed)
{
CurrentXP -= Needed;
CurrentLevelInt+=1;
Needed = ComputeXPForLevel(CurrentLevelInt);
Leveled = true;
}
if (Leveled)
{
SetLevel(static_cast<float>(CurrentLevelInt));
SetXPToNextLevel(Needed);
}
SetXP(FMath::Max(0.0f, CurrentXP));
if (Leveled)
{
HandleLevelUp(LevelsGained);
}
}
void ULevelAttributeSet::HandleLevelUp(int32 LevelsGained)
{
// This function can be expanded to include additional logic when a level-up occurs.
// For example, you might want to notify other systems, play a sound, etc.
OnLevelChanged.Broadcast(this, GetLevel() - LevelsGained, GetLevel());
}
void ULevelAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetXPAttribute())
{
ConsumeXPGain();
}
if (Data.EvaluatedData.Attribute == GetXPGainAttribute()||Data.EvaluatedData.Attribute == GetXPAttribute())
{
SetXP(FMath::Max(0.0f, GetXP()));
TryProcessLevelUp();
}
if (Data.EvaluatedData.Attribute == GetLevelAttribute())
{
const int32 Lvl = FMath::Max(1,FMath::FloorToInt(GetLevel()));
SetLevel(static_cast<float>(Lvl));
SetXP(FMath::Clamp(GetXP(),0.0f,ComputeXPForLevel(Lvl)));
SetXPToNextLevel(ComputeXPForLevel(Lvl));
}
}

View File

@@ -1,6 +1,6 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
#include "ManaAttributeSet.h" #include "Attributes/ManaAttributeSet.h"
UManaAttributeSet::UManaAttributeSet() UManaAttributeSet::UManaAttributeSet()
{ {
@@ -51,7 +51,7 @@ void UManaAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallba
} }
SetCost(0.0f); SetCost(0.0f);
} }
if (Data.EvaluatedData.Attribute==GetMaxManaAttribute()) if (Data.EvaluatedData.Attribute==GetRestoreAttribute())
{ {
const float RestoreValue = GetMaxMana(); const float RestoreValue = GetMaxMana();
const float OldMana = GetMana(); const float OldMana = GetMana();

View File

@@ -0,0 +1,62 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Attributes/StaminaAttributeSet.h"
UStaminaAttributeSet::UStaminaAttributeSet()
{
InitStamina(100.0f);
InitMaxStamina(100.0f);
}
void UStaminaAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UStaminaAttributeSet, Stamina, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UStaminaAttributeSet, MaxStamina, COND_None, REPNOTIFY_Always);
}
void UStaminaAttributeSet::OnRep_Stamina(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UStaminaAttributeSet, Stamina, OldValue);
const float OldStamina = OldValue.GetCurrentValue();
const float NewStamina = GetStamina();
OnStaminaChanged.Broadcast(this, OldStamina, NewStamina);
}
void UStaminaAttributeSet::OnRep_MaxStamina(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UStaminaAttributeSet, MaxStamina, OldValue);
const float OldMaxStamina = OldValue.GetCurrentValue();
const float NewMaxStamina = GetMaxStamina();
OnMaxStaminaChanged.Broadcast(this, OldMaxStamina, NewMaxStamina);
}
void UStaminaAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetStaminaAttribute())
{
SetStamina(FMath::Clamp(GetStamina(), 0.0f, GetMaxStamina()));
}
if (Data.EvaluatedData.Attribute == GetDrainAttribute())
{
const float DrainValue = GetDrain();
const float OldStamina = GetStamina();
const float StaminaMax = GetMaxStamina();
const float NewStamina = FMath::Clamp(OldStamina-DrainValue,0.0f, StaminaMax);
if (OldStamina!=NewStamina)
{
SetStamina(NewStamina);
}
SetDrain(0.0f);
}
if (Data.EvaluatedData.Attribute==GetRestoreAttribute())
{
const float RestoreValue = GetRestore();
const float OldStamina = GetStamina();
const float StaminaMax = GetMaxStamina();
const float NewStamina = FMath::Clamp(OldStamina+RestoreValue,0.0f, StaminaMax);
if (OldStamina!=NewStamina)
{
SetStamina(NewStamina);
}
}
}

View File

@@ -3,59 +3,54 @@
#include "ElistriaAbilitySystemComponent.h" #include "ElistriaAbilitySystemComponent.h"
#include "NativeGameplayTags.h"
#include "PlayerGameplayAbilitiesDataAsset.h" #include "PlayerGameplayAbilitiesDataAsset.h"
void UElistriaAbilitySystemComponent::ServerActivateAbilityByInputID_Implementation(FGameplayAbilitySpecHandle Handle,int32 InputID) UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Input_Confirm, "Input.Confirm");
{ UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Input_Cancel, "Input.Cancel");
TryActivateAbility(Handle);
}
void UElistriaAbilitySystemComponent::GrantAbilitiesFromDataAsset(const UPlayerGameplayAbilitiesDataAsset* AbilitiesDataAsset) void UElistriaAbilitySystemComponent::GrantAbilitiesFromDataAsset(const UPlayerGameplayAbilitiesDataAsset* AbilitiesDataAsset)
{ {
if (!AbilitiesDataAsset) return; if (!AbilitiesDataAsset) return;
for (const FGameplayInputAbilityInfo& AbilityInfo : AbilitiesDataAsset->GetMappings())
{
if (!AbilityInfo.IsValid()||!AbilityInfo.bAutoGive) continue;
for (const FGameplayInputAbilityInfo& AbilityInfo : AbilitiesDataAsset->GetInputAbilities()) FGameplayAbilitySpec Spec(AbilityInfo.AbilityClass,1,INDEX_NONE);
{
if (AbilityInfo.IsValid())
{
FGameplayAbilitySpec AbilitySpec(AbilityInfo.AbilityClass, 1, AbilityInfo.InputID);
FGameplayAbilitySpecHandle SpecHandle = GiveAbility(AbilitySpec);
InputIDToAbilitySpecHandleMap.Add(AbilityInfo.InputID, SpecHandle);
}
}
}
void UElistriaAbilitySystemComponent::AbilityLocalInputPressed(int32 InputID) FGameplayAbilitySpecHandle Handle = GiveAbility(Spec);
if (FGameplayAbilitySpec* Found = FindAbilitySpecFromHandle(Handle))
{ {
if (FGameplayAbilitySpecHandle* HandlePtr = SlotToAbilityHandleMap.Find(InputID)) if (AbilityInfo.InputTag.IsValid()&&!Found->DynamicAbilityTags.HasTagExact(AbilityInfo.InputTag))
{ {
if (GetOwnerRole() < ROLE_Authority) Found->DynamicAbilityTags.AddTagFast(AbilityInfo.InputTag);
{ MarkAbilitySpecDirty(*Found);
ServerActivateAbilityByInputID(*HandlePtr, InputID);
} }
TryActivateAbility(*HandlePtr); TagToSpecHandleMap.Add(AbilityInfo.InputTag, Handle);
} }
} }
void UElistriaAbilitySystemComponent::EquipAbility(TSubclassOf<UGameplayAbility> NewAbility, int32 SlotIndex)
{
if (!NewAbility) return;
UnequipAbility(SlotIndex);
FGameplayAbilitySpec Spec(NewAbility,1,SlotIndex);
FGameplayAbilitySpecHandle SpecHandle = GiveAbility(Spec);
SlotToAbilityHandleMap.Add(SlotIndex, SpecHandle);
OnAbilitiesChanged.Broadcast(this); OnAbilitiesChanged.Broadcast(this);
} }
void UElistriaAbilitySystemComponent::UnequipAbility(int32 SlotIndex) void UElistriaAbilitySystemComponent::HandleInputTag(ETriggerEvent EventType, FGameplayTag InputTag)
{ {
if (FGameplayAbilitySpecHandle* HandlePtr = SlotToAbilityHandleMap.Find(SlotIndex)) if (!InputTag.IsValid()) return;
{
ClearAbility(*HandlePtr);
SlotToAbilityHandleMap.Remove(SlotIndex);
OnAbilitiesChanged.Broadcast(this); if (InputTag == TAG_Input_Confirm)
{
TargetConfirm();
return;
}
if (InputTag == TAG_Input_Cancel)
{
TargetCancel();
return;
}
if (EventType == ETriggerEvent::Started||EventType == ETriggerEvent::Triggered)
{
FGameplayTagContainer Tags(InputTag);
TryActivateAbilitiesByTag(Tags, true);
} }
} }

View File

@@ -1,5 +1,5 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
#include "HealthAttributeSet.h" #include "ElistriaAttributeSetBase.h"

View File

@@ -7,7 +7,7 @@
void UElistriaEnhancedInputComponent::ClearAbilityBindings() void UElistriaEnhancedInputComponent::ClearAbilityBindings()
{ {
for (uint32 Handle : AbilityActionBindings) for (int32 Handle : AbilityActionBindings)
{ {
RemoveBindingByHandle(Handle); RemoveBindingByHandle(Handle);
} }

View File

@@ -1,75 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "MagickPlayerController.h"
#include "ElistriaEnhancedInputComponent.h"
#include "MagickPlayerState.h"
void AMagickPlayerController::OnPossess(APawn *InPawn)
{
Super::OnPossess(InPawn);
UE_LOG(LogTemp, Display, TEXT("OnPossess"));
AMagickPlayerState* PS = GetPlayerState<AMagickPlayerState>();
UElistriaAbilitySystemComponent* ASC = PS ? PS->GetAbilitySystemComponent() : nullptr;
if (PS)
{
PS->SetupAbilityActorInfo();
if (ASC)
{
ASC->OnAbilitiesChanged.AddDynamic(this,&AMagickPlayerController::OnAbilitiesChanged);
}
}
}
void AMagickPlayerController::OnAbilitiesChanged(UElistriaAbilitySystemComponent* ASC)
{
RebindAbilityInputs();
}
void AMagickPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
if (UElistriaEnhancedInputComponent* EIC = Cast<UElistriaEnhancedInputComponent>(InputComponent))
{
if (InputAbilitiesDataAsset)
{
EIC->BindAbilityActions(InputAbilitiesDataAsset, this, &AMagickPlayerController::AbilityInputPressed);
}
}
}
void AMagickPlayerController::AbilityInputPressed(int32 InputID)
{
if (AMagickPlayerState* PS = GetPlayerState<AMagickPlayerState>())
{
if (UElistriaAbilitySystemComponent* ASC = PS ? PS->GetAbilitySystemComponent() : nullptr)
{
ASC->AbilityLocalInputPressed(InputID);
}
}
}
void AMagickPlayerController::BeginPlay()
{
Super::BeginPlay();
if (UInputMappingContext* IMC = InputMappingContext)
{
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
{
Subsystem->AddMappingContext(IMC, 0);
}
}
}
void AMagickPlayerController::RebindAbilityInputs()
{
if (UElistriaEnhancedInputComponent* EIC = Cast<UElistriaEnhancedInputComponent>(InputComponent))
{
EIC -> ClearAbilityBindings();
if (InputAbilitiesDataAsset)
{
EIC->BindAbilityActions(InputAbilitiesDataAsset,this,&AMagickPlayerController::AbilityInputPressed);
}
}
}

View File

@@ -0,0 +1,93 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Player/MagickPlayerController.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "PlayerGameplayAbilitiesDataAsset.h"
#include "ElistriaEnhancedInputComponent.h"
#include "ElistriaAbilitySystemComponent.h"
#include "Player/MagickPlayerState.h"
void AMagickPlayerController::BeginPlay()
{
Super::BeginPlay();
if (InputMappingContext)
{
if (UEnhancedInputLocalPlayerSubsystem* Sub = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
{
Sub->AddMappingContext(InputMappingContext,0);
}
}
}
void AMagickPlayerController::OnPossess(APawn *InPawn)
{
Super::OnPossess(InPawn);
if (AMagickPlayerState* PS = GetPlayerState<AMagickPlayerState>())
{
if (UElistriaAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent())
{
PS->SetupAbilityActorInfo();
ASC->OnAbilitiesChanged.AddDynamic(this, &AMagickPlayerController::OnASCGranted);
if (InputAbilitiesDataAsset)
{
ASC->GrantAbilitiesFromDataAsset(InputAbilitiesDataAsset);
}
}
}
}
void AMagickPlayerController::OnAbilitiesChanged(UElistriaAbilitySystemComponent* ASC)
{
RebindAbilityInputs();
}
void AMagickPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
RebindAbilityInputs();
}
void AMagickPlayerController::OnASCGranted(UElistriaAbilitySystemComponent* ASC)
{
RebindAbilityInputs();
}
void AMagickPlayerController::RebindAbilityInputs()
{
if (UElistriaEnhancedInputComponent* EIC = Cast<UElistriaEnhancedInputComponent>(InputComponent))
{
EIC->ClearAbilityBindings();
if (InputAbilitiesDataAsset)
{
EIC->BindAbilityActionsByTag(InputAbilitiesDataAsset,this,&AMagickPlayerController::HandleInput);
}
}
}
void AMagickPlayerController::AbilityInputTag(const FInputActionInstance& Instance, FGameplayTag InputTag)
{
if (!InputTag.IsValid()) return;
if (AMagickPlayerState* PS = GetPlayerState<AMagickPlayerState>())
{
if (UElistriaAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent())
{
ASC->HandleInputTag(Instance.GetTriggerEvent(), InputTag);
}
}
}
void AMagickPlayerController::HandleInput(const FInputActionInstance& Instance, FGameplayTag InputTag)
{
if (!InputTag.IsValid()) return;
if (AMagickPlayerState* PS = GetPlayerState<AMagickPlayerState>())
{
if (UElistriaAbilitySystemComponent* ASC = PS->GetAbilitySystemComponent())
{
ASC->HandleInputTag(Instance.GetTriggerEvent(), InputTag);
}
}
}

View File

@@ -1,15 +1,16 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
#include "Player/MagickPlayerState.h"
#include "MagickPlayerState.h" #include "Player/MagickPlayerController.h"
#include "Net/UnrealNetwork.h"
AMagickPlayerState::AMagickPlayerState() AMagickPlayerState::AMagickPlayerState()
{ {
ElistriaAbilitySystemComponent = CreateDefaultSubobject<UElistriaAbilitySystemComponent>(TEXT("AbilitySystem")); ElistriaAbilitySystemComponent = CreateDefaultSubobject<UElistriaAbilitySystemComponent>(TEXT("AbilitySystem"));
ManaSet = CreateDefaultSubobject<UManaAttributeSet>(TEXT("ManaSet")); ManaSet = CreateDefaultSubobject<UManaAttributeSet>(TEXT("ManaSet"));
HealthSet = CreateDefaultSubobject<UHealthAttributeSet>(TEXT("HealthSet"));
StaminaSet = CreateDefaultSubobject<UStaminaAttributeSet>(TEXT("StaminaSet"));
LevelSet = CreateDefaultSubobject<ULevelAttributeSet>(TEXT("XPSet"));
} }
UElistriaAbilitySystemComponent* AMagickPlayerState::GetAbilitySystemComponent() const UElistriaAbilitySystemComponent* AMagickPlayerState::GetAbilitySystemComponent() const
@@ -30,6 +31,8 @@ void AMagickPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& O
DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, ElistriaAbilitySystemComponent, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, ElistriaAbilitySystemComponent, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, ManaSet, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, ManaSet, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, HealthSet, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(AMagickPlayerState, StaminaSet, COND_None, REPNOTIFY_Always);
} }
void AMagickPlayerState::SetupAbilityActorInfo() void AMagickPlayerState::SetupAbilityActorInfo()
@@ -54,6 +57,18 @@ void AMagickPlayerState::SetupAbilityActorInfo()
{ {
ElistriaAbilitySystemComponent->AddAttributeSetSubobject(ManaSet.Get()); ElistriaAbilitySystemComponent->AddAttributeSetSubobject(ManaSet.Get());
} }
if (HealthSet)
{
ElistriaAbilitySystemComponent->AddAttributeSetSubobject(HealthSet.Get());
}
if (StaminaSet)
{
ElistriaAbilitySystemComponent->AddAttributeSetSubobject(StaminaSet.Get());
}
if (LevelSet)
{
ElistriaAbilitySystemComponent->AddAttributeSetSubobject(LevelSet.Get());
}
} }
} }

View File

@@ -2,43 +2,3 @@
#include "PlayerGameplayAbilitiesDataAsset.h" #include "PlayerGameplayAbilitiesDataAsset.h"
UPlayerGameplayAbilitiesDataAsset::UPlayerGameplayAbilitiesDataAsset(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
// Constructor implementation
}
const TSet<FGameplayInputAbilityInfo>& UPlayerGameplayAbilitiesDataAsset::GetInputAbilities() const
{
return InputAbilities;
}
#if WITH_EDITOR
void UPlayerGameplayAbilitiesDataAsset::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
const FProperty* Property = PropertyChangedEvent.Property;
if (Property && Property->GetName()==GET_MEMBER_NAME_CHECKED(UPlayerGameplayAbilitiesDataAsset, InputAbilities)&& !InputAbilities.IsEmpty())
{
TArray<FGameplayInputAbilityInfo> InputAbilitiesArray = InputAbilities.Array();
for (int32 i = InputAbilitiesArray.Num() - 1; i >= 0; i--)
{
const int32 PrevIndex = i - 1;
if (InputAbilitiesArray[i]==InputAbilitiesArray[PrevIndex])
{
InputAbilitiesArray.RemoveAtSwap(i);
}
}
InputAbilities.Reset();
for (int32 i=0; i<InputAbilitiesArray.Num(); i++)
{
FGameplayInputAbilityInfo& AbilityInfo = InputAbilitiesArray[i];
AbilityInfo.InputID = i;
InputAbilities.Add(AbilityInfo);
}
}
}
#endif

View File

@@ -0,0 +1,57 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "ElistriaAttributeSetBase.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"
#include "HealthAttributeSet.generated.h"
/**
*
*/
UCLASS()
class ELISTRIA_CALLING_API UHealthAttributeSet : public UElistriaAttributeSetBase
{
GENERATED_BODY()
public:
UHealthAttributeSet();
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,ReplicatedUsing=OnRep_Health)
FGameplayAttributeData Health;
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,ReplicatedUsing=OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData Damage;
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData Heal;
ATTRIBUTE_ACCESSORS(UHealthAttributeSet, Health)
ATTRIBUTE_ACCESSORS(UHealthAttributeSet, MaxHealth)
ATTRIBUTE_ACCESSORS(UHealthAttributeSet, Damage)
ATTRIBUTE_ACCESSORS(UHealthAttributeSet, Heal)
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldValue);
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldValue);
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnHealthChanged;
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnMaxHealthChanged;
};

View File

@@ -0,0 +1,76 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "ElistriaAttributeSetBase.h"
#include "AbilitySystemComponent.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"
#include "ManaAttributeSet.h"
#include "LevelAttributeSet.generated.h"
/**
*
*/
UCLASS()
class ELISTRIA_CALLING_API ULevelAttributeSet : public UElistriaAttributeSetBase
{
GENERATED_BODY()
public:
ULevelAttributeSet();
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing=OnRep_Level)
FGameplayAttributeData Level;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing=OnRep_XP)
FGameplayAttributeData XP;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing = OnRep_XPToNextLevel)
FGameplayAttributeData XPToNextLevel;
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData XPGain;
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData XPLoss;
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData MaxLevel;
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, XP)
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, Level)
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, MaxLevel)
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, XPToNextLevel)
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, XPGain)
ATTRIBUTE_ACCESSORS(ULevelAttributeSet, XPLoss)
UFUNCTION()
void OnRep_Level(const FGameplayAttributeData& OldValue);
UFUNCTION()
void OnRep_XP(const FGameplayAttributeData& OldValue);
UFUNCTION()
void OnRep_XPToNextLevel(const FGameplayAttributeData& OldValue);
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnLevelChanged;
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnXPChanged;
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnXPToNextLevelChanged;
protected:
float ComputeXPForLevel(int32 InLevel) const;
void HandleLevelUp(int32 LevelsGained);
void ConsumeXPGain();
void TryProcessLevelUp();
};

View File

@@ -3,8 +3,8 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h" #include "AbilitySystemComponent.h"
#include "ElistriaAttributeSetBase.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h" #include "GameplayEffectExtension.h"
#include "ManaAttributeSet.generated.h" #include "ManaAttributeSet.generated.h"
@@ -13,16 +13,8 @@
* *
*/ */
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAttributeChangedEvent, UAttributeSet*, AttributeSet, float, OldValue, float, NewValue);
UCLASS() UCLASS()
class ELISTRIA_CALLING_API UManaAttributeSet : public UAttributeSet class ELISTRIA_CALLING_API UManaAttributeSet : public UElistriaAttributeSetBase
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@@ -0,0 +1,53 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "ElistriaAttributeSetBase.h"
#include "HealthAttributeSet.h"
#include "StaminaAttributeSet.generated.h"
/**
*
*/
UCLASS()
class ELISTRIA_CALLING_API UStaminaAttributeSet : public UElistriaAttributeSetBase
{
GENERATED_BODY()
public:
UStaminaAttributeSet();
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing=OnRep_Stamina)
FGameplayAttributeData Stamina;
ATTRIBUTE_ACCESSORS(UStaminaAttributeSet, Stamina)
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, ReplicatedUsing=OnRep_MaxStamina)
FGameplayAttributeData MaxStamina;
ATTRIBUTE_ACCESSORS(UStaminaAttributeSet, MaxStamina)
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData Drain;
ATTRIBUTE_ACCESSORS(UStaminaAttributeSet, Drain)
UPROPERTY(VisibleAnywhere)
FGameplayAttributeData Restore;
ATTRIBUTE_ACCESSORS(UStaminaAttributeSet, Restore)
UFUNCTION()
void OnRep_Stamina(const FGameplayAttributeData& OldValue);
UFUNCTION()
void OnRep_MaxStamina(const FGameplayAttributeData& OldValue);
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnStaminaChanged;
UPROPERTY(BlueprintAssignable)
FAttributeChangedEvent OnMaxStaminaChanged;
};

View File

@@ -11,35 +11,36 @@
/** /**
* *
*/ */
class UPlayerGameplayAbilitiesDataAsset;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnASCGrantedInputAbilties, UElistriaAbilitySystemComponent*, ASC);
UCLASS() UCLASS()
class ELISTRIA_CALLING_API UElistriaAbilitySystemComponent : public UAbilitySystemComponent class ELISTRIA_CALLING_API UElistriaAbilitySystemComponent : public UAbilitySystemComponent
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UFUNCTION(Server, Reliable) UPROPERTY(BlueprintAssignable, Category="AbilitySystem")
void ServerActivateAbilityByInputID(FGameplayAbilitySpecHandle Handle, int32 InputID); FOnASCGrantedInputAbilties OnGrantedInputAbilties;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable, Category="AbilitySystem")
void EquipAbility(TSubclassOf<UGameplayAbility> NewAbility, int32 SlotIndex); void GrantAbilitiesFromDataAsset(const UPlayerGameplayAbilitiesDataAsset* AbilitiesDataAsset);
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable, Category="AbilitySystem")
void UnequipAbility(int32 SlotIndex); void HandleInputTag(ETriggerEvent EventType, FGameplayTag InputTag);
void RefreshInputBindings(); UFUNCTION(BlueprintCallable, Category="AbilitySystem")
void ConfirmTargetingInput(){TargetConfirm();}
UFUNCTION(BlueprintCallable, Category="AbilitySystem")
void CancelTargetingInput(){TargetCancel();}
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAbilitiesChanged, UElistriaAbilitySystemComponent*, ASC); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAbilitiesChanged, UElistriaAbilitySystemComponent*, ASC);
UPROPERTY(BlueprintAssignable) UPROPERTY(BlueprintAssignable)
FOnAbilitiesChanged OnAbilitiesChanged; FOnAbilitiesChanged OnAbilitiesChanged;
void GrantAbilitiesFromDataAsset(const UPlayerGameplayAbilitiesDataAsset* AbilitiesDataAsset);
virtual void AbilityLocalInputPressed(int32 InputID) override;
private: private:
TMap<int32, FGameplayAbilitySpecHandle> InputIDToAbilitySpecHandleMap;
UPROPERTY() UPROPERTY()
TMap<int32, FGameplayAbilitySpecHandle> SlotToAbilityHandleMap; TMap<FGameplayTag, FGameplayAbilitySpecHandle> TagToSpecHandleMap;
void ServerActivateAbilityByInputID_Implementation(FGameplayAbilitySpecHandle Handle, int32 InputID);
}; };

View File

@@ -0,0 +1,24 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "ElistriaAttributeSetBase.generated.h"
/**
*
*/
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAttributeChangedEvent, UAttributeSet*, AttributeSet, float, OldValue, float, NewValue);
UCLASS()
class ELISTRIA_CALLING_API UElistriaAttributeSetBase : public UAttributeSet
{
GENERATED_BODY()
};

View File

@@ -14,26 +14,42 @@ UCLASS()
class ELISTRIA_CALLING_API UElistriaEnhancedInputComponent : public UEnhancedInputComponent class ELISTRIA_CALLING_API UElistriaEnhancedInputComponent : public UEnhancedInputComponent
{ {
GENERATED_BODY() GENERATED_BODY()
public:
template<class UserClass, typename FuncType>
void BindAbilityActions(const UPlayerGameplayAbilitiesDataAsset* InputConfig, UserClass* Object, FuncType Func);
public:
template <class UserClass>
void BindAbilityActionsByTag(const UPlayerGameplayAbilitiesDataAsset* InputConfig, UserClass* Object,
void (UserClass::*Func)(const FInputActionInstance&, FGameplayTag));
UFUNCTION(BlueprintCallable, Category="Input")
void ClearAbilityBindings(); void ClearAbilityBindings();
private: private:
TArray<uint32> AbilityActionBindings; TArray<int32> AbilityActionBindings;
}; };
template<class UserClass, typename FuncType> template <class UserClass>
void UElistriaEnhancedInputComponent::BindAbilityActions(const UPlayerGameplayAbilitiesDataAsset* InputConfig, UserClass* Object, FuncType Func) void UElistriaEnhancedInputComponent::BindAbilityActionsByTag(const UPlayerGameplayAbilitiesDataAsset* InputConfig, UserClass* Object, void (UserClass::*Func)(const FInputActionInstance&, FGameplayTag))
{ {
if (!InputConfig) return; if (!InputConfig||!Func) return;
for (const FGameplayInputAbilityInfo& AbilityInfo : InputConfig->GetInputAbilities()) static const ETriggerEvent EventsToBind[]={
ETriggerEvent::Started,
ETriggerEvent::Completed,
ETriggerEvent::Canceled,
ETriggerEvent::Triggered,
ETriggerEvent::Ongoing
};
for (const FGameplayInputAbilityInfo& Info : InputConfig->AbilityMappings)
{ {
if (AbilityInfo.IsValid()) if (!Info.IsValid()) continue;
for (ETriggerEvent Event : EventsToBind)
{ {
BindAction(AbilityInfo.InputAction,ETriggerEvent::Triggered,Object,Func,AbilityInfo.InputID); FEnhancedInputActionEventBinding& Binding = BindAction(Info.InputAction,Event,Object,Func,Info.InputTag);
AbilityActionBindings.Add(Binding.GetHandle());
} }
} }
{
} }
}

View File

@@ -1,17 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "HealthAttributeSet.generated.h"
/**
*
*/
UCLASS()
class ELISTRIA_CALLING_API UHealthAttributeSet : public UAttributeSet
{
GENERATED_BODY()
};

View File

@@ -7,35 +7,50 @@
#include "GameFramework/PlayerController.h" #include "GameFramework/PlayerController.h"
#include "InputMappingContext.h" #include "InputMappingContext.h"
#include "EnhancedInputSubsystems.h" #include "EnhancedInputSubsystems.h"
#include "ElistriaEnhancedInputComponent.h"
class UPlayerGameplayAbilitiesDataAsset;
class UInputMappingContext;
class UElistriaEnhancedInputComponent;
class UElistriaAbilitySystemComponent;
class AMagickPlayerState;
struct FInputActionInstance;
#include "MagickPlayerController.generated.h" #include "MagickPlayerController.generated.h"
/** /**
* *
*/ */
UCLASS() UCLASS()
class ELISTRIA_CALLING_API AMagickPlayerController : public APlayerController class ELISTRIA_CALLING_API AMagickPlayerController : public APlayerController
{ {
GENERATED_BODY() GENERATED_BODY()
public:
virtual void SetupInputComponent() override;
virtual void OnPossess(APawn* InPawn) override; virtual void OnPossess(APawn* InPawn) override;
virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable, Category="Input")
void RebindAbilityInputs();
UFUNCTION()
void OnASCGranted(UElistriaAbilitySystemComponent* ASC);
UFUNCTION()
void HandleInput(const FInputActionInstance& Instance, FGameplayTag InputTag);
UFUNCTION() UFUNCTION()
void OnAbilitiesChanged(UElistriaAbilitySystemComponent* ASC); void OnAbilitiesChanged(UElistriaAbilitySystemComponent* ASC);
public: UFUNCTION()
void AbilityInputTag(const FInputActionInstance& Instance, FGameplayTag InputTag);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Input") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Input")
TObjectPtr<UPlayerGameplayAbilitiesDataAsset> InputAbilitiesDataAsset; TObjectPtr<UPlayerGameplayAbilitiesDataAsset> InputAbilitiesDataAsset;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Input") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Input")
TObjectPtr<UInputMappingContext> InputMappingContext; TObjectPtr<UInputMappingContext> InputMappingContext;
virtual void SetupInputComponent() override;
UFUNCTION()
void AbilityInputPressed(int32 InputID);
virtual void BeginPlay() override;
void RebindAbilityInputs();
}; };

View File

@@ -6,8 +6,13 @@
#include "GameFramework/PlayerState.h" #include "GameFramework/PlayerState.h"
#include "AbilitySystemInterface.h" #include "AbilitySystemInterface.h"
#include "ElistriaAbilitySystemComponent.h" #include "ElistriaAbilitySystemComponent.h"
#include "ManaAttributeSet.h" #include "Attributes/ManaAttributeSet.h"
#include "MagickPlayerController.h" #include "Attributes/StaminaAttributeSet.h"
#include "Attributes/HealthAttributeSet.h"
#include "Attributes/LevelAttributeSet.h"
class AMagickPlayerController;
#include "MagickPlayerState.generated.h" #include "MagickPlayerState.generated.h"
UCLASS(Config=game) UCLASS(Config=game)
@@ -15,8 +20,6 @@ class ELISTRIA_CALLING_API AMagickPlayerState : public APlayerState, public IAbi
{ {
GENERATED_BODY() GENERATED_BODY()
virtual void BeginPlay() override; virtual void BeginPlay() override;
public: public:
@@ -34,6 +37,15 @@ protected:
UPROPERTY(Replicated) UPROPERTY(Replicated)
TObjectPtr<class UManaAttributeSet> ManaSet; TObjectPtr<class UManaAttributeSet> ManaSet;
UPROPERTY(Replicated)
TObjectPtr<UStaminaAttributeSet> StaminaSet;
UPROPERTY(Replicated)
TObjectPtr<UHealthAttributeSet> HealthSet;
UPROPERTY(Replicated)
TObjectPtr<ULevelAttributeSet> LevelSet;
private: private:
}; };

View File

@@ -12,43 +12,32 @@
*/ */
class UInputAction; class UInputAction;
USTRUCT() USTRUCT(BlueprintType)
struct FGameplayInputAbilityInfo struct FGameplayInputAbilityInfo
{ {
GENERATED_USTRUCT_BODY() GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, Category = "GameplayInputAbilityInfo") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability")
TSubclassOf<UGameplayAbility> AbilityClass; TSubclassOf<UGameplayAbility> AbilityClass;
UPROPERTY(EditAnywhere, Category = "GameplayInputAbilityInfo") UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "Ability")
TObjectPtr<UInputAction> InputAction; TObjectPtr<UInputAction> InputAction;
UPROPERTY(VisibleAnywhere, Category = "GameplayInputAbilityInfo") UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "Ability", meta = (Categories="Input"))
int32 InputID; FGameplayTag InputTag;
bool IsValid() const UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "Ability")
bool bAutoGive = true;
bool IsValid() const{ return AbilityClass && InputAction && InputTag.IsValid();}
bool operator==(const FGameplayInputAbilityInfo& Other) const
{ {
return AbilityClass && InputAction; return AbilityClass == Other.AbilityClass && InputAction == Other.InputAction && InputTag == Other.InputTag;
} }
bool operator==(const FGameplayInputAbilityInfo& other) const
{
return AbilityClass == other.AbilityClass && InputID == other.InputID;
}
bool operator!=(const FGameplayInputAbilityInfo& other) const
{
return !operator==(other);
}
friend uint32 GetTypeHash(const FGameplayInputAbilityInfo& Item) friend uint32 GetTypeHash(const FGameplayInputAbilityInfo& Item)
{ {
return HashCombine(GetTypeHash(Item.AbilityClass), Item.InputID); return HashCombine(GetTypeHash(Item.AbilityClass), GetTypeHash(Item.InputTag));
}
FGameplayInputAbilityInfo()
: InputID(INDEX_NONE)
{
} }
}; };
@@ -57,16 +46,44 @@ class ELISTRIA_CALLING_API UPlayerGameplayAbilitiesDataAsset : public UDataAsset
{ {
GENERATED_BODY() GENERATED_BODY()
protected:
UPROPERTY(EditAnywhere, Category = "AbilitySystem")
TSet<FGameplayInputAbilityInfo> InputAbilities;
public: public:
UPlayerGameplayAbilitiesDataAsset(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="AbilitySystem")
TArray<FGameplayInputAbilityInfo> AbilityMappings;
const TSet<FGameplayInputAbilityInfo>& GetInputAbilities() const; UFUNCTION(BlueprintPure, Category = "AbilitySystem")
void GetAllMappings(TArray<FGameplayInputAbilityInfo>& Out) const { Out = AbilityMappings; }
UFUNCTION(BlueprintCallable, Category = "AbilitySystem")
void AddMapping(const FGameplayInputAbilityInfo& Entry)
{
if (!Entry.IsValid()) return;
AbilityMappings.Add(Entry);
}
UFUNCTION(BlueprintCallable, Category = "AbilitySystem")
void RemoveByTag(FGameplayTag InputTag)
{
AbilityMappings.RemoveAll([&](const FGameplayInputAbilityInfo& E) { return E.InputTag == InputTag; });
}
UFUNCTION(BlueprintPure, Category = "AbilitySystem")
void FindByTag(FGameplayTag InputTag, TArray<FGameplayInputAbilityInfo>& Out) const
{
for (const auto& E : AbilityMappings)
{
if (E.InputTag == InputTag)
{
Out.Add(E);
}
}
}
const TArray<FGameplayInputAbilityInfo>& GetMappings() const { return AbilityMappings; }
#if WITH_EDITOR #if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override
{
Super::PostEditChangeProperty(PropertyChangedEvent);
// Ensure uniqueness (Set already helps). Could add validation if needed.
}
#endif #endif
}; };