A stacking GE with `OverflowEffects` set applies those effects on the first application (stack 0→1), while still well under `StackLimitCount`. Overflow effects should only fire once the stack actually goes over the limit. Independent of `AbilitySystem.ActiveGameplayEffectOverflowBehavior`.
File: GameplayAbilities/Private/GameplayEffect.cpp
Function: FActiveGameplayEffectsContainer::ApplyGameplayEffectSpec
Symptom
A stacking GE with OverflowEffects
set applies those effects on the first application (stack 0→1), while still well under StackLimitCount
. Overflow effects should only fire once the stack actually goes over the limit. Independent of AbilitySystem.ActiveGameplayEffectOverflowBehavior
.
Repro: a GE with HasDuration
+ AggregateByTarget
+ StackLimitCount=3
+ OverflowEffects=[GE_Marker]
, applied once. Stack count is 1, but GE_Marker
is already active. Stacking 2→3 and overflow at the cap work fine — only the first application is wrong.
Cause
The initial-application branch (no existing stackable instance) calls the overflow handler without any check:
FGameplayEffectSpec SpecCopy = Spec;
SpecCopy.SetStackCount(0);
if (!HandleActiveGameplayEffectStackOverflow(*AppliedActiveGE, SpecCopy, Spec, InPredictionKey))
{
UE_VLOG_UELOG(Owner, LogGameplayEffects, Log, TEXT("Application of %s denied (StackLimit)"), *Spec.ToSimpleString());
return nullptr;
}
The OverflowEffects
loop inside HandleActiveGameplayEffectStackOverflow
does not check the limit itself. The stacking branch guards this call with if (bStackCountAtLimit || bWillOverflowStacks)
; the initial-application branch is missing the same guard, so any GE with OverflowEffects
triggers them once on creation.
The intent (per the comment “Account for applying multiple stacks in our initial application”) was to handle a spec whose own stack count already exceeds the limit, but it ended up running for every initial application.
Fix
Only handle overflow on the initial application when the spec’s own stack count already exceeds a finite limit:
+ if (Spec.Def->StackLimitCount > 0 && Spec.GetStackCount() > Spec.Def->StackLimitCount)
+ {
FGameplayEffectSpec SpecCopy = Spec;
SpecCopy.SetStackCount(0);
if (!HandleActiveGameplayEffectStackOverflow(*AppliedActiveGE, SpecCopy, Spec, InPredictionKey))
{
UE_VLOG_UELOG(Owner, LogGameplayEffects, Log, TEXT("Application of %s denied (StackLimit)"), *Spec.ToSimpleString());
return nullptr;
}
+ }
This only blocks the one wrong case — an initial application under the limit. Initial overflow from SetStackCount(N)
with N over the limit, overflow at the cap, and the deny path are unchanged. No API change.
Thanks for the report! Confirmed this is definitely an oversight with the initial stack counts. I’ve created a jira ticket from this and assigned it.