Files
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

239 lines
7.1 KiB
C#

using System;
using System.Collections;
using Server.Network;
using Server.Items;
using Server.Targeting;
using Server.Spells;
namespace Server.ACC.CSS.Systems.Ancient
{
public class AncientSwarmSpell : AncientSpell
{
private static SpellInfo m_Info = new SpellInfo(
"Swarm", "Kal Bet Xen",
203,
9051,
Reagent.Nightshade,
Reagent.MandrakeRoot,
Reagent.Bloodmoss
);
public override SpellCircle Circle
{
get { return SpellCircle.Third; }
}
public AncientSwarmSpell(Mobile caster, Item scroll)
: base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
if (CheckSequence())
Caster.Target = new InternalTarget(this);
}
public void Target(Mobile m)
{
if (!Caster.CanSee(m))
{
Caster.SendLocalizedMessage(500237); // Target can not be seen.
}
else if (CheckHSequence(m))
{
if (this.Scroll != null)
Scroll.Consume();
SpellHelper.Turn(Caster, m);
SpellHelper.CheckReflect((int)this.Circle, Caster, ref m);
if (m.Spell != null)
m.Spell.OnCasterHurt();
m.Paralyzed = false;
if (CheckResisted(m))
{
m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
}
else
{
if (!m_Table.Contains(m))
{
Timer t = new InternalTimer(m, Caster);
t.Start();
m_Table[m] = t;
}
m.SendMessage("A swarm of insects surrounds you, and starts to sting you!");
m.FixedParticles(0x91B, 1, 240, 9916, 1159, 3, EffectLayer.Head);
m.PlaySound(0x230);
}
}
FinishSequence();
}
public virtual bool CheckResisted(Mobile target)
{
double n = GetResistPercent(target, Circle);
n /= 100.0;
if (n <= 0.0)
return false;
if (n >= 1.0)
return true;
int maxSkill = (1 + (int)Circle) * 10;
maxSkill += (1 + ((int)Circle / 6)) * 25;
if (target.Skills[SkillName.MagicResist].Value < maxSkill)
target.CheckSkill(SkillName.MagicResist, 0.0, 120.0);
return (n >= Utility.RandomDouble());
}
public virtual double GetResistPercent(Mobile target, SpellCircle circle)
{
double firstPercent = target.Skills[SkillName.MagicResist].Value / 5.0;
double secondPercent = target.Skills[SkillName.MagicResist].Value - (((Caster.Skills[CastSkill].Value - 20.0) / 5.0) + (1 + (int)circle) * 5.0);
return (firstPercent > secondPercent ? firstPercent : secondPercent) / 2.0; // Seems should be about half of what stratics says.
}
private static Hashtable m_Table = new Hashtable();
public static void RemoveCurse(Mobile m)
{
Timer t = (Timer)m_Table[m];
if (t == null)
return;
t.Stop();
m.SendMessage("The swarm stop stinging.");
m_Table.Remove(m);
}
private class InternalTimer : Timer
{
private Mobile m_Target, m_From;
private double m_MinBaseDamage, m_MaxBaseDamage;
private DateTime m_NextHit;
private int m_HitDelay;
private int m_Count, m_MaxCount;
public InternalTimer(Mobile target, Mobile from)
: base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1))
{
Priority = TimerPriority.FiftyMS;
m_Target = target;
m_From = from;
double timeLevel = from.Skills[SkillName.EvalInt].Value / 10;
m_MinBaseDamage = timeLevel - 2;
m_MaxBaseDamage = timeLevel + 1;
m_HitDelay = 5;
m_NextHit = DateTime.Now + TimeSpan.FromSeconds(m_HitDelay);
m_Count = (int)timeLevel;
if (m_Count < 4)
m_Count = 4;
m_MaxCount = m_Count;
}
protected override void OnTick()
{
if (!m_Target.Alive)
{
m_Table.Remove(m_Target);
Stop();
}
if (!m_Target.Alive || DateTime.Now < m_NextHit)
return;
--m_Count;
if (m_HitDelay > 1)
{
m_Target.FixedParticles(0x91B, 1, 240, 9916, 1159, 3, EffectLayer.Head);
m_Target.PlaySound(0x230);
if (m_MaxCount < 5)
{
--m_HitDelay;
}
else
{
int delay = (int)(Math.Ceiling((1.0 + (5 * m_Count)) / m_MaxCount));
if (delay <= 5)
m_HitDelay = delay;
else
m_HitDelay = 5;
}
}
if (m_Count == 0)
{
m_Target.SendMessage("The swarm stop stinging.");
m_Table.Remove(m_Target);
Stop();
}
else
{
m_NextHit = DateTime.Now + TimeSpan.FromSeconds(m_HitDelay);
double damage = m_MinBaseDamage + (Utility.RandomDouble() * (m_MaxBaseDamage - m_MinBaseDamage));
damage *= (3 - (((double)m_Target.Stam / m_Target.StamMax) * 2));
if (damage < 1)
damage = 1;
if (!m_Target.Player)
damage *= 1.75;
AOS.Damage(m_Target, m_From, (int)damage, 0, 0, 0, 100, 0);
}
}
}
private class InternalTarget : Target
{
private AncientSwarmSpell m_Owner;
public InternalTarget(AncientSwarmSpell owner)
: base(12, false, TargetFlags.Harmful)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
if (o is Mobile)
{
m_Owner.Target((Mobile)o);
}
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}