using System; using System.Collections.Generic; using Server.Items; using Server.Engines.CannedEvil; using Server.Guilds; using Server.Factions; using Server.Engines.PartySystem; using Server.Regions; namespace Server.Spells.Necromancy { public class ExorcismSpell : NecromancerSpell { private static SpellInfo m_Info = new SpellInfo( "Exorcism", "Ort Corp Grav", 203, 9031, Reagent.NoxCrystal, Reagent.GraveDust ); public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 2.0 ); public override double RequiredSkill => 80.0; public override int RequiredMana => 40; public ExorcismSpell( Mobile caster, Item scroll ) : base( caster, scroll, m_Info ) { } public override bool CheckCast() { if ( Caster.Skills.SpiritSpeak.Value < 100.0 ) { Caster.SendLocalizedMessage( 1072112 ); // You must have GM Spirit Speak to use this spell return false; } return base.CheckCast(); } public override bool DelayedDamage => false; private static readonly int Range = (Core.ML ? 48 : 18); public override int ComputeKarmaAward() { return 0; //no karma lost from this spell! } public override void OnCast() { ChampionSpawnRegion r = Caster.Region.GetRegion( typeof( ChampionSpawnRegion ) ) as ChampionSpawnRegion; if ( r == null || !Caster.InRange( r.ChampionSpawn, Range ) ) { Caster.SendLocalizedMessage( 1072111 ); // You are not in a valid exorcism region. } else if ( CheckSequence() ) { Map map = Caster.Map; if ( map != null ) { List targets = new List(); foreach( Mobile m in r.ChampionSpawn.GetMobilesInRange( Range ) ) if ( IsValidTarget( m ) ) targets.Add( m ); for( int i = 0; i < targets.Count; ++i ) { Mobile m = targets[i]; //Suprisingly, no sparkle type effects m.Location = GetNearestShrine( m ); } } } FinishSequence(); } private bool IsValidTarget( Mobile m ) { if ( !m.Player || m.Alive ) return false; Corpse c = m.Corpse as Corpse; Map map = m.Map; if ( c != null && !c.Deleted && map != null && c.Map == map ) { if ( SpellHelper.IsAnyT2A( map, c.Location ) && SpellHelper.IsAnyT2A( map, m.Location ) ) return false; //Same Map, both in T2A, ie, same 'sub server'. if ( m.Region.IsPartOf( typeof( DungeonRegion ) ) == Region.Find( c.Location, map ).IsPartOf( typeof( DungeonRegion ) ) ) return false; //Same Map, both in Dungeon region OR They're both NOT in a dungeon region. //Just an approximation cause RunUO doens't divide up the world the same way OSI does ;p } Party p = Party.Get( m ); if ( p != null && p.Contains( Caster ) ) return false; if ( m.Guild != null && Caster.Guild != null ) { Guild mGuild = m.Guild as Guild; Guild cGuild = Caster.Guild as Guild; if ( mGuild.IsAlly( cGuild ) ) return false; if ( mGuild == cGuild ) return false; } Faction f = Faction.Find( m ); if ( Faction.Facet == m.Map && f != null && f == Faction.Find( Caster ) ) return false; return true; } private static Point3D GetNearestShrine( Mobile m ) { Map map = m.Map; Point3D[] locList; if ( map == Map.Felucca || map == Map.Trammel ) locList = m_BritanniaLocs; else if ( map == Map.Ilshenar ) locList = m_IllshLocs; else if ( map == Map.Tokuno ) locList = m_TokunoLocs; else if ( map == Map.Malas ) locList = m_MalasLocs; else locList = new Point3D[0]; Point3D closest = Point3D.Zero; double minDist = double.MaxValue; for( int i = 0; i < locList.Length; i++ ) { Point3D p = locList[i]; double dist = m.GetDistanceToSqrt( p ); if ( minDist > dist ) { closest = p; minDist = dist; } } return closest; } private static readonly Point3D[] m_BritanniaLocs = { new Point3D( 1470, 843, 0 ), new Point3D( 1857, 865, -1 ), new Point3D( 4220, 563, 36 ), new Point3D( 1732, 3528, 0 ), new Point3D( 1300, 644, 8 ), new Point3D( 3355, 302, 9 ), new Point3D( 1606, 2490, 5 ), new Point3D( 2500, 3931, 3 ), new Point3D( 4264, 3707, 0 ) }; private static readonly Point3D[] m_IllshLocs = { new Point3D( 1222, 474, -17 ), new Point3D( 718, 1360, -60), new Point3D( 297, 1014, -19 ), new Point3D( 986, 1006, -36 ), new Point3D( 1180, 1288, -30 ), new Point3D( 1538, 1341, -3 ), new Point3D( 528, 223, -38 ) }; private static readonly Point3D[] m_MalasLocs = { new Point3D ( 976, 517, -30 ) }; private static readonly Point3D[] m_TokunoLocs = { new Point3D( 710, 1162, 25 ), new Point3D( 1034, 515, 18 ), new Point3D( 295, 712, 55 ) }; } }