using System; using System.Collections.Generic; using Server.Targeting; namespace Server.Spells.Fourth { public class CurseSpell : MagerySpell, ITargetingSpell { private static readonly SpellInfo _info = new( "Curse", "Des Sanct", 227, 9031, Reagent.Nightshade, Reagent.Garlic, Reagent.SulfurousAsh ); private static readonly Dictionary _table = new(); public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, _info) { } public override SpellCircle Circle => SpellCircle.Fourth; public static bool DoCurse(Mobile caster, Mobile m) { var duration = SpellHelper.GetDuration(caster, m); if (duration == TimeSpan.Zero) { return false; } // Allow curse duration to refresh if the new curse is longer if (_table.TryGetValue(m, out var existingTimer) && existingTimer.Next - Core.Now > duration && Core.AOS) { return false; } var newStrOffset = SpellHelper.GetOffset(caster, m, StatType.Str, true); var newDexOffset = SpellHelper.GetOffset(caster, m, StatType.Dex, true); var newIntOffset = SpellHelper.GetOffset(caster, m, StatType.Int, true); if (newStrOffset == 0 && newDexOffset == 0 && newIntOffset == 0) { return false; } var oldStrOffset = SpellHelper.GetCurse(caster, m, StatType.Str); var oldDexOffset = SpellHelper.GetCurse(caster, m, StatType.Dex); var oldIntOffset = SpellHelper.GetCurse(caster, m, StatType.Int); if (oldStrOffset <= newStrOffset && oldDexOffset <= newDexOffset && oldIntOffset <= newIntOffset) { return false; } var strCurse = SpellHelper.AddStatCurse(caster, m, StatType.Str, newStrOffset, duration); var dexCurse = SpellHelper.AddStatCurse(caster, m, StatType.Dex, newDexOffset, duration); var intCurse = SpellHelper.AddStatCurse(caster, m, StatType.Int, newIntOffset, duration, true); if (!strCurse && !dexCurse && !intCurse) { return false; } existingTimer?.Stop(); m.UpdateResistances(); _table[m] = Timer.DelayCall(duration, mob => RemoveEffect(mob), m); m.Spell?.OnCasterHurt(); m.Paralyzed = false; m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); m.PlaySound(0x1E1); var percentage = (int)(SpellHelper.GetOffsetScalar(caster, m, true) * 100); var args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}"; BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, duration, m, args)); return true; } public void Target(Mobile m) { if (CheckHSequence(m)) { SpellHelper.Turn(Caster, m); SpellHelper.CheckReflect((int)Circle, Caster, ref m); if (DoCurse(Caster, m)) { HarmfulSpell(m); } else { DoHurtFizzle(); } } } public override void OnCast() { Caster.Target = new SpellTarget(this, TargetFlags.Harmful); } public static bool RemoveEffect(Mobile m) { if (_table.Remove(m, out var timer)) { timer.Stop(); m.UpdateResistances(); return true; } return false; } public static bool UnderEffect(Mobile m) => _table.ContainsKey(m); } }