Summary
A stacking GameplayEffect incorrectly triggers its OverflowEffect on the first application.
What Type of Bug are you experiencing?
Gameplay Effect
Steps to Reproduce
Create an Infinite GE with Stack Per Target and StackLimitCount 3.
Add an OverflowEffect and enable Deny Overflow Application and Clear Stack on Overflow.
Apply the GE once with StackCount 1 to a target with no existing stack.
Expected Result
StackCount should become 1. Overflow should only occur when applying beyond 3 stacks.
Observed Result
The OverflowEffect executes immediately and the stacking GE is rejected.
Affects Versions
5.8
Platform(s)
Windows
Additional Notes
The initial-application branch in FActiveGameplayEffectsContainer::ApplyGameplayEffectSpec() calls HandleActiveGameplayEffectStackOverflow() unconditionally. The handler does not verify whether OldSpec.StackCount + OverflowingSpec.StackCount exceeds the limit.
Reproduced in Standalone with Authority, so replication is not involved.
I’ve hit this too and reproduced it in my own project on 5.8.1. My case is the opposite deny setting to the OP’s, so between us both configurations are covered.
Repro (Deny Overflow Application = false):
- GE_Base: Has Duration, Stack Per Target, Stack Limit Count 5, Overflow Effects = [GE_Threshold], Deny Overflow Application unchecked.
- Server-side, apply GE_Base once to a target with no existing instance:
MakeOutgoingSpec (StackCount 1, verified) → ApplyGameplayEffectSpecToTarget.
showdebug abilitysystem on the target.
Expected: GE_Base at 1 of 5 stacks, no GE_Threshold.
Observed: GE_Base lands at 1 stack and GE_Threshold is applied in the same application. The overflow spec inherits the applier’s context via InitializeFromLinkedSpec, so in the debugger it looks like a completely normal application from the instigator.
So: Deny = true → overflow fires and the base’s first application is rejected (OP’s case). Deny = false → overflow fires alongside a successful 1-stack base (mine).
Mine was on a listen server with authority; with the OP’s Standalone repro, replication is ruled out.
Where it happens in source (5.8.1 GameplayEffect.cpp, screenshots attached):
The initial-application branch of FActiveGameplayEffectsContainer::ApplyGameplayEffectSpec.The path that creates a new FActiveGameplayEffect when the target has no existing instance, makes a stack-count-0 copy of the spec (~L4356-4358) and calls HandleActiveGameplayEffectStackOverflow unconditionally (~L4360). Inside the handler, bAtStackLimit and bRefreshToLimit are computed (~L3708–3709) but the loop that applies OverflowEffects (~L3711–3719) isn’t gated by either, they only affect the return value and the deny/clear handling. So any stackable GE with a populated Overflow Effects array fires them on its very first application, and with Deny set the return value is false at 0 stacks, which is why the base application gets rejected.
Just guessing here, but this looks like a regression from the fix for the initial-application stack-limit gap. The first-application path now clamps correctly, but fires the overflow loop along with it. Gating the loop on the pre-application count actually being at the limit would restore the old behaviour while keeping the clamp.
The workaround I’ve gone with for now is to just stop using Overflow Effects entirely and apply threshold effects manually after checking GetCurrentStackCount().