Files
Cog/Source/CogSample/CogSampleGameplayAbility.cpp
T
2023-10-05 16:57:43 -04:00

194 lines
7.9 KiB
C++

#include "CogSampleGameplayAbility.h"
#include "CogSampleTagLibrary.h"
#include "CogSampleGameplayEffectContext.h"
#include "CogSampleFunctionLibrary_Gameplay.h"
#include "CogSampleAttributeSet_Caster.h"
//--------------------------------------------------------------------------------------------------------------------------
UCogSampleGameplayAbility::UCogSampleGameplayAbility()
{
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
ActivationBlockedTags.AddTag(Tag_Status_Dead);
}
//--------------------------------------------------------------------------------------------------------------------------
float UCogSampleGameplayAbility::GetUnmitigatedCooldownDuration_Implementation() const
{
return Cooldown.GetValueAtLevel(GetAbilityLevel());
}
//--------------------------------------------------------------------------------------------------------------------------
float UCogSampleGameplayAbility::GetUnmitigatedCost_Implementation() const
{
return Cost.GetValueAtLevel(GetAbilityLevel());
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogSampleGameplayAbility::CheckCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags /*= nullptr*/) const
{
if (ActorInfo == nullptr)
{
return false;
}
if (ActorInfo->AbilitySystemComponent->HasMatchingGameplayTag(Tag_Status_NoCooldown))
{
return true;
}
if (Super::CheckCooldown(Handle, ActorInfo, OptionalRelevantTags))
{
return true;
}
if (OptionalRelevantTags != nullptr)
{
OptionalRelevantTags->AddTag(Tag_Ability_Activation_Fail_Cooldown);
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogSampleGameplayAbility::CheckCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags /*= nullptr*/) const
{
if (ActorInfo == nullptr)
{
return false;
}
if (ActorInfo->AbilitySystemComponent->HasMatchingGameplayTag(Tag_Status_NoCost))
{
return true;
}
UGameplayEffect* CostEffect = GetCostGameplayEffect();
if (CostEffect != nullptr)
{
//-----------------------------------------------------------------------------------
// Can always start ability if cost == 0.
//-----------------------------------------------------------------------------------
if (IsCostGameplayEffectIsZero(CostEffect, GetAbilityLevel(Handle, ActorInfo), MakeEffectContext(Handle, ActorInfo)))
{
return true;
}
//-----------------------------------------------------------------------------------
// Can start ability if it cost stamina and stamina > 0
//-----------------------------------------------------------------------------------
if (CostEffect->InheritableGameplayEffectTags.CombinedTags.HasTag(Tag_Effect_Type_Cost_Stamina))
{
const float Stamina = ActorInfo->AbilitySystemComponent->GetNumericAttribute(UCogSampleAttributeSet_Caster::GetStaminaAttribute());
if (Stamina > 0)
{
return true;
}
}
}
//-----------------------------------------------------------------------------------
// Handle general case
//-----------------------------------------------------------------------------------
if (Super::CheckCost(Handle, ActorInfo, OptionalRelevantTags))
{
return true;
}
if (OptionalRelevantTags != nullptr)
{
OptionalRelevantTags->AddTag(Tag_Ability_Activation_Fail_Cost);
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------------
const FGameplayTagContainer* UCogSampleGameplayAbility::GetCooldownTags() const
{
FGameplayTagContainer* MutableTags = const_cast<FGameplayTagContainer*>(&CachedCooldownTags);
MutableTags->Reset();
const FGameplayTagContainer* ParentTags = Super::GetCooldownTags();
if (ParentTags)
{
MutableTags->AppendTags(*ParentTags);
}
MutableTags->AddTag(SlotTag);
return MutableTags;
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleGameplayAbility::ApplyCooldown(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const
{
if (GetUnmitigatedCooldownDuration() <= 0.0f)
{
return;
}
if (UGameplayEffect* CooldownEffect = GetCooldownGameplayEffect())
{
FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(CooldownEffect->GetClass(), GetAbilityLevel());
SpecHandle.Data.Get()->DynamicGrantedTags.AddTag(SlotTag);
ApplyGameplayEffectSpecToOwner(Handle, ActorInfo, ActivationInfo, SpecHandle);
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleGameplayAbility::ApplyCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const
{
if (GetUnmitigatedCost() <= 0.0f)
{
return;
}
if (UGameplayEffect* CostEffect = GetCostGameplayEffect())
{
FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(CostEffect->GetClass(), GetAbilityLevel());
ApplyGameplayEffectSpecToOwner(Handle, ActorInfo, ActivationInfo, SpecHandle);
}
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogSampleGameplayAbility::IsCostGameplayEffectIsZero(const UGameplayEffect* GameplayEffect, float Level, const FGameplayEffectContextHandle& EffectContext) const
{
FGameplayEffectSpec Spec(GameplayEffect, EffectContext, Level);
Spec.CalculateModifierMagnitudes();
for (int32 ModIdx = 0; ModIdx < Spec.Modifiers.Num(); ++ModIdx)
{
const FGameplayModifierInfo& ModDef = Spec.Def->Modifiers[ModIdx];
const FModifierSpec& ModSpec = Spec.Modifiers[ModIdx];
const float CostValue = ModSpec.GetEvaluatedMagnitude();
//----------------------------------------------------------------------------------------------
// The Cost in the Data is positive, but UCogSampleModifierCalculation_Cost negates it.
// Therefore a cost less than zero is an actual cost, and a cost of 0 or greater can be ignored
//----------------------------------------------------------------------------------------------
if (CostValue < 0)
{
return false;
}
}
return true;
}
//--------------------------------------------------------------------------------------------------------------------------
float UCogSampleGameplayAbility::GetFloatValueAtAbilityLevel(const FScalableFloat& ScalableFloat) const
{
return UCogSampleFunctionLibrary_Gameplay::GetFloatValue(ScalableFloat, GetAbilityLevel());
}
//--------------------------------------------------------------------------------------------------------------------------
bool UCogSampleGameplayAbility::GetBoolValueAtAbilityLevel(const FScalableFloat& ScalableFloat) const
{
return UCogSampleFunctionLibrary_Gameplay::GetBoolValue(ScalableFloat, GetAbilityLevel());
}
//--------------------------------------------------------------------------------------------------------------------------
int32 UCogSampleGameplayAbility::GetIntValueAtAbilityLevel(const FScalableFloat& ScalableFloat) const
{
return UCogSampleFunctionLibrary_Gameplay::GetIntValue(ScalableFloat, GetAbilityLevel());
}