Reorganizes Project (#41)
This commit is contained in:
parent
08bf44af9a
commit
3614a66aee
3499 changed files with 79 additions and 55 deletions
155
Projects/Scripts/Spells/Fourth/ArchCure.cs
Normal file
155
Projects/Scripts/Spells/Fourth/ArchCure.cs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class ArchCureSpell : MagerySpell, ISpellTargetingPoint3D
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Arch Cure", "Vas An Nox",
|
||||
215,
|
||||
9061,
|
||||
Reagent.Garlic,
|
||||
Reagent.Ginseng,
|
||||
Reagent.MandrakeRoot
|
||||
);
|
||||
|
||||
public ArchCureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
// Arch cure is now 1/4th of a second faster
|
||||
public override TimeSpan CastDelayBase => base.CastDelayBase - TimeSpan.FromSeconds(0.25);
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public void Target(IPoint3D p)
|
||||
{
|
||||
if (!Caster.CanSee(p))
|
||||
{
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
SpellHelper.Turn(Caster, p);
|
||||
|
||||
SpellHelper.GetSurfaceTop(ref p);
|
||||
|
||||
List<Mobile> targets = new List<Mobile>();
|
||||
|
||||
Map map = Caster.Map;
|
||||
Mobile directTarget = p as Mobile;
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
bool feluccaRules = map.Rules == MapRules.FeluccaRules;
|
||||
|
||||
// You can target any living mobile directly, beneficial checks apply
|
||||
if (directTarget != null && Caster.CanBeBeneficial(directTarget, false))
|
||||
targets.Add(directTarget);
|
||||
|
||||
IPooledEnumerable<Mobile> eable = map.GetMobilesInRange(new Point3D(p), 2);
|
||||
targets.AddRange(eable.Where(m => m != directTarget).Where(m => AreaCanTarget(m, feluccaRules)));
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
Effects.PlaySound(p, Caster.Map, 0x299);
|
||||
|
||||
if (targets.Count > 0)
|
||||
{
|
||||
int cured = 0;
|
||||
|
||||
for (int i = 0; i < targets.Count; ++i)
|
||||
{
|
||||
Mobile m = targets[i];
|
||||
|
||||
Caster.DoBeneficial(m);
|
||||
|
||||
Poison poison = m.Poison;
|
||||
|
||||
if (poison != null)
|
||||
{
|
||||
int chanceToCure = 10000 + (int)(Caster.Skills.Magery.Value * 75) -
|
||||
(poison.Level + 1) * 1750;
|
||||
chanceToCure /= 100;
|
||||
chanceToCure -= 1;
|
||||
|
||||
if (chanceToCure > Utility.Random(100) && m.CurePoison(Caster))
|
||||
++cured;
|
||||
}
|
||||
|
||||
m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist);
|
||||
m.PlaySound(0x1E0);
|
||||
}
|
||||
|
||||
if (cured > 0)
|
||||
Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons!
|
||||
}
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private bool AreaCanTarget(Mobile target, bool feluccaRules)
|
||||
{
|
||||
/* Arch cure area effect won't cure aggressors, victims, murderers, criminals or monsters.
|
||||
* In Felucca, it will also not cure summons and pets.
|
||||
* For red players it will only cure themselves and guild members.
|
||||
*/
|
||||
|
||||
if (!Caster.CanBeBeneficial(target, false))
|
||||
return false;
|
||||
|
||||
if (Core.AOS && target != Caster)
|
||||
{
|
||||
if (IsAggressor(target) || IsAggressed(target))
|
||||
return false;
|
||||
|
||||
if ((!IsInnocentTo(Caster, target) || !IsInnocentTo(target, Caster)) && !IsAllyTo(Caster, target))
|
||||
return false;
|
||||
|
||||
if (feluccaRules && !(target is PlayerMobile))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsAggressor(Mobile m)
|
||||
{
|
||||
foreach (AggressorInfo info in Caster.Aggressors)
|
||||
if (m == info.Attacker && !info.Expired)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsAggressed(Mobile m)
|
||||
{
|
||||
foreach (AggressorInfo info in Caster.Aggressed)
|
||||
if (m == info.Defender && !info.Expired)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsInnocentTo(Mobile from, Mobile to)
|
||||
{
|
||||
return Notoriety.Compute(from, to) == Notoriety.Innocent;
|
||||
}
|
||||
|
||||
private static bool IsAllyTo(Mobile from, Mobile to)
|
||||
{
|
||||
return Notoriety.Compute(from, to) == Notoriety.Ally;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
Projects/Scripts/Spells/Fourth/ArchProtection.cs
Normal file
134
Projects/Scripts/Spells/Fourth/ArchProtection.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Engines.PartySystem;
|
||||
using Server.Spells.Second;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class ArchProtectionSpell : MagerySpell, ISpellTargetingPoint3D
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Arch Protection", "Vas Uus Sanct",
|
||||
Core.AOS ? 239 : 215,
|
||||
9011,
|
||||
Reagent.Garlic,
|
||||
Reagent.Ginseng,
|
||||
Reagent.MandrakeRoot,
|
||||
Reagent.SulfurousAsh
|
||||
);
|
||||
|
||||
private static Dictionary<Mobile, int> _Table = new Dictionary<Mobile, int>();
|
||||
|
||||
public ArchProtectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public void Target(IPoint3D p)
|
||||
{
|
||||
if (!Caster.CanSee(p))
|
||||
{
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
SpellHelper.Turn(Caster, p);
|
||||
|
||||
SpellHelper.GetSurfaceTop(ref p);
|
||||
|
||||
if (!Core.AOS)
|
||||
Effects.PlaySound(p, Caster.Map, 0x299);
|
||||
|
||||
if (Caster.Map == null)
|
||||
{
|
||||
FinishSequence();
|
||||
return;
|
||||
}
|
||||
|
||||
IEnumerable<Mobile> targets = Caster.Map.GetMobilesInRange(new Point3D(p), Core.AOS ? 2 : 3)
|
||||
.Where(m => Caster.CanBeBeneficial(m, false));
|
||||
|
||||
if (Core.AOS)
|
||||
{
|
||||
Party party = Party.Get(Caster);
|
||||
|
||||
foreach (Mobile m in targets)
|
||||
{
|
||||
if (m == Caster || party?.Contains(m) == true)
|
||||
{
|
||||
Caster.DoBeneficial(m);
|
||||
ProtectionSpell.Toggle(Caster, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int val = (int)(Caster.Skills.Magery.Value / 10.0 + 1);
|
||||
|
||||
foreach (Mobile m in targets)
|
||||
{
|
||||
if (m.BeginAction<ArchProtectionSpell>())
|
||||
{
|
||||
Caster.DoBeneficial(m);
|
||||
m.VirtualArmorMod += val;
|
||||
|
||||
AddEntry(m, val);
|
||||
new InternalTimer(m, Caster).Start();
|
||||
|
||||
m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist);
|
||||
m.PlaySound(0x1F7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private static void AddEntry(Mobile m, int v)
|
||||
{
|
||||
_Table[m] = v;
|
||||
}
|
||||
|
||||
public static void RemoveEntry(Mobile m)
|
||||
{
|
||||
if (_Table.TryGetValue(m, out int v))
|
||||
{
|
||||
_Table.Remove(m);
|
||||
m.EndAction<ArchProtectionSpell>();
|
||||
m.VirtualArmorMod -= v;
|
||||
if (m.VirtualArmorMod < 0)
|
||||
m.VirtualArmorMod = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
|
||||
public InternalTimer(Mobile target, Mobile caster) : base(TimeSpan.FromSeconds(0))
|
||||
{
|
||||
double time = caster.Skills.Magery.Value * 1.2;
|
||||
if (time > 144)
|
||||
time = 144;
|
||||
Delay = TimeSpan.FromSeconds(time);
|
||||
Priority = TimerPriority.OneSecond;
|
||||
|
||||
m_Owner = target;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
RemoveEntry(m_Owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Projects/Scripts/Spells/Fourth/Curse.cs
Normal file
91
Projects/Scripts/Spells/Fourth/Curse.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class CurseSpell : MagerySpell, ISpellTargetingMobile
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Curse", "Des Sanct",
|
||||
227,
|
||||
9031,
|
||||
Reagent.Nightshade,
|
||||
Reagent.Garlic,
|
||||
Reagent.SulfurousAsh
|
||||
);
|
||||
|
||||
private static HashSet<Mobile> m_UnderEffect = new HashSet<Mobile>();
|
||||
|
||||
public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public static void RemoveEffect(Mobile m)
|
||||
{
|
||||
m_UnderEffect.Remove(m);
|
||||
|
||||
m.UpdateResistances();
|
||||
}
|
||||
|
||||
public static bool UnderEffect(Mobile m)
|
||||
{
|
||||
return m_UnderEffect.Contains(m);
|
||||
}
|
||||
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
if (!Caster.CanSee(m))
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
else if (CheckHSequence(m))
|
||||
{
|
||||
SpellHelper.Turn(Caster, m);
|
||||
|
||||
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
|
||||
|
||||
SpellHelper.AddStatCurse(Caster, m, StatType.Str);
|
||||
SpellHelper.DisableSkillCheck = true;
|
||||
SpellHelper.AddStatCurse(Caster, m, StatType.Dex);
|
||||
SpellHelper.AddStatCurse(Caster, m, StatType.Int);
|
||||
SpellHelper.DisableSkillCheck = false;
|
||||
|
||||
if (Caster.Player && m.Player /*&& Caster != m */ && !UnderEffect(m)
|
||||
) //On OSI you CAN curse yourself and get this effect.
|
||||
{
|
||||
TimeSpan duration = SpellHelper.GetDuration(Caster, m);
|
||||
m_UnderEffect.Add(m);
|
||||
Timer.DelayCall(duration, RemoveEffect, m);
|
||||
m.UpdateResistances();
|
||||
}
|
||||
|
||||
m.Spell?.OnCasterHurt();
|
||||
|
||||
m.Paralyzed = false;
|
||||
|
||||
m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist);
|
||||
m.PlaySound(0x1E1);
|
||||
|
||||
int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
|
||||
TimeSpan length = SpellHelper.GetDuration(Caster, m);
|
||||
|
||||
string args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}";
|
||||
|
||||
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args));
|
||||
|
||||
HarmfulSpell(m);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
280
Projects/Scripts/Spells/Fourth/FireField.cs
Normal file
280
Projects/Scripts/Spells/Fourth/FireField.cs
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class FireFieldSpell : MagerySpell, ISpellTargetingPoint3D
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Fire Field", "In Flam Grav",
|
||||
215,
|
||||
9041,
|
||||
false,
|
||||
Reagent.BlackPearl,
|
||||
Reagent.SpidersSilk,
|
||||
Reagent.SulfurousAsh
|
||||
);
|
||||
|
||||
public FireFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public void Target(IPoint3D p)
|
||||
{
|
||||
if (!Caster.CanSee(p))
|
||||
{
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
else if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
|
||||
{
|
||||
SpellHelper.Turn(Caster, p);
|
||||
|
||||
SpellHelper.GetSurfaceTop(ref p);
|
||||
|
||||
int dx = Caster.Location.X - p.X;
|
||||
int dy = Caster.Location.Y - p.Y;
|
||||
int rx = (dx - dy) * 44;
|
||||
int ry = (dx + dy) * 44;
|
||||
|
||||
bool eastToWest;
|
||||
|
||||
if (rx >= 0 && ry >= 0)
|
||||
eastToWest = false;
|
||||
else if (rx >= 0)
|
||||
eastToWest = true;
|
||||
else if (ry >= 0)
|
||||
eastToWest = true;
|
||||
else
|
||||
eastToWest = false;
|
||||
|
||||
Effects.PlaySound(p, Caster.Map, 0x20C);
|
||||
|
||||
int itemID = eastToWest ? 0x398C : 0x3996;
|
||||
|
||||
TimeSpan duration;
|
||||
|
||||
if (Core.AOS)
|
||||
duration = TimeSpan.FromSeconds((15 + Caster.Skills.Magery.Fixed / 5) / 4);
|
||||
else
|
||||
duration = TimeSpan.FromSeconds(4.0 + Caster.Skills.Magery.Value * 0.5);
|
||||
|
||||
for (int i = -2; i <= 2; ++i)
|
||||
{
|
||||
Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z);
|
||||
|
||||
new FireFieldItem(itemID, loc, Caster, Caster.Map, duration, i);
|
||||
}
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
[DispellableField]
|
||||
public class FireFieldItem : Item
|
||||
{
|
||||
private Mobile m_Caster;
|
||||
private int m_Damage;
|
||||
private DateTime m_End;
|
||||
private Timer m_Timer;
|
||||
|
||||
public FireFieldItem(int itemID, Point3D loc, Mobile caster, Map map, TimeSpan duration, int val,
|
||||
int damage = 2) : base(itemID)
|
||||
{
|
||||
bool canFit = SpellHelper.AdjustField(ref loc, map, 12, false);
|
||||
|
||||
Visible = false;
|
||||
Movable = false;
|
||||
Light = LightType.Circle300;
|
||||
|
||||
MoveToWorld(loc, map);
|
||||
|
||||
m_Caster = caster;
|
||||
|
||||
m_Damage = damage;
|
||||
|
||||
m_End = DateTime.UtcNow + duration;
|
||||
|
||||
m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(Math.Abs(val) * 0.2), caster.InLOS(this), canFit);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public FireFieldItem(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool BlocksFit => true;
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
m_Timer?.Stop();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write(m_Damage);
|
||||
writer.Write(m_Caster);
|
||||
writer.WriteDeltaTime(m_End);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
m_Damage = reader.ReadInt();
|
||||
goto case 1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
m_Caster = reader.ReadMobile();
|
||||
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
m_End = reader.ReadDeltaTime();
|
||||
|
||||
m_Timer = new InternalTimer(this, TimeSpan.Zero, true, true);
|
||||
m_Timer.Start();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (version < 2)
|
||||
m_Damage = 2;
|
||||
}
|
||||
|
||||
public override bool OnMoveOver(Mobile m)
|
||||
{
|
||||
if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) &&
|
||||
SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false))
|
||||
{
|
||||
if (SpellHelper.CanRevealCaster(m))
|
||||
m_Caster.RevealingAction();
|
||||
|
||||
m_Caster.DoHarmful(m);
|
||||
|
||||
int damage = m_Damage;
|
||||
|
||||
if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0))
|
||||
{
|
||||
damage = 1;
|
||||
|
||||
m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
|
||||
}
|
||||
|
||||
AOS.Damage(m, m_Caster, damage, 0, 100, 0, 0, 0);
|
||||
m.PlaySound(0x208);
|
||||
|
||||
(m as BaseCreature)?.OnHarmfulSpell(m_Caster);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private static Queue m_Queue = new Queue();
|
||||
private bool m_InLOS, m_CanFit;
|
||||
private FireFieldItem m_Item;
|
||||
|
||||
public InternalTimer(FireFieldItem item, TimeSpan delay, bool inLOS, bool canFit) : base(delay,
|
||||
TimeSpan.FromSeconds(1.0))
|
||||
{
|
||||
m_Item = item;
|
||||
m_InLOS = inLOS;
|
||||
m_CanFit = canFit;
|
||||
|
||||
Priority = TimerPriority.FiftyMS;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Item.Deleted)
|
||||
return;
|
||||
|
||||
if (!m_Item.Visible)
|
||||
{
|
||||
if (m_InLOS && m_CanFit)
|
||||
m_Item.Visible = true;
|
||||
else
|
||||
m_Item.Delete();
|
||||
|
||||
if (!m_Item.Deleted)
|
||||
{
|
||||
m_Item.ProcessDelta();
|
||||
Effects.SendLocationParticles(
|
||||
EffectItem.Create(m_Item.Location, m_Item.Map, EffectItem.DefaultDuration), 0x376A, 9, 10,
|
||||
5029);
|
||||
}
|
||||
}
|
||||
else if (DateTime.UtcNow > m_Item.m_End)
|
||||
{
|
||||
m_Item.Delete();
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
Map map = m_Item.Map;
|
||||
Mobile caster = m_Item.m_Caster;
|
||||
|
||||
if (map == null || caster == null)
|
||||
return;
|
||||
|
||||
foreach (Mobile m in m_Item.GetMobilesInRange(0))
|
||||
if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != caster) &&
|
||||
SpellHelper.ValidIndirectTarget(caster, m) && caster.CanBeHarmful(m, false))
|
||||
m_Queue.Enqueue(m);
|
||||
|
||||
while (m_Queue.Count > 0)
|
||||
{
|
||||
Mobile m = (Mobile)m_Queue.Dequeue();
|
||||
|
||||
if (SpellHelper.CanRevealCaster(m))
|
||||
caster.RevealingAction();
|
||||
|
||||
caster.DoHarmful(m);
|
||||
|
||||
int damage = m_Item.m_Damage;
|
||||
|
||||
if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0))
|
||||
{
|
||||
damage = 1;
|
||||
|
||||
m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
|
||||
}
|
||||
|
||||
AOS.Damage(m, caster, damage, 0, 100, 0, 0, 0);
|
||||
m.PlaySound(0x208);
|
||||
|
||||
(m as BaseCreature)?.OnHarmfulSpell(caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Projects/Scripts/Spells/Fourth/GreaterHeal.cs
Normal file
85
Projects/Scripts/Spells/Fourth/GreaterHeal.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
using Server.Engines.ConPVP;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class GreaterHealSpell : MagerySpell, ISpellTargetingMobile
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Greater Heal", "In Vas Mani",
|
||||
204,
|
||||
9061,
|
||||
Reagent.Garlic,
|
||||
Reagent.Ginseng,
|
||||
Reagent.MandrakeRoot,
|
||||
Reagent.SpidersSilk
|
||||
);
|
||||
|
||||
public GreaterHealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (DuelContext.CheckSuddenDeath(Caster))
|
||||
{
|
||||
Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
if (!Caster.CanSee(m))
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
else if (m is BaseCreature creature && creature.IsAnimatedDead)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive.
|
||||
}
|
||||
else if (m.IsDeadBondedPet)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead!
|
||||
}
|
||||
else if (m is Golem)
|
||||
{
|
||||
Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500951); // You cannot heal that.
|
||||
}
|
||||
else if (m.Poisoned || MortalStrike.IsWounded(m))
|
||||
{
|
||||
Caster.LocalOverheadMessage(MessageType.Regular, 0x22, Caster == m ? 1005000 : 1010398);
|
||||
}
|
||||
else if (CheckBSequence(m))
|
||||
{
|
||||
SpellHelper.Turn(Caster, m);
|
||||
|
||||
// Algorithm: (40% of magery) + (1-10)
|
||||
|
||||
int toHeal = (int)(Caster.Skills.Magery.Value * 0.4);
|
||||
toHeal += Utility.Random(1, 10);
|
||||
|
||||
//m.Heal( toHeal, Caster );
|
||||
SpellHelper.Heal(toHeal, m, Caster);
|
||||
|
||||
m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist);
|
||||
m.PlaySound(0x202);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Projects/Scripts/Spells/Fourth/Lightning.cs
Normal file
69
Projects/Scripts/Spells/Fourth/Lightning.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class LightningSpell : MagerySpell, ISpellTargetingMobile
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Lightning", "Por Ort Grav",
|
||||
239,
|
||||
9021,
|
||||
Reagent.MandrakeRoot,
|
||||
Reagent.SulfurousAsh
|
||||
);
|
||||
|
||||
public LightningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override bool DelayedDamage => false;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
if (!Caster.CanSee(m))
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
else if (CheckHSequence(m))
|
||||
{
|
||||
SpellHelper.Turn(Caster, m);
|
||||
|
||||
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
|
||||
|
||||
double damage;
|
||||
|
||||
if (Core.AOS)
|
||||
{
|
||||
damage = GetNewAosDamage(23, 1, 4, m);
|
||||
}
|
||||
else
|
||||
{
|
||||
damage = Utility.Random(12, 9);
|
||||
|
||||
if (CheckResisted(m))
|
||||
{
|
||||
damage *= 0.75;
|
||||
|
||||
m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
|
||||
}
|
||||
|
||||
damage *= GetDamageScalar(m);
|
||||
}
|
||||
|
||||
m.BoltEffect(0);
|
||||
|
||||
SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Projects/Scripts/Spells/Fourth/ManaDrain.cs
Normal file
108
Projects/Scripts/Spells/Fourth/ManaDrain.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class ManaDrainSpell : MagerySpell, ISpellTargetingMobile
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Mana Drain", "Ort Rel",
|
||||
215,
|
||||
9031,
|
||||
Reagent.BlackPearl,
|
||||
Reagent.MandrakeRoot,
|
||||
Reagent.SpidersSilk
|
||||
);
|
||||
|
||||
private static HashSet<Mobile> m_Table = new HashSet<Mobile>();
|
||||
|
||||
public ManaDrainSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12);
|
||||
}
|
||||
|
||||
private void AosDelay_Callback(Mobile m, int mana)
|
||||
{
|
||||
if (m.Alive && !m.IsDeadBondedPet)
|
||||
{
|
||||
m.Mana += mana;
|
||||
|
||||
m.FixedEffect(0x3779, 10, 25);
|
||||
m.PlaySound(0x28E);
|
||||
}
|
||||
|
||||
m_Table.Remove(m);
|
||||
}
|
||||
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
if (!Caster.CanSee(m))
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
else if (CheckHSequence(m))
|
||||
{
|
||||
SpellHelper.Turn(Caster, m);
|
||||
|
||||
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
|
||||
|
||||
m.Spell?.OnCasterHurt();
|
||||
|
||||
m.Paralyzed = false;
|
||||
|
||||
if (Core.AOS)
|
||||
{
|
||||
int toDrain = 40 + (int)(GetDamageSkill(Caster) - GetResistSkill(m));
|
||||
|
||||
if (toDrain < 0)
|
||||
toDrain = 0;
|
||||
else if (toDrain > m.Mana)
|
||||
toDrain = m.Mana;
|
||||
|
||||
if (m_Table.Contains(m))
|
||||
toDrain = 0;
|
||||
|
||||
m.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head);
|
||||
m.PlaySound(0x1F8);
|
||||
|
||||
if (toDrain > 0)
|
||||
{
|
||||
m.Mana -= toDrain;
|
||||
|
||||
m_Table.Add(m);
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(5.0), () => AosDelay_Callback(m, toDrain));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CheckResisted(m))
|
||||
m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
|
||||
else if (m.Mana >= 100)
|
||||
m.Mana -= Utility.Random(1, 100);
|
||||
else
|
||||
m.Mana -= Utility.Random(1, m.Mana);
|
||||
|
||||
m.FixedParticles(0x374A, 10, 15, 5032, EffectLayer.Head);
|
||||
m.PlaySound(0x1F8);
|
||||
}
|
||||
|
||||
HarmfulSpell(m);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public override double GetResistPercent(Mobile target)
|
||||
{
|
||||
return 99.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
143
Projects/Scripts/Spells/Fourth/Recall.cs
Normal file
143
Projects/Scripts/Spells/Fourth/Recall.cs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
using Server.Factions;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Spells.Necromancy;
|
||||
|
||||
namespace Server.Spells.Fourth
|
||||
{
|
||||
public class RecallSpell : MagerySpell, IRecallSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Recall", "Kal Ort Por",
|
||||
239,
|
||||
9031,
|
||||
Reagent.BlackPearl,
|
||||
Reagent.Bloodmoss,
|
||||
Reagent.MandrakeRoot
|
||||
);
|
||||
|
||||
private Runebook m_Book;
|
||||
|
||||
private RunebookEntry m_Entry;
|
||||
|
||||
public RecallSpell(Mobile caster, RunebookEntry entry = null, Runebook book = null, Item scroll = null) :
|
||||
base(caster, scroll, m_Info)
|
||||
{
|
||||
m_Entry = entry;
|
||||
m_Book = book;
|
||||
}
|
||||
|
||||
public override SpellCircle Circle => SpellCircle.Fourth;
|
||||
|
||||
public override void GetCastSkills(out double min, out double max)
|
||||
{
|
||||
if (TransformationSpellHelper.UnderTransformation(Caster, typeof(WraithFormSpell)))
|
||||
min = max = 0;
|
||||
else if (Core.SE && m_Book != null) //recall using Runebook charge
|
||||
min = max = 0;
|
||||
else
|
||||
base.GetCastSkills(out min, out max);
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if (m_Entry == null)
|
||||
Caster.Target = new RecallSpellTarget(this);
|
||||
else
|
||||
Effect(m_Entry.Location, m_Entry.Map, true);
|
||||
}
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (Sigil.ExistsOn(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Caster.Criminal)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SpellHelper.CheckCombat(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle??
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WeightOverloading.IsOverloaded(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move.
|
||||
return false;
|
||||
}
|
||||
|
||||
return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom);
|
||||
}
|
||||
|
||||
public void Effect(Point3D loc, Map map, bool checkMulti)
|
||||
{
|
||||
if (Sigil.ExistsOn(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil.
|
||||
}
|
||||
else if (map == null || !Core.AOS && Caster.Map != map)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1005569); // You can not recall to another facet.
|
||||
}
|
||||
else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom))
|
||||
{
|
||||
}
|
||||
else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo))
|
||||
{
|
||||
}
|
||||
else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young)
|
||||
{
|
||||
mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young.
|
||||
}
|
||||
else if (Caster.Kills >= 5 && map != Map.Felucca)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there.
|
||||
}
|
||||
else if (Caster.Criminal)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily.
|
||||
}
|
||||
else if (SpellHelper.CheckCombat(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle??
|
||||
}
|
||||
else if (WeightOverloading.IsOverloaded(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move.
|
||||
}
|
||||
else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501942); // That location is blocked.
|
||||
}
|
||||
else if (checkMulti && SpellHelper.CheckMulti(loc, map))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501942); // That location is blocked.
|
||||
}
|
||||
else if (m_Book != null && m_Book.CurCharges <= 0)
|
||||
{
|
||||
Caster.SendLocalizedMessage(502412); // There are no charges left on that item.
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
BaseCreature.TeleportPets(Caster, loc, map, true);
|
||||
|
||||
if (m_Book != null)
|
||||
--m_Book.CurCharges;
|
||||
|
||||
Caster.PlaySound(0x1FC);
|
||||
Caster.MoveToWorld(loc, map);
|
||||
Caster.PlaySound(0x1FC);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue