Fixes code according to modern code style. Fixes a few expression bugs.
This commit is contained in:
parent
89eea25e5f
commit
970fd563b2
3324 changed files with 441118 additions and 433755 deletions
|
|
@ -5,161 +5,164 @@ using Server.Mobiles;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class ArcaneCircleSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Arcane Circle", "Myrshalee",
|
||||
-1
|
||||
);
|
||||
public class ArcaneCircleSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Arcane Circle", "Myrshalee",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 0.5 );
|
||||
public ArcaneCircleSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5);
|
||||
|
||||
public ArcaneCircleSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( !IsValidLocation( Caster.Location, Caster.Map ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1072705 ); // You must be standing on an arcane circle, pentagram or abbatoir to use this spell.
|
||||
return false;
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (!IsValidLocation(Caster.Location, Caster.Map))
|
||||
{
|
||||
Caster.SendLocalizedMessage(
|
||||
1072705); // You must be standing on an arcane circle, pentagram or abbatoir to use this spell.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( GetArcanists().Count < 2 )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1080452 ); //There are not enough spellweavers present to create an Arcane Focus.
|
||||
return false;
|
||||
}
|
||||
if (GetArcanists().Count < 2)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1080452); //There are not enough spellweavers present to create an Arcane Focus.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( CheckSequence() )
|
||||
{
|
||||
Caster.FixedParticles( 0x3779, 10, 20, 0x0, EffectLayer.Waist );
|
||||
Caster.PlaySound( 0x5C0 );
|
||||
public override void OnCast()
|
||||
{
|
||||
if (CheckSequence())
|
||||
{
|
||||
Caster.FixedParticles(0x3779, 10, 20, 0x0, EffectLayer.Waist);
|
||||
Caster.PlaySound(0x5C0);
|
||||
|
||||
List<Mobile> Arcanists = GetArcanists();
|
||||
List<Mobile> Arcanists = GetArcanists();
|
||||
|
||||
TimeSpan duration = TimeSpan.FromHours( Math.Max( 1, (int)(Caster.Skills.Spellweaving.Value / 24) ) );
|
||||
TimeSpan duration = TimeSpan.FromHours(Math.Max(1, (int)(Caster.Skills.Spellweaving.Value / 24)));
|
||||
|
||||
int strengthBonus = Math.Min( Arcanists.Count, IsSanctuary( Caster.Location, Caster.Map ) ? 6 : 5 ); //The Sanctuary is a special, single location place
|
||||
int strengthBonus =
|
||||
Math.Min(Arcanists.Count,
|
||||
IsSanctuary(Caster.Location, Caster.Map)
|
||||
? 6
|
||||
: 5); //The Sanctuary is a special, single location place
|
||||
|
||||
for( int i = 0; i < Arcanists.Count; i++ )
|
||||
GiveArcaneFocus( Arcanists[i], duration, strengthBonus );
|
||||
}
|
||||
for (int i = 0; i < Arcanists.Count; i++)
|
||||
GiveArcaneFocus(Arcanists[i], duration, strengthBonus);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private static bool IsSanctuary( Point3D p, Map m )
|
||||
{
|
||||
return (m == Map.Trammel || m == Map.Felucca) && p.X == 6267 && p.Y == 131;
|
||||
}
|
||||
private static bool IsSanctuary(Point3D p, Map m)
|
||||
{
|
||||
return (m == Map.Trammel || m == Map.Felucca) && p.X == 6267 && p.Y == 131;
|
||||
}
|
||||
|
||||
private static bool IsValidLocation( Point3D location, Map map )
|
||||
{
|
||||
LandTile lt = map.Tiles.GetLandTile( location.X, location.Y ); // Land Tiles
|
||||
private static bool IsValidLocation(Point3D location, Map map)
|
||||
{
|
||||
LandTile lt = map.Tiles.GetLandTile(location.X, location.Y); // Land Tiles
|
||||
|
||||
if ( IsValidTile( lt.ID ) && lt.Z == location.Z )
|
||||
return true;
|
||||
if (IsValidTile(lt.ID) && lt.Z == location.Z)
|
||||
return true;
|
||||
|
||||
StaticTile[] tiles = map.Tiles.GetStaticTiles( location.X, location.Y ); // Static Tiles
|
||||
StaticTile[] tiles = map.Tiles.GetStaticTiles(location.X, location.Y); // Static Tiles
|
||||
|
||||
for( int i = 0; i < tiles.Length; ++i )
|
||||
{
|
||||
StaticTile t = tiles[i];
|
||||
ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
for (int i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
StaticTile t = tiles[i];
|
||||
ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
|
||||
|
||||
int tand = t.ID;
|
||||
int tand = t.ID;
|
||||
|
||||
if ( t.Z + id.CalcHeight != location.Z )
|
||||
continue;
|
||||
if ( IsValidTile( tand ) )
|
||||
return true;
|
||||
}
|
||||
if (t.Z + id.CalcHeight != location.Z)
|
||||
continue;
|
||||
if (IsValidTile(tand))
|
||||
return true;
|
||||
}
|
||||
|
||||
IPooledEnumerable<Item> eable = map.GetItemsInRange( location, 0 ); // Added Tiles
|
||||
IPooledEnumerable<Item> eable = map.GetItemsInRange(location, 0); // Added Tiles
|
||||
|
||||
foreach( Item item in eable )
|
||||
{
|
||||
ItemData id = item.ItemData;
|
||||
foreach (Item item in eable)
|
||||
{
|
||||
ItemData id = item.ItemData;
|
||||
|
||||
if ( item == null || item.Z + id.CalcHeight != location.Z )
|
||||
continue;
|
||||
if ( IsValidTile( item.ItemID ) )
|
||||
{
|
||||
eable.Free();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (item == null || item.Z + id.CalcHeight != location.Z)
|
||||
continue;
|
||||
if (IsValidTile(item.ItemID))
|
||||
{
|
||||
eable.Free();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
return false;
|
||||
}
|
||||
eable.Free();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsValidTile( int itemID )
|
||||
{
|
||||
//Per OSI, Center tile only
|
||||
return (itemID == 0xFEA || itemID == 0x1216 || itemID == 0x307F || itemID == 0x1D10 || itemID == 0x1D0F || itemID == 0x1D1F || itemID == 0x1D12 ); // Pentagram center, Abbatoir center, Arcane Circle Center, Bloody Pentagram has 4 tiles at center
|
||||
}
|
||||
public static bool IsValidTile(int itemID)
|
||||
{
|
||||
//Per OSI, Center tile only
|
||||
return itemID == 0xFEA || itemID == 0x1216 || itemID == 0x307F || itemID == 0x1D10 || itemID == 0x1D0F ||
|
||||
itemID == 0x1D1F ||
|
||||
itemID == 0x1D12; // Pentagram center, Abbatoir center, Arcane Circle Center, Bloody Pentagram has 4 tiles at center
|
||||
}
|
||||
|
||||
private List<Mobile> GetArcanists()
|
||||
{
|
||||
List<Mobile> weavers = new List<Mobile>();
|
||||
private List<Mobile> GetArcanists()
|
||||
{
|
||||
List<Mobile> weavers = new List<Mobile>();
|
||||
|
||||
weavers.Add( Caster );
|
||||
weavers.Add(Caster);
|
||||
|
||||
//OSI Verified: Even enemies/combatants count
|
||||
foreach( Mobile m in Caster.GetMobilesInRange( 1 ) ) //Range verified as 1
|
||||
{
|
||||
if ( m != Caster && m is PlayerMobile && Caster.CanBeBeneficial( m, false ) && Math.Abs( Caster.Skills.Spellweaving.Value - m.Skills.Spellweaving.Value ) <= 20 && !(m is Clone) )
|
||||
{
|
||||
weavers.Add( m );
|
||||
}
|
||||
// Everyone gets the Arcane Focus, power capped elsewhere
|
||||
}
|
||||
//OSI Verified: Even enemies/combatants count
|
||||
foreach (Mobile m in Caster.GetMobilesInRange(1)) //Range verified as 1
|
||||
if (m != Caster && m is PlayerMobile && Caster.CanBeBeneficial(m, false) &&
|
||||
Math.Abs(Caster.Skills.Spellweaving.Value - m.Skills.Spellweaving.Value) <= 20 && !(m is Clone))
|
||||
weavers.Add(m);
|
||||
// Everyone gets the Arcane Focus, power capped elsewhere
|
||||
|
||||
return weavers;
|
||||
}
|
||||
return weavers;
|
||||
}
|
||||
|
||||
private void GiveArcaneFocus( Mobile to, TimeSpan duration, int strengthBonus )
|
||||
{
|
||||
if ( to == null ) //Sanity
|
||||
return;
|
||||
private void GiveArcaneFocus(Mobile to, TimeSpan duration, int strengthBonus)
|
||||
{
|
||||
if (to == null) //Sanity
|
||||
return;
|
||||
|
||||
ArcaneFocus focus = FindArcaneFocus( to );
|
||||
ArcaneFocus focus = FindArcaneFocus(to);
|
||||
|
||||
if ( focus == null )
|
||||
{
|
||||
ArcaneFocus f = new ArcaneFocus( duration, strengthBonus );
|
||||
if ( to.PlaceInBackpack( f ) )
|
||||
{
|
||||
f.SendTimeRemainingMessage( to );
|
||||
to.SendLocalizedMessage( 1072740 ); // An arcane focus appears in your backpack.
|
||||
}
|
||||
else
|
||||
{
|
||||
f.Delete();
|
||||
}
|
||||
|
||||
}
|
||||
else //OSI renewal rules: the new one will override the old one, always.
|
||||
{
|
||||
to.SendLocalizedMessage( 1072828 ); // Your arcane focus is renewed.
|
||||
focus.LifeSpan = duration;
|
||||
focus.CreationTime = DateTime.UtcNow;
|
||||
focus.StrengthBonus = strengthBonus;
|
||||
focus.InvalidateProperties();
|
||||
focus.SendTimeRemainingMessage( to );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (focus == null)
|
||||
{
|
||||
ArcaneFocus f = new ArcaneFocus(duration, strengthBonus);
|
||||
if (to.PlaceInBackpack(f))
|
||||
{
|
||||
f.SendTimeRemainingMessage(to);
|
||||
to.SendLocalizedMessage(1072740); // An arcane focus appears in your backpack.
|
||||
}
|
||||
else
|
||||
{
|
||||
f.Delete();
|
||||
}
|
||||
}
|
||||
else //OSI renewal rules: the new one will override the old one, always.
|
||||
{
|
||||
to.SendLocalizedMessage(1072828); // Your arcane focus is renewed.
|
||||
focus.LifeSpan = duration;
|
||||
focus.CreationTime = DateTime.UtcNow;
|
||||
focus.StrengthBonus = strengthBonus;
|
||||
focus.InvalidateProperties();
|
||||
focus.SendTimeRemainingMessage(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +1,47 @@
|
|||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public abstract class ArcaneForm : ArcanistSpell, ITransformationSpell
|
||||
{
|
||||
public abstract int Body { get; }
|
||||
public virtual int Hue => 0;
|
||||
public abstract class ArcaneForm : ArcanistSpell, ITransformationSpell
|
||||
{
|
||||
public ArcaneForm(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual int PhysResistOffset => 0;
|
||||
public virtual int FireResistOffset => 0;
|
||||
public virtual int ColdResistOffset => 0;
|
||||
public virtual int PoisResistOffset => 0;
|
||||
public virtual int NrgyResistOffset => 0;
|
||||
public abstract int Body{ get; }
|
||||
public virtual int Hue => 0;
|
||||
|
||||
public ArcaneForm( Mobile caster, Item scroll, SpellInfo info ) : base( caster, scroll, info )
|
||||
{
|
||||
}
|
||||
public virtual int PhysResistOffset => 0;
|
||||
public virtual int FireResistOffset => 0;
|
||||
public virtual int ColdResistOffset => 0;
|
||||
public virtual int PoisResistOffset => 0;
|
||||
public virtual int NrgyResistOffset => 0;
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( !TransformationSpellHelper.CheckCast( Caster, this ) )
|
||||
return false;
|
||||
public virtual double TickRate => 1.0;
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
public virtual void OnTick(Mobile m)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
TransformationSpellHelper.OnCast( Caster, this );
|
||||
public virtual void DoEffect(Mobile m)
|
||||
{
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
public virtual void RemoveEffect(Mobile m)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual double TickRate => 1.0;
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (!TransformationSpellHelper.CheckCast(Caster, this))
|
||||
return false;
|
||||
|
||||
public virtual void OnTick( Mobile m )
|
||||
{
|
||||
}
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
public virtual void DoEffect( Mobile m )
|
||||
{
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
TransformationSpellHelper.OnCast(Caster, this);
|
||||
|
||||
public virtual void RemoveEffect( Mobile m )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,48 +3,54 @@ using Server.Mobiles;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public abstract class ArcaneSummon<T> : ArcanistSpell where T : BaseCreature
|
||||
{
|
||||
public abstract int Sound { get; }
|
||||
public abstract class ArcaneSummon<T> : ArcanistSpell where T : BaseCreature
|
||||
{
|
||||
public ArcaneSummon(Mobile caster, Item scroll, SpellInfo info)
|
||||
: base(caster, scroll, info)
|
||||
{
|
||||
}
|
||||
|
||||
public ArcaneSummon( Mobile caster, Item scroll, SpellInfo info )
|
||||
: base( caster, scroll, info )
|
||||
{
|
||||
}
|
||||
public abstract int Sound{ get; }
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( !base.CheckCast() )
|
||||
return false;
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (!base.CheckCast())
|
||||
return false;
|
||||
|
||||
if ( (Caster.Followers + 1) > Caster.FollowersMax )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1074270 ); // You have too many followers to summon another one.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Followers + 1 > Caster.FollowersMax)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1074270); // You have too many followers to summon another one.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( CheckSequence() )
|
||||
{
|
||||
TimeSpan duration = TimeSpan.FromMinutes( Caster.Skills.Spellweaving.Value /24 + FocusLevel*2 );
|
||||
int summons = Math.Min( 1+FocusLevel, Caster.FollowersMax - Caster.Followers );
|
||||
public override void OnCast()
|
||||
{
|
||||
if (CheckSequence())
|
||||
{
|
||||
TimeSpan duration = TimeSpan.FromMinutes(Caster.Skills.Spellweaving.Value / 24 + FocusLevel * 2);
|
||||
int summons = Math.Min(1 + FocusLevel, Caster.FollowersMax - Caster.Followers);
|
||||
|
||||
for( int i = 0; i < summons; i++ )
|
||||
{
|
||||
BaseCreature bc;
|
||||
for (int i = 0; i < summons; i++)
|
||||
{
|
||||
BaseCreature bc;
|
||||
|
||||
try { bc = Activator.CreateInstance<T>(); }
|
||||
catch { break; }
|
||||
try
|
||||
{
|
||||
bc = Activator.CreateInstance<T>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SpellHelper.Summon( bc, Caster, Sound, duration, false, false );
|
||||
}
|
||||
SpellHelper.Summon(bc, Caster, Sound, duration, false, false);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +1,161 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Engines.MLQuests;
|
||||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public abstract class ArcanistSpell : Spell
|
||||
{
|
||||
public abstract double RequiredSkill { get; }
|
||||
public abstract int RequiredMana { get; }
|
||||
public abstract class ArcanistSpell : Spell
|
||||
{
|
||||
private int m_CastTimeFocusLevel;
|
||||
|
||||
public override SkillName CastSkill => SkillName.Spellweaving;
|
||||
public override SkillName DamageSkill => SkillName.Spellweaving;
|
||||
public ArcanistSpell(Mobile caster, Item scroll, SpellInfo info)
|
||||
: base(caster, scroll, info)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ClearHandsOnCast => false;
|
||||
public abstract double RequiredSkill{ get; }
|
||||
public abstract int RequiredMana{ get; }
|
||||
|
||||
private int m_CastTimeFocusLevel;
|
||||
public override SkillName CastSkill => SkillName.Spellweaving;
|
||||
public override SkillName DamageSkill => SkillName.Spellweaving;
|
||||
|
||||
public ArcanistSpell( Mobile caster, Item scroll, SpellInfo info )
|
||||
: base( caster, scroll, info )
|
||||
{
|
||||
}
|
||||
public override bool ClearHandsOnCast => false;
|
||||
|
||||
public virtual int FocusLevel => m_CastTimeFocusLevel;
|
||||
public virtual int FocusLevel => m_CastTimeFocusLevel;
|
||||
|
||||
public static int GetFocusLevel( Mobile from )
|
||||
{
|
||||
ArcaneFocus focus = FindArcaneFocus( from );
|
||||
public static int GetFocusLevel(Mobile from)
|
||||
{
|
||||
ArcaneFocus focus = FindArcaneFocus(from);
|
||||
|
||||
if ( focus == null || focus.Deleted )
|
||||
return 0;
|
||||
if (focus == null || focus.Deleted)
|
||||
return 0;
|
||||
|
||||
return focus.StrengthBonus;
|
||||
}
|
||||
return focus.StrengthBonus;
|
||||
}
|
||||
|
||||
public static ArcaneFocus FindArcaneFocus( Mobile from )
|
||||
{
|
||||
if ( from?.Backpack == null )
|
||||
return null;
|
||||
public static ArcaneFocus FindArcaneFocus(Mobile from)
|
||||
{
|
||||
if (from?.Backpack == null)
|
||||
return null;
|
||||
|
||||
if ( from.Holding is ArcaneFocus )
|
||||
return (ArcaneFocus)from.Holding;
|
||||
if (from.Holding is ArcaneFocus)
|
||||
return (ArcaneFocus)from.Holding;
|
||||
|
||||
return from.Backpack.FindItemByType<ArcaneFocus>();
|
||||
}
|
||||
return from.Backpack.FindItemByType<ArcaneFocus>();
|
||||
}
|
||||
|
||||
public static bool CheckExpansion( Mobile from )
|
||||
{
|
||||
if ( !(from is PlayerMobile) )
|
||||
return true;
|
||||
public static bool CheckExpansion(Mobile from)
|
||||
{
|
||||
if (!(from is PlayerMobile))
|
||||
return true;
|
||||
|
||||
if ( from.NetState == null )
|
||||
return false;
|
||||
if (from.NetState == null)
|
||||
return false;
|
||||
|
||||
return from.NetState.SupportsExpansion( Expansion.ML );
|
||||
}
|
||||
return from.NetState.SupportsExpansion(Expansion.ML);
|
||||
}
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( !base.CheckCast() )
|
||||
return false;
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (!base.CheckCast())
|
||||
return false;
|
||||
|
||||
Mobile caster = Caster;
|
||||
Mobile caster = Caster;
|
||||
|
||||
if ( !CheckExpansion( caster ) )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1072176 ); // You must upgrade to the Mondain's Legacy Expansion Pack before using that ability
|
||||
return false;
|
||||
}
|
||||
if (!CheckExpansion(caster))
|
||||
{
|
||||
caster.SendLocalizedMessage(
|
||||
1072176); // You must upgrade to the Mondain's Legacy Expansion Pack before using that ability
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( caster is PlayerMobile )
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext( (PlayerMobile)caster );
|
||||
if (caster is PlayerMobile)
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext((PlayerMobile)caster);
|
||||
|
||||
if ( context == null || !context.Spellweaving )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1073220 ); // You must have completed the epic arcanist quest to use this ability.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (context == null || !context.Spellweaving)
|
||||
{
|
||||
caster.SendLocalizedMessage(
|
||||
1073220); // You must have completed the epic arcanist quest to use this ability.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int mana = ScaleMana( RequiredMana );
|
||||
int mana = ScaleMana(RequiredMana);
|
||||
|
||||
if ( caster.Mana < mana )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
if (caster.Mana < mana)
|
||||
{
|
||||
caster.SendLocalizedMessage(1060174,
|
||||
mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( caster.Skills[CastSkill].Value < RequiredSkill )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1063013, $"{RequiredSkill.ToString("F1")}\t{"#1044114"}"); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
|
||||
return false;
|
||||
}
|
||||
if (caster.Skills[CastSkill].Value < RequiredSkill)
|
||||
{
|
||||
caster.SendLocalizedMessage(1063013,
|
||||
$"{RequiredSkill.ToString("F1")}\t{"#1044114"}"); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetCastSkills( out double min, out double max )
|
||||
{
|
||||
min = RequiredSkill - 12.5; //per 5 on Friday, 2/16/07
|
||||
max = RequiredSkill + 37.5;
|
||||
}
|
||||
public override void GetCastSkills(out double min, out double max)
|
||||
{
|
||||
min = RequiredSkill - 12.5; //per 5 on Friday, 2/16/07
|
||||
max = RequiredSkill + 37.5;
|
||||
}
|
||||
|
||||
public override int GetMana()
|
||||
{
|
||||
return RequiredMana;
|
||||
}
|
||||
public override int GetMana()
|
||||
{
|
||||
return RequiredMana;
|
||||
}
|
||||
|
||||
public override void DoFizzle()
|
||||
{
|
||||
Caster.PlaySound( 0x1D6 );
|
||||
Caster.NextSpellTime = Core.TickCount;
|
||||
}
|
||||
public override void DoFizzle()
|
||||
{
|
||||
Caster.PlaySound(0x1D6);
|
||||
Caster.NextSpellTime = Core.TickCount;
|
||||
}
|
||||
|
||||
public override void DoHurtFizzle()
|
||||
{
|
||||
Caster.PlaySound( 0x1D6 );
|
||||
}
|
||||
public override void DoHurtFizzle()
|
||||
{
|
||||
Caster.PlaySound(0x1D6);
|
||||
}
|
||||
|
||||
public override void OnDisturb( DisturbType type, bool message )
|
||||
{
|
||||
base.OnDisturb( type, message );
|
||||
public override void OnDisturb(DisturbType type, bool message)
|
||||
{
|
||||
base.OnDisturb(type, message);
|
||||
|
||||
if ( message )
|
||||
Caster.PlaySound( 0x1D6 );
|
||||
}
|
||||
if (message)
|
||||
Caster.PlaySound(0x1D6);
|
||||
}
|
||||
|
||||
public override void OnBeginCast()
|
||||
{
|
||||
base.OnBeginCast();
|
||||
public override void OnBeginCast()
|
||||
{
|
||||
base.OnBeginCast();
|
||||
|
||||
SendCastEffect();
|
||||
m_CastTimeFocusLevel = GetFocusLevel( Caster );
|
||||
}
|
||||
SendCastEffect();
|
||||
m_CastTimeFocusLevel = GetFocusLevel(Caster);
|
||||
}
|
||||
|
||||
public virtual void SendCastEffect()
|
||||
{
|
||||
Caster.FixedEffect( 0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3 );
|
||||
}
|
||||
public virtual void SendCastEffect()
|
||||
{
|
||||
Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3);
|
||||
}
|
||||
|
||||
public virtual bool CheckResisted( Mobile m )
|
||||
{
|
||||
double percent = (50 + 2*(GetResistSkill( m ) - GetDamageSkill( Caster )))/100; //TODO: According to the guide this is it.. but.. is it correct per OSI?
|
||||
public virtual bool CheckResisted(Mobile m)
|
||||
{
|
||||
double percent =
|
||||
(50 + 2 * (GetResistSkill(m) - GetDamageSkill(Caster))) /
|
||||
100; //TODO: According to the guide this is it.. but.. is it correct per OSI?
|
||||
|
||||
if ( percent <= 0 )
|
||||
return false;
|
||||
if (percent <= 0)
|
||||
return false;
|
||||
|
||||
if ( percent >= 1.0 )
|
||||
return true;
|
||||
if (percent >= 1.0)
|
||||
return true;
|
||||
|
||||
return (percent >= Utility.RandomDouble());
|
||||
}
|
||||
}
|
||||
}
|
||||
return percent >= Utility.RandomDouble();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,131 +3,130 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class AttuneWeaponSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Attune Weapon", "Haeldril",
|
||||
-1
|
||||
);
|
||||
public class AttuneWeaponSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Attune Weapon", "Haeldril",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.0 );
|
||||
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
|
||||
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
public AttuneWeaponSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public AttuneWeaponSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0);
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( m_Table.ContainsKey( Caster ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
|
||||
return false;
|
||||
}
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
|
||||
if ( !Caster.CanBeginAction( typeof( AttuneWeaponSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1075124 ); // You must wait before casting that spell again.
|
||||
return false;
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (m_Table.ContainsKey(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
if (!Caster.CanBeginAction(typeof(AttuneWeaponSpell)))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again.
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( CheckSequence() )
|
||||
{
|
||||
Caster.PlaySound( 0x5C3 );
|
||||
Caster.FixedParticles( 0x3728, 1, 13, 0x26B8, 0x455, 7, EffectLayer.Waist );
|
||||
Caster.FixedParticles( 0x3779, 1, 15, 0x251E, 0x3F, 7, EffectLayer.Waist );
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
public override void OnCast()
|
||||
{
|
||||
if (CheckSequence())
|
||||
{
|
||||
Caster.PlaySound(0x5C3);
|
||||
Caster.FixedParticles(0x3728, 1, 13, 0x26B8, 0x455, 7, EffectLayer.Waist);
|
||||
Caster.FixedParticles(0x3779, 1, 15, 0x251E, 0x3F, 7, EffectLayer.Waist);
|
||||
|
||||
int damageAbsorb = (int)(18 + ((skill-10)/10)*3 + (FocusLevel * 6));
|
||||
Caster.MeleeDamageAbsorb = damageAbsorb;
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
|
||||
TimeSpan duration = TimeSpan.FromSeconds( 60 + (FocusLevel * 12) );
|
||||
int damageAbsorb = (int)(18 + (skill - 10) / 10 * 3 + FocusLevel * 6);
|
||||
Caster.MeleeDamageAbsorb = damageAbsorb;
|
||||
|
||||
ExpireTimer t = new ExpireTimer( Caster, duration );
|
||||
t.Start();
|
||||
TimeSpan duration = TimeSpan.FromSeconds(60 + FocusLevel * 12);
|
||||
|
||||
m_Table[Caster] = t;
|
||||
ExpireTimer t = new ExpireTimer(Caster, duration);
|
||||
t.Start();
|
||||
|
||||
Caster.BeginAction( typeof( AttuneWeaponSpell ) );
|
||||
m_Table[Caster] = t;
|
||||
|
||||
BuffInfo.AddBuff( Caster, new BuffInfo( BuffIcon.AttuneWeapon, 1075798, duration, Caster, damageAbsorb.ToString() ) );
|
||||
}
|
||||
Caster.BeginAction(typeof(AttuneWeaponSpell));
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
BuffInfo.AddBuff(Caster,
|
||||
new BuffInfo(BuffIcon.AttuneWeapon, 1075798, duration, Caster, damageAbsorb.ToString()));
|
||||
}
|
||||
|
||||
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public static void TryAbsorb( Mobile defender, ref int damage )
|
||||
{
|
||||
if ( damage == 0 || !IsAbsorbing( defender ) || defender.MeleeDamageAbsorb <= 0 )
|
||||
return;
|
||||
public static void TryAbsorb(Mobile defender, ref int damage)
|
||||
{
|
||||
if (damage == 0 || !IsAbsorbing(defender) || defender.MeleeDamageAbsorb <= 0)
|
||||
return;
|
||||
|
||||
int absorbed = Math.Min( damage, defender.MeleeDamageAbsorb );
|
||||
int absorbed = Math.Min(damage, defender.MeleeDamageAbsorb);
|
||||
|
||||
damage -= absorbed;
|
||||
defender.MeleeDamageAbsorb -= absorbed;
|
||||
damage -= absorbed;
|
||||
defender.MeleeDamageAbsorb -= absorbed;
|
||||
|
||||
defender.SendLocalizedMessage( 1075127, $"{absorbed}\t{defender.MeleeDamageAbsorb}"); // ~1_damage~ point(s) of damage have been absorbed. A total of ~2_remaining~ point(s) of shielding remain.
|
||||
defender.SendLocalizedMessage(1075127,
|
||||
$"{absorbed}\t{defender.MeleeDamageAbsorb}"); // ~1_damage~ point(s) of damage have been absorbed. A total of ~2_remaining~ point(s) of shielding remain.
|
||||
|
||||
if ( defender.MeleeDamageAbsorb <= 0 )
|
||||
StopAbsorbing( defender, true );
|
||||
}
|
||||
if (defender.MeleeDamageAbsorb <= 0)
|
||||
StopAbsorbing(defender, true);
|
||||
}
|
||||
|
||||
public static bool IsAbsorbing( Mobile m )
|
||||
{
|
||||
return m_Table.ContainsKey( m );
|
||||
}
|
||||
public static bool IsAbsorbing(Mobile m)
|
||||
{
|
||||
return m_Table.ContainsKey(m);
|
||||
}
|
||||
|
||||
public static void StopAbsorbing( Mobile m, bool message )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out ExpireTimer t ))
|
||||
{
|
||||
t.DoExpire( message );
|
||||
}
|
||||
}
|
||||
public static void StopAbsorbing(Mobile m, bool message)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out ExpireTimer t)) t.DoExpire(message);
|
||||
}
|
||||
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
|
||||
public ExpireTimer( Mobile m, TimeSpan delay )
|
||||
: base( delay )
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
public ExpireTimer(Mobile m, TimeSpan delay)
|
||||
: base(delay)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire( true );
|
||||
}
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire(true);
|
||||
}
|
||||
|
||||
public void DoExpire( bool message )
|
||||
{
|
||||
Stop();
|
||||
public void DoExpire(bool message)
|
||||
{
|
||||
Stop();
|
||||
|
||||
m_Mobile.MeleeDamageAbsorb = 0;
|
||||
m_Mobile.MeleeDamageAbsorb = 0;
|
||||
|
||||
if ( message )
|
||||
{
|
||||
m_Mobile.SendLocalizedMessage( 1075126 ); // Your attunement fades.
|
||||
m_Mobile.PlaySound( 0x1F8 );
|
||||
}
|
||||
if (message)
|
||||
{
|
||||
m_Mobile.SendLocalizedMessage(1075126); // Your attunement fades.
|
||||
m_Mobile.PlaySound(0x1F8);
|
||||
}
|
||||
|
||||
m_Table.Remove( m_Mobile );
|
||||
m_Table.Remove(m_Mobile);
|
||||
|
||||
DelayCall( TimeSpan.FromSeconds( 120 ), delegate { m_Mobile.EndAction( typeof( AttuneWeaponSpell ) ); } );
|
||||
BuffInfo.RemoveBuff( m_Mobile, BuffIcon.AttuneWeapon );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DelayCall(TimeSpan.FromSeconds(120), delegate { m_Mobile.EndAction(typeof(AttuneWeaponSpell)); });
|
||||
BuffInfo.RemoveBuff(m_Mobile, BuffIcon.AttuneWeapon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,140 +3,139 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class EssenceOfWindSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo( "Essence of Wind", "Anathrae", -1 );
|
||||
public class EssenceOfWindSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo("Essence of Wind", "Anathrae", -1);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 3.0 );
|
||||
private static Dictionary<Mobile, EssenceOfWindInfo> m_Table = new Dictionary<Mobile, EssenceOfWindInfo>();
|
||||
|
||||
public override double RequiredSkill => 52.0;
|
||||
public override int RequiredMana => 40;
|
||||
public EssenceOfWindSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public EssenceOfWindSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0);
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( CheckSequence() )
|
||||
{
|
||||
Caster.PlaySound( 0x5C6 );
|
||||
public override double RequiredSkill => 52.0;
|
||||
public override int RequiredMana => 40;
|
||||
|
||||
int range = 5 + FocusLevel;
|
||||
int damage = 25 + FocusLevel;
|
||||
public override void OnCast()
|
||||
{
|
||||
if (CheckSequence())
|
||||
{
|
||||
Caster.PlaySound(0x5C6);
|
||||
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
int range = 5 + FocusLevel;
|
||||
int damage = 25 + FocusLevel;
|
||||
|
||||
TimeSpan duration = TimeSpan.FromSeconds( (int)(skill / 24) + FocusLevel );
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
|
||||
int fcMalus = FocusLevel + 1;
|
||||
int ssiMalus = 2 * (FocusLevel + 1);
|
||||
TimeSpan duration = TimeSpan.FromSeconds((int)(skill / 24) + FocusLevel);
|
||||
|
||||
List<Mobile> targets = new List<Mobile>();
|
||||
int fcMalus = FocusLevel + 1;
|
||||
int ssiMalus = 2 * (FocusLevel + 1);
|
||||
|
||||
foreach( Mobile m in Caster.GetMobilesInRange( range ) )
|
||||
{
|
||||
if ( Caster != m && Caster.InLOS( m ) && SpellHelper.ValidIndirectTarget( Caster, m ) && Caster.CanBeHarmful( m, false ) )
|
||||
targets.Add( m );
|
||||
}
|
||||
List<Mobile> targets = new List<Mobile>();
|
||||
|
||||
for( int i = 0; i < targets.Count; i++ )
|
||||
{
|
||||
Mobile m = targets[i];
|
||||
foreach (Mobile m in Caster.GetMobilesInRange(range))
|
||||
if (Caster != m && Caster.InLOS(m) && SpellHelper.ValidIndirectTarget(Caster, m) &&
|
||||
Caster.CanBeHarmful(m, false))
|
||||
targets.Add(m);
|
||||
|
||||
Caster.DoHarmful( m );
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
Mobile m = targets[i];
|
||||
|
||||
SpellHelper.Damage( this, m, damage, 0, 0, 100, 0, 0 );
|
||||
Caster.DoHarmful(m);
|
||||
|
||||
if ( !CheckResisted( m ) ) //No message on resist
|
||||
{
|
||||
m_Table[m] = new EssenceOfWindInfo( m, fcMalus, ssiMalus, duration );
|
||||
SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0);
|
||||
|
||||
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.EssenceOfWind, 1075802, duration, m,
|
||||
$"{fcMalus.ToString()}\t{ssiMalus.ToString()}") );
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!CheckResisted(m)) //No message on resist
|
||||
{
|
||||
m_Table[m] = new EssenceOfWindInfo(m, fcMalus, ssiMalus, duration);
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EssenceOfWind, 1075802, duration, m,
|
||||
$"{fcMalus.ToString()}\t{ssiMalus.ToString()}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Mobile, EssenceOfWindInfo> m_Table = new Dictionary<Mobile, EssenceOfWindInfo>();
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private class EssenceOfWindInfo
|
||||
{
|
||||
public Mobile Defender { get; }
|
||||
public static int GetFCMalus(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out EssenceOfWindInfo info))
|
||||
return info.FCMalus;
|
||||
|
||||
public int FCMalus { get; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int SSIMalus { get; }
|
||||
public static int GetSSIMalus(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out EssenceOfWindInfo info))
|
||||
return info.SSIMalus;
|
||||
|
||||
public ExpireTimer Timer { get; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
public EssenceOfWindInfo( Mobile defender, int fcMalus, int ssiMalus, TimeSpan duration )
|
||||
{
|
||||
Defender = defender;
|
||||
FCMalus = fcMalus;
|
||||
SSIMalus = ssiMalus;
|
||||
public static bool IsDebuffed(Mobile m)
|
||||
{
|
||||
return m_Table.ContainsKey(m);
|
||||
}
|
||||
|
||||
Timer = new ExpireTimer( Defender, duration );
|
||||
Timer.Start();
|
||||
}
|
||||
}
|
||||
public static void StopDebuffing(Mobile m, bool message)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out EssenceOfWindInfo info))
|
||||
info.Timer.DoExpire(message);
|
||||
}
|
||||
|
||||
public static int GetFCMalus( Mobile m )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out EssenceOfWindInfo info ))
|
||||
return info.FCMalus;
|
||||
private class EssenceOfWindInfo
|
||||
{
|
||||
public EssenceOfWindInfo(Mobile defender, int fcMalus, int ssiMalus, TimeSpan duration)
|
||||
{
|
||||
Defender = defender;
|
||||
FCMalus = fcMalus;
|
||||
SSIMalus = ssiMalus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Timer = new ExpireTimer(Defender, duration);
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
public static int GetSSIMalus( Mobile m )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out EssenceOfWindInfo info ))
|
||||
return info.SSIMalus;
|
||||
public Mobile Defender{ get; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
public int FCMalus{ get; }
|
||||
|
||||
public static bool IsDebuffed( Mobile m )
|
||||
{
|
||||
return m_Table.ContainsKey( m );
|
||||
}
|
||||
public int SSIMalus{ get; }
|
||||
|
||||
public static void StopDebuffing( Mobile m, bool message )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out EssenceOfWindInfo info ))
|
||||
info.Timer.DoExpire( message );
|
||||
}
|
||||
public ExpireTimer Timer{ get; }
|
||||
}
|
||||
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
|
||||
public ExpireTimer( Mobile m, TimeSpan delay ) : base( delay )
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
public ExpireTimer(Mobile m, TimeSpan delay) : base(delay)
|
||||
{
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire( true );
|
||||
}
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire(true);
|
||||
}
|
||||
|
||||
public void DoExpire( bool message )
|
||||
{
|
||||
Stop();
|
||||
/*
|
||||
if ( message )
|
||||
{
|
||||
}
|
||||
*/
|
||||
m_Table.Remove( m_Mobile );
|
||||
public void DoExpire(bool message)
|
||||
{
|
||||
Stop();
|
||||
/*
|
||||
if ( message )
|
||||
{
|
||||
}
|
||||
*/
|
||||
m_Table.Remove(m_Mobile);
|
||||
|
||||
BuffInfo.RemoveBuff( m_Mobile, BuffIcon.EssenceOfWind );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BuffInfo.RemoveBuff(m_Mobile, BuffIcon.EssenceOfWind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,87 +2,75 @@ using System;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class EtherealVoyageSpell : ArcaneForm
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Ethereal Voyage", "Orlavdra",
|
||||
-1
|
||||
);
|
||||
public class EtherealVoyageSpell : ArcaneForm
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Ethereal Voyage", "Orlavdra",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 3.5 );
|
||||
public EtherealVoyageSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 24.0;
|
||||
public override int RequiredMana => 32;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5);
|
||||
|
||||
public override int Body => 0x302;
|
||||
public override int Hue => 0x48F;
|
||||
public override double RequiredSkill => 24.0;
|
||||
public override int RequiredMana => 32;
|
||||
|
||||
public EtherealVoyageSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override int Body => 0x302;
|
||||
public override int Hue => 0x48F;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.AggressiveAction += delegate( AggressiveActionEventArgs e )
|
||||
{
|
||||
if ( TransformationSpellHelper.UnderTransformation( e.Aggressor, typeof( EtherealVoyageSpell ) ) )
|
||||
{
|
||||
TransformationSpellHelper.RemoveContext( e.Aggressor, true );
|
||||
}
|
||||
};
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.AggressiveAction += delegate(AggressiveActionEventArgs e)
|
||||
{
|
||||
if (TransformationSpellHelper.UnderTransformation(e.Aggressor, typeof(EtherealVoyageSpell)))
|
||||
TransformationSpellHelper.RemoveContext(e.Aggressor, true);
|
||||
};
|
||||
}
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( TransformationSpellHelper.UnderTransformation( Caster, typeof( EtherealVoyageSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
|
||||
}
|
||||
else if ( !Caster.CanBeginAction( typeof( EtherealVoyageSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1075124 ); // You must wait before casting that spell again.
|
||||
}
|
||||
else if ( Caster.Combatant != null )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1072586 ); // You cannot cast Ethereal Voyage while you are in combat.
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CheckCast();
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (TransformationSpellHelper.UnderTransformation(Caster, typeof(EtherealVoyageSpell)))
|
||||
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
|
||||
else if (!Caster.CanBeginAction(typeof(EtherealVoyageSpell)))
|
||||
Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again.
|
||||
else if (Caster.Combatant != null)
|
||||
Caster.SendLocalizedMessage(1072586); // You cannot cast Ethereal Voyage while you are in combat.
|
||||
else
|
||||
return base.CheckCast();
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void DoEffect( Mobile m )
|
||||
{
|
||||
m.PlaySound( 0x5C8 );
|
||||
m.SendLocalizedMessage( 1074770 ); // You are now under the effects of Ethereal Voyage.
|
||||
public override void DoEffect(Mobile m)
|
||||
{
|
||||
m.PlaySound(0x5C8);
|
||||
m.SendLocalizedMessage(1074770); // You are now under the effects of Ethereal Voyage.
|
||||
|
||||
double skill = Caster.Skills.Spellweaving.Value;
|
||||
double skill = Caster.Skills.Spellweaving.Value;
|
||||
|
||||
TimeSpan duration = TimeSpan.FromSeconds( 12 + (int)(skill / 24) + (FocusLevel * 2) );
|
||||
TimeSpan duration = TimeSpan.FromSeconds(12 + (int)(skill / 24) + FocusLevel * 2);
|
||||
|
||||
Timer.DelayCall<Mobile>( duration, RemoveEffect, Caster );
|
||||
Timer.DelayCall(duration, RemoveEffect, Caster);
|
||||
|
||||
Caster.BeginAction( typeof( EtherealVoyageSpell ) ); //Cannot cast this spell for another 5 minutes(300sec) after effect removed.
|
||||
Caster.BeginAction(
|
||||
typeof(EtherealVoyageSpell)); //Cannot cast this spell for another 5 minutes(300sec) after effect removed.
|
||||
|
||||
BuffInfo.AddBuff( Caster, new BuffInfo( BuffIcon.EtherealVoyage, 1031613, 1075805, duration, Caster ) );
|
||||
}
|
||||
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.EtherealVoyage, 1031613, 1075805, duration, Caster));
|
||||
}
|
||||
|
||||
public override void RemoveEffect( Mobile m )
|
||||
{
|
||||
m.SendLocalizedMessage( 1074771 ); // You are no longer under the effects of Ethereal Voyage.
|
||||
public override void RemoveEffect(Mobile m)
|
||||
{
|
||||
m.SendLocalizedMessage(1074771); // You are no longer under the effects of Ethereal Voyage.
|
||||
|
||||
TransformationSpellHelper.RemoveContext( m, true );
|
||||
TransformationSpellHelper.RemoveContext(m, true);
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromMinutes( 5 ), delegate
|
||||
{
|
||||
m.EndAction( typeof( EtherealVoyageSpell ) );
|
||||
} );
|
||||
Timer.DelayCall(TimeSpan.FromMinutes(5), delegate { m.EndAction(typeof(EtherealVoyageSpell)); });
|
||||
|
||||
BuffInfo.RemoveBuff( m, BuffIcon.EtherealVoyage );
|
||||
}
|
||||
}
|
||||
}
|
||||
BuffInfo.RemoveBuff(m, BuffIcon.EtherealVoyage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,213 +1,205 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Mobiles;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class GiftOfLifeSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Gift of Life", "Illorae",
|
||||
-1
|
||||
);
|
||||
public class GiftOfLifeSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Gift of Life", "Illorae",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 4.0 );
|
||||
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
|
||||
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 70;
|
||||
public GiftOfLifeSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public GiftOfLifeSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(4.0);
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.PlayerDeath += delegate( PlayerDeathEventArgs e )
|
||||
{
|
||||
HandleDeath( e.Mobile );
|
||||
};
|
||||
}
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 70;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget( this );
|
||||
}
|
||||
public double HitsScalar => (Caster.Skills.Spellweaving.Value / 2.4 + FocusLevel) / 100;
|
||||
|
||||
public void Target( Mobile m )
|
||||
{
|
||||
BaseCreature bc = m as BaseCreature;
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.PlayerDeath += delegate(PlayerDeathEventArgs e) { HandleDeath(e.Mobile); };
|
||||
}
|
||||
|
||||
if ( !Caster.CanSee( m ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
|
||||
}
|
||||
else if ( m.IsDeadBondedPet || !m.Alive )
|
||||
{
|
||||
// As per Osi: Nothing happens.
|
||||
}
|
||||
else if ( m != Caster && (bc == null || !bc.IsBonded || bc.ControlMaster != Caster) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1072077 ); // You may only cast this spell on yourself or a bonded pet.
|
||||
}
|
||||
else if ( m_Table.ContainsKey( m ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
|
||||
}
|
||||
else if ( CheckBSequence( m ) )
|
||||
{
|
||||
if ( Caster == m )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1074774 ); // You weave powerful magic, protecting yourself from death.
|
||||
}
|
||||
else
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1074775 ); // You weave powerful magic, protecting your pet from death.
|
||||
SpellHelper.Turn( Caster, m );
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget(this);
|
||||
}
|
||||
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
BaseCreature bc = m as BaseCreature;
|
||||
|
||||
if (!Caster.CanSee(m))
|
||||
{
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
else if (m.IsDeadBondedPet || !m.Alive)
|
||||
{
|
||||
// As per Osi: Nothing happens.
|
||||
}
|
||||
else if (m != Caster && (bc == null || !bc.IsBonded || bc.ControlMaster != Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet.
|
||||
}
|
||||
else if (m_Table.ContainsKey(m))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
|
||||
}
|
||||
else if (CheckBSequence(m))
|
||||
{
|
||||
if (Caster == m)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1074774); // You weave powerful magic, protecting yourself from death.
|
||||
}
|
||||
else
|
||||
{
|
||||
Caster.SendLocalizedMessage(1074775); // You weave powerful magic, protecting your pet from death.
|
||||
SpellHelper.Turn(Caster, m);
|
||||
}
|
||||
|
||||
|
||||
m.PlaySound( 0x244 );
|
||||
m.FixedParticles( 0x3709, 1, 30, 0x26ED, 5, 2, EffectLayer.Waist );
|
||||
m.FixedParticles( 0x376A, 1, 30, 0x251E, 5, 3, EffectLayer.Waist );
|
||||
m.PlaySound(0x244);
|
||||
m.FixedParticles(0x3709, 1, 30, 0x26ED, 5, 2, EffectLayer.Waist);
|
||||
m.FixedParticles(0x376A, 1, 30, 0x251E, 5, 3, EffectLayer.Waist);
|
||||
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
|
||||
TimeSpan duration = TimeSpan.FromMinutes( ((int)(skill / 24))* 2 + FocusLevel );
|
||||
TimeSpan duration = TimeSpan.FromMinutes((int)(skill / 24) * 2 + FocusLevel);
|
||||
|
||||
ExpireTimer t = new ExpireTimer( m, duration, this );
|
||||
t.Start();
|
||||
ExpireTimer t = new ExpireTimer(m, duration, this);
|
||||
t.Start();
|
||||
|
||||
m_Table[m] = t;
|
||||
m_Table[m] = t;
|
||||
|
||||
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true ) );
|
||||
}
|
||||
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true));
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private static Dictionary<Mobile, ExpireTimer> m_Table = new Dictionary<Mobile, ExpireTimer>();
|
||||
public static void HandleDeath(Mobile m)
|
||||
{
|
||||
if (m_Table.ContainsKey(m))
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(2, 4)), HandleDeath_OnCallback, m);
|
||||
}
|
||||
|
||||
public static void HandleDeath( Mobile m )
|
||||
{
|
||||
if ( m_Table.ContainsKey( m ) )
|
||||
Timer.DelayCall<Mobile>( TimeSpan.FromSeconds( Utility.RandomMinMax( 2, 4 ) ), HandleDeath_OnCallback, m );
|
||||
}
|
||||
private static void HandleDeath_OnCallback(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out ExpireTimer timer))
|
||||
{
|
||||
double hitsScalar = timer.Spell.HitsScalar;
|
||||
|
||||
private static void HandleDeath_OnCallback( Mobile m )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out ExpireTimer timer ))
|
||||
{
|
||||
double hitsScalar = timer.Spell.HitsScalar;
|
||||
if (m is BaseCreature && m.IsDeadBondedPet)
|
||||
{
|
||||
BaseCreature pet = (BaseCreature)m;
|
||||
Mobile master = pet.GetMaster();
|
||||
|
||||
if ( m is BaseCreature && m.IsDeadBondedPet )
|
||||
{
|
||||
BaseCreature pet = (BaseCreature)m;
|
||||
Mobile master = pet.GetMaster();
|
||||
if (master?.NetState != null && Utility.InUpdateRange(pet, master))
|
||||
{
|
||||
master.CloseGump(typeof(PetResurrectGump));
|
||||
master.SendGump(new PetResurrectGump(master, pet, hitsScalar));
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Mobile> friends = pet.Friends;
|
||||
|
||||
if ( master?.NetState != null && Utility.InUpdateRange( pet, master ) )
|
||||
{
|
||||
master.CloseGump( typeof( PetResurrectGump ) );
|
||||
master.SendGump( new PetResurrectGump( master, pet, hitsScalar ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Mobile> friends = pet.Friends;
|
||||
for (int i = 0; friends != null && i < friends.Count; i++)
|
||||
{
|
||||
Mobile friend = friends[i];
|
||||
|
||||
for( int i = 0; friends != null && i < friends.Count; i++ )
|
||||
{
|
||||
Mobile friend = friends[i];
|
||||
if (friend.NetState != null && Utility.InUpdateRange(pet, friend))
|
||||
{
|
||||
friend.CloseGump(typeof(PetResurrectGump));
|
||||
friend.SendGump(new PetResurrectGump(friend, pet));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m.CloseGump(typeof(ResurrectGump));
|
||||
m.SendGump(new ResurrectGump(m, hitsScalar));
|
||||
}
|
||||
|
||||
if ( friend.NetState != null && Utility.InUpdateRange( pet, friend ) )
|
||||
{
|
||||
friend.CloseGump( typeof( PetResurrectGump ) );
|
||||
friend.SendGump( new PetResurrectGump( friend, pet ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m.CloseGump( typeof( ResurrectGump ) );
|
||||
m.SendGump( new ResurrectGump( m, hitsScalar ) );
|
||||
}
|
||||
//Per OSI, buff is removed when gump sent, irregardless of online status or acceptence
|
||||
timer.DoExpire();
|
||||
}
|
||||
}
|
||||
|
||||
//Per OSI, buff is removed when gump sent, irregardless of online status or acceptence
|
||||
timer.DoExpire();
|
||||
}
|
||||
public static void OnLogin(LoginEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
|
||||
}
|
||||
if (m == null || m.Alive || m_Table[m] == null)
|
||||
return;
|
||||
|
||||
public double HitsScalar => ((Caster.Skills.Spellweaving.Value/2.4) + FocusLevel)/100;
|
||||
HandleDeath_OnCallback(m);
|
||||
}
|
||||
|
||||
public static void OnLogin( LoginEventArgs e )
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
|
||||
if ( m == null || m.Alive || m_Table[m] == null )
|
||||
return;
|
||||
public ExpireTimer(Mobile m, TimeSpan delay, GiftOfLifeSpell spell)
|
||||
: base(delay)
|
||||
{
|
||||
m_Mobile = m;
|
||||
Spell = spell;
|
||||
}
|
||||
|
||||
HandleDeath_OnCallback( m );
|
||||
}
|
||||
public GiftOfLifeSpell Spell{ get; }
|
||||
|
||||
private class ExpireTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire();
|
||||
}
|
||||
|
||||
public GiftOfLifeSpell Spell { get; }
|
||||
public void DoExpire()
|
||||
{
|
||||
Stop();
|
||||
|
||||
public ExpireTimer( Mobile m, TimeSpan delay, GiftOfLifeSpell spell )
|
||||
: base( delay )
|
||||
{
|
||||
m_Mobile = m;
|
||||
Spell = spell;
|
||||
}
|
||||
m_Mobile.SendLocalizedMessage(1074776); // You are no longer protected with Gift of Life.
|
||||
m_Table.Remove(m_Mobile);
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
DoExpire();
|
||||
}
|
||||
BuffInfo.RemoveBuff(m_Mobile, BuffIcon.GiftOfLife);
|
||||
}
|
||||
}
|
||||
|
||||
public void DoExpire()
|
||||
{
|
||||
Stop();
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private GiftOfLifeSpell m_Owner;
|
||||
|
||||
m_Mobile.SendLocalizedMessage( 1074776 ); // You are no longer protected with Gift of Life.
|
||||
m_Table.Remove( m_Mobile );
|
||||
public InternalTarget(GiftOfLifeSpell owner)
|
||||
: base(10, false, TargetFlags.Beneficial)
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
BuffInfo.RemoveBuff( m_Mobile, BuffIcon.GiftOfLife );
|
||||
}
|
||||
}
|
||||
protected override void OnTarget(Mobile m, object o)
|
||||
{
|
||||
if (o is Mobile)
|
||||
m_Owner.Target((Mobile)o);
|
||||
else
|
||||
m.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet.
|
||||
}
|
||||
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private GiftOfLifeSpell m_Owner;
|
||||
|
||||
public InternalTarget( GiftOfLifeSpell owner )
|
||||
: base( 10, false, TargetFlags.Beneficial )
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile m, object o )
|
||||
{
|
||||
if ( o is Mobile )
|
||||
{
|
||||
m_Owner.Target( (Mobile)o );
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SendLocalizedMessage( 1072077 ); // You may only cast this spell on yourself or a bonded pet.
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile m )
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void OnTargetFinish(Mobile m)
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,181 +4,175 @@ using Server.Targeting;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class GiftOfRenewalSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Gift of Renewal", "Olorisstra",
|
||||
-1
|
||||
);
|
||||
public class GiftOfRenewalSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Gift of Renewal", "Olorisstra",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 3.0 );
|
||||
private static Dictionary<Mobile, GiftOfRenewalInfo> m_Table = new Dictionary<Mobile, GiftOfRenewalInfo>();
|
||||
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
public GiftOfRenewalSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public GiftOfRenewalSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0);
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget( this );
|
||||
}
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
|
||||
public void Target( Mobile m )
|
||||
{
|
||||
if ( !Caster.CanSee( m ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
|
||||
}
|
||||
if ( m_Table.ContainsKey( m ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501775 ); // This spell is already in effect.
|
||||
}
|
||||
else if ( !Caster.CanBeginAction( typeof( GiftOfRenewalSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501789 ); // You must wait before trying again.
|
||||
}
|
||||
else if ( CheckBSequence( m ) )
|
||||
{
|
||||
SpellHelper.Turn( Caster, m );
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget(this);
|
||||
}
|
||||
|
||||
Caster.FixedEffect( 0x374A, 10, 20 );
|
||||
Caster.PlaySound( 0x5C9 );
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (!Caster.CanSee(m)) Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
if (m_Table.ContainsKey(m))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501775); // This spell is already in effect.
|
||||
}
|
||||
else if (!Caster.CanBeginAction(typeof(GiftOfRenewalSpell)))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501789); // You must wait before trying again.
|
||||
}
|
||||
else if (CheckBSequence(m))
|
||||
{
|
||||
SpellHelper.Turn(Caster, m);
|
||||
|
||||
if ( m.Poisoned )
|
||||
{
|
||||
m.CurePoison( m );
|
||||
}
|
||||
else
|
||||
{
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
Caster.FixedEffect(0x374A, 10, 20);
|
||||
Caster.PlaySound(0x5C9);
|
||||
|
||||
int hitsPerRound = 5 + (int)(skill / 24) + FocusLevel;
|
||||
TimeSpan duration = TimeSpan.FromSeconds( 30 + (FocusLevel * 10) );
|
||||
if (m.Poisoned)
|
||||
{
|
||||
m.CurePoison(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
|
||||
GiftOfRenewalInfo info = new GiftOfRenewalInfo( Caster, m, hitsPerRound );
|
||||
int hitsPerRound = 5 + (int)(skill / 24) + FocusLevel;
|
||||
TimeSpan duration = TimeSpan.FromSeconds(30 + FocusLevel * 10);
|
||||
|
||||
Timer.DelayCall( duration,
|
||||
delegate
|
||||
{
|
||||
if ( StopEffect( m ) )
|
||||
{
|
||||
m.PlaySound( 0x455 );
|
||||
m.SendLocalizedMessage( 1075071 ); // The Gift of Renewal has faded.
|
||||
}
|
||||
} );
|
||||
GiftOfRenewalInfo info = new GiftOfRenewalInfo(Caster, m, hitsPerRound);
|
||||
|
||||
Timer.DelayCall(duration,
|
||||
delegate
|
||||
{
|
||||
if (StopEffect(m))
|
||||
{
|
||||
m.PlaySound(0x455);
|
||||
m.SendLocalizedMessage(1075071); // The Gift of Renewal has faded.
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
m_Table[m] = info;
|
||||
|
||||
m_Table[m] = info;
|
||||
Caster.BeginAction(typeof(GiftOfRenewalSpell));
|
||||
|
||||
Caster.BeginAction( typeof( GiftOfRenewalSpell ) );
|
||||
BuffInfo.AddBuff(m,
|
||||
new BuffInfo(BuffIcon.GiftOfRenewal, 1031602, 1075797, duration, m, hitsPerRound.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.GiftOfRenewal, 1031602, 1075797, duration, m, hitsPerRound.ToString() ) );
|
||||
}
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
public static bool StopEffect(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out GiftOfRenewalInfo info))
|
||||
{
|
||||
m_Table.Remove(m);
|
||||
|
||||
private static Dictionary<Mobile, GiftOfRenewalInfo> m_Table = new Dictionary<Mobile, GiftOfRenewalInfo>();
|
||||
info.m_Timer.Stop();
|
||||
BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal);
|
||||
|
||||
private class GiftOfRenewalInfo
|
||||
{
|
||||
public Mobile m_Caster;
|
||||
public Mobile m_Mobile;
|
||||
public int m_HitsPerRound;
|
||||
public InternalTimer m_Timer;
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(60), delegate { info.m_Caster.EndAction(typeof(GiftOfRenewalSpell)); });
|
||||
|
||||
public GiftOfRenewalInfo( Mobile caster, Mobile mobile, int hitsPerRound )
|
||||
{
|
||||
m_Caster = caster;
|
||||
m_Mobile = mobile;
|
||||
m_HitsPerRound = hitsPerRound;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_Timer = new InternalTimer( this );
|
||||
m_Timer.Start();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
public GiftOfRenewalInfo m_Info;
|
||||
private class GiftOfRenewalInfo
|
||||
{
|
||||
public Mobile m_Caster;
|
||||
public int m_HitsPerRound;
|
||||
public Mobile m_Mobile;
|
||||
public InternalTimer m_Timer;
|
||||
|
||||
public InternalTimer( GiftOfRenewalInfo info )
|
||||
: base( TimeSpan.FromSeconds( 2.0 ), TimeSpan.FromSeconds( 2.0 ) )
|
||||
{
|
||||
m_Info = info;
|
||||
}
|
||||
public GiftOfRenewalInfo(Mobile caster, Mobile mobile, int hitsPerRound)
|
||||
{
|
||||
m_Caster = caster;
|
||||
m_Mobile = mobile;
|
||||
m_HitsPerRound = hitsPerRound;
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
Mobile m = m_Info.m_Mobile;
|
||||
m_Timer = new InternalTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_Table.ContainsKey( m ) )
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
public GiftOfRenewalInfo m_Info;
|
||||
|
||||
if ( !m.Alive )
|
||||
{
|
||||
Stop();
|
||||
StopEffect( m );
|
||||
return;
|
||||
}
|
||||
public InternalTimer(GiftOfRenewalInfo info)
|
||||
: base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0))
|
||||
{
|
||||
m_Info = info;
|
||||
}
|
||||
|
||||
if ( m.Hits >= m.HitsMax )
|
||||
return;
|
||||
protected override void OnTick()
|
||||
{
|
||||
Mobile m = m_Info.m_Mobile;
|
||||
|
||||
int toHeal = m_Info.m_HitsPerRound;
|
||||
if (!m_Table.ContainsKey(m))
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
SpellHelper.Heal( toHeal, m, m_Info.m_Caster );
|
||||
m.FixedParticles( 0x376A, 9, 32, 5005, EffectLayer.Waist );
|
||||
}
|
||||
}
|
||||
if (!m.Alive)
|
||||
{
|
||||
Stop();
|
||||
StopEffect(m);
|
||||
return;
|
||||
}
|
||||
|
||||
public static bool StopEffect( Mobile m )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out GiftOfRenewalInfo info ))
|
||||
{
|
||||
m_Table.Remove( m );
|
||||
if (m.Hits >= m.HitsMax)
|
||||
return;
|
||||
|
||||
info.m_Timer.Stop();
|
||||
BuffInfo.RemoveBuff( m, BuffIcon.GiftOfRenewal );
|
||||
int toHeal = m_Info.m_HitsPerRound;
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 60 ), delegate { info.m_Caster.EndAction( typeof( GiftOfRenewalSpell ) ); } );
|
||||
SpellHelper.Heal(toHeal, m, m_Info.m_Caster);
|
||||
m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private GiftOfRenewalSpell m_Owner;
|
||||
|
||||
return false;
|
||||
}
|
||||
public InternalTarget(GiftOfRenewalSpell owner)
|
||||
: base(10, false, TargetFlags.Beneficial)
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private GiftOfRenewalSpell m_Owner;
|
||||
protected override void OnTarget(Mobile m, object o)
|
||||
{
|
||||
if (o is Mobile) m_Owner.Target((Mobile)o);
|
||||
}
|
||||
|
||||
public InternalTarget( GiftOfRenewalSpell owner )
|
||||
: base( 10, false, TargetFlags.Beneficial )
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile m, object o )
|
||||
{
|
||||
if ( o is Mobile )
|
||||
{
|
||||
m_Owner.Target( (Mobile)o );
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile m )
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void OnTargetFinish(Mobile m)
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,130 +4,131 @@ using Server.Items;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class ImmolatingWeaponSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Immolating Weapon", "Thalshara",
|
||||
-1
|
||||
);
|
||||
public class ImmolatingWeaponSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Immolating Weapon", "Thalshara",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.0 );
|
||||
private static Dictionary<BaseWeapon, ImmolatingWeaponEntry> m_WeaponDamageTable =
|
||||
new Dictionary<BaseWeapon, ImmolatingWeaponEntry>();
|
||||
|
||||
public override double RequiredSkill => 10.0;
|
||||
public override int RequiredMana => 32;
|
||||
public ImmolatingWeaponSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public ImmolatingWeaponSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0);
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
BaseWeapon weapon = Caster.Weapon as BaseWeapon;
|
||||
public override double RequiredSkill => 10.0;
|
||||
public override int RequiredMana => 32;
|
||||
|
||||
if ( weapon == null || weapon is Fists || weapon is BaseRanged )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1060179 ); // You must be wielding a weapon to use this ability!
|
||||
return false;
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
BaseWeapon weapon = Caster.Weapon as BaseWeapon;
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
if (weapon == null || weapon is Fists || weapon is BaseRanged)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability!
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
BaseWeapon weapon = Caster.Weapon as BaseWeapon;
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
if ( weapon == null || weapon is Fists || weapon is BaseRanged )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1060179 ); // You must be wielding a weapon to use this ability!
|
||||
}
|
||||
else if ( CheckSequence() )
|
||||
{
|
||||
Caster.PlaySound( 0x5CA );
|
||||
Caster.FixedParticles( 0x36BD, 20, 10, 5044, EffectLayer.Head );
|
||||
public override void OnCast()
|
||||
{
|
||||
BaseWeapon weapon = Caster.Weapon as BaseWeapon;
|
||||
|
||||
if ( !IsImmolating( weapon ) ) // On OSI, the effect is not re-applied
|
||||
{
|
||||
double skill = Caster.Skills.Spellweaving.Value;
|
||||
if (weapon == null || weapon is Fists || weapon is BaseRanged)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability!
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
Caster.PlaySound(0x5CA);
|
||||
Caster.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
|
||||
|
||||
int duration = 10 + (int)( skill / 24 ) + FocusLevel;
|
||||
int damage = 5 + (int)( skill / 24 ) + FocusLevel;
|
||||
if (!IsImmolating(weapon)) // On OSI, the effect is not re-applied
|
||||
{
|
||||
double skill = Caster.Skills.Spellweaving.Value;
|
||||
|
||||
Timer stopTimer = Timer.DelayCall<BaseWeapon>( TimeSpan.FromSeconds( duration ), StopImmolating, weapon );
|
||||
int duration = 10 + (int)(skill / 24) + FocusLevel;
|
||||
int damage = 5 + (int)(skill / 24) + FocusLevel;
|
||||
|
||||
m_WeaponDamageTable[weapon] = new ImmolatingWeaponEntry( damage, stopTimer, Caster );
|
||||
weapon.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
Timer stopTimer = Timer.DelayCall(TimeSpan.FromSeconds(duration), StopImmolating, weapon);
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
m_WeaponDamageTable[weapon] = new ImmolatingWeaponEntry(damage, stopTimer, Caster);
|
||||
weapon.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<BaseWeapon, ImmolatingWeaponEntry> m_WeaponDamageTable = new Dictionary<BaseWeapon, ImmolatingWeaponEntry>();
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public static bool IsImmolating( BaseWeapon weapon )
|
||||
{
|
||||
return m_WeaponDamageTable.ContainsKey( weapon );
|
||||
}
|
||||
public static bool IsImmolating(BaseWeapon weapon)
|
||||
{
|
||||
return m_WeaponDamageTable.ContainsKey(weapon);
|
||||
}
|
||||
|
||||
public static int GetImmolatingDamage( BaseWeapon weapon )
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue( weapon, out ImmolatingWeaponEntry entry ))
|
||||
return entry.m_Damage;
|
||||
public static int GetImmolatingDamage(BaseWeapon weapon)
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue(weapon, out ImmolatingWeaponEntry entry))
|
||||
return entry.m_Damage;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void DoEffect( BaseWeapon weapon, Mobile target )
|
||||
{
|
||||
Timer.DelayCall<DelayedEffectEntry>( TimeSpan.FromSeconds( 0.25 ), FinishEffect, new DelayedEffectEntry( weapon, target ) );
|
||||
}
|
||||
public static void DoEffect(BaseWeapon weapon, Mobile target)
|
||||
{
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(0.25), FinishEffect, new DelayedEffectEntry(weapon, target));
|
||||
}
|
||||
|
||||
private static void FinishEffect( DelayedEffectEntry effect )
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue( effect.m_Weapon, out ImmolatingWeaponEntry entry ))
|
||||
AOS.Damage( effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0 );
|
||||
}
|
||||
private static void FinishEffect(DelayedEffectEntry effect)
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue(effect.m_Weapon, out ImmolatingWeaponEntry entry))
|
||||
AOS.Damage(effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static void StopImmolating( BaseWeapon weapon )
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue( weapon, out ImmolatingWeaponEntry entry ))
|
||||
{
|
||||
entry.m_Caster?.PlaySound( 0x27 );
|
||||
public static void StopImmolating(BaseWeapon weapon)
|
||||
{
|
||||
if (m_WeaponDamageTable.TryGetValue(weapon, out ImmolatingWeaponEntry entry))
|
||||
{
|
||||
entry.m_Caster?.PlaySound(0x27);
|
||||
|
||||
entry.m_Timer.Stop();
|
||||
entry.m_Timer.Stop();
|
||||
|
||||
m_WeaponDamageTable.Remove( weapon );
|
||||
m_WeaponDamageTable.Remove(weapon);
|
||||
|
||||
weapon.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
weapon.InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private class ImmolatingWeaponEntry
|
||||
{
|
||||
public int m_Damage;
|
||||
public Timer m_Timer;
|
||||
public Mobile m_Caster;
|
||||
private class ImmolatingWeaponEntry
|
||||
{
|
||||
public Mobile m_Caster;
|
||||
public int m_Damage;
|
||||
public Timer m_Timer;
|
||||
|
||||
public ImmolatingWeaponEntry( int damage, Timer stopTimer, Mobile caster )
|
||||
{
|
||||
m_Damage = damage;
|
||||
m_Timer = stopTimer;
|
||||
m_Caster = caster;
|
||||
}
|
||||
}
|
||||
public ImmolatingWeaponEntry(int damage, Timer stopTimer, Mobile caster)
|
||||
{
|
||||
m_Damage = damage;
|
||||
m_Timer = stopTimer;
|
||||
m_Caster = caster;
|
||||
}
|
||||
}
|
||||
|
||||
private class DelayedEffectEntry
|
||||
{
|
||||
public BaseWeapon m_Weapon;
|
||||
public Mobile m_Target;
|
||||
private class DelayedEffectEntry
|
||||
{
|
||||
public Mobile m_Target;
|
||||
public BaseWeapon m_Weapon;
|
||||
|
||||
public DelayedEffectEntry( BaseWeapon weapon, Mobile target )
|
||||
{
|
||||
m_Weapon = weapon;
|
||||
m_Target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public DelayedEffectEntry(BaseWeapon weapon, Mobile target)
|
||||
{
|
||||
m_Weapon = weapon;
|
||||
m_Target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,59 +2,59 @@ using System;
|
|||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class ArcaneFocus : TransientItem
|
||||
{
|
||||
public override int LabelNumber => 1032629; // Arcane Focus
|
||||
public class ArcaneFocus : TransientItem
|
||||
{
|
||||
[Constructible]
|
||||
public ArcaneFocus()
|
||||
: this(TimeSpan.FromHours(1), 1)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int StrengthBonus { get; set; }
|
||||
[Constructible]
|
||||
public ArcaneFocus(int lifeSpan, int strengthBonus)
|
||||
: this(TimeSpan.FromSeconds(lifeSpan), strengthBonus)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public ArcaneFocus()
|
||||
: this( TimeSpan.FromHours( 1 ), 1 )
|
||||
{
|
||||
}
|
||||
public ArcaneFocus(TimeSpan lifeSpan, int strengthBonus) : base(0x3155, lifeSpan)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
StrengthBonus = strengthBonus;
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public ArcaneFocus( int lifeSpan, int strengthBonus )
|
||||
: this( TimeSpan.FromSeconds( lifeSpan ), strengthBonus )
|
||||
{
|
||||
}
|
||||
public ArcaneFocus(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public ArcaneFocus( TimeSpan lifeSpan, int strengthBonus ) : base( 0x3155, lifeSpan )
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
StrengthBonus = strengthBonus;
|
||||
}
|
||||
public override int LabelNumber => 1032629; // Arcane Focus
|
||||
|
||||
public ArcaneFocus( Serial serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int StrengthBonus{ get; set; }
|
||||
|
||||
public override void GetProperties( ObjectPropertyList list )
|
||||
{
|
||||
base.GetProperties( list );
|
||||
public override TextDefinition InvalidTransferMessage => 1073480; // Your arcane focus disappears.
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
list.Add( 1060485, StrengthBonus.ToString() ); // strength bonus ~1_val~
|
||||
}
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
public override TextDefinition InvalidTransferMessage => 1073480; // Your arcane focus disappears.
|
||||
public override bool Nontransferable => true;
|
||||
list.Add(1060485, StrengthBonus.ToString()); // strength bonus ~1_val~
|
||||
}
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int)0 );
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0);
|
||||
|
||||
writer.Write( StrengthBonus );
|
||||
}
|
||||
writer.Write(StrengthBonus);
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
StrengthBonus = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
StrengthBonus = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,100 +2,101 @@ using System;
|
|||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class TransientItem : Item
|
||||
{
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public TimeSpan LifeSpan { get; set; }
|
||||
public class TransientItem : Item
|
||||
{
|
||||
private Timer m_Timer;
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public DateTime CreationTime { get; set; }
|
||||
[Constructible]
|
||||
public TransientItem(int itemID, TimeSpan lifeSpan)
|
||||
: base(itemID)
|
||||
{
|
||||
CreationTime = DateTime.UtcNow;
|
||||
LifeSpan = lifeSpan;
|
||||
|
||||
private Timer m_Timer;
|
||||
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry);
|
||||
}
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
public override void HandleInvalidTransfer( Mobile from )
|
||||
{
|
||||
if ( InvalidTransferMessage != null )
|
||||
TextDefinition.SendMessageTo( from, InvalidTransferMessage );
|
||||
public TransientItem(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
Delete();
|
||||
}
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TimeSpan LifeSpan{ get; set; }
|
||||
|
||||
public virtual TextDefinition InvalidTransferMessage => null;
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public DateTime CreationTime{ get; set; }
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public virtual TextDefinition InvalidTransferMessage => null;
|
||||
|
||||
public override void HandleInvalidTransfer(Mobile from)
|
||||
{
|
||||
if (InvalidTransferMessage != null)
|
||||
TextDefinition.SendMessageTo(from, InvalidTransferMessage);
|
||||
|
||||
Delete();
|
||||
}
|
||||
|
||||
|
||||
public virtual void Expire( Mobile parent )
|
||||
{
|
||||
parent?.SendLocalizedMessage( 1072515, Name ?? $"#{LabelNumber}" ); // The ~1_name~ expired...
|
||||
public virtual void Expire(Mobile parent)
|
||||
{
|
||||
parent?.SendLocalizedMessage(1072515, Name ?? $"#{LabelNumber}"); // The ~1_name~ expired...
|
||||
|
||||
Effects.PlaySound( GetWorldLocation(), Map, 0x201 );
|
||||
Effects.PlaySound(GetWorldLocation(), Map, 0x201);
|
||||
|
||||
Delete();
|
||||
}
|
||||
Delete();
|
||||
}
|
||||
|
||||
public virtual void SendTimeRemainingMessage( Mobile to )
|
||||
{
|
||||
to.SendLocalizedMessage( 1072516,
|
||||
$"{Name ?? $"#{LabelNumber}"}\t{(int) LifeSpan.TotalSeconds}"); // ~1_name~ will expire in ~2_val~ seconds!
|
||||
}
|
||||
public virtual void SendTimeRemainingMessage(Mobile to)
|
||||
{
|
||||
to.SendLocalizedMessage(1072516,
|
||||
$"{Name ?? $"#{LabelNumber}"}\t{(int)LifeSpan.TotalSeconds}"); // ~1_name~ will expire in ~2_val~ seconds!
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
m_Timer?.Stop();
|
||||
public override void OnDelete()
|
||||
{
|
||||
m_Timer?.Stop();
|
||||
|
||||
base.OnDelete();
|
||||
}
|
||||
base.OnDelete();
|
||||
}
|
||||
|
||||
public virtual void CheckExpiry()
|
||||
{
|
||||
if ( (CreationTime + LifeSpan) < DateTime.UtcNow )
|
||||
Expire( RootParent as Mobile );
|
||||
else
|
||||
InvalidateProperties();
|
||||
}
|
||||
public virtual void CheckExpiry()
|
||||
{
|
||||
if (CreationTime + LifeSpan < DateTime.UtcNow)
|
||||
Expire(RootParent as Mobile);
|
||||
else
|
||||
InvalidateProperties();
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public TransientItem( int itemID, TimeSpan lifeSpan )
|
||||
: base( itemID )
|
||||
{
|
||||
CreationTime = DateTime.UtcNow;
|
||||
LifeSpan = lifeSpan;
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 5 ), TimeSpan.FromSeconds( 5 ), CheckExpiry );
|
||||
}
|
||||
TimeSpan remaining = CreationTime + LifeSpan - DateTime.UtcNow;
|
||||
|
||||
public TransientItem( Serial serial )
|
||||
: base( serial )
|
||||
{
|
||||
}
|
||||
list.Add(1072517, ((int)remaining.TotalSeconds).ToString()); // Lifespan: ~1_val~ seconds
|
||||
}
|
||||
|
||||
public override void GetProperties( ObjectPropertyList list )
|
||||
{
|
||||
base.GetProperties( list );
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0);
|
||||
|
||||
TimeSpan remaining = ((CreationTime + LifeSpan) - DateTime.UtcNow);
|
||||
writer.Write(LifeSpan);
|
||||
writer.Write(CreationTime);
|
||||
}
|
||||
|
||||
list.Add( 1072517, ((int)remaining.TotalSeconds).ToString() ); // Lifespan: ~1_val~ seconds
|
||||
}
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int)0 );
|
||||
LifeSpan = reader.ReadTimeSpan();
|
||||
CreationTime = reader.ReadDateTime();
|
||||
|
||||
writer.Write( LifeSpan );
|
||||
writer.Write( CreationTime );
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
|
||||
LifeSpan = reader.ReadTimeSpan();
|
||||
CreationTime = reader.ReadDateTime();
|
||||
|
||||
m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 5 ), TimeSpan.FromSeconds( 5 ), CheckExpiry );
|
||||
}
|
||||
}
|
||||
}
|
||||
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +1,62 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class ArcaneFey : BaseCreature
|
||||
{
|
||||
public override string CorpseName => "a pixie corpse";
|
||||
public override double DispelDifficulty => 70.0;
|
||||
public override double DispelFocus => 20.0;
|
||||
public class ArcaneFey : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public ArcaneFey() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Name = NameList.RandomName("pixie");
|
||||
Body = 128;
|
||||
BaseSoundID = 0x467;
|
||||
|
||||
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
|
||||
public override bool InitialInnocent => true;
|
||||
SetStr(20);
|
||||
SetDex(150);
|
||||
SetInt(125);
|
||||
|
||||
[Constructible]
|
||||
public ArcaneFey() : base( AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4 )
|
||||
{
|
||||
Name = NameList.RandomName( "pixie" );
|
||||
Body = 128;
|
||||
BaseSoundID = 0x467;
|
||||
SetDamage(9, 15);
|
||||
|
||||
SetStr( 20 );
|
||||
SetDex( 150 );
|
||||
SetInt( 125 );
|
||||
SetDamageType(ResistanceType.Physical, 100);
|
||||
|
||||
SetDamage( 9, 15 );
|
||||
SetResistance(ResistanceType.Physical, 80, 90);
|
||||
SetResistance(ResistanceType.Fire, 40, 50);
|
||||
SetResistance(ResistanceType.Cold, 40, 50);
|
||||
SetResistance(ResistanceType.Poison, 40, 50);
|
||||
SetResistance(ResistanceType.Energy, 40, 50);
|
||||
|
||||
SetDamageType( ResistanceType.Physical, 100 );
|
||||
SetSkill(SkillName.EvalInt, 70.1, 80.0);
|
||||
SetSkill(SkillName.Magery, 70.1, 80.0);
|
||||
SetSkill(SkillName.Meditation, 70.1, 80.0);
|
||||
SetSkill(SkillName.MagicResist, 50.5, 100.0);
|
||||
SetSkill(SkillName.Tactics, 10.1, 20.0);
|
||||
SetSkill(SkillName.Wrestling, 10.1, 12.5);
|
||||
|
||||
SetResistance( ResistanceType.Physical, 80, 90 );
|
||||
SetResistance( ResistanceType.Fire, 40, 50 );
|
||||
SetResistance( ResistanceType.Cold, 40, 50 );
|
||||
SetResistance( ResistanceType.Poison, 40, 50 );
|
||||
SetResistance( ResistanceType.Energy, 40, 50 );
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
|
||||
SetSkill( SkillName.EvalInt, 70.1, 80.0 );
|
||||
SetSkill( SkillName.Magery, 70.1, 80.0 );
|
||||
SetSkill( SkillName.Meditation, 70.1, 80.0 );
|
||||
SetSkill( SkillName.MagicResist, 50.5, 100.0 );
|
||||
SetSkill( SkillName.Tactics, 10.1, 20.0 );
|
||||
SetSkill( SkillName.Wrestling, 10.1, 12.5 );
|
||||
ControlSlots = 1;
|
||||
}
|
||||
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
public ArcaneFey(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
ControlSlots = 1;
|
||||
}
|
||||
public override string CorpseName => "a pixie corpse";
|
||||
public override double DispelDifficulty => 70.0;
|
||||
public override double DispelFocus => 20.0;
|
||||
|
||||
public ArcaneFey( Serial serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
|
||||
public override bool InitialInnocent => true;
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int) 0 );
|
||||
}
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +1,63 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class ArcaneFiend : BaseCreature
|
||||
{
|
||||
public override string CorpseName => "an imp corpse";
|
||||
public override double DispelDifficulty => 70.0;
|
||||
public override double DispelFocus => 20.0;
|
||||
public class ArcaneFiend : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public ArcaneFiend() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Body = 74;
|
||||
BaseSoundID = 422;
|
||||
|
||||
public override PackInstinct PackInstinct => PackInstinct.Daemon;
|
||||
public override bool BleedImmune => true; //TODO: Verify on OSI. Guide says this.
|
||||
public override string DefaultName => "an imp";
|
||||
SetStr(55);
|
||||
SetDex(40);
|
||||
SetInt(60);
|
||||
|
||||
[Constructible]
|
||||
public ArcaneFiend() : base( AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4 )
|
||||
{
|
||||
Body = 74;
|
||||
BaseSoundID = 422;
|
||||
SetDamage(10, 14);
|
||||
|
||||
SetStr( 55 );
|
||||
SetDex( 40 );
|
||||
SetInt( 60 );
|
||||
SetDamageType(ResistanceType.Physical, 0);
|
||||
SetDamageType(ResistanceType.Fire, 50);
|
||||
SetDamageType(ResistanceType.Poison, 50);
|
||||
|
||||
SetDamage( 10, 14 );
|
||||
SetResistance(ResistanceType.Physical, 25, 35);
|
||||
SetResistance(ResistanceType.Fire, 40, 50);
|
||||
SetResistance(ResistanceType.Cold, 20, 30);
|
||||
SetResistance(ResistanceType.Poison, 30, 40);
|
||||
SetResistance(ResistanceType.Energy, 30, 40);
|
||||
|
||||
SetDamageType( ResistanceType.Physical, 0 );
|
||||
SetDamageType( ResistanceType.Fire, 50 );
|
||||
SetDamageType( ResistanceType.Poison, 50 );
|
||||
SetSkill(SkillName.EvalInt, 20.1, 30.0);
|
||||
SetSkill(SkillName.Magery, 60.1, 70.0);
|
||||
SetSkill(SkillName.MagicResist, 30.1, 50.0);
|
||||
SetSkill(SkillName.Tactics, 42.1, 50.0);
|
||||
SetSkill(SkillName.Wrestling, 40.1, 44.0);
|
||||
|
||||
SetResistance( ResistanceType.Physical, 25, 35 );
|
||||
SetResistance( ResistanceType.Fire, 40, 50 );
|
||||
SetResistance( ResistanceType.Cold, 20, 30 );
|
||||
SetResistance( ResistanceType.Poison, 30, 40 );
|
||||
SetResistance( ResistanceType.Energy, 30, 40 );
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
|
||||
SetSkill( SkillName.EvalInt, 20.1, 30.0 );
|
||||
SetSkill( SkillName.Magery, 60.1, 70.0 );
|
||||
SetSkill( SkillName.MagicResist, 30.1, 50.0 );
|
||||
SetSkill( SkillName.Tactics, 42.1, 50.0 );
|
||||
SetSkill( SkillName.Wrestling, 40.1, 44.0 );
|
||||
ControlSlots = 1;
|
||||
}
|
||||
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
public ArcaneFiend(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
ControlSlots = 1;
|
||||
}
|
||||
public override string CorpseName => "an imp corpse";
|
||||
public override double DispelDifficulty => 70.0;
|
||||
public override double DispelFocus => 20.0;
|
||||
|
||||
public ArcaneFiend( Serial serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
public override PackInstinct PackInstinct => PackInstinct.Daemon;
|
||||
public override bool BleedImmune => true; //TODO: Verify on OSI. Guide says this.
|
||||
public override string DefaultName => "an imp";
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int) 0 );
|
||||
}
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,84 +2,84 @@ using System;
|
|||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class NatureFury : BaseCreature
|
||||
{
|
||||
public override bool DeleteCorpseOnDeath => Core.AOS;
|
||||
public override bool IsHouseSummonable => true;
|
||||
public class NatureFury : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public NatureFury()
|
||||
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Body = 0x33;
|
||||
Hue = 0x4001;
|
||||
|
||||
public override double DispelDifficulty => 125.0;
|
||||
public override double DispelFocus => 90.0;
|
||||
SetStr(150);
|
||||
SetDex(150);
|
||||
SetInt(100);
|
||||
|
||||
public override bool BleedImmune => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
SetHits(80);
|
||||
SetStam(250);
|
||||
SetMana(0);
|
||||
|
||||
public override bool AlwaysMurderer => true;
|
||||
public override string DefaultName => "a nature's fury";
|
||||
SetDamage(6, 8);
|
||||
|
||||
[Constructible]
|
||||
public NatureFury()
|
||||
: base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
|
||||
{
|
||||
Body = 0x33;
|
||||
Hue = 0x4001;
|
||||
SetDamageType(ResistanceType.Poison, 100);
|
||||
SetDamageType(ResistanceType.Physical, 0);
|
||||
SetResistance(ResistanceType.Physical, 90);
|
||||
|
||||
SetStr( 150 );
|
||||
SetDex( 150 );
|
||||
SetInt( 100 );
|
||||
SetSkill(SkillName.Wrestling, 90.0);
|
||||
SetSkill(SkillName.MagicResist, 70.0);
|
||||
SetSkill(SkillName.Tactics, 100.0);
|
||||
|
||||
SetHits( 80 );
|
||||
SetStam( 250 );
|
||||
SetMana( 0 );
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
|
||||
SetDamage( 6, 8 );
|
||||
ControlSlots = 1;
|
||||
}
|
||||
|
||||
SetDamageType( ResistanceType.Poison, 100 );
|
||||
SetDamageType( ResistanceType.Physical, 0 );
|
||||
SetResistance( ResistanceType.Physical, 90 );
|
||||
public NatureFury(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
SetSkill( SkillName.Wrestling, 90.0 );
|
||||
SetSkill( SkillName.MagicResist, 70.0 );
|
||||
SetSkill( SkillName.Tactics, 100.0 );
|
||||
public override bool DeleteCorpseOnDeath => Core.AOS;
|
||||
public override bool IsHouseSummonable => true;
|
||||
|
||||
Fame = 0;
|
||||
Karma = 0;
|
||||
public override double DispelDifficulty => 125.0;
|
||||
public override double DispelFocus => 90.0;
|
||||
|
||||
ControlSlots = 1;
|
||||
}
|
||||
public override bool BleedImmune => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
|
||||
public override void MoveToWorld( Point3D loc, Map map )
|
||||
{
|
||||
base.MoveToWorld( loc, map );
|
||||
Timer.DelayCall( TimeSpan.Zero, DoEffects );
|
||||
}
|
||||
public override bool AlwaysMurderer => true;
|
||||
public override string DefaultName => "a nature's fury";
|
||||
|
||||
public void DoEffects()
|
||||
{
|
||||
FixedParticles( 0x91C, 10, 180, 0x2543, 0, 0, EffectLayer.Waist );
|
||||
PlaySound( 0xE );
|
||||
PlaySound( 0x1BC );
|
||||
public override void MoveToWorld(Point3D loc, Map map)
|
||||
{
|
||||
base.MoveToWorld(loc, map);
|
||||
Timer.DelayCall(TimeSpan.Zero, DoEffects);
|
||||
}
|
||||
|
||||
if ( Alive && !Deleted )
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 7.0 ), DoEffects );
|
||||
}
|
||||
public void DoEffects()
|
||||
{
|
||||
FixedParticles(0x91C, 10, 180, 0x2543, 0, 0, EffectLayer.Waist);
|
||||
PlaySound(0xE);
|
||||
PlaySound(0x1BC);
|
||||
|
||||
public NatureFury( Serial serial )
|
||||
: base( serial )
|
||||
{
|
||||
}
|
||||
if (Alive && !Deleted)
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(7.0), DoEffects);
|
||||
}
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int)0 );
|
||||
}
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,121 +1,121 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Regions;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class NatureFurySpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Nature's Fury", "Rauvvrae",
|
||||
-1,
|
||||
false
|
||||
);
|
||||
public class NatureFurySpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Nature's Fury", "Rauvvrae",
|
||||
-1,
|
||||
false
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.5 );
|
||||
public NatureFurySpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5);
|
||||
|
||||
public NatureFurySpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override double RequiredSkill => 0.0;
|
||||
public override int RequiredMana => 24;
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( !base.CheckCast() )
|
||||
return false;
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (!base.CheckCast())
|
||||
return false;
|
||||
|
||||
if ( ( Caster.Followers + 1 ) > Caster.FollowersMax )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1049645 ); // You have too many followers to summon that creature.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Followers + 1 > Caster.FollowersMax)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget( this );
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget(this);
|
||||
}
|
||||
|
||||
public void Target( IPoint3D point )
|
||||
{
|
||||
Point3D p = new Point3D( point );
|
||||
Map map = Caster.Map;
|
||||
public void Target(IPoint3D point)
|
||||
{
|
||||
Point3D p = new Point3D(point);
|
||||
Map map = Caster.Map;
|
||||
|
||||
if ( map == null )
|
||||
return;
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
HouseRegion r = Region.Find( p, map ).GetRegion( typeof( HouseRegion ) ) as HouseRegion;
|
||||
HouseRegion r = Region.Find(p, map).GetRegion(typeof(HouseRegion)) as HouseRegion;
|
||||
|
||||
if ( r?.House != null && !r.House.IsFriend( Caster ) )
|
||||
return;
|
||||
if (r?.House != null && !r.House.IsFriend(Caster))
|
||||
return;
|
||||
|
||||
if ( !map.CanSpawnMobile( p.X, p.Y, p.Z ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 501942 ); // That location is blocked.
|
||||
}
|
||||
else if ( SpellHelper.CheckTown( p, Caster ) && CheckSequence() )
|
||||
{
|
||||
TimeSpan duration = TimeSpan.FromSeconds( Caster.Skills.Spellweaving.Value / 24 + 25 + FocusLevel * 2 );
|
||||
if (!map.CanSpawnMobile(p.X, p.Y, p.Z))
|
||||
{
|
||||
Caster.SendLocalizedMessage(501942); // That location is blocked.
|
||||
}
|
||||
else if (SpellHelper.CheckTown(p, Caster) && CheckSequence())
|
||||
{
|
||||
TimeSpan duration = TimeSpan.FromSeconds(Caster.Skills.Spellweaving.Value / 24 + 25 + FocusLevel * 2);
|
||||
|
||||
NatureFury nf = new NatureFury();
|
||||
BaseCreature.Summon( nf, false, Caster, p, 0x5CB, duration );
|
||||
NatureFury nf = new NatureFury();
|
||||
BaseCreature.Summon(nf, false, Caster, p, 0x5CB, duration);
|
||||
|
||||
new InternalTimer( nf ).Start();
|
||||
}
|
||||
new InternalTimer(nf).Start();
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private NatureFurySpell m_Owner;
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private NatureFurySpell m_Owner;
|
||||
|
||||
public InternalTarget( NatureFurySpell owner )
|
||||
: base( 10, true, TargetFlags.None )
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
public InternalTarget(NatureFurySpell 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 OnTarget(Mobile from, object o)
|
||||
{
|
||||
if (o is IPoint3D)
|
||||
m_Owner.Target((IPoint3D)o);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile from )
|
||||
{
|
||||
m_Owner?.FinishSequence();
|
||||
}
|
||||
}
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
m_Owner?.FinishSequence();
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private NatureFury m_NatureFury;
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private NatureFury m_NatureFury;
|
||||
|
||||
public InternalTimer( NatureFury nf )
|
||||
: base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 5.0 ) )
|
||||
{
|
||||
m_NatureFury = nf;
|
||||
}
|
||||
public InternalTimer(NatureFury nf)
|
||||
: base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
||||
{
|
||||
m_NatureFury = nf;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( m_NatureFury.Deleted || !m_NatureFury.Alive || m_NatureFury.DamageMin > 20 )
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_NatureFury.DamageMin;
|
||||
++m_NatureFury.DamageMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_NatureFury.Deleted || !m_NatureFury.Alive || m_NatureFury.DamageMin > 20)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
++m_NatureFury.DamageMin;
|
||||
++m_NatureFury.DamageMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,53 +3,53 @@ using Server.Network;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class ReaperFormSpell : ArcaneForm
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo( "Reaper Form", "Tarisstree", -1 );
|
||||
public class ReaperFormSpell : ArcaneForm
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo("Reaper Form", "Tarisstree", -1);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 2.5 );
|
||||
public ReaperFormSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += OnLogin;
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.5);
|
||||
|
||||
public static void OnLogin( LoginEventArgs e )
|
||||
{
|
||||
TransformContext context = TransformationSpellHelper.GetContext( e.Mobile );
|
||||
public override double RequiredSkill => 24.0;
|
||||
public override int RequiredMana => 34;
|
||||
|
||||
if ( context != null && context.Type == typeof( ReaperFormSpell ) )
|
||||
e.Mobile.Send( SpeedControl.WalkSpeed );
|
||||
}
|
||||
public override int Body => 0x11D;
|
||||
|
||||
public override double RequiredSkill => 24.0;
|
||||
public override int RequiredMana => 34;
|
||||
public override int FireResistOffset => -25;
|
||||
public override int PhysResistOffset => 5 + FocusLevel;
|
||||
public override int ColdResistOffset => 5 + FocusLevel;
|
||||
public override int PoisResistOffset => 5 + FocusLevel;
|
||||
public override int NrgyResistOffset => 5 + FocusLevel;
|
||||
|
||||
public override int Body => 0x11D;
|
||||
public virtual int SwingSpeedBonus => 10 + FocusLevel;
|
||||
public virtual int SpellDamageBonus => 10 + FocusLevel;
|
||||
|
||||
public override int FireResistOffset => -25;
|
||||
public override int PhysResistOffset => 5 + FocusLevel;
|
||||
public override int ColdResistOffset => 5 + FocusLevel;
|
||||
public override int PoisResistOffset => 5 + FocusLevel;
|
||||
public override int NrgyResistOffset => 5 + FocusLevel;
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += OnLogin;
|
||||
}
|
||||
|
||||
public virtual int SwingSpeedBonus => 10 + FocusLevel;
|
||||
public virtual int SpellDamageBonus => 10 + FocusLevel;
|
||||
public static void OnLogin(LoginEventArgs e)
|
||||
{
|
||||
TransformContext context = TransformationSpellHelper.GetContext(e.Mobile);
|
||||
|
||||
public ReaperFormSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
if (context != null && context.Type == typeof(ReaperFormSpell))
|
||||
e.Mobile.Send(SpeedControl.WalkSpeed);
|
||||
}
|
||||
|
||||
public override void DoEffect( Mobile m )
|
||||
{
|
||||
m.PlaySound( 0x1BA );
|
||||
public override void DoEffect(Mobile m)
|
||||
{
|
||||
m.PlaySound(0x1BA);
|
||||
|
||||
m.Send( SpeedControl.WalkSpeed );
|
||||
}
|
||||
m.Send(SpeedControl.WalkSpeed);
|
||||
}
|
||||
|
||||
public override void RemoveEffect( Mobile m )
|
||||
{
|
||||
m.Send( SpeedControl.Disable );
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void RemoveEffect(Mobile m)
|
||||
{
|
||||
m.Send(SpeedControl.Disable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +1,46 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
using Server.Engines.MLQuests;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class SummonFeySpell : ArcaneSummon<ArcaneFey>
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Summon Fey", "Alalithra",
|
||||
-1
|
||||
);
|
||||
public class SummonFeySpell : ArcaneSummon<ArcaneFey>
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Summon Fey", "Alalithra",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.5 );
|
||||
public SummonFeySpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 10;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5);
|
||||
|
||||
public SummonFeySpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 10;
|
||||
|
||||
public override int Sound => 0x217;
|
||||
public override int Sound => 0x217;
|
||||
|
||||
public override bool CheckSequence()
|
||||
{
|
||||
Mobile caster = Caster;
|
||||
public override bool CheckSequence()
|
||||
{
|
||||
Mobile caster = Caster;
|
||||
|
||||
// This is done after casting completes
|
||||
if ( caster is PlayerMobile )
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext( (PlayerMobile)caster );
|
||||
// This is done after casting completes
|
||||
if (caster is PlayerMobile)
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext((PlayerMobile)caster);
|
||||
|
||||
if ( context == null || !context.SummonFey )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1074563 ); // You haven't forged a friendship with the fey and are unable to summon their aid.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (context == null || !context.SummonFey)
|
||||
{
|
||||
caster.SendLocalizedMessage(
|
||||
1074563); // You haven't forged a friendship with the fey and are unable to summon their aid.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.CheckSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.CheckSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +1,45 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
using Server.Engines.MLQuests;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class SummonFiendSpell : ArcaneSummon<ArcaneFiend>
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Summon Fiend", "Nylisstra",
|
||||
-1
|
||||
);
|
||||
public class SummonFiendSpell : ArcaneSummon<ArcaneFiend>
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Summon Fiend", "Nylisstra",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 2.0 );
|
||||
public SummonFiendSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 10;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0);
|
||||
|
||||
public SummonFiendSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override double RequiredSkill => 38.0;
|
||||
public override int RequiredMana => 10;
|
||||
|
||||
public override int Sound => 0x216;
|
||||
public override int Sound => 0x216;
|
||||
|
||||
public override bool CheckSequence()
|
||||
{
|
||||
Mobile caster = Caster;
|
||||
public override bool CheckSequence()
|
||||
{
|
||||
Mobile caster = Caster;
|
||||
|
||||
// This is done after casting completes
|
||||
if ( caster is PlayerMobile )
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext( (PlayerMobile)caster );
|
||||
// This is done after casting completes
|
||||
if (caster is PlayerMobile)
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext((PlayerMobile)caster);
|
||||
|
||||
if ( context == null || !context.SummonFiend )
|
||||
{
|
||||
caster.SendLocalizedMessage( 1074564 ); // You haven't demonstrated mastery to summon a fiend.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (context == null || !context.SummonFiend)
|
||||
{
|
||||
caster.SendLocalizedMessage(1074564); // You haven't demonstrated mastery to summon a fiend.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.CheckSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.CheckSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,96 +3,94 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class ThunderstormSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Thunderstorm", "Erelonia",
|
||||
-1
|
||||
);
|
||||
public class ThunderstormSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Thunderstorm", "Erelonia",
|
||||
-1
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.5 );
|
||||
private static Dictionary<Mobile, Timer> m_Table = new Dictionary<Mobile, Timer>();
|
||||
|
||||
public override double RequiredSkill => 10.0;
|
||||
public override int RequiredMana => 32;
|
||||
public ThunderstormSpell(Mobile caster, Item scroll)
|
||||
: base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public ThunderstormSpell( Mobile caster, Item scroll )
|
||||
: base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5);
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( CheckSequence() )
|
||||
{
|
||||
Caster.PlaySound( 0x5CE );
|
||||
public override double RequiredSkill => 10.0;
|
||||
public override int RequiredMana => 32;
|
||||
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
public override void OnCast()
|
||||
{
|
||||
if (CheckSequence())
|
||||
{
|
||||
Caster.PlaySound(0x5CE);
|
||||
|
||||
int damage = Math.Max( 11, 10 + (int)(skill / 24) ) + FocusLevel;
|
||||
double skill = Caster.Skills[SkillName.Spellweaving].Value;
|
||||
|
||||
int sdiBonus = AosAttributes.GetValue( Caster, AosAttribute.SpellDamage );
|
||||
int damage = Math.Max(11, 10 + (int)(skill / 24)) + FocusLevel;
|
||||
|
||||
int pvmDamage = damage * ( 100 + sdiBonus );
|
||||
pvmDamage /= 100;
|
||||
int sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage);
|
||||
|
||||
if ( sdiBonus > 15 )
|
||||
sdiBonus = 15;
|
||||
int pvmDamage = damage * (100 + sdiBonus);
|
||||
pvmDamage /= 100;
|
||||
|
||||
int pvpDamage = damage * ( 100 + sdiBonus );
|
||||
pvpDamage /= 100;
|
||||
if (sdiBonus > 15)
|
||||
sdiBonus = 15;
|
||||
|
||||
int range = 2 + FocusLevel;
|
||||
TimeSpan duration = TimeSpan.FromSeconds( 5 + FocusLevel );
|
||||
int pvpDamage = damage * (100 + sdiBonus);
|
||||
pvpDamage /= 100;
|
||||
|
||||
List<Mobile> targets = new List<Mobile>();
|
||||
int range = 2 + FocusLevel;
|
||||
TimeSpan duration = TimeSpan.FromSeconds(5 + FocusLevel);
|
||||
|
||||
foreach( Mobile m in Caster.GetMobilesInRange( range ) )
|
||||
{
|
||||
if ( Caster != m && SpellHelper.ValidIndirectTarget( Caster, m ) && Caster.CanBeHarmful( m, false ) && Caster.InLOS( m ) )
|
||||
targets.Add( m );
|
||||
}
|
||||
List<Mobile> targets = new List<Mobile>();
|
||||
|
||||
for( int i = 0; i < targets.Count; i++ )
|
||||
{
|
||||
Mobile m = targets[i];
|
||||
foreach (Mobile m in Caster.GetMobilesInRange(range))
|
||||
if (Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) &&
|
||||
Caster.InLOS(m))
|
||||
targets.Add(m);
|
||||
|
||||
Caster.DoHarmful( m );
|
||||
for (int i = 0; i < targets.Count; i++)
|
||||
{
|
||||
Mobile m = targets[i];
|
||||
|
||||
Spell oldSpell = m.Spell as Spell;
|
||||
Caster.DoHarmful(m);
|
||||
|
||||
SpellHelper.Damage( this, m, ( m.Player && Caster.Player ) ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100 );
|
||||
Spell oldSpell = m.Spell as Spell;
|
||||
|
||||
if ( oldSpell != null && oldSpell != m.Spell )
|
||||
{
|
||||
if ( !CheckResisted( m ) )
|
||||
{
|
||||
m_Table[m] = Timer.DelayCall<Mobile>( duration, DoExpire, m );
|
||||
SpellHelper.Damage(this, m, m.Player && Caster.Player ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100);
|
||||
|
||||
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.Thunderstorm, 1075800, duration, m, GetCastRecoveryMalus( m ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldSpell != null && oldSpell != m.Spell)
|
||||
if (!CheckResisted(m))
|
||||
{
|
||||
m_Table[m] = Timer.DelayCall(duration, DoExpire, m);
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
BuffInfo.AddBuff(m,
|
||||
new BuffInfo(BuffIcon.Thunderstorm, 1075800, duration, m, GetCastRecoveryMalus(m)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Mobile, Timer> m_Table = new Dictionary<Mobile, Timer>();
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public static int GetCastRecoveryMalus( Mobile m )
|
||||
{
|
||||
return m_Table.ContainsKey( m ) ? 6 : 0;
|
||||
}
|
||||
public static int GetCastRecoveryMalus(Mobile m)
|
||||
{
|
||||
return m_Table.ContainsKey(m) ? 6 : 0;
|
||||
}
|
||||
|
||||
public static void DoExpire( Mobile m )
|
||||
{
|
||||
if (m_Table.TryGetValue( m, out Timer t ))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove( m );
|
||||
public static void DoExpire(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out Timer t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove(m);
|
||||
|
||||
BuffInfo.RemoveBuff( m, BuffIcon.Thunderstorm );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,90 +3,89 @@ using Server.Targeting;
|
|||
|
||||
namespace Server.Spells.Spellweaving
|
||||
{
|
||||
public class WordOfDeathSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo( "Word of Death", "Nyraxle", -1 );
|
||||
public class WordOfDeathSpell : ArcanistSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo("Word of Death", "Nyraxle", -1);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 3.5 );
|
||||
public WordOfDeathSpell(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 80.0;
|
||||
public override int RequiredMana => 50;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5);
|
||||
|
||||
public WordOfDeathSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override double RequiredSkill => 80.0;
|
||||
public override int RequiredMana => 50;
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget( this );
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.Target = new InternalTarget(this);
|
||||
}
|
||||
|
||||
public void Target( Mobile m )
|
||||
{
|
||||
if ( !Caster.CanSee( m ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
|
||||
}
|
||||
else if ( CheckHSequence( m ) )
|
||||
{
|
||||
Point3D loc = m.Location;
|
||||
loc.Z += 50;
|
||||
public void Target(Mobile m)
|
||||
{
|
||||
if (!Caster.CanSee(m))
|
||||
{
|
||||
Caster.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
else if (CheckHSequence(m))
|
||||
{
|
||||
Point3D loc = m.Location;
|
||||
loc.Z += 50;
|
||||
|
||||
m.PlaySound( 0x211 );
|
||||
m.FixedParticles( 0x3779, 1, 30, 0x26EC, 0x3, 0x3, EffectLayer.Waist );
|
||||
m.PlaySound(0x211);
|
||||
m.FixedParticles(0x3779, 1, 30, 0x26EC, 0x3, 0x3, EffectLayer.Waist);
|
||||
|
||||
Effects.SendMovingParticles( new Entity( Serial.Zero, loc, m.Map ), new Entity( Serial.Zero, m.Location, m.Map ), 0xF5F, 1, 0, true, false, 0x21, 0x3F, 0x251D, 0, 0, EffectLayer.Head, 0 );
|
||||
Effects.SendMovingParticles(new Entity(Serial.Zero, loc, m.Map), new Entity(Serial.Zero, m.Location, m.Map),
|
||||
0xF5F, 1, 0, true, false, 0x21, 0x3F, 0x251D, 0, 0, EffectLayer.Head, 0);
|
||||
|
||||
double percentage = 0.05 * FocusLevel;
|
||||
double percentage = 0.05 * FocusLevel;
|
||||
|
||||
int damage;
|
||||
int damage;
|
||||
|
||||
if ( !m.Player && (((double)m.Hits / (double)m.HitsMax) < percentage ))
|
||||
{
|
||||
damage = 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
int minDamage = (int)Caster.Skills.Spellweaving.Value / 5;
|
||||
int maxDamage = (int)Caster.Skills.Spellweaving.Value / 3;
|
||||
damage = Utility.RandomMinMax(minDamage, maxDamage);
|
||||
int damageBonus = AosAttributes.GetValue( Caster, AosAttribute.SpellDamage );
|
||||
if (m.Player && damageBonus > 15)
|
||||
damageBonus = 15;
|
||||
damage *= damageBonus + 100;
|
||||
damage /= 100;
|
||||
}
|
||||
if (!m.Player && m.Hits / (double)m.HitsMax < percentage)
|
||||
{
|
||||
damage = 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
int minDamage = (int)Caster.Skills.Spellweaving.Value / 5;
|
||||
int maxDamage = (int)Caster.Skills.Spellweaving.Value / 3;
|
||||
damage = Utility.RandomMinMax(minDamage, maxDamage);
|
||||
int damageBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage);
|
||||
if (m.Player && damageBonus > 15)
|
||||
damageBonus = 15;
|
||||
damage *= damageBonus + 100;
|
||||
damage /= 100;
|
||||
}
|
||||
|
||||
int[] types = new int[4];
|
||||
types[Utility.Random( types.Length )] = 100;
|
||||
int[] types = new int[4];
|
||||
types[Utility.Random(types.Length)] = 100;
|
||||
|
||||
SpellHelper.Damage( this, m, damage, 0, types[0], types[1], types[2], types[3] ); //Chaos damage. Random elemental damage
|
||||
}
|
||||
SpellHelper.Damage(this, m, damage, 0, types[0], types[1], types[2],
|
||||
types[3]); //Chaos damage. Random elemental damage
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private WordOfDeathSpell m_Owner;
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private WordOfDeathSpell m_Owner;
|
||||
|
||||
public InternalTarget( WordOfDeathSpell owner ) : base( 10, false, TargetFlags.Harmful )
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
public InternalTarget(WordOfDeathSpell owner) : base(10, false, TargetFlags.Harmful)
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile m, object o )
|
||||
{
|
||||
if ( o is Mobile )
|
||||
{
|
||||
m_Owner.Target( (Mobile)o );
|
||||
}
|
||||
}
|
||||
protected override void OnTarget(Mobile m, object o)
|
||||
{
|
||||
if (o is Mobile) m_Owner.Target((Mobile)o);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile m )
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void OnTargetFinish(Mobile m)
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue