Jump to content
  • 0

CC stacking issues



Currently replaying PoE with CC-heavy party and having a very annoying problem with stacked CC sometimes "cancelling" each other. Today I've had enough of this and decided to investigate :) So far, I've identified 3 main issues.


Knockdown and paralyze interaction

To reproduce, cast both wizard's Slicken and cipher's Mental Binding on same target. Depending on the application order, there will be slightly different results. Let's consider paralyze after knockdown.

1. Knockdown is applied, AIController::HandleKnockedDownEvent() will see that no knockdown is already active and push KnockedDown state on the state stack.

2. When Paralyze is applied, first Knockdown is suppressed. AIController::HandleKnockedDownEvent() will find existing knockdown state and call KnockedDown::Standup(), which will start 0.2sec "standing up" animation. Knockdown remains on the top of the state stack.

3. Paralyze is applied, AIController::HandleParalyzedEvent() will try to push the state. However, AIStateManager::PushState will fail: the topmost stack entry (KnockDown) has higher priority (9 vs 7) and paralyze has CanBeQueuedIfLowerPriority property set to false. Because of that, stack won't be changed.

4. A bit later, when standup animation is finished, KnockedDown::Update() will pop topmost state stack entry (KnockedDown); the next topmost entry is some normal AI action, so CC will essentially end, despite both knockdown (suppressed) and paralyze effects being active.


Note that similar situation doesn't happen for stun effect, because AIController::HandleStunnedEvent() has extra logic to deal with this situation: if topmost stack entry has higher priority, it will call AIStateManager::QueueStateAtTop() instead of PushState().


So there are two possible solutions: either add extra logic similar to stun for paralyze handler, or change CanBeQueuedIfLowerPriority to true. I'm currently playing with the second solution; it seems to be harmless (the only higher-priority states are PushedBack, KnockedDown, Unconscious and Dead; for former two the behaviour is correct, and for latter two it doesn't matter, since they disallow queueing via AllowsQueueing == false).


Asymmetrical effect suppression check

To reproduce, cast both cipher's Mental Binding and druid's Embrace the Earth-Talon. At the moment when second spell is applied, petrify's duration should be smaller. What happens is that both StopAnimation effects will suppress each other. This happens because of rather scary bug in StatusEffect::Suppresses():

1. Petrify will suppress Paralyze due to Affliction::OverridesAffliction check (petrify is "stronger" affliction than paralyze, as expected).

2. Paralyze will also suppress Petrify, because there is no "mirroring" check (if (eff.AfflictionOrigin.OverridesAffliction(this.AfflictionOrigin) return false). Instead, another check will suppress Petrify, since it has smaller TimeLeft (lol).


As a result, mob won't be CC'd until Petrify ends, at which point Paralyze will become unsuppressed and mob will thus become paralyzed until end of the spell.


For now, I've locally rewritten the function to be symmetric, which seems to solve the issue.


Note that I don't understand why do we even have this "longer effect suppresses shorter one" logic - it seems that everything would work without it just as well (if we suppress longer one, it will become unsuppressed anyway when shorter effect ends). However, even without this check the symmetrical "affliction strength" check is still needed, otherwise we could get similar mutual suppression depending on tiebreaker flag.


Knockdown from multiple sources

To reproduce, cast both wizard's Slicken and wizard's Call to Slumber on single target. At the moment when second spell is applied, mob will begin standing up, and then CC will be effectively disabled. What happens is that we have two sources of KnockedDown state.

1. When second knockdown is applied, AIController::HandleKnockedDownEvent() will find existing KnockedDown state and update its duration (rather than creating new one).

2. After that, one of the knockdown effects will become suppressed, and AIController::HandleKnockedDownEvent() will call KnockedDown::Standup() on the only KnockedDown state in the stack. This will start the 0.2sec standup animation.

3. When animation ends, KnockedDown is popped off stack and CC essentially ends, despite two effects providing it still being active.


This one I'm not sure how to fix. Maybe make KnockedDown status effects "stackable"? Not sure what side-effects it will cause. Pushing multiple KnockedDown states probably won't work, since non-top one could expire earlier. In any case, at least for my party this isn't a critical issue, since most of the knockdown effects apply Prone affliction, and I don't need to use Call to Slumber much.


I realize that we're unlikely to get any more official patches for PoE1. But maybe someone can at least validate that my solutions won't break something unexpected, and maybe propose a good solution for the multi-knockdown issue.

Link to comment
Share on other sites

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...