Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,134 @@
using System;
using Server;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public abstract class MysticSpell : Spell
{
public MysticSpell(Mobile caster, Item scroll, SpellInfo info)
: base(caster, scroll, info)
{
}
public abstract SpellCircle Circle { get; }
private static int[] m_ManaTable = new int[] { 4, 6, 9, 11, 14, 20, 40, 50 };
public override TimeSpan CastDelayBase { get { return TimeSpan.FromMilliseconds(((4 + (int)Circle) * CastDelaySecondsPerTick) * 1000); } }
public override double CastDelayFastScalar { get { return 1.0; } }
public double ChanceOffset { get { return Caster is Server.Mobiles.PlayerMobile ? 20.0 : 30.0; } }
private const double ChanceLength = 100.0 / 7.0;
public override void GetCastSkills(out double min, out double max)
{
int circle = (int)Circle;
if (Scroll != null)
circle -= 2;
double avg = ChanceLength * circle;
min = avg - ChanceOffset;
max = avg + ChanceOffset;
}
public override SkillName CastSkill { get { return SkillName.Mysticism; } }
public override SkillName DamageSkill
{
get
{
if (Caster.Skills[SkillName.Imbuing].Value >= Caster.Skills[SkillName.Focus].Value)
return SkillName.Imbuing;
return SkillName.Focus;
}
}
public override void SendCastEffect()
{
if(Caster.Player)
Caster.FixedEffect(0x37C4, 87, (int)(GetCastDelay().TotalSeconds * 28), 0x66C, 3);
}
public override int GetMana()
{
if (Core.TOL && this is HailStormSpell)
return 50;
return m_ManaTable[(int)Circle];
}
public override TimeSpan GetCastRecovery()
{
if (Scroll is SpellStone)
return TimeSpan.Zero;
return base.GetCastRecovery();
}
public override TimeSpan GetCastDelay()
{
if (Scroll is SpellStone)
return TimeSpan.Zero;
return base.GetCastDelay();
}
public override bool CheckCast()
{
if (!base.CheckCast())
return false;
return true;
}
public virtual bool CheckResisted(Mobile target)
{
double n = GetResistPercent(target);
n /= 100.0;
if (n <= 0.0)
return false;
if (n >= 1.0)
return true;
int circle = Math.Max(5, 1 + (int)Circle);
int maxSkill = circle * 10;
maxSkill += (circle / 6) * 25;
if (target.Skills[SkillName.MagicResist].Value < maxSkill)
target.CheckSkill(SkillName.MagicResist, 0.0, target.Skills[SkillName.MagicResist].Cap);
return (n >= Utility.RandomDouble());
}
public virtual double GetResistPercentForCircle(Mobile target, SpellCircle circle)
{
double value = GetResistSkill(target);
double firstPercent = value / 5.0;
double secondPercent = value - (((Caster.Skills[CastSkill].Value - 20.0) / 5.0) + (Math.Max(5, 1 + (int)circle)) * 5.0);
return (firstPercent > secondPercent ? firstPercent : secondPercent) / 2.0; // Seems should be about half of what stratics says.
}
public virtual double GetResistPercent(Mobile target)
{
return GetResistPercentForCircle(target, Circle);
}
public static double GetBaseSkill(Mobile m)
{
return m.Skills[SkillName.Mysticism].Value;
}
public static double GetBoostSkill(Mobile m)
{
return Math.Max(m.Skills[SkillName.Imbuing].Value, m.Skills[SkillName.Focus].Value);
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class AnimatedWeaponSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Fourth; } }
private static SpellInfo m_Info = new SpellInfo(
"Animated Weapon", "In Jux Por Ylem",
230,
9022,
Reagent.BlackPearl,
Reagent.MandrakeRoot,
Reagent.Nightshade,
Reagent.Bone
);
public AnimatedWeaponSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void Target(IPoint3D p)
{
if ((Caster.Followers + 4) > Caster.FollowersMax)
{
Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature.
return;
}
Map map = Caster.Map;
SpellHelper.GetSurfaceTop(ref p);
if (map == null || (Caster.IsPlayer() && !map.CanSpawnMobile(p.X, p.Y, p.Z)))
{
Caster.SendLocalizedMessage(501942); // That location is blocked.
}
else if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
{
int level = (int)((GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 2.0);
TimeSpan duration = TimeSpan.FromSeconds(10 + level);
BaseCreature summon = new AnimatedWeapon(Caster, level);
BaseCreature.Summon(summon, false, Caster, new Point3D(p), 0x212, duration);
summon.PlaySound(0x64A);
Effects.SendTargetParticles(summon, 0x3728, 10, 10, 0x13AA, (EffectLayer)255);
}
FinishSequence();
}
public class InternalTarget : Target
{
private AnimatedWeaponSpell m_Owner;
public InternalTarget(AnimatedWeaponSpell owner)
: base(12, true, TargetFlags.None)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D)
m_Owner.Target((IPoint3D)o);
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class BombardSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Sixth; } }
public override bool DelayedDamage { get { return true; } }
public override bool DelayedDamageStacking { get { return false; } }
private static SpellInfo m_Info = new SpellInfo(
"Bombard", "Corp Por Ylem",
230,
9022,
Reagent.Bloodmoss,
Reagent.Garlic,
Reagent.SulfurousAsh,
Reagent.DragonBlood
);
public BombardSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(IDamageable d)
{
if (d == null)
{
return;
}
else if (CheckHSequence(d))
{
IDamageable target = d;
IDamageable source = Caster;
SpellHelper.Turn(Caster, target);
if (Core.SA && HasDelayContext(target))
{
DoHurtFizzle();
return;
}
if (SpellHelper.CheckReflect((int)Circle, ref source, ref target))
{
Server.Timer.DelayCall(TimeSpan.FromSeconds(.5), () =>
{
source.MovingEffect(target, 0x1363, 12, 1, false, true, 0, 0);
source.PlaySound(0x64B);
});
}
Caster.MovingEffect(d, 0x1363, 12, 1, false, true, 0, 0);
Caster.PlaySound(0x64B);
SpellHelper.Damage(this, target, (int)GetNewAosDamage(40, 1, 5, target), 100, 0, 0, 0, 0);
if (target is Mobile)
{
Timer.DelayCall(TimeSpan.FromMilliseconds(1200), () =>
{
if (!CheckResisted((Mobile)target))
{
int secs = (int)((GetDamageSkill(this.Caster) / 10) - (GetResistSkill((Mobile)target) / 10));
if (secs < 0)
secs = 0;
((Mobile)target).Paralyze(TimeSpan.FromSeconds(secs));
}
});
}
}
FinishSequence();
}
public class InternalTarget : Target
{
public BombardSpell Owner { get; set; }
public InternalTarget(BombardSpell owner)
: this(owner, false)
{
}
public InternalTarget(BombardSpell 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 if (o is IDamageable)
{
SpellHelper.Turn(from, o);
Owner.OnTarget((IDamageable)o);
}
}
protected override void OnTargetFinish(Mobile from)
{
Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,264 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Engines.PartySystem;
using Server.Items;
using Server.Spells.First;
using Server.Spells.Fourth;
using Server.Spells.Necromancy;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class CleansingWindsSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Sixth; } }
private static SpellInfo m_Info = new SpellInfo(
"Cleansing Winds", "In Vas Mani Hur",
230,
9022,
Reagent.Garlic,
Reagent.Ginseng,
Reagent.MandrakeRoot,
Reagent.DragonBlood
);
public CleansingWindsSpell(Mobile caster, Item scroll)
: base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(object o)
{
var targeted = o as Mobile;
if (targeted == null)
return;
if (CheckBSequence(targeted))
{
/* Soothing winds attempt to neutralize poisons, lift curses, and heal a valid
* Target. The Caster's Mysticism and either Focus or Imbuing (whichever is
* greater) skills determine the effectiveness of the Cleansing Winds.
*/
Caster.PlaySound(0x64C);
var targets = new List<Mobile> { targeted };
targets.AddRange(FindAdditionalTargets(targeted).Take(3)); // This effect can hit up to 3 additional players beyond the primary target.
double primarySkill = Caster.Skills[CastSkill].Value;
double secondarySkill = Caster.Skills[DamageSkill].Value;
var toHeal = (int)((primarySkill + secondarySkill) / 4.0) + Utility.RandomMinMax(-3, 3);
toHeal /= targets.Count; // The effectiveness of the spell is reduced by the number of targets affected.
foreach (var target in targets)
{
// WARNING: This spell will flag the caster as a criminal if a criminal or murderer party member is close enough
// to the target to receive the benefits from the area of effect.
Caster.DoBeneficial(target);
PlayEffect(target);
int toHealMod = toHeal;
if (target.Poisoned)
{
int poisonLevel = target.Poison.RealLevel + 1;
int chanceToCure = (10000 + (int)((primarySkill + secondarySkill) / 2 * 75) - (poisonLevel * 1750)) / 100;
if (chanceToCure > Utility.Random(100) && target.CurePoison(Caster))
{
// Poison reduces healing factor by 15% per level of poison.
toHealMod -= (int)(toHeal * poisonLevel * 0.15);
}
else
{
// If the cure fails, the target will not be healed.
toHealMod = 0;
}
}
// Cleansing Winds will not heal the target after removing mortal wound.
if (MortalStrike.IsWounded(target))
{
toHealMod = 0;
}
var curseLevel = RemoveCurses(target);
if (toHealMod > 0 && curseLevel > 0)
{
// Each Curse reduces healing by 3 points + 1% per curse level.
toHealMod = toHealMod - (curseLevel * 3);
toHealMod = toHealMod - (int)((double)toHealMod * ((double)curseLevel / 100.0));
}
if (toHealMod > 0)
SpellHelper.Heal(toHealMod, target, Caster);
}
}
FinishSequence();
}
private static void PlayEffect(Mobile m)
{
m.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
var from = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z - 10), m.Map);
var to = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + 50), m.Map);
Effects.SendMovingParticles(from, to, 0x2255, 1, 0, false, false, 13, 3, 9501, 1, 0, EffectLayer.Head, 0x100);
}
private IEnumerable<Mobile> FindAdditionalTargets(Mobile targeted)
{
var casterParty = Party.Get(Caster);
if (casterParty == null)
yield break;
IPooledEnumerable eable = Caster.Map.GetMobilesInRange(new Point3D(targeted), 2);
foreach (Mobile m in eable)
{
if (m == null || m == targeted)
continue;
// Players in the area must be in the casters party in order to receive the beneficial effects of the spell.
if (Caster.CanBeBeneficial(m, false) && casterParty.Contains(m))
yield return m;
}
eable.Free();
}
public static int RemoveCurses(Mobile m)
{
int curseLevel = 0;
if (SleepSpell.IsUnderSleepEffects(m))
{
SleepSpell.EndSleep(m);
curseLevel += 2;
}
if (EvilOmenSpell.TryEndEffect(m))
{
curseLevel += 1;
}
if (StrangleSpell.RemoveCurse(m))
{
curseLevel += 2;
}
if (CorpseSkinSpell.RemoveCurse(m))
{
curseLevel += 3;
}
if (CurseSpell.UnderEffect(m))
{
CurseSpell.RemoveEffect(m);
curseLevel += 4;
}
if (BloodOathSpell.RemoveCurse(m))
{
curseLevel += 3;
}
if (MindRotSpell.HasMindRotScalar(m))
{
MindRotSpell.ClearMindRotScalar(m);
curseLevel += 2;
}
if (SpellPlagueSpell.HasSpellPlague(m))
{
SpellPlagueSpell.RemoveFromList(m);
curseLevel += 4;
}
if (FeeblemindSpell.IsUnderEffects(m))
{
FeeblemindSpell.RemoveEffects(m);
curseLevel += 1;
}
if (ClumsySpell.IsUnderEffects(m))
{
ClumsySpell.RemoveEffects(m);
curseLevel += 1;
}
if (WeakenSpell.IsUnderEffects(m))
{
WeakenSpell.RemoveEffects(m);
curseLevel += 1;
}
if (MortalStrike.IsWounded(m))
{
MortalStrike.EndWound(m);
curseLevel += 2;
}
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);
BuffInfo.RemoveBuff(m, BuffIcon.CorpseSkin);
BuffInfo.RemoveBuff(m, BuffIcon.Strangle);
BuffInfo.RemoveBuff(m, BuffIcon.EvilOmen);
return curseLevel;
}
public class InternalTarget : Target
{
public CleansingWindsSpell Owner { get; set; }
public InternalTarget(CleansingWindsSpell owner)
: this(owner, false)
{
}
public InternalTarget(CleansingWindsSpell owner, bool allowland)
: base(12, allowland, TargetFlags.Beneficial)
{
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();
}
}
}
}

View File

@@ -0,0 +1,112 @@
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class EagleStrikeSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Third; } }
public override bool DelayedDamage { get { return true; } }
public override bool DelayedDamageStacking { get { return false; } }
private static SpellInfo m_Info = new SpellInfo(
"Eagle Strike", "Kal Por Xen",
230,
9022,
Reagent.Bloodmoss,
Reagent.Bone,
Reagent.MandrakeRoot,
Reagent.SpidersSilk
);
public EagleStrikeSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(IDamageable d)
{
if (d == null)
{
return;
}
else if (CheckHSequence(d))
{
IDamageable target = d;
IDamageable source = Caster;
SpellHelper.Turn(Caster, target);
if (Core.SA && HasDelayContext(target))
{
DoHurtFizzle();
return;
}
if (SpellHelper.CheckReflect((int)Circle, ref source, ref target))
{
Timer.DelayCall(TimeSpan.FromSeconds(.5), () =>
{
source.MovingEffect(target, 0x407A, 8, 1, false, true, 0, 0);
source.PlaySound(0x2EE);
});
}
Caster.MovingEffect(d, 0x407A, 8, 1, false, true, 0, 0);
Caster.PlaySound(0x2EE);
Timer.DelayCall(TimeSpan.FromSeconds(.5), () =>
{
Caster.PlaySound(0x64D);
});
SpellHelper.Damage(this, target, (int)GetNewAosDamage(19, 1, 5, target), 0, 0, 0, 0, 100);
}
FinishSequence();
}
public class InternalTarget : Target
{
public EagleStrikeSpell Owner { get; set; }
public InternalTarget(EagleStrikeSpell owner)
: this(owner, false)
{
}
public InternalTarget(EagleStrikeSpell 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 if (o is IDamageable)
{
SpellHelper.Turn(from, o);
Owner.OnTarget((IDamageable)o);
}
}
protected override void OnTargetFinish(Mobile from)
{
Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections;
using Server.Items;
using Server.Network;
using System.Collections.Generic;
using Server.Spells.Mysticism;
using Server.Spells;
namespace Server.Gumps
{
public class EnchantSpellGump : Gump
{
private Mobile m_Caster;
private Item m_Scroll;
private BaseWeapon m_Weapon;
public EnchantSpellGump(Mobile caster, Item scroll, BaseWeapon weapon)
: base(20, 20)
{
m_Caster = caster;
m_Scroll = scroll;
m_Weapon = weapon;
int font = 0x07FF;
AddBackground(0, 0, 260, 187, 3600);
AddAlphaRegion(5, 15, 242, 170);
AddImageTiled(220, 15, 30, 162, 10464);
AddItem(0, 3, 6882);
AddItem(-8, 170, 6880);
AddItem(185, 3, 6883);
AddItem(192, 170, 6881);
AddHtmlLocalized(20, 22, 150, 16, 1080133, font, false, false); //Select Enchant
AddButton(20, 50, 9702, 9703, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 50, 200, 16, 1079705, font, false, false); //Hit Lighting
AddButton(20, 75, 9702, 9703, 2, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 75, 200, 16, 1079703, font, false, false); //Hit Fireball
AddButton(20, 100, 9702, 9703, 3, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 100, 200, 16, 1079704, font, false, false); //Hit Harm
AddButton(20, 125, 9702, 9703, 4, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 125, 200, 16, 1079706, font, false, false); //Hit Magic Arrow
AddButton(20, 150, 9702, 9703, 5, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 150, 200, 16, 1079702, font, false, false); //Hit Dispel
}
public override void OnResponse(NetState sender, RelayInfo info)
{
AosWeaponAttribute attr = AosWeaponAttribute.HitLightning;
switch (info.ButtonID)
{
default:
m_Caster.SendLocalizedMessage(1080132); //You decide not to enchant your weapon.
return;
case 1: //Hit Lightning
{
attr = AosWeaponAttribute.HitLightning;
break;
}
case 2: //Hit Fireball
{
attr = AosWeaponAttribute.HitFireball;
break;
}
case 3: //Hit Harm
{
attr = AosWeaponAttribute.HitHarm;
break;
}
case 4: //Hit Magic Arrow
{
attr = AosWeaponAttribute.HitMagicArrow;
break;
}
case 5: //Hit Dispel
{
attr = AosWeaponAttribute.HitDispel;
break;
}
}
Spell spell = new EnchantSpell(m_Caster, m_Scroll, m_Weapon, attr);
spell.Cast();
}
}
}

View File

@@ -0,0 +1,259 @@
using System;
using Server.Gumps;
using Server.Items;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
using Server.Spells;
using Server.Network;
using Server.Spells.Spellweaving;
namespace Server.Spells.Mysticism
{
public class EnchantSpell : MysticSpell
{
private static readonly string ModName = "EnchantAttribute";
public override SpellCircle Circle { get { return SpellCircle.Second; } }
public override bool ClearHandsOnCast { get { return false; } }
public BaseWeapon Weapon { get; set; }
public AosWeaponAttribute Attribute { get; set; }
private static SpellInfo m_Info = new SpellInfo(
"Enchant", "In Ort Ylem",
230,
9022,
Reagent.SpidersSilk,
Reagent.MandrakeRoot,
Reagent.SulfurousAsh
);
public EnchantSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public EnchantSpell( Mobile caster, Item scroll, BaseWeapon weapon, AosWeaponAttribute attribute ) : base( caster, scroll, m_Info )
{
Weapon = weapon;
this.Attribute = attribute;
}
public override bool CheckCast()
{
if (Weapon == null)
{
BaseWeapon wep = Caster.Weapon as BaseWeapon;
if (wep == null)
{
Caster.SendLocalizedMessage(501078); // You must be holding a weapon.
}
else
{
if (Caster.HasGump(typeof(EnchantSpellGump)))
{
Caster.CloseGump(typeof(EnchantSpellGump));
}
var gump = new EnchantSpellGump(Caster, Scroll, wep);
int serial = gump.Serial;
Caster.SendGump(gump);
Timer.DelayCall(TimeSpan.FromSeconds(30), () =>
{
var current = Caster.FindGump(typeof(EnchantSpellGump));
if (current != null && current.Serial == serial)
{
Caster.CloseGump(typeof(EnchantSpellGump));
FinishSequence();
}
});
}
return false;
}
else if (IsUnderSpellEffects(Caster, Weapon))
{
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
return false;
}
else if (ImmolatingWeaponSpell.IsImmolating(Caster, Weapon) || Weapon.ConsecratedContext != null)
{
Caster.SendLocalizedMessage(1080128); //You cannot use this ability while your weapon is enchanted.
return false;
}
else if (Weapon.FocusWeilder != null)
{
Caster.SendLocalizedMessage(1080446); // You cannot enchant an item that is under the effects of the ninjitsu focus attack ability.
return false;
}
else if (Weapon.WeaponAttributes.HitLightning > 0 || Weapon.WeaponAttributes.HitFireball > 0 || Weapon.WeaponAttributes.HitHarm > 0 || Weapon.WeaponAttributes.HitMagicArrow > 0 || Weapon.WeaponAttributes.HitDispel > 0)
{
Caster.SendLocalizedMessage(1080127); // This weapon already has a hit spell effect and cannot be enchanted.
return false;
}
return true;
}
public override void OnCast()
{
BaseWeapon wep = Caster.Weapon as BaseWeapon;
if (wep == null || wep != Weapon)
{
Caster.SendLocalizedMessage(501078); // You must be holding a weapon.
}
else if (IsUnderSpellEffects(Caster, Weapon))
{
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
}
else if (ImmolatingWeaponSpell.IsImmolating(Caster, Weapon) || Weapon.ConsecratedContext != null)
{
Caster.SendLocalizedMessage(1080128); //You cannot use this ability while your weapon is enchanted.
}
else if (Weapon.FocusWeilder != null)
{
Caster.SendLocalizedMessage(1080446); // You cannot enchant an item that is under the effects of the ninjitsu focus attack ability.
}
else if (Weapon.WeaponAttributes.HitLightning > 0 || Weapon.WeaponAttributes.HitFireball > 0 || Weapon.WeaponAttributes.HitHarm > 0 || Weapon.WeaponAttributes.HitMagicArrow > 0 || Weapon.WeaponAttributes.HitDispel > 0)
{
Caster.SendLocalizedMessage(1080127); // This weapon already has a hit spell effect and cannot be enchanted.
}
else if (CheckSequence() && Caster.Weapon == Weapon)
{
Caster.PlaySound(0x64E);
Caster.FixedEffect(0x36CB, 1, 9, 1915, 0);
int prim = (int)Caster.Skills[CastSkill].Value;
int sec = (int)Caster.Skills[DamageSkill].Value;
int value = (60 * (prim + sec)) / 240;
double duration = ((double)(prim + sec) / 2.0) + 30.0;
int malus = 0;
if (Table == null)
Table = new Dictionary<Mobile, EnchantmentTimer>();
Enhancement.SetValue(Caster, this.Attribute, value, ModName);
if (prim >= 80 && sec >= 80 && Weapon.Attributes.SpellChanneling == 0)
{
Enhancement.SetValue(Caster, AosAttribute.SpellChanneling, 1, ModName);
Enhancement.SetValue(Caster, AosAttribute.CastSpeed, -1, ModName);
malus = 1;
}
Table[Caster] = new EnchantmentTimer(Caster, Weapon, this.Attribute, value, malus, duration);
int loc;
switch (this.Attribute)
{
default:
case AosWeaponAttribute.HitLightning: loc = 1060423; break;
case AosWeaponAttribute.HitFireball: loc = 1060420; break;
case AosWeaponAttribute.HitHarm: loc = 1060421; break;
case AosWeaponAttribute.HitMagicArrow: loc = 1060426; break;
case AosWeaponAttribute.HitDispel: loc = 1060417; break;
}
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Enchant, 1080126, loc, TimeSpan.FromSeconds(duration), Caster, value.ToString()));
Weapon.EnchantedWeilder = Caster;
Weapon.InvalidateProperties();
}
FinishSequence();
}
public static Dictionary<Mobile, EnchantmentTimer> Table { get; set; }
public static bool IsUnderSpellEffects(Mobile Caster, BaseWeapon wep)
{
if (Table == null)
return false;
return Table.ContainsKey(Caster) && Table[Caster].Weapon == wep;
}
public static AosWeaponAttribute BonusAttribute(Mobile from)
{
if (Table.ContainsKey(from))
return Table[from].WeaponAttribute;
return AosWeaponAttribute.HitColdArea;
}
public static int BonusValue(Mobile from)
{
if (Table.ContainsKey(from))
return Table[from].AttributeValue;
return 0;
}
public static bool CastingMalus(Mobile from, BaseWeapon weapon)
{
if (Table.ContainsKey(from))
return Table[from].CastingMalus > 0;
return false;
}
public static void RemoveEnchantment(Mobile caster)
{
if(Table != null && Table.ContainsKey(caster))
{
Table[caster].Stop();
Table[caster] = null;
Table.Remove(caster);
caster.SendLocalizedMessage(1115273); // The enchantment on your weapon has expired.
caster.PlaySound(0x1E6);
Enhancement.RemoveMobile(caster);
}
}
public static void OnWeaponRemoved(BaseWeapon wep, Mobile from)
{
if(IsUnderSpellEffects(from, wep))
RemoveEnchantment(from);
if (wep.EnchantedWeilder != null)
wep.EnchantedWeilder = null;
}
}
public class EnchantmentTimer : Timer
{
public Mobile Owner { get; set; }
public BaseWeapon Weapon { get; set; }
public AosWeaponAttribute WeaponAttribute { get; set; }
public int AttributeValue { get; set; }
public int CastingMalus { get; set; }
public EnchantmentTimer(Mobile owner, BaseWeapon wep, AosWeaponAttribute attribute, int value, int malus, double duration) : base(TimeSpan.FromSeconds(duration))
{
Owner = owner;
Weapon = wep;
WeaponAttribute = attribute;
AttributeValue = value;
CastingMalus = malus;
this.Start();
}
protected override void OnTick()
{
if(Weapon != null)
Weapon.EnchantedWeilder = null;
EnchantSpell.RemoveEnchantment(Owner);
}
}
}

View File

@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class HailStormSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Seventh; } }
public override bool DelayedDamage { get { return true; } }
public override DamageType SpellDamageType { get { return DamageType.SpellAOE; } }
private static SpellInfo m_Info = new SpellInfo(
"Hail Storm", "Kal Des Ylem",
230,
9022,
Reagent.BlackPearl,
Reagent.Bloodmoss,
Reagent.MandrakeRoot,
Reagent.DragonBlood
);
public HailStormSpell(Mobile caster, Item scroll)
: base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(IPoint3D p)
{
if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
{
SpellHelper.Turn(Caster, p);
SpellHelper.GetSurfaceTop(ref p);
Map map = Caster.Map;
if (map == null)
return;
Rectangle2D effectArea = new Rectangle2D(p.X - 3, p.Y - 3, 6, 6);
Effects.PlaySound(p, map, 0x64F);
for (int x = effectArea.X; x <= effectArea.X + effectArea.Width; x++)
{
for (int y = effectArea.Y; y <= effectArea.Y + effectArea.Height; y++)
{
if (x == effectArea.X && y == effectArea.Y ||
x >= effectArea.X + effectArea.Width - 1 && y >= effectArea.Y + effectArea.Height - 1 ||
y >= effectArea.Y + effectArea.Height - 1 && x == effectArea.X ||
y == effectArea.Y && x >= effectArea.X + effectArea.Width - 1)
continue;
IPoint3D pnt = new Point3D(x, y, p.Z);
SpellHelper.GetSurfaceTop(ref pnt);
Timer.DelayCall<Point3D>(TimeSpan.FromMilliseconds(Utility.RandomMinMax(100, 300)), point =>
{
Effects.SendLocationEffect(point, map, 0x3779, 12, 11, 0x63, 0);
},
new Point3D(pnt));
}
}
var list = AcquireIndirectTargets(p, 2).ToList();
int count = list.Count;
foreach (var id in list)
{
if (id.Deleted)
continue;
int damage = GetNewAosDamage(51, 1, 5, id is PlayerMobile, id);
if (count > 2)
damage = (damage * 2) / count;
Caster.DoHarmful(id);
SpellHelper.Damage(this, id, damage, 0, 0, 100, 0, 0);
Server.Effects.SendTargetParticles(id, 0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255, 0);
}
ColUtility.Free(list);
}
FinishSequence();
}
public class InternalTarget : Target
{
private HailStormSpell m_Owner;
public InternalTarget(HailStormSpell owner)
: base(10, true, TargetFlags.None)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D)
m_Owner.OnTarget((IPoint3D)o);
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class HealingStoneSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.First; } }
public override TimeSpan CastDelayBase { get { return TimeSpan.FromSeconds(5); } }
private static SpellInfo m_Info = new SpellInfo(
"Healing Stone", "Kal In Mani",
230,
9022,
Reagent.Bone,
Reagent.Garlic,
Reagent.Ginseng,
Reagent.SpidersSilk
);
public HealingStoneSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public override void OnCast()
{
if ( Caster.Backpack != null && CheckSequence() )
{
Item[] stones = Caster.Backpack.FindItemsByType( typeof( HealingStone ) );
for ( int i = 0; i < stones.Length; i++ )
stones[i].Delete();
int amount = (int)((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) * 1.5);
int maxHeal = (int)((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 5);
Caster.PlaySound( 0x650 );
Caster.FixedParticles(0x3779, 1, 15, 0x251E, 0, 0, EffectLayer.Waist);
Caster.Backpack.DropItem( new HealingStone( Caster, amount, maxHeal ) );
Caster.SendLocalizedMessage( 1080115 ); // A Healing Stone appears in your backpack.
}
FinishSequence();
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class MassSleepSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Fifth; } }
private static SpellInfo m_Info = new SpellInfo(
"Mass Sleep", "Vas Zu",
230,
9022,
Reagent.Ginseng,
Reagent.Nightshade,
Reagent.SpidersSilk
);
public MassSleepSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public class InternalTarget : Target
{
private MassSleepSpell m_Owner;
public InternalTarget(MassSleepSpell owner)
: base(10, true, TargetFlags.None)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D)
m_Owner.Target((IPoint3D)o);
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
public void Target(IPoint3D p)
{
if (!Caster.CanSee(p))
{
Caster.SendLocalizedMessage(500237); // Target can not be seen.
}
else if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
{
Map map = Caster.Map;
if (map == null)
return;
foreach (var m in AcquireIndirectTargets(p, 3).OfType<Mobile>())
{
double duration = ((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 20) + 3;
duration -= GetResistSkill(m) / 10;
if (duration > 0)
{
Caster.DoHarmful(m);
SleepSpell.DoSleep(Caster, m, TimeSpan.FromSeconds(duration));
}
}
}
FinishSequence();
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Spells.Fifth;
using Server.Spells.Seventh;
namespace Server.Spells.Mysticism
{
public abstract class MysticTransformationSpell : MysticSpell, ITransformationSpell
{
public abstract int Body{ get; }
public virtual int Hue{ get{ return 0; } }
public virtual int PhysResistOffset{ get{ return 0; } }
public virtual int FireResistOffset{ get{ return 0; } }
public virtual int ColdResistOffset{ get{ return 0; } }
public virtual int PoisResistOffset{ get{ return 0; } }
public virtual int NrgyResistOffset{ get{ return 0; } }
public MysticTransformationSpell( Mobile caster, Item scroll, SpellInfo info ) : base( caster, scroll, info )
{
}
public override bool BlockedByHorrificBeast{ get{ return false; } }
public override bool CheckCast()
{
if( !TransformationSpellHelper.CheckCast( Caster, this ) )
return false;
return base.CheckCast();
}
public override void OnCast()
{
TransformationSpellHelper.OnCast( Caster, this );
FinishSequence();
}
public virtual double TickRate{ get{ return 1.0; } }
public virtual void OnTick( Mobile m )
{
}
public virtual void DoEffect( Mobile m )
{
}
public virtual void RemoveEffect( Mobile m )
{
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class NetherBoltSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.First; } }
private static SpellInfo m_Info = new SpellInfo(
"Nether Bolt", "In Corp Ylem",
230,
9022,
Reagent.BlackPearl,
Reagent.SulfurousAsh
);
public NetherBoltSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override bool DelayedDamage { get { return true; } }
public override bool DelayedDamageStacking { get { return false; } }
public override Type[] DelayDamageFamily { get { return new Type[] { typeof(Server.Spells.First.MagicArrowSpell) }; } }
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(IDamageable d)
{
if (d == null)
{
return;
}
else if (CheckHSequence(d))
{
IDamageable target = d;
IDamageable source = Caster;
SpellHelper.Turn(Caster, target);
if (Core.SA && HasDelayContext(target))
{
DoHurtFizzle();
return;
}
if (SpellHelper.CheckReflect((int)Circle, ref source, ref target))
{
Timer.DelayCall(TimeSpan.FromSeconds(.5), () =>
{
source.MovingParticles(target, 0x36D4, 7, 0, false, true, 0x49A, 0, 0, 9502, 4019, 0x160);
source.PlaySound(0x211);
});
}
double damage = GetNewAosDamage(10, 1, 4, target);
SpellHelper.Damage(this, target, damage, 0, 0, 0, 0, 0, 100, 0);
Caster.MovingParticles(d, 0x36D4, 7, 0, false, true, 0x49A, 0, 0, 9502, 4019, 0x160);
Caster.PlaySound(0x211);
}
FinishSequence();
}
public class InternalTarget : Target
{
public NetherBoltSpell Owner { get; set; }
public InternalTarget(NetherBoltSpell owner)
: this(owner, false)
{
}
public InternalTarget(NetherBoltSpell 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 if (o is IDamageable)
{
SpellHelper.Turn(from, o);
Owner.OnTarget((IDamageable)o);
}
}
protected override void OnTargetFinish(Mobile from)
{
Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class NetherCycloneSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Eighth; } }
public override DamageType SpellDamageType { get { return DamageType.SpellAOE; } }
private static SpellInfo m_Info = new SpellInfo(
"Nether Cyclone", "Grav Hur",
230,
9022,
Reagent.MandrakeRoot,
Reagent.Nightshade,
Reagent.SulfurousAsh,
Reagent.Bloodmoss
);
public NetherCycloneSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(IPoint3D p)
{
if (p != null && CheckSequence())
{
SpellHelper.Turn(Caster, p);
SpellHelper.GetSurfaceTop(ref p);
Map map = Caster.Map;
if (map != null)
{
Rectangle2D effectArea = new Rectangle2D(p.X - 3, p.Y - 3, 6, 6);
Effects.PlaySound(p, map, 0x64F);
for (int x = effectArea.X; x <= effectArea.X + effectArea.Width; x++)
{
for (int y = effectArea.Y; y <= effectArea.Y + effectArea.Height; y++)
{
if (x == effectArea.X && y == effectArea.Y ||
x >= effectArea.X + effectArea.Width - 1 && y >= effectArea.Y + effectArea.Height - 1 ||
y >= effectArea.Y + effectArea.Height - 1 && x == effectArea.X ||
y == effectArea.Y && x >= effectArea.X + effectArea.Width - 1)
continue;
IPoint3D pnt = new Point3D(x, y, p.Z);
SpellHelper.GetSurfaceTop(ref pnt);
Timer.DelayCall<Point3D>(TimeSpan.FromMilliseconds(Utility.RandomMinMax(100, 300)), point =>
{
Effects.SendLocationEffect(point, map, 0x375A, 8, 11, 0x49A, 0);
},
new Point3D(pnt));
}
}
foreach(var d in AcquireIndirectTargets(p, 3))
{
Server.Effects.SendTargetParticles(d, 0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255, 0);
double damage = (((Caster.Skills[CastSkill].Value + (Caster.Skills[DamageSkill].Value / 2)) * .66) + Utility.RandomMinMax(1, 6));
SpellHelper.Damage(this, d, damage, 0, 0, 0, 0, 0, 100, 0);
if (d is Mobile)
{
Mobile m = d as Mobile;
double stamSap = (damage / 3);
double manaSap = (damage / 3);
double mod = m.Skills[SkillName.MagicResist].Value - ((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 2);
if (mod > 0)
{
mod /= 100;
stamSap *= mod;
manaSap *= mod;
}
m.Stam -= (int)stamSap;
m.Mana -= (int)manaSap;
Timer.DelayCall(TimeSpan.FromSeconds(10), () =>
{
if (m.Alive)
{
m.Stam += (int)stamSap;
m.Mana += (int)manaSap;
}
});
}
Effects.SendLocationParticles(EffectItem.Create(d.Location, map, EffectItem.DefaultDuration), 0x37CC, 1, 40, 97, 3, 9917, 0);
}
}
}
FinishSequence();
}
public class InternalTarget : Target
{
public NetherCycloneSpell Owner { get; set; }
public InternalTarget(NetherCycloneSpell owner)
: this(owner, false)
{
}
public InternalTarget(NetherCycloneSpell owner, bool allowland)
: base(12, allowland, TargetFlags.None)
{
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 if(o is IPoint3D)
{
SpellHelper.Turn(from, o);
Owner.OnTarget((IPoint3D)o);
}
}
protected override void OnTargetFinish(Mobile from)
{
Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,342 @@
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
using System.Collections.Generic;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Third;
using Server.Spells.Fourth;
using Server.Spells.Fifth;
using Server.Spells.Ninjitsu;
namespace Server.Spells.Mysticism
{
public enum BuffType
{
None,
MagicReflect,
ReactiveArmor,
Protection,
Transformation,
StrBonus,
DexBonus,
IntBonus,
BarrabHemolymph,
UraliTrance,
Bless
}
public class PurgeMagicSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Second; } }
private static SpellInfo m_Info = new SpellInfo(
"Purge", "An Ort Sanct ",
230,
9022,
Reagent.Garlic,
Reagent.MandrakeRoot,
Reagent.SulfurousAsh,
Reagent.FertileDirt
);
public PurgeMagicSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(object o)
{
Mobile target = o as Mobile;
if (target == null)
return;
if (m_CurseTable.ContainsKey(Caster))
{
Caster.SendLocalizedMessage(1154212); //You may not use the Purge Magic spell while you are under its curse.
}
else if (m_ImmuneTable.ContainsKey(target) || m_CurseTable.ContainsKey(target))
{
Caster.SendLocalizedMessage(1080119); // Your Purge Magic has been resisted!
}
else if (CheckHSequence(target))
{
if (CheckResisted(target))
{
target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy.
Caster.SendLocalizedMessage(1080119); //Your Purge Magic has been resisted!
}
else
{
SpellHelper.CheckReflect((int)Circle, Caster, ref target);
Caster.PlaySound(0x655);
Effects.SendLocationParticles(EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 1, 13, 0x834, 0, 0x13B2, 0);
BuffType type = GetRandomBuff(target);
if (type != BuffType.None)
{
string arg = "";
switch (type)
{
case BuffType.MagicReflect:
MagicReflectSpell.EndReflect(target);
arg = "magic reflect";
break;
case BuffType.ReactiveArmor:
ReactiveArmorSpell.EndArmor(target);
arg = "reactive armor";
break;
case BuffType.Protection:
ProtectionSpell.EndProtection(target);
arg = "protection";
break;
case BuffType.Transformation:
TransformationSpellHelper.RemoveContext(target, true);
arg = "transformation spell";
break;
case BuffType.StrBonus:
arg = "strength bonus";
target.RemoveStatMod("[Magic] Str Buff");
BuffInfo.RemoveBuff(target, BuffIcon.Strength);
break;
case BuffType.DexBonus:
arg = "dexterity bonus";
target.RemoveStatMod("[Magic] Dex Buff");
BuffInfo.RemoveBuff(target, BuffIcon.Agility);
break;
case BuffType.IntBonus:
arg = "intelligence bonus";
target.RemoveStatMod("[Magic] Int Buff");
BuffInfo.RemoveBuff(target, BuffIcon.Cunning);
break;
case BuffType.BarrabHemolymph:
arg = "Barrab hemolymph";
EodonianPotion.RemoveEffects(target, PotionEffect.Barrab);
break;
case BuffType.UraliTrance:
arg = "Urali Trance";
EodonianPotion.RemoveEffects(target, PotionEffect.Urali);
break;
case BuffType.Bless:
arg = "bless";
target.RemoveStatMod("[Magic] Str Buff");
target.RemoveStatMod("[Magic] Dex Buff");
target.RemoveStatMod("[Magic] Int Buff");
BuffInfo.RemoveBuff(target, BuffIcon.Bless);
BlessSpell.RemoveBless(target);
break;
}
target.SendLocalizedMessage(1080117, arg); //Your ~1_ABILITY_NAME~ has been purged.
Caster.SendLocalizedMessage(1080118, arg); //Your target's ~1_ABILITY_NAME~ has been purged.
int duration = (int)((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 15);
if (duration <= 0)
duration = 1;
m_ImmuneTable.Add(target, new ImmuneTimer(target, TimeSpan.FromSeconds(duration)));
}
else
{
Caster.SendLocalizedMessage(1080120); //Your target has no magic that can be purged.
int duration = (int)((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 28);
if (duration <= 0)
duration = 1;
m_CurseTable.Add(target, new CurseTimer(target, Caster, TimeSpan.FromSeconds(duration)));
}
}
}
FinishSequence();
}
public BuffType GetRandomBuff(Mobile target)
{
List<BuffType> buffs = new List<BuffType>();
if (MagicReflectSpell.HasReflect(target))
buffs.Add(BuffType.MagicReflect);
if (ReactiveArmorSpell.HasArmor(target))
buffs.Add(BuffType.ReactiveArmor);
if (ProtectionSpell.HasProtection(target))
buffs.Add(BuffType.Protection);
TransformContext context = TransformationSpellHelper.GetContext(target);
if (context != null && context.Type != typeof(AnimalForm))
buffs.Add(BuffType.Transformation);
if (BlessSpell.IsBlessed(target))
{
buffs.Add(BuffType.Bless);
}
else
{
StatMod mod = target.GetStatMod("[Magic] Str Buff");
if (mod != null)
buffs.Add(BuffType.StrBonus);
mod = target.GetStatMod("[Magic] Dex Buff");
if (mod != null)
buffs.Add(BuffType.DexBonus);
mod = target.GetStatMod("[Magic] Int Buff");
if (mod != null)
buffs.Add(BuffType.IntBonus);
}
if (EodonianPotion.IsUnderEffects(target, PotionEffect.Barrab))
buffs.Add(BuffType.BarrabHemolymph);
if (EodonianPotion.IsUnderEffects(target, PotionEffect.Urali))
buffs.Add(BuffType.UraliTrance);
if (buffs.Count == 0)
return BuffType.None;
BuffType type = buffs[Utility.Random(buffs.Count)];
buffs.Clear();
return type;
}
private static Dictionary<Mobile, ImmuneTimer> m_ImmuneTable = new Dictionary<Mobile, ImmuneTimer>();
private static Dictionary<Mobile, CurseTimer> m_CurseTable = new Dictionary<Mobile, CurseTimer>();
public static void RemoveImmunity(Mobile from)
{
if (m_ImmuneTable.ContainsKey(from))
{
m_ImmuneTable[from].Stop();
m_ImmuneTable.Remove(from);
}
}
public static void RemoveCurse(Mobile from, Mobile caster)
{
if (m_CurseTable.ContainsKey(from))
{
m_CurseTable[from].Stop();
if (DateTime.UtcNow > m_CurseTable[from].StartTime)
{
TimeSpan inEffect = DateTime.UtcNow - m_CurseTable[from].StartTime;
int damage = 5 * (int)inEffect.TotalSeconds;
from.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
from.PlaySound(0x307);
m_CurseTable.Remove(from);
AOS.Damage(from, caster, damage, 0, 0, 0, 0, 0, 100, 0);
}
}
m_ImmuneTable[from] = new ImmuneTimer(from, TimeSpan.FromSeconds(16));
}
public static void OnMobileDoDamage(Mobile from)
{
if (from != null && m_CurseTable.ContainsKey(from))
RemoveCurse(from, m_CurseTable[from].Caster);
}
public static bool IsUnderCurseEffects(Mobile from)
{
return m_CurseTable.ContainsKey(from);
}
private class ImmuneTimer : Timer
{
private Mobile m_Mobile;
public ImmuneTimer(Mobile mob, TimeSpan duration) : base(duration)
{
m_Mobile = mob;
Start();
}
protected override void OnTick()
{
PurgeMagicSpell.RemoveImmunity(m_Mobile);
}
}
private class CurseTimer : Timer
{
private Mobile m_Mobile;
private Mobile m_Caster;
private DateTime m_StartTime;
public DateTime StartTime { get { return m_StartTime; } }
public Mobile Caster { get { return m_Caster; } }
public CurseTimer(Mobile mob, Mobile caster, TimeSpan duration)
: base(duration)
{
m_Mobile = mob;
m_Caster = caster;
m_StartTime = DateTime.UtcNow;
Start();
}
protected override void OnTick()
{
PurgeMagicSpell.RemoveCurse(m_Mobile, m_Caster);
}
}
public class InternalTarget : Target
{
public PurgeMagicSpell Owner { get; set; }
public InternalTarget(PurgeMagicSpell owner)
: this(owner, false)
{
}
public InternalTarget(PurgeMagicSpell 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();
}
}
}
}

View File

@@ -0,0 +1,89 @@
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Spells;
using Server.Targeting;
namespace Server.Spells.Mysticism
{
public class RisingColossusSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Eighth; } }
private static SpellInfo m_Info = new SpellInfo(
"Rising Colossus", "Kal Vas Xen Corp Ylem",
230,
9022,
Reagent.DaemonBone,
Reagent.DragonBlood,
Reagent.FertileDirt,
Reagent.Nightshade
);
public RisingColossusSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void Target(IPoint3D p)
{
if ((Caster.Followers + 5) > Caster.FollowersMax)
{
Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature.
return;
}
Map map = Caster.Map;
SpellHelper.GetSurfaceTop(ref p);
if (map == null || (Caster.IsPlayer() && !map.CanSpawnMobile(p.X, p.Y, p.Z)))
{
Caster.SendLocalizedMessage(501942); // That location is blocked.
}
else if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
{
double baseskill = Caster.Skills[SkillName.Mysticism].Value;
double boostskill = GetBoostSkill(Caster);
int level = (int)(baseskill + boostskill);
TimeSpan duration = TimeSpan.FromSeconds(level / 3);
BaseCreature summon = new RisingColossus(Caster, baseskill, boostskill);
BaseCreature.Summon(summon, false, Caster, new Point3D(p), 0x656, duration);
Effects.SendTargetParticles(summon, 0x3728, 10, 10, 0x13AA, (EffectLayer)255);
}
FinishSequence();
}
public class InternalTarget : Target
{
private RisingColossusSpell m_Owner;
public InternalTarget(RisingColossusSpell owner)
: base(12, true, TargetFlags.None)
{
m_Owner = owner;
}
protected override void OnTarget(Mobile from, object o)
{
if (o is IPoint3D)
m_Owner.Target((IPoint3D)o);
}
protected override void OnTargetFinish(Mobile from)
{
m_Owner.FinishSequence();
}
}
}
}

View File

@@ -0,0 +1,190 @@
using System;
using Server;
using Server.Targeting;
using System.Collections.Generic;
using Server.Network;
namespace Server.Spells.Mysticism
{
public class SleepSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Third; } }
private static SpellInfo m_Info = new SpellInfo(
"Sleep", "In Zu",
230,
9022,
Reagent.Nightshade,
Reagent.SpidersSilk,
Reagent.BlackPearl
);
public SleepSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
{
}
public override void OnCast()
{
Caster.Target = new InternalTarget(this);
}
public void OnTarget(object o)
{
Mobile target = o as Mobile;
if (target == null)
{
return;
}
else if (target.Paralyzed)
{
Caster.SendLocalizedMessage(1080134); //Your target is already immobilized and cannot be slept.
}
else if (m_ImmunityList.Contains(target))
{
Caster.SendLocalizedMessage(1080135); //Your target cannot be put to sleep.
}
else if (CheckHSequence(target))
{
SpellHelper.CheckReflect((int)Circle, Caster, ref target);
double duration = ((Caster.Skills[CastSkill].Value + Caster.Skills[DamageSkill].Value) / 20) + 2;
duration -= GetResistSkill(target) / 10;
if (duration <= 0 || StoneFormSpell.CheckImmunity(target))
{
Caster.SendLocalizedMessage(1080136); //Your target resists sleep.
target.SendLocalizedMessage(1080137); //You resist sleep.
}
else
DoSleep(Caster, target, TimeSpan.FromSeconds(duration));
}
FinishSequence();
}
private static Dictionary<Mobile, SleepTimer> m_Table = new Dictionary<Mobile, SleepTimer>();
private static List<Mobile> m_ImmunityList = new List<Mobile>();
public static void DoSleep(Mobile caster, Mobile target, TimeSpan duration)
{
target.Combatant = null;
target.SendSpeedControl(SpeedControlType.WalkSpeed);
if (m_Table.ContainsKey(target))
m_Table[target].Stop();
m_Table[target] = new SleepTimer(target, duration);
BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Sleep, 1080139, 1080140, duration, target));
target.Delta(MobileDelta.WeaponDamage);
}
public static void AddToSleepTable(Mobile from, TimeSpan duration)
{
m_Table.Add(from, new SleepTimer(from, duration));
}
public static bool IsUnderSleepEffects(Mobile from)
{
return m_Table.ContainsKey(from);
}
public static void OnDamage(Mobile from)
{
if (m_Table.ContainsKey(from))
EndSleep(from);
}
public class SleepTimer : Timer
{
private Mobile m_Target;
private DateTime m_EndTime;
public SleepTimer(Mobile target, TimeSpan duration)
: base(TimeSpan.Zero, TimeSpan.FromSeconds(0.5))
{
m_EndTime = DateTime.UtcNow + duration;
m_Target = target;
Start();
}
protected override void OnTick()
{
if (m_EndTime < DateTime.UtcNow)
{
EndSleep(m_Target);
Stop();
}
else
{
Effects.SendTargetParticles(m_Target, 0x3779, 1, 32, 0x13BA, EffectLayer.Head);
}
}
}
public static void EndSleep(Mobile target)
{
if (m_Table.ContainsKey(target))
{
target.SendSpeedControl(SpeedControlType.Disable);
m_Table[target].Stop();
m_Table.Remove(target);
BuffInfo.RemoveBuff(target, BuffIcon.Sleep);
double immduration = target.Skills[SkillName.MagicResist].Value / 10;
m_ImmunityList.Add(target);
Timer.DelayCall(TimeSpan.FromSeconds(immduration), new TimerStateCallback(RemoveImmunity_Callback), target);
target.Delta(MobileDelta.WeaponDamage);
}
}
public static void RemoveImmunity_Callback(object state)
{
Mobile m = (Mobile)state;
if (m_ImmunityList.Contains(m))
m_ImmunityList.Remove(m);
}
public class InternalTarget : Target
{
public SleepSpell Owner { get; set; }
public InternalTarget(SleepSpell owner)
: this(owner, false)
{
}
public InternalTarget(SleepSpell 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();
}
}
}
}

View File

@@ -0,0 +1,253 @@
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<SpellPlagueTimer>());
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<Mobile, List<SpellPlagueTimer>> m_Table = new Dictionary<Mobile, List<SpellPlagueTimer>>();
public static bool HasSpellPlague(Mobile from)
{
foreach (KeyValuePair<Mobile, List<SpellPlagueTimer>> 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<Mobile, List<SpellPlagueTimer>> 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);
}
}
}

View File

@@ -0,0 +1,307 @@
using System;
using Server.Gumps;
using Server.Items;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Network;
namespace Server.Spells.Mysticism
{
public class SpellTriggerSpell : MysticSpell
{
public override SpellCircle Circle { get { return SpellCircle.Fifth; } }
private static SpellInfo m_Info = new SpellInfo(
"Spell Trigger", "In Vas Ort Ex ",
230,
9022,
Reagent.Garlic,
Reagent.MandrakeRoot,
Reagent.SpidersSilk,
Reagent.DragonBlood
);
public SpellTriggerSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public override void OnCast()
{
if (Caster.HasGump(typeof(SpellTriggerGump)))
Caster.CloseGump(typeof(SpellTriggerGump));
var gump = new SpellTriggerGump(this, Caster);
int serial = gump.Serial;
Caster.SendGump(gump);
Timer.DelayCall(TimeSpan.FromSeconds(30), () =>
{
var current = Caster.FindGump(typeof(SpellTriggerGump));
if (current != null && current.Serial == serial)
{
Caster.CloseGump(typeof(EnchantSpellGump));
FinishSequence();
}
});
}
private class SpellTriggerGump : Gump
{
private Spell m_Spell;
private int m_Skill;
public SpellTriggerGump(Spell spell, Mobile m)
: base(60, 36)
{
m_Spell = spell;
AddPage(0);
AddBackground(0, 0, 520, 404, 0x13BE);
AddImageTiled(10, 10, 500, 20, 0xA40);
AddImageTiled(10, 40, 500, 324, 0xA40);
AddImageTiled(10, 374, 500, 20, 0xA40);
AddAlphaRegion(10, 10, 500, 384);
AddButton(10, 374, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(45, 376, 450, 20, 1060051, 0x7FFF, false, false); // CANCEL
AddHtmlLocalized(14, 12, 500, 20, 1080151, 0x7FFF, false, false); // <center>Spell Trigger Selection Menu</center>
AddPage(1);
m_Skill = (int)(GetBaseSkill(m) + GetBoostSkill(m));
int idx = 0;
for (int i = 0; i < m_Definitions.Length; i++)
{
SpellTriggerDef entry = m_Definitions[i];
if (m_Skill >= (entry.Rank * 40))
{
idx++;
if (idx == 11)
{
AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 2);
AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF, false, false); // Next
AddPage(2);
AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1);
AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF, false, false); // Back
idx = 1;
}
if ((idx % 2) != 0)
{
AddImageTiledButton(14, 44 + (64 * (idx - 1) / 2), 0x918, 0x919, 100 + i, GumpButtonType.Reply, 0, entry.ItemId, 0, 15, 20);
AddTooltip(entry.Tooltip);
AddHtmlLocalized(98, 44 + (64 * (idx - 1) / 2), 170, 60, entry.Cliloc, 0x7FFF, false, false);
}
else
{
AddImageTiledButton(264, 44 + (64 * (idx - 2) / 2), 0x918, 0x919, 100 + i, GumpButtonType.Reply, 0, entry.ItemId, 0, 15, 20);
AddTooltip(entry.Tooltip);
AddHtmlLocalized(348, 44 + (64 * (idx - 2) / 2), 170, 60, entry.Cliloc, 0x7FFF, false, false);
}
}
else
{
break;
}
}
}
public override void OnResponse(NetState sender, RelayInfo info)
{
Mobile from = sender.Mobile;
if (from.Backpack != null && info.ButtonID >= 100 && info.ButtonID <= 110 && m_Spell.CheckSequence())
{
Item[] stones = from.Backpack.FindItemsByType(typeof(SpellStone));
for (int i = 0; i < stones.Length; i++)
stones[i].Delete();
SpellTriggerDef entry = m_Definitions[info.ButtonID - 100];
if (m_Skill >= (entry.Rank * 40))
{
from.PlaySound(0x659);
from.PlaceInBackpack(new SpellStone(entry));
from.SendLocalizedMessage(1080165); // A Spell Stone appears in your backpack
}
}
m_Spell.FinishSequence();
}
}
private static SpellTriggerDef[] m_Definitions = new SpellTriggerDef[]
{
new SpellTriggerDef( 677, "Nether Bolt", 1, 1031678, 1095193, 0x2D9E ),
new SpellTriggerDef( 678, "Healing Stone", 1, 1031679, 1095194, 0x2D9F ),
new SpellTriggerDef( 679, "Purge Magic", 2, 1031680, 1095195, 0x2DA0 ),
new SpellTriggerDef( 680, "Enchant", 2, 1031681, 1095196, 0x2DA1 ),
new SpellTriggerDef( 681, "Sleep", 3, 1031682, 1095197, 0x2DA2 ),
new SpellTriggerDef( 682, "Eagle Strike", 3, 1031683, 1095198, 0x2DA3 ),
new SpellTriggerDef( 683, "Animated Weapon", 4, 1031684, 1095199, 0x2DA4 ),
new SpellTriggerDef( 684, "Stone Form", 4, 1031685, 1095200, 0x2DA5 ),
new SpellTriggerDef( 686, "Mass Sleep", 5, 1031687, 1095202, 0x2DA7 ),
new SpellTriggerDef( 687, "Cleansing Winds", 6, 1031688, 1095203, 0x2DA8 ),
new SpellTriggerDef( 688, "Bombard", 6, 1031689, 1095204, 0x2DA9 )
};
public static SpellTriggerDef[] Definitions { get { return m_Definitions; } }
}
public class SpellTriggerDef
{
private int m_SpellId;
private string m_Name;
private int m_Rank;
private int m_Cliloc;
private int m_Tooltip;
private int m_ItemId;
public int SpellId { get { return m_SpellId; } }
public string Name { get { return m_Name; } }
public int Rank { get { return m_Rank; } }
public int Cliloc { get { return m_Cliloc; } }
public int Tooltip { get { return m_Tooltip; } }
public int ItemId { get { return m_ItemId; } }
public SpellTriggerDef(int spellId, string name, int rank, int cliloc, int tooltip, int itemId)
{
m_SpellId = spellId;
m_Name = name;
m_Rank = rank;
m_Cliloc = cliloc;
m_Tooltip = tooltip;
m_ItemId = itemId;
}
}
public class SpellStone : SpellScroll
{
private SpellTriggerDef m_SpellDef;
public override bool Nontransferable { get { return true; } }
[Constructable]
public SpellStone(SpellTriggerDef spellDef)
: base(spellDef.SpellId, 0x4079, 1)
{
this.m_SpellDef = spellDef;
this.LootType = LootType.Blessed;
}
public override bool DropToWorld(Mobile from, Point3D p)
{
this.Delete();
return false;
}
public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
{
return false;
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
}
private static Dictionary<Mobile, DateTime> m_CooldownTable = new Dictionary<Mobile, DateTime>();
public override void OnDoubleClick(Mobile from)
{
if (m_CooldownTable.ContainsKey(from))
{
DateTime next = m_CooldownTable[from];
int seconds = (int)(next - DateTime.UtcNow).TotalSeconds + 1;
// You must wait ~1_seconds~ seconds before you can use this item.
from.SendLocalizedMessage(1079263, seconds.ToString());
return;
}
base.OnDoubleClick(from);
}
public void Use(Mobile from)
{
m_CooldownTable[from] = DateTime.UtcNow + TimeSpan.FromSeconds(300.0);
Timer.DelayCall(TimeSpan.FromSeconds(300.0), new TimerCallback(
delegate
{
m_CooldownTable.Remove(from);
}));
Delete();
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1080166, m_SpellDef.Name); // Use: ~1_spellName~
}
public SpellStone(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1);
writer.Write((int)m_SpellDef.SpellId);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
{
int spellId = reader.ReadInt();
for (int i = 0; i < SpellTriggerSpell.Definitions.Length; i++)
{
SpellTriggerDef def = SpellTriggerSpell.Definitions[i];
if (def.SpellId == spellId)
{
m_SpellDef = def;
break;
}
}
if (m_SpellDef == null)
Delete();
break;
}
case 0:
{
Delete();
break;
}
}
}
}
}

View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using Server.Network;
namespace Server.Spells.Mysticism
{
public class StoneFormSpell : MysticTransformationSpell
{
private static HashSet<Mobile> m_Effected = new HashSet<Mobile>();
public static bool IsEffected(Mobile m)
{
return m_Effected.Contains(m);
}
private static SpellInfo m_Info = new SpellInfo(
"Stone Form", "In Rel Ylem",
230,
9022,
Reagent.Bloodmoss,
Reagent.FertileDirt,
Reagent.Garlic
);
private int m_ResisMod;
public override SpellCircle Circle { get { return SpellCircle.Fourth; } }
public override TimeSpan CastDelayBase { get { return TimeSpan.FromSeconds( 2.0 ); } }
public override int Body{ get{ return 705; } }
public override int PhysResistOffset { get { return m_ResisMod; } }
public override int FireResistOffset { get { return m_ResisMod; } }
public override int ColdResistOffset { get { return m_ResisMod; } }
public override int PoisResistOffset { get { return m_ResisMod; } }
public override int NrgyResistOffset { get { return m_ResisMod; } }
public StoneFormSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
{
}
public override bool CheckCast()
{
bool doCast = base.CheckCast();
if (doCast && Caster.Flying)
{
Caster.SendLocalizedMessage(1112567); // You are flying.
doCast = false;
}
if (doCast)
m_ResisMod = GetResBonus(Caster);
return doCast;
}
public override void DoEffect( Mobile m )
{
m.PlaySound( 0x65A );
m.FixedParticles( 0x3728, 1, 13, 9918, 92, 3, EffectLayer.Head );
Timer.DelayCall(new TimerCallback(MobileDelta_Callback));
m_Effected.Add(m);
if (!Core.HS)
{
m.SendSpeedControl(SpeedControlType.WalkSpeed);
}
string args = String.Format("{0}\t{1}\t{2}\t{3}\t{4}", "-10", "-2", GetResBonus(m).ToString(), GetMaxResistance(m).ToString(), GetDamBonus(m).ToString());
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.StoneForm, 1080145, 1080146, args));
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.PoisonImmunity, 1153785, 1153814));
}
public void MobileDelta_Callback()
{
Caster.Delta(MobileDelta.WeaponDamage);
Caster.UpdateResistances();
}
public override void RemoveEffect( Mobile m )
{
if (!Core.HS)
{
m.SendSpeedControl(SpeedControlType.Disable);
}
m.Delta( MobileDelta.WeaponDamage );
m_Effected.Remove(m);
BuffInfo.RemoveBuff(m, BuffIcon.StoneForm);
BuffInfo.RemoveBuff(m, BuffIcon.PoisonImmunity);
}
public static void Initialize()
{
if (!Core.HS)
{
EventSink.Login += new LoginEventHandler(OnLogin);
}
}
public static void OnLogin(LoginEventArgs e)
{
TransformContext context = TransformationSpellHelper.GetContext(e.Mobile);
if (context != null && context.Type == typeof(StoneFormSpell))
e.Mobile.SendSpeedControl(SpeedControlType.WalkSpeed);
}
public static int GetMaxResistBonus(Mobile m)
{
if (TransformationSpellHelper.UnderTransformation(m, typeof(StoneFormSpell)))
{
return GetMaxResistance(m);
}
return 0;
}
public static int GetResistanceBonus(Mobile m)
{
if (TransformationSpellHelper.UnderTransformation(m, typeof(StoneFormSpell)))
{
return GetResBonus(m);
}
return 0;
}
public static int GetDamageBonus(Mobile m)
{
if (TransformationSpellHelper.UnderTransformation(m, typeof(StoneFormSpell)))
{
return GetDamBonus(m);
}
return 0;
}
public static double StatOffsetReduction(Mobile caster, Mobile m)
{
if (TransformationSpellHelper.UnderTransformation(m, typeof(StoneFormSpell)))
{
int prim = (int)m.Skills[SkillName.Mysticism].Value;
int sec = (int)m.Skills[SkillName.Imbuing].Value;
if (m.Skills[SkillName.Focus].Value > sec)
sec = (int)m.Skills[SkillName.Focus].Value;
caster.SendLocalizedMessage(1080192); // Your target resists your ability reduction magic.
return (double)(prim + sec) / 480;
}
return 1.0;
}
private static int GetResBonus(Mobile m)
{
int prim = (int)m.Skills[SkillName.Mysticism].Value;
int sec = (int)m.Skills[SkillName.Imbuing].Value;
if (m.Skills[SkillName.Focus].Value > sec)
sec = (int)m.Skills[SkillName.Focus].Value;
return Math.Max(2, (prim + sec) / 24);
}
private static int GetMaxResistance(Mobile m)
{
if (Server.Items.BaseArmor.HasRefinedResist(m))
return 0;
int prim = (int)m.Skills[SkillName.Mysticism].Value;
int sec = (int)m.Skills[SkillName.Imbuing].Value;
if (m.Skills[SkillName.Focus].Value > sec)
sec = (int)m.Skills[SkillName.Focus].Value;
return Math.Max(2, (prim + sec) / 48);
}
private static int GetDamBonus(Mobile m)
{
int prim = (int)m.Skills[SkillName.Mysticism].Value;
int sec = (int)m.Skills[SkillName.Imbuing].Value;
if (m.Skills[SkillName.Focus].Value > sec)
sec = (int)m.Skills[SkillName.Focus].Value;
return Math.Max(0, (prim + sec) / 12);
}
public static bool CheckImmunity(Mobile from)
{
if (TransformationSpellHelper.UnderTransformation(from, typeof(StoneFormSpell)))
{
int prim = (int)from.Skills[SkillName.Mysticism].Value;
int sec = (int)from.Skills[SkillName.Imbuing].Value;
if (from.Skills[SkillName.Focus].Value > sec)
sec = (int)from.Skills[SkillName.Focus].Value;
int immunity = (int)(((double)(prim + sec) / 480) * 100);
if (Server.Spells.Necromancy.EvilOmenSpell.TryEndEffect(from))
immunity -= 30;
return immunity > Utility.Random(100);
}
return false;
}
}
}