From fcd5881ac521d669036a4c7cea109ef3b8d17c11 Mon Sep 17 00:00:00 2001 From: zheneq Date: Thu, 25 Jul 2024 18:19:05 +0400 Subject: [PATCH] Allow effects to dispel their movement debuffs without removing the whole effect --- Assembly-CSharp/ActorStatus.cs | 8 +++- Assembly-CSharp/Effect.cs | 9 ++++ Assembly-CSharp/StandardActorEffect.cs | 64 ++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Assembly-CSharp/ActorStatus.cs b/Assembly-CSharp/ActorStatus.cs index 7a02f797..54580f3b 100644 --- a/Assembly-CSharp/ActorStatus.cs +++ b/Assembly-CSharp/ActorStatus.cs @@ -609,7 +609,13 @@ private void HandleStatusImmunityChangeForEffects(StatusType status, bool gained && effect.CanBeDispelledByStatusImmunity() && !effectsToRemove.Contains(effect)) { - effectsToRemove.Add(effect); + // custom - attempt to dispel slow/root, remove the whole effect if failed + if (!effect.DispelMovementDebuff()) + { + effectsToRemove.Add(effect); + } + // rogues + // effectsToRemove.Add(effect); } } diff --git a/Assembly-CSharp/Effect.cs b/Assembly-CSharp/Effect.cs index dd5b642c..2d39e8c0 100644 --- a/Assembly-CSharp/Effect.cs +++ b/Assembly-CSharp/Effect.cs @@ -720,12 +720,21 @@ public virtual bool HasDispellableMovementDebuff() { return false; } + + // custom + public virtual bool DispelMovementDebuff() + { + return false; + } + // TODO EFFECTS Not dispelling can break things + // (e.g. movement range won't update if your Unstoppable wears off but you still have Slow underneath it) public virtual bool CanBeDispelledByStatusImmunity() { return true; } + // TODO EFFECTS Should be used to merge buffs and debuffs applied on the same phase? public virtual bool WillApplyStatus(StatusType status) { return false; diff --git a/Assembly-CSharp/StandardActorEffect.cs b/Assembly-CSharp/StandardActorEffect.cs index a9f6f882..710dc4c2 100644 --- a/Assembly-CSharp/StandardActorEffect.cs +++ b/Assembly-CSharp/StandardActorEffect.cs @@ -16,6 +16,7 @@ public class StandardActorEffect : Effect private bool m_shouldPlaySequences = true; private List m_statusAdded = new List(); private List m_statusesToAddOnTurnStart = new List(); + private List m_statModsApplied = new List(); private int m_absorbToAddOnTurnStart; private bool m_canBeDispelledByStatus; @@ -225,6 +226,7 @@ private void AddMods() { if (abilityStatMod.stat != StatType.INVALID) { + m_statModsApplied.Add(abilityStatMod); // custom actorStats.AddStatMod(abilityStatMod.stat, abilityStatMod.modType, abilityStatMod.modValue); } // rogues @@ -302,7 +304,11 @@ private void RemoveMods() ActorStats actorStats = Target.GetActorStats(); // rogues //EquipmentStats equipmentStats = Target.GetEquipmentStats(); - foreach (AbilityStatMod abilityStatMod in m_data.m_statMods) + + // custom + foreach (AbilityStatMod abilityStatMod in m_statModsApplied) + // rogues + // foreach (AbilityStatMod abilityStatMod in m_data.m_statMods) { if (abilityStatMod.stat != StatType.INVALID) { @@ -692,7 +698,9 @@ public override bool ShouldEndEarly() public override bool HasDispellableMovementDebuff() { - foreach (AbilityStatMod abilityStatMod in m_data.m_statMods) + foreach (AbilityStatMod abilityStatMod in m_statModsApplied) + // rogues + // foreach (AbilityStatMod abilityStatMod in m_data.m_statMods) { if (abilityStatMod.stat != StatType.Movement_Horizontal) { @@ -709,7 +717,10 @@ public override bool HasDispellableMovementDebuff() } } - foreach (StatusType statusChange in m_data.m_statusChanges) + // custom + foreach (StatusType statusChange in m_statusAdded) + // rogues + // foreach (StatusType statusChange in m_data.m_statusChanges) { if (ActorStatus.IsDispellableMovementDebuff(statusChange)) { @@ -720,6 +731,53 @@ public override bool HasDispellableMovementDebuff() return false; } + // custom -- see also HasDispellableMovementDebuff + public override bool DispelMovementDebuff() + { + List statModsToRemove = new List(); + foreach (AbilityStatMod abilityStatMod in m_statModsApplied) + { + if (abilityStatMod.stat != StatType.Movement_Horizontal) + { + continue; + } + + bool isDebuff = abilityStatMod.modType == ModType.Multiplier + ? abilityStatMod.modValue < 1f + : abilityStatMod.modValue < 0f; + + if (isDebuff) + { + statModsToRemove.Add(abilityStatMod); + } + } + + ActorStats actorStats = Target.GetActorStats(); + foreach (AbilityStatMod abilityStatMod in statModsToRemove) + { + m_statModsApplied.Remove(abilityStatMod); + actorStats.RemoveStatMod(abilityStatMod.stat, abilityStatMod.modType, abilityStatMod.modValue); + } + + List statusesToRemove = new List(); + foreach (StatusType statusChange in m_statusAdded) + { + if (ActorStatus.IsDispellableMovementDebuff(statusChange)) + { + statusesToRemove.Add(statusChange); + } + } + + ActorStatus actorStatus = Target.GetComponent(); + foreach (StatusType statusType in statusesToRemove) + { + m_statusAdded.Remove(statusType); + actorStatus.RemoveStatus(statusType); + } + + return true; + } + public void OverrideCanBeDispelledByStatusImmunity(bool canBeDispelled) { if (m_canBeDispelledByStatus != canBeDispelled)