// Copyright Echo Devgroup #include "AbilitySystem/AuraAttributeSet.h" #include "AbilitySystemBlueprintLibrary.h" #include "GameplayEffectExtension.h" #include "GameFramework/Character.h" #include "Net/UnrealNetwork.h" #include "AuraGameplayTags.h" UAuraAttributeSet::UAuraAttributeSet() { const FAuraGameplayTags& GameplayTags = FAuraGameplayTags::Get(); TagsToAttributes.Add(GameplayTags.Attributes_Vital_Health, GetHealthAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Vital_MaxHealth, GetMaxHealthAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Vital_Mana, GetManaAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Vital_MaxMana, GetMaxManaAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Primary_Strength, GetStrengthAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Primary_Intelligence, GetIntelligenceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Primary_Resilience, GetResilienceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Primary_Vigor, GetVigorAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_Armor, GetArmorAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_ArmorPenetration, GetArmorPenetrationAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_BlockChance, GetBlockChanceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_CriticalHitChance, GetCriticalHitChanceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_CriticalHitDamage, GetCriticalHitChanceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_CriticalHitResistance, GetCriticalHitResistanceAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_HealthRegeneration, GetHealthRegenerationAttribute); TagsToAttributes.Add(GameplayTags.Attributes_Secondary_ManaRegeneration, GetManaRegenerationAttribute); } void UAuraAttributeSet::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); //Replicate Lifetime of each attribute /*Primary Stats *Strength, Intelligence, Resilience, Vigor */ DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Strength, COND_None, REPNOTIFY_Always); //Effects Physical Damage DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Intelligence, COND_None, REPNOTIFY_Always); //Effects Max Mana, Mana Regen, Magical Damage DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Resilience, COND_None, REPNOTIFY_Always); //Increases Armor DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Vigor, COND_None, REPNOTIFY_Always); //Increases Max Health, Armor, Health Regenerated /*Secondary Stats *Armor, Armor Penetration, Block Chance, Critical Hit Chance, Critical Hit Damage, Critical Hit Resistance, Health Regeneration, Mana Regeneration */ DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Armor, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, ArmorPenetration, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, BlockChance, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, CriticalHitChance, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, CriticalHitDamage, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, CriticalHitResistance, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, HealthRegeneration, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, ManaRegeneration, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, MaxMana, COND_None, REPNOTIFY_Always); /*Vital Stats *Max Health - Have to be initialized after MaxHealth as an Instant Gameplay Effect * Max Mana - Has to be initialized after MaxMana as an Instant Gameplay Effect */ DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Health, COND_None, REPNOTIFY_Always); DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Mana, COND_None, REPNOTIFY_Always); } void UAuraAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) { Super::PreAttributeChange(Attribute, NewValue); if (Attribute == GetHealthAttribute()) { NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth()); } if (Attribute == GetManaAttribute()) { NewValue = FMath::Clamp(NewValue, 0.f, GetMaxMana()); } } void UAuraAttributeSet::SetEffectProperties(const FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const { if (Data.EvaluatedData.Attribute == GetHealthAttribute()) { // Source = Causer of the effect, Target = target of the effect (Owner of this Attribute Set) Props.EffectContextHandle = Data.EffectSpec.GetContext(); Props.SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent(); if (IsValid(Props.SourceASC) && Props.SourceASC->AbilityActorInfo.IsValid() && Props.SourceASC->AbilityActorInfo.IsValid()) { Props.SourceAvatarActor = Props.SourceASC->AbilityActorInfo->AvatarActor.Get(); Props.SourceController = Props.SourceASC->AbilityActorInfo->PlayerController.Get(); if (Props.SourceController == nullptr && Props.SourceAvatarActor != nullptr) { if (APawn* Pawn = Cast(Props.SourceAvatarActor)) { Props.SourceController = Pawn->GetController(); } } if (Props.SourceController) { Props.SourceCharacter = Cast(Props.SourceController->GetPawn()); } } } //Get all the target actor if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid()) { Props.TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get(); Props.TargetController = Data.Target.AbilityActorInfo->PlayerController.Get(); Props.TargetCharacter = Cast(Props.TargetAvatarActor); Props.TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor); } } void UAuraAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) { Super::PostGameplayEffectExecute(Data); FEffectProperties Props; SetEffectProperties(Data, Props); if (Data.EvaluatedData.Attribute == GetHealthAttribute()) { //if the value being modified is Health SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth())); } if (Data.EvaluatedData.Attribute == GetManaAttribute()) { //If the value being modified is Mana SetMana(FMath::Clamp(GetMana(), 0.f, GetMaxMana())); } } /*On_Rep for each stat *Vital Stats *Health, MaxHealth, Mana, MaxMana*/ void UAuraAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Health,OldHealth); } void UAuraAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,MaxHealth,OldMaxHealth); } void UAuraAttributeSet::OnRep_Mana(const FGameplayAttributeData& OldMana) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Mana,OldMana); } void UAuraAttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,MaxMana,OldMaxMana); } /*Primary Stats *Strength, Intelligence, Resilience, Vigor*/ void UAuraAttributeSet::OnRep_Strength(const FGameplayAttributeData& OldStrength) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Strength,OldStrength); } void UAuraAttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Intelligence,OldIntelligence); } void UAuraAttributeSet::OnRep_Resilience(const FGameplayAttributeData& OldResilience) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Resilience,OldResilience); } void UAuraAttributeSet::OnRep_Vigor(const FGameplayAttributeData& OldVigor) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Vigor,OldVigor); } /*Secondary Stats *Armor, Armor Penetration, Block Chance, Critical Hit Chance, Critical Hit Damage, Critical Hit Resistance, Health Regeneration, Mana Regeneration */ void UAuraAttributeSet::OnRep_Armor(const FGameplayAttributeData& OldArmor) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,Armor,OldArmor); } void UAuraAttributeSet::OnRep_ArmorPenetration(const FGameplayAttributeData& OldArmorPenetration) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,ArmorPenetration,OldArmorPenetration); } void UAuraAttributeSet::OnRep_BlockChance(const FGameplayAttributeData& OldBlockChance) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,BlockChance,OldBlockChance); } void UAuraAttributeSet::OnRep_CriticalHitChance(const FGameplayAttributeData& OldCriticalHitChance) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,CriticalHitChance,OldCriticalHitChance); } void UAuraAttributeSet::OnRep_CriticalHitDamage(const FGameplayAttributeData& OldCriticalHitDamage) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,CriticalHitDamage,OldCriticalHitDamage); } void UAuraAttributeSet::OnRep_CriticalHitResistance(const FGameplayAttributeData& OldCriticalHitResistance) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,CriticalHitResistance,OldCriticalHitResistance); } void UAuraAttributeSet::OnRep_HealthRegeneration(const FGameplayAttributeData& OldHealthRegeneration) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,HealthRegeneration,OldHealthRegeneration); } void UAuraAttributeSet::OnRep_ManaRegeneration(const FGameplayAttributeData& OldManaRegeneration) const { GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet,ManaRegeneration,OldManaRegeneration); }