using System; using Server.Mobiles; using Server.Targeting; using System.Collections.Generic; namespace Server.Spells.Mysticism { public class SpellPlagueSpell : MysticSpell { private static SpellInfo m_Info = new SpellInfo( "Spell Plague", "Vas Rel Jux Ort", 230, 9022, Reagent.DaemonBone, Reagent.DragonBlood, Reagent.Nightshade, Reagent.SulfurousAsh ); public override SpellCircle Circle { get { return SpellCircle.Seventh; } } public SpellPlagueSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info) { } public override void OnCast() { Caster.Target = new InternalTarget(this); } public void OnTarget(object o) { Mobile m = o as Mobile; if (m == null) return; if (!(m is PlayerMobile || m is BaseCreature)) { Caster.SendLocalizedMessage(1080194); // Your target cannot be affected by spell plague. } else if (CheckResisted(m)) { m.SendLocalizedMessage(1080199); //You resist spell plague. Caster.SendLocalizedMessage(1080200); //Your target resists spell plague. } else if (CheckHSequence(m)) { SpellHelper.CheckReflect((int)Circle, Caster, ref m); SpellHelper.Turn(Caster, m); Caster.PlaySound(0x658); m.FixedParticles(0x375A, 1, 17, 9919, 1161, 7, EffectLayer.Waist); m.FixedParticles(0x3728, 1, 13, 9502, 1161, 7, (EffectLayer)255); if (!m_Table.ContainsKey(m) || m_Table[m] == null) m_Table.Add(m, new List()); m_Table[m].Add(new SpellPlagueTimer(Caster, m, TimeSpan.FromSeconds(8))); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.SpellPlague, 1031690, 1080167, TimeSpan.FromSeconds(8), m)); DoExplosion(m, Caster, true, 1); } FinishSequence(); } private static Dictionary> m_Table = new Dictionary>(); public static bool HasSpellPlague(Mobile from) { foreach (KeyValuePair> kvp in m_Table) { if (kvp.Value != null) { foreach (SpellPlagueTimer timer in kvp.Value) { if (timer.Caster == from) return true; } } } return false; } public static void OnMobileDamaged(Mobile from) { if (m_Table.ContainsKey(from) && m_Table[from].Count > 0 && m_Table[from][0].NextUse < DateTime.UtcNow) { int amount = m_Table[from][0].Amount; bool doExplosion = false; double mod = from.Skills[SkillName.MagicResist].Value >= 70.0 ? (from.Skills[SkillName.MagicResist].Value / 1000 * 3) : 0.0; if (mod < 0) mod = .01; if (amount == 0 && .90 - mod > Utility.RandomDouble()) doExplosion = true; else if (amount == 1 && .60 - mod > Utility.RandomDouble()) doExplosion = true; else if (amount == 2 && .30 - mod > Utility.RandomDouble()) doExplosion = true; if (doExplosion) { SpellPlagueTimer timer = m_Table[from][0]; timer.NextUse = DateTime.UtcNow + TimeSpan.FromSeconds(1.5); DoExplosion(from, timer.Caster, false, amount); timer.Amount++; } } } public static void DoExplosion(Mobile from, Mobile caster, bool initial, int amount) { double prim = caster.Skills[SkillName.Mysticism].Value; double sec = caster.Skills[SkillName.Imbuing].Value; if (caster.Skills[SkillName.Focus].Value > sec) sec = caster.Skills[SkillName.Focus].Value; int damage = (int)((prim + sec) / 12) + Utility.RandomMinMax(1, 6); if (amount > 1) damage /= amount; from.PlaySound(0x658); from.FixedParticles(0x375A, 1, 17, 9919, 1161, 7, EffectLayer.Waist); from.FixedParticles(0x3728, 1, 13, 9502, 1161, 7, (EffectLayer)255); int sdiBonus = SpellHelper.GetSpellDamageBonus(caster, from, SkillName.Mysticism, from is PlayerMobile); damage *= (100 + sdiBonus); damage /= 100; SpellHelper.Damage(null, TimeSpan.Zero, from, caster, damage, 0, 0, 0, 0, 0, DFAlgorithm.Standard, 100, 0); } public static void RemoveFromList(Mobile from) { if (m_Table.ContainsKey(from) && m_Table[from].Count > 0) { Mobile caster = m_Table[from][0].Caster; m_Table[from].Remove(m_Table[from][0]); if (m_Table[from].Count == 0) { m_Table.Remove(from); BuffInfo.RemoveBuff(from, BuffIcon.SpellPlague); } foreach (KeyValuePair> kvp in m_Table) { foreach (SpellPlagueTimer Ttimer in kvp.Value) { if (Ttimer.Caster == caster) return; } } BuffInfo.RemoveBuff(caster, BuffIcon.SpellPlague); } } public class InternalTarget : Target { public SpellPlagueSpell Owner { get; set; } public InternalTarget(SpellPlagueSpell owner) : this(owner, false) { } public InternalTarget(SpellPlagueSpell owner, bool allowland) : base(12, allowland, TargetFlags.Harmful) { Owner = owner; } protected override void OnTarget(Mobile from, object o) { if (o == null) return; if (!from.CanSee(o)) from.SendLocalizedMessage(500237); // Target can not be seen. else { SpellHelper.Turn(from, o); Owner.OnTarget(o); } } protected override void OnTargetFinish(Mobile from) { Owner.FinishSequence(); } } } public class SpellPlagueTimer : Timer { private Mobile m_Caster; private Mobile m_Owner; private int m_Amount; private DateTime m_NextUse; public Mobile Caster { get { return m_Caster; } } public int Amount { get { return m_Amount; } set { m_Amount = value; if (m_Amount >= 3) EndTimer(); } } public DateTime NextUse { get { return m_NextUse; } set { m_NextUse = value; } } public SpellPlagueTimer(Mobile caster, Mobile owner, TimeSpan duration) : base(duration) { m_Caster = caster; m_Owner = owner; m_Amount = 0; m_NextUse = DateTime.UtcNow; this.Start(); } protected override void OnTick() { EndTimer(); } private void EndTimer() { this.Stop(); SpellPlagueSpell.RemoveFromList(m_Owner); } } }