From bd4e6fc30ead0c1a405909fe031f57d969f9bf07 Mon Sep 17 00:00:00 2001 From: mark1145 Date: Fri, 8 Jul 2022 16:59:46 +1000 Subject: [PATCH] fix: Fixes curses and spell effects (#1112) * * Fix statmod naming mismatch: everything in code searches for "[Magic] {type} Offset" but stat reductions are being added as "[Magic] {type} Curse" * Clarifies and cleans up curses * Fixes blood oath * * NobleSacrifice remove all curses in one go * Dont need a method * Fix extra parentheses Co-authored-by: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> --- .../UOContent/Engines/ConPVP/DuelContext.cs | 12 +++- .../Factions/Mobiles/Guards/GuardAI.cs | 13 +--- .../UOContent/Items/Talismans/BaseTalisman.cs | 14 ++-- .../Items/Weapons/Abilities/MortalStrike.cs | 18 +++-- Projects/UOContent/Spells/Base/SpellHelper.cs | 2 +- .../Spells/Chivalry/NobleSacrifice.cs | 51 +++++++------- .../UOContent/Spells/Chivalry/RemoveCurse.cs | 49 +++++-------- .../Spells/Mysticism/SpellPlagueSpell.cs | 16 +++-- .../Spells/Necromancy/BloodOathSpell.cs | 70 +++++++++---------- .../UOContent/Spells/Necromancy/MindRot.cs | 7 +- 10 files changed, 126 insertions(+), 126 deletions(-) diff --git a/Projects/UOContent/Engines/ConPVP/DuelContext.cs b/Projects/UOContent/Engines/ConPVP/DuelContext.cs index 8217c5af8..591f755bd 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelContext.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelContext.cs @@ -1817,12 +1817,18 @@ namespace Server.Engines.ConPVP public static void Debuff(Mobile mob) { - mob.RemoveStatMod("[Magic] Str Offset"); - mob.RemoveStatMod("[Magic] Dex Offset"); - mob.RemoveStatMod("[Magic] Int Offset"); + mob.RemoveStatMod("[Magic] Str Buff"); + mob.RemoveStatMod("[Magic] Dex Buff"); + mob.RemoveStatMod("[Magic] Int Buff"); + mob.RemoveStatMod("[Magic] Str Curse"); + mob.RemoveStatMod("[Magic] Dex Curse"); + mob.RemoveStatMod("[Magic] Int Curse"); mob.RemoveStatMod("Concussion"); mob.RemoveStatMod("blood-rose"); mob.RemoveStatMod("clarity-potion"); + mob.RemoveStatMod("RoseOfTrinsicPetal"); + mob.RemoveStatMod("Holy Bless"); + mob.RemoveStatMod("Holy Curse"); OrangePetals.RemoveContext(mob); diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs index 81bac5bc5..833b56681 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs @@ -209,17 +209,8 @@ namespace Server.Factions return true; } - public int GetStatMod(Mobile mob, StatType type) - { - var mod = mob.GetStatMod($"[Magic] {type} Offset"); - - if (mod == null) - { - return 0; - } - - return mod.Offset; - } + public static int GetStatMod(Mobile mob, StatType type) => + mob.GetStatMod($"[Magic] {type} Curse")?.Offset ?? 0; public Spell RandomOffenseSpell() { diff --git a/Projects/UOContent/Items/Talismans/BaseTalisman.cs b/Projects/UOContent/Items/Talismans/BaseTalisman.cs index 42a8efcb9..37aca5420 100644 --- a/Projects/UOContent/Items/Talismans/BaseTalisman.cs +++ b/Projects/UOContent/Items/Talismans/BaseTalisman.cs @@ -1238,24 +1238,22 @@ namespace Server.Items 0x100 ); - StatMod mod; - - mod = target.GetStatMod("[Magic] Str Offset"); + var mod = target.GetStatMod("[Magic] Str Curse"); if (mod?.Offset < 0) { - target.RemoveStatMod("[Magic] Str Offset"); + target.RemoveStatMod("[Magic] Str Curse"); } - mod = target.GetStatMod("[Magic] Dex Offset"); + mod = target.GetStatMod("[Magic] Dex Curse"); if (mod?.Offset < 0) { - target.RemoveStatMod("[Magic] Dex Offset"); + target.RemoveStatMod("[Magic] Dex Curse"); } - mod = target.GetStatMod("[Magic] Int Offset"); + mod = target.GetStatMod("[Magic] Int Curse"); if (mod?.Offset < 0) { - target.RemoveStatMod("[Magic] Int Offset"); + target.RemoveStatMod("[Magic] Int Curse"); } target.Paralyzed = false; diff --git a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs index 5c98873f1..4c2894a73 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs @@ -41,12 +41,15 @@ namespace Server.Items public static bool IsWounded(Mobile m) => _table.ContainsKey(m); - private static void StopTimer(Mobile m) + private static bool StopTimer(Mobile m) { if (_table.Remove(m, out var timerToken)) { timerToken.Cancel(); + return true; } + + return false; } public static void BeginWound(Mobile m, TimeSpan duration) @@ -58,11 +61,16 @@ namespace Server.Items m.YellowHealthbar = true; } - public static void EndWound(Mobile m) + public static bool EndWound(Mobile m) { - StopTimer(m); - m.YellowHealthbar = false; - m.SendLocalizedMessage(1060208); // You are no longer mortally wounded. + if (StopTimer(m)) + { + m.YellowHealthbar = false; + m.SendLocalizedMessage(1060208); // You are no longer mortally wounded. + return true; + } + + return false; } } } diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 6cd1a8f5b..787fddb03 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -303,7 +303,7 @@ namespace Server.Spells public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, int bonus, TimeSpan duration) { var offset = bonus; - var name = $"[Magic] {type} Offset"; + var name = $"[Magic] {type} Buff"; var mod = target.GetStatMod(name); diff --git a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs index 9e8e4e4c7..f44066b35 100644 --- a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs +++ b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs @@ -1,7 +1,10 @@ using System; using System.Collections.Generic; using Server.Gumps; +using Server.Items; using Server.Mobiles; +using Server.Spells.Fourth; +using Server.Spells.Mysticism; using Server.Spells.Necromancy; namespace Server.Spells.Chivalry @@ -83,7 +86,7 @@ namespace Server.Spells.Chivalry } else { - var sendEffect = false; + bool sendEffect = false; if (m.Poisoned && m.CurePoison(Caster)) { @@ -108,26 +111,24 @@ namespace Server.Spells.Chivalry sendEffect = true; } - StatMod mod; - - mod = m.GetStatMod("[Magic] Str Offset"); + var mod = m.GetStatMod("[Magic] Str Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Str Offset"); + m.RemoveStatMod("[Magic] Str Curse"); sendEffect = true; } - mod = m.GetStatMod("[Magic] Dex Offset"); + mod = m.GetStatMod("[Magic] Dex Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Dex Offset"); + m.RemoveStatMod("[Magic] Dex Curse"); sendEffect = true; } - mod = m.GetStatMod("[Magic] Int Offset"); + mod = m.GetStatMod("[Magic] Int Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Int Offset"); + m.RemoveStatMod("[Magic] Int Curse"); sendEffect = true; } @@ -137,22 +138,24 @@ namespace Server.Spells.Chivalry sendEffect = true; } - if (EvilOmenSpell.TryEndEffect(m)) - { - sendEffect = true; - } + sendEffect = EvilOmenSpell.TryEndEffect(m) || sendEffect; + sendEffect = StrangleSpell.RemoveCurse(m) || sendEffect; + sendEffect = CorpseSkinSpell.RemoveCurse(m) || sendEffect; + sendEffect = CurseSpell.RemoveEffect(m) || sendEffect; + sendEffect = MortalStrike.EndWound(m) || sendEffect; + sendEffect = MindRotSpell.ClearMindRotScalar(m) || sendEffect; + sendEffect = BloodOathSpell.RemoveCurse(m) || sendEffect; + sendEffect = SpellPlagueSpell.RemoveEffect(m) || sendEffect; - if (StrangleSpell.RemoveCurse(m)) - { - sendEffect = true; - } - - if (CorpseSkinSpell.RemoveCurse(m)) - { - sendEffect = true; - } - - // TODO: Should this remove blood oath? Pain spike? + // TODO: Move these into their respective end effect methods + BuffInfo.RemoveBuff(m, BuffIcon.Clumsy); + BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind); + BuffInfo.RemoveBuff(m, BuffIcon.Weaken); + BuffInfo.RemoveBuff(m, BuffIcon.Curse); + BuffInfo.RemoveBuff(m, BuffIcon.MassCurse); + BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike); + BuffInfo.RemoveBuff(m, BuffIcon.Strangle); + BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen); if (sendEffect) { diff --git a/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs b/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs index 21357ec64..bd0561773 100644 --- a/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs +++ b/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs @@ -2,6 +2,7 @@ using System; using Server.Engines.ConPVP; using Server.Items; using Server.Spells.Fourth; +using Server.Spells.Mysticism; using Server.Spells.Necromancy; using Server.Targeting; @@ -44,24 +45,13 @@ namespace Server.Spells.Chivalry * Chance of removing curse is affected by Caster's Karma. */ - int chance; - - if (Caster.Karma < -5000) + int chance = Caster.Karma switch { - chance = 0; - } - else if (Caster.Karma < 0) - { - chance = (int)Math.Sqrt(20000 + Caster.Karma) - 122; - } - else if (Caster.Karma < 5625) - { - chance = (int)Math.Sqrt(Caster.Karma) + 25; - } - else - { - chance = 100; - } + < -5000 => 0, + < 0 => (int)Math.Sqrt(20000 + Caster.Karma) - 122, + < 5625 => (int)Math.Sqrt(Caster.Karma) + 25, + _ => 100 + }; if (chance > Utility.Random(100)) { @@ -88,22 +78,22 @@ namespace Server.Spells.Chivalry 0x100 ); - var mod = m.GetStatMod("[Magic] Str Offset"); + var mod = m.GetStatMod("[Magic] Str Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Str Offset"); + m.RemoveStatMod("[Magic] Str Curse"); } - mod = m.GetStatMod("[Magic] Dex Offset"); + mod = m.GetStatMod("[Magic] Dex Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Dex Offset"); + m.RemoveStatMod("[Magic] Dex Curse"); } - mod = m.GetStatMod("[Magic] Int Offset"); + mod = m.GetStatMod("[Magic] Int Curse"); if (mod?.Offset < 0) { - m.RemoveStatMod("[Magic] Int Offset"); + m.RemoveStatMod("[Magic] Int Curse"); } m.Paralyzed = false; @@ -113,22 +103,19 @@ namespace Server.Spells.Chivalry CorpseSkinSpell.RemoveCurse(m); CurseSpell.RemoveEffect(m); MortalStrike.EndWound(m); - if (Core.ML) - { - BloodOathSpell.RemoveCurse(m); - } - MindRotSpell.ClearMindRotScalar(m); + BloodOathSpell.RemoveCurse(m); + SpellPlagueSpell.RemoveEffect(m); + // TODO: Move these into their respective end effect methods BuffInfo.RemoveBuff(m, BuffIcon.Clumsy); BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind); BuffInfo.RemoveBuff(m, BuffIcon.Weaken); BuffInfo.RemoveBuff(m, BuffIcon.Curse); BuffInfo.RemoveBuff(m, BuffIcon.MassCurse); BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike); - BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); - - // TODO: Should this remove blood oath? Pain spike? + BuffInfo.RemoveBuff(m, BuffIcon.Strangle); + BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen); } else { diff --git a/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs b/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs index 23c991a4d..eb6f708ea 100644 --- a/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs @@ -80,12 +80,16 @@ namespace Server.Spells.Mysticism public static bool UnderEffect(Mobile m) => _table.ContainsKey(m); - public static void RemoveEffect(Mobile m) + public static bool RemoveEffect(Mobile m) { - if (_table.TryGetValue(m, out var context)) + if (_table.Remove(m, out var context)) { - context.EndPlague(false); + context.Stop(); + BuffInfo.RemoveBuff(m, BuffIcon.SpellPlague); + return true; } + + return false; } public static void CheckPlague(Mobile m) @@ -179,9 +183,9 @@ namespace Server.Spells.Mysticism } } - public void EndPlague(bool restart = true) + public void EndPlague() { - if (restart && m_Next != null) + if (m_Next != null) { _table[m_Target] = m_Next; m_Next.StartPlague(); @@ -191,6 +195,8 @@ namespace Server.Spells.Mysticism _table.Remove(m_Target); BuffInfo.RemoveBuff(m_Target, BuffIcon.SpellPlague); } + + Stop(); } } diff --git a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs index 0b6b1aadf..d1209838d 100644 --- a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs @@ -65,8 +65,7 @@ namespace Server.Spells.Necromancy * ((ss-rm)/8)+8 */ - _table.TryGetValue(m, out var timer); - timer?.DoExpire(); + RemoveCurse(m); m_OathTable[Caster] = Caster; m_OathTable[m] = Caster; @@ -84,7 +83,7 @@ namespace Server.Spells.Necromancy var duration = TimeSpan.FromSeconds((GetDamageSkill(Caster) - GetResistSkill(m)) / 8 + 8); m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain - timer = new ExpireTimer(Caster, m, duration); + var timer = new ExpireTimer(Caster, m, duration); timer.Start(); BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.BloodOathCaster, 1075659, duration, Caster, m.Name)); @@ -102,10 +101,30 @@ namespace Server.Spells.Necromancy Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); } - public static void RemoveCurse(Mobile m) + public static bool RemoveCurse(Mobile target) { - _table.TryGetValue(m, out var t); - t?.DoExpire(); + if (_table.Remove(target, out var timer)) + { + var caster = timer.Caster; + if (m_OathTable.Remove(caster)) + { + caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. + } + + if (m_OathTable.Remove(target)) + { + target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. + } + + timer.Stop(); + + BuffInfo.RemoveBuff(caster, BuffIcon.BloodOathCaster); + BuffInfo.RemoveBuff(target, BuffIcon.BloodOathCurse); + + return true; + } + + return false; } public static Mobile GetBloodOath(Mobile m) => @@ -113,48 +132,29 @@ namespace Server.Spells.Necromancy private class ExpireTimer : Timer { - private readonly Mobile m_Caster; - private readonly DateTime m_End; - private readonly Mobile m_Target; + private Mobile _target; + private DateTime _end; + + public Mobile Caster { get; } public ExpireTimer(Mobile caster, Mobile target, TimeSpan delay) : base( TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0) ) { - m_Caster = caster; - m_Target = target; - m_End = Core.Now + delay; + Caster = caster; + _target = target; + _end = Core.Now + delay; } protected override void OnTick() { - if (m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive || - Core.Now >= m_End) + if (Caster.Deleted || _target.Deleted || !Caster.Alive || !_target.Alive || + Core.Now >= _end) { - DoExpire(); + RemoveCurse(_target); } } - - public void DoExpire() - { - if (m_OathTable.Remove(m_Caster)) - { - m_Caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - } - - if (m_OathTable.Remove(m_Target)) - { - m_Target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - } - - Stop(); - - BuffInfo.RemoveBuff(m_Caster, BuffIcon.BloodOathCaster); - BuffInfo.RemoveBuff(m_Target, BuffIcon.BloodOathCurse); - - _table.Remove(m_Caster); - } } } } diff --git a/Projects/UOContent/Spells/Necromancy/MindRot.cs b/Projects/UOContent/Spells/Necromancy/MindRot.cs index 784fcaa11..c541d8896 100644 --- a/Projects/UOContent/Spells/Necromancy/MindRot.cs +++ b/Projects/UOContent/Spells/Necromancy/MindRot.cs @@ -71,15 +71,17 @@ namespace Server.Spells.Necromancy Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); } - public static void ClearMindRotScalar(Mobile m) + public static bool ClearMindRotScalar(Mobile m) { if (_table.Remove(m, out var tmpB)) { tmpB.m_MRExpireTimer.Stop(); m.SendLocalizedMessage(1060872); // Your mind feels normal again. + BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); + return true; } - BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); + return false; } public static bool HasMindRotScalar(Mobile m) => _table.ContainsKey(m); @@ -127,7 +129,6 @@ namespace Server.Spells.Necromancy if (m_Target.Deleted || !m_Target.Alive || Core.Now >= m_End) { MindRotSpell.ClearMindRotScalar(m_Target); - Stop(); } } }