RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Black Lich

Black Lich

version 3.0

Updates
Added Lich Staff.
Raised rate on wraiths it summons so dont spawn to many to fast.
Fixed necromage ai removed wither spell. This should keep monsters from attacking lich thanks to zardd for bug report on that.

Black Lich Features:
Will summons Wraiths to help it.
Will polymorph attacker into a skeleton
Drops Black Lich staff as loot.

Install:
You will need Necromage Ai if you dont have that just ask me ill add it to my post. Then just drop in Black Lich into you runuo.

Planned Features:
Blacklich AI

Bugs:
None

I credit the person who came up with necromageai for that .cs file
 

Attachments

  • blacklich.cs
    5.2 KB · Views: 440
  • lichstaff.cs
    1.5 KB · Views: 391
  • NecroMageAI.cs
    23.2 KB · Views: 402
here you are :)

this not my script so no credit for me all credit goes to dude made it :)

okay find this code in baseai

public enum AIType
{
AI_Use_Default,
AI_Melee,
AI_Animal,
AI_Archer,
AI_Healer,
AI_Vendor,
AI_Mage,
AI_Berserk,
AI_Predator,
AI_Thief

Add this right after thief ai
AI_Necromage
dont forgot get to add , on the AI_Thief or wont read and cause a error.

now go down and find this line
SkillName.Meditation
Add this line right after it
SkillName.Necromancy
now dont forgot the , behind meditation


Now open basecreature.cs
find this line
case AIType.AI_Thief:
m_AI = new ThiefAI(this);
break;

Add this after it
case AIType.AI_Necromage:
m_AI = new NecromageAI(this);
break;

All done any errors post ill fix them. :)

if you dont want to use this as a necromage ai i can post the black lich using just mage ai :)
 

Greystar

Wanderer
interesting concept kinda reminds me of an evil version of the wolf mom and pups that was in the archives... VERY evil version that is.
 
hhee never seen that hehe whats name of it ill look it up :)

well im making version 3.0 much better more stuff ect :)

my next project will be New Ice Dragon :) im trying to make monsters come alive more like the are post to be cause you get sick of the same old monsters thats easy to beat.

I been thinking no one can or should beable to kill a dragon by them selfs pff dragons should be stronger drakes i see a one person killing that but a drag or a lich come on lichs was post to be the strongest so are dragons :) but thanks guys im glad you likes it :)

watch out for new version and new mobiles that are post to do what the was created to do by the real D&D team.
 

zardd

Sorceror
Brilliant script simple to get going as well and works great.

Only issue i have encounted if you can call it that is that when the lich summons a monster the slkeletons/spectres generally will attack the lich what would need to be done to make these summoned monsters immune to the lich attacks and so they agro on the players / other things and not the lich.

Look forward to some of your other D&D releases.
 

Greystar

Wanderer
Dragon Slayer said:
hhee never seen that hehe whats name of it ill look it up :)

well im making version 3.0 much better more stuff ect :)

my next project will be New Ice Dragon :) im trying to make monsters come alive more like the are post to be cause you get sick of the same old monsters thats easy to beat.

I been thinking no one can or should beable to kill a dragon by them selfs pff dragons should be stronger drakes i see a one person killing that but a drag or a lich come on lichs was post to be the strongest so are dragons :) but thanks guys im glad you likes it :)

watch out for new version and new mobiles that are post to do what the was created to do by the real D&D team.


Use the advanced search feature and find all threads started by David with wolf in the thread it will show up quickly.
 

zardd

Sorceror
What will the white lich do..

Something like a uber fairy? :D
Will only agro on negative karma things and uses paladin / magery?
*just a stab in the wind no thought was used in the above statement :rolleyes: *


Dragon Slayer:
The way i replicated this issue was to spawn a black lich.
Then tile something like militiafighter's near it 10 or so.. yeah i like to watch things get slaughtered...
Anyway i think it maybe to do with wither but sometimes as soon as a skeleton is spawned it seems to agro straight onto the lich :(
 
okay i think i did find it has to do with necromage ai you are right around that spot the spells its casting is casuing monsters to attack so im going to be fixing that necromagie ai to be more brilliant hehe so version 3.0 will come with a updated ai :p im calling it blacklich ai

um white lich LOL well could be a dead white wizard hmm makes me think hehe yeah could use paladin ai but or what about a necropaladin ai for a white lich ? or a magepaladin ai well post all thoughts about that .
 

zardd

Sorceror
Considering necromancy and paladin spell damage / magnitude are controlled by karma negative being necromancy and prositive being paladin bonus's making a necropaladin prolly wouldnt work to well hence i suggested PaladinMage..
I just dont imagine the spells to be all that powerful with that taken into account.

Oh well glad i found something to keep you busy with :p
Keep up the good work and thank you for sharing these.
 

zardd

Sorceror
Changes for Blacklich v2 to stop 'Team killing wraiths'

Well since this guy is banned..
For those that still have version 2 of this script..
You can stop the wraiths and also skeletons attacking each other by doing the following:

Code:
using System;
using Server;
using Server.Items;
using Server.Spells;
using Server.Spells.Seventh;
using Server.Spells.Fifth;

namespace Server.Mobiles
{
	public class BlackLich : BaseCreature
	{
		[Constructable]
		public BlackLich() : base( AIType.AI_Necromage, FightMode.Closest, 10, 1, 0.2, 0.4 )
		{
			SpeechHue = Utility.RandomDyedHue();
			Hue = 0x2C3;
			Female = false;
			BodyValue = 24;
			BaseSoundID = 1001;
			Name = "a black lich";

			SetStr( 416, 505 );
			SetDex( 146, 165 );
			SetInt( 566, 655 );

			SetHits( 2000 );
			SetMana( 2000 );

			SetDamage( 10, 15 );

			SetDamageType( ResistanceType.Physical, 70 );
			SetDamageType( ResistanceType.Cold, 15 );
			SetDamageType( ResistanceType.Energy, 15 );

			SetResistance( ResistanceType.Physical, 40, 50 );
			SetResistance( ResistanceType.Fire, 30, 40 );
			SetResistance( ResistanceType.Cold, 50, 60 );
			SetResistance( ResistanceType.Poison, 50, 60 );
			SetResistance( ResistanceType.Energy, 40, 50 );

			SetSkill( SkillName.EvalInt, 77.6, 87.5 );
			SetSkill( SkillName.Necromancy, 100.6, 120.5 );
			SetSkill( SkillName.SpiritSpeak, 110.1, 120.5 );
			SetSkill( SkillName.Magery, 90.1, 100.1);
			SetSkill( SkillName.Poisoning, 80.5 );
			SetSkill( SkillName.Meditation, 110.0 );
			SetSkill( SkillName.MagicResist, 80.1, 85.0 );
			SetSkill( SkillName.Parry, 90.1, 95.1 );
			SetSkill( SkillName.Tactics, 120.0 );
			SetSkill( SkillName.Wrestling, 70.1, 80.0 );

			Fame = 24000;
			Karma = -24000;

			VirtualArmor = 65;

			PackNecroReg( 50, 100 );
			PackGold( 5500, 8000 );
			AddItem( new NecromancerSpellbook( (UInt64)0xFFFF ) );
			
		}

		public override void GenerateLoot()
		{
			AddLoot( LootPack.MedScrolls, 4 );
		}

		public override bool CanRummageCorpses{ get{ return true; } }
		public override bool AlwaysMurderer{ get{ return true; } }
		public override bool Unprovokable{ get{ return true; } }
		public override bool Uncalmable{ get{ return true; } }
		public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
		public override int TreasureMapLevel{ get{ return 5; } }

		public void Polymorph( Mobile m )
		{
			if ( !m.CanBeginAction( typeof( PolymorphSpell ) ) || !m.CanBeginAction( typeof( IncognitoSpell ) ) || m.IsBodyMod )
				return;

			IMount mount = m.Mount;

			if ( mount != null )
				mount.Rider = null;

			if ( m.Mounted )
				return;

			if ( m.BeginAction( typeof( PolymorphSpell ) ) )
			{
				Item disarm = m.FindItemOnLayer( Layer.OneHanded );

				if ( disarm != null && disarm.Movable )
					m.AddToBackpack( disarm );

				disarm = m.FindItemOnLayer( Layer.TwoHanded );

				if ( disarm != null && disarm.Movable )
					m.AddToBackpack( disarm );

				m.BodyMod = 50;
				m.HueMod = 0;

				new ExpirePolymorphTimer( m ).Start();
			}
		}

		private class ExpirePolymorphTimer : Timer
		{
			private Mobile m_Owner;

			public ExpirePolymorphTimer( Mobile owner ) : base( TimeSpan.FromMinutes( 3.0 ) )
			{
				m_Owner = owner;

				Priority = TimerPriority.OneSecond;
			}

			protected override void OnTick()
			{
				if ( !m_Owner.CanBeginAction( typeof( PolymorphSpell ) ) )
				{
					m_Owner.BodyMod = 0;
					m_Owner.HueMod = -1;
					m_Owner.EndAction( typeof( PolymorphSpell ) );
				}
			}
		}

		public void SpawnWraiths( Mobile target )
		{
			Map map = this.Map;

			if ( map == null )
				return;

			int newWraiths = Utility.RandomMinMax( 1, 3 );

			for ( int i = 0; i < newWraiths; ++i )
			{
				Wraith wraith = new Wraith();

				wraith.Team = this.Team;
				wraith.FightMode = FightMode.Closest;

				bool validLocation = false;
				Point3D loc = this.Location;

				for ( int j = 0; !validLocation && j < 10; ++j )
				{
					int x = X + Utility.Random( 3 ) - 1;
					int y = Y + Utility.Random( 3 ) - 1;
					int z = map.GetAverageZ( x, y );

					if ( validLocation = map.CanFit( x, y, this.Z, 16, false, false ) )
						loc = new Point3D( x, y, Z );
					else if ( validLocation = map.CanFit( x, y, z, 16, false, false ) )
						loc = new Point3D( x, y, z );
				}

				wraith.MoveToWorld( loc, map );
// Change the below line from wraith.Combatant = target; to read the below. 
				[B][COLOR="Red"]wraith.Combatant = null;[/COLOR][/B]
			}
		}

		public void DoSpecialAbility( Mobile target )
		{
			if ( 0.50 >= Utility.RandomDouble() )
				Polymorph( target );

			if ( 0.05 >= Utility.RandomDouble() )
				SpawnWraiths( target );
		}

		public override void OnGaveMeleeAttack( Mobile defender )
		{
			base.OnGaveMeleeAttack( defender );

			DoSpecialAbility( defender );

			defender.Damage( Utility.Random( 20, 10 ), this );
			defender.Stam -= Utility.Random( 20, 10 );
			defender.Mana -= Utility.Random( 20, 10 );
		}

		public override void OnGotMeleeAttack( Mobile attacker )
		{
			base.OnGotMeleeAttack( attacker );

			DoSpecialAbility( attacker );

		}

		public BlackLich( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 0 );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();
		}
	}
}

By doing this you dont need to disable wither from the NecroMage AI
I still wanted the black lich and other NecroMage monsters i have made to cast wither so basically i changed the way wraith.combatant target when the wraiths / skeletons are spawned.

Some people may have already worked this out..
Apologies but this post was more for those that have not yet worked it out and maybe in the same boat as me (not wanting the necromage script to not cast wither)

*as normal any of you professional scriptors.. input is welcome :)
 

dianus

Wanderer
Hello, I need help with this file. I am currently using this script on Runuo1.0 and its working fine. Love it :) I am trying to put this script in RunUo2.0 but keeps crashing on me, these are the errors I get:
Code:
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
 + Customes/Black Lich/NecroMageAI.cs:
    CS0103: Line 70: The name 'AquireFocusMob' does not exist in the current con
text
    CS0103: Line 161: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0103: Line 422: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0103: Line 440: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0103: Line 454: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0117: Line 475: 'Server.Mobiles.BaseCreature' does not contain a definitio
n for 'Controled'
    CS0103: Line 580: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0103: Line 628: The name 'AquireFocusMob' does not exist in the current co
ntext
    CS0029: Line 657: Cannot implicitly convert type 'System.Collections.Generic
.List<Server.AggressorInfo>' to 'System.Collections.ArrayList'
    CS0029: Line 658: Cannot implicitly convert type 'System.Collections.Generic
.List<Server.AggressorInfo>' to 'System.Collections.ArrayList'
Scripts: One or more scripts failed to compile or no script files were found.
 - Press return to exit, or R to try again.
This is the script:
Code:
using System;
using System.Collections;
using Server.Targeting;
using Server.Network;
using Server.Mobiles;
using Server.Items;
using Server.Spells;
using Server.Spells.First;
using Server.Spells.Second;
using Server.Spells.Third;
using Server.Spells.Fourth;
using Server.Spells.Fifth;
using Server.Spells.Sixth;
using Server.Spells.Seventh;
using Server.Spells.Necromancy;
using Server.Misc;
using Server.Regions;
using Server.SkillHandlers;

namespace Server.Mobiles
{
	public class NecromageAI : BaseAI
	{
		private DateTime m_NextCastTime;

		public NecromageAI( BaseCreature m ) : base( m )
		{
		}

		public override bool Think()
		{
			if ( m_Mobile.Deleted )
				return false;

			Target targ = m_Mobile.Target;

			if ( targ != null )
			{
				ProcessTarget( targ );

				return true;
			}
			else
			{
				return base.Think();
			}
		}

		public virtual bool SmartAI
		{
			get{ return ( m_Mobile is BaseVendor || m_Mobile is BaseEscortable ); }
		}

		private const double HealChance = 0.05; // 5% chance to heal at gm necromancy, uses spirit speak healing
		private const double TeleportChance = 0.05; // 5% chance to teleport at gm necromancy
		private const double DispelChance = 0.75; // 75% chance to dispel at gm necromancy

		public virtual double ScaleByNecromancy( double v )
		{
			return m_Mobile.Skills[SkillName.Necromancy].Value * v * 0.01;
		}
		
		public virtual double ScaleByMagery( double v )
		{
			return m_Mobile.Skills[SkillName.Magery].Value * v * 0.01;
		}

		public override bool DoActionWander()
		{
			if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
			{
				if ( m_Mobile.Debug )
					m_Mobile.DebugSay( "I am going to attack {0}", m_Mobile.FocusMob.Name );

				m_Mobile.Combatant = m_Mobile.FocusMob;
				Action = ActionType.Combat;
				m_NextCastTime = DateTime.Now;
			}
			else if ( SmartAI && m_Mobile.Mana < m_Mobile.ManaMax )
			{
				m_Mobile.DebugSay( "I am going to meditate" );

				m_Mobile.UseSkill( SkillName.Meditation );
			}
			else
			{
				m_Mobile.DebugSay( "I am wandering" );

				m_Mobile.Warmode = false;

				base.DoActionWander();

				if ( m_Mobile.Poisoned )
				{
					new CureSpell( m_Mobile, null ).Cast();
				}
				else if ( !m_Mobile.Summoned && (SmartAI || (ScaleByMagery( HealChance ) > Utility.RandomDouble())) )
				{
					if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
					{
						if ( !new GreaterHealSpell( m_Mobile, null ).Cast() )
							new HealSpell( m_Mobile, null ).Cast();
					}
					else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 10) )
					{
						new HealSpell( m_Mobile, null ).Cast();
					}
				}
			}

			return true;
		}

		public void RunTo( Mobile m )
		{
			if ( !SmartAI )
			{
				if ( !MoveTo( m, true, m_Mobile.RangeFight ) )
					OnFailedMove();

				return;
			}

			if ( m.Paralyzed || m.Frozen )
			{
				if ( m_Mobile.InRange( m, 1 ) )
					RunFrom( m );
				else if ( !m_Mobile.InRange( m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2 ) && !MoveTo( m, true, 1 ) )
					OnFailedMove();
			}
			else
			{
				if ( !m_Mobile.InRange( m, m_Mobile.RangeFight ) )
				{
					if ( !MoveTo( m, true, 1 ) )
						OnFailedMove();
				}
				else if ( m_Mobile.InRange( m, m_Mobile.RangeFight - 1 ) )
				{
					RunFrom( m );
				}
			}
		}

		public void RunFrom( Mobile m )
		{
			Run( (m_Mobile.GetDirectionTo( m ) - 4) & Direction.Mask );
		}

		public void OnFailedMove()
		{
			if ( !m_Mobile.DisallowAllMoves && (SmartAI ? Utility.Random( 4 ) == 0 : ScaleByMagery( TeleportChance ) > Utility.RandomDouble()) )
			{
				if ( m_Mobile.Target != null )
					m_Mobile.Target.Cancel( m_Mobile, TargetCancelType.Canceled );

				new TeleportSpell( m_Mobile, null ).Cast();

				m_Mobile.DebugSay( "I am stuck, I'm going to try teleporting away" );
			}
			else if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
			{
				if ( m_Mobile.Debug )
					m_Mobile.DebugSay( "My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name );

				m_Mobile.Combatant = m_Mobile.FocusMob;
				Action = ActionType.Combat;
			}
			else
			{
				m_Mobile.DebugSay( "I am stuck" );
			}
		}

		public void Run( Direction d )
		{
			if ( (m_Mobile.Spell != null && m_Mobile.Spell.IsCasting) || m_Mobile.Paralyzed || m_Mobile.Frozen || m_Mobile.DisallowAllMoves )
				return;

			m_Mobile.Direction = d | Direction.Running;

			if ( !DoMove( m_Mobile.Direction, true ) )
				OnFailedMove();
		}

		public virtual Spell GetRandomDamageSpell()
		{
			int maxCircle = (int)((m_Mobile.Skills[SkillName.Necromancy].Value + 50.0) / (100.0 / 7.0));
			int minCircle = (int)((m_Mobile.Skills[SkillName.Magery].Value + 50.0) / (100.0 / 7.0));

			if ( maxCircle < 2 && minCircle < 8 )
				maxCircle = 2;
				minCircle = 8;

			switch ( Utility.Random( minCircle + (maxCircle*2) ) )
			{
				case  0: return new FireballSpell( m_Mobile, null );
				case  1: return new PainSpikeSpell( m_Mobile, null );
				case  2: return new MindBlastSpell( m_Mobile, null );
				case  3: return new BloodOathSpell( m_Mobile, null );
				case  4: return new FlameStrikeSpell( m_Mobile, null );
				case  5: return new EvilOmenSpell( m_Mobile, null );
				case  6: return new CurseSpell( m_Mobile, null );
				case  7: return new MindRotSpell( m_Mobile, null );
				case  8: return new LightningSpell( m_Mobile, null );
				case  9: return new StrangleSpell( m_Mobile, null );
				//case 10: return new WitherSpell( m_Mobile, null );
				case 10: return new VengefulSpiritSpell( m_Mobile, null );
				default: return new FlameStrikeSpell( m_Mobile, null );
			}
		}

		public virtual Spell DoDispel( Mobile toDispel )
		{
			if ( !SmartAI )
			{
				if ( ScaleByMagery( DispelChance ) > Utility.RandomDouble() )
					return new DispelSpell( m_Mobile, null );

				return ChooseSpell( toDispel );
			}

			Spell spell = null;

			if ( !m_Mobile.Summoned && Utility.Random( 0, 4 + (m_Mobile.Hits == 0 ? m_Mobile.HitsMax : (m_Mobile.HitsMax / m_Mobile.Hits)) ) >= 3 )
			{
				if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
					m_Mobile.UseSkill( SkillName.SpiritSpeak );
				else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 20) )
					m_Mobile.UseSkill( SkillName.SpiritSpeak );
			}

			if ( spell == null )
			{
				if ( !m_Mobile.DisallowAllMoves && Utility.Random( (int)m_Mobile.GetDistanceToSqrt( toDispel ) ) == 0 )
					spell = new TeleportSpell( m_Mobile, null );
				else if ( Utility.Random( 3 ) == 0 && !m_Mobile.InRange( toDispel, 3 ) && !toDispel.Paralyzed && !toDispel.Frozen )
					spell = new ParalyzeSpell( m_Mobile, null );
				else
					spell = new DispelSpell( m_Mobile, null );
			}

			return spell;
		}

		public virtual Spell ChooseSpell( Mobile c )
		{
			if ( !SmartAI )
			{
				if ( !m_Mobile.Summoned && ScaleByMagery( HealChance ) > Utility.RandomDouble() )
				{
					if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
						return new GreaterHealSpell( m_Mobile, null );
					else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 10) )
						return new HealSpell( m_Mobile, null );
				}

				return GetRandomDamageSpell();
			}

			Spell spell = null;

			int healChance = (m_Mobile.Hits == 0 ? m_Mobile.HitsMax : (m_Mobile.HitsMax / m_Mobile.Hits));

			if ( m_Mobile.Summoned )
				healChance = 0;

			switch ( Utility.Random( 5 + healChance ) )
			{
				case 0: // Heal  myself
				{
					if ( !m_Mobile.Summoned )
					{
						if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
							m_Mobile.UseSkill( SkillName.SpiritSpeak );
						else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 10) )
							m_Mobile.UseSkill( SkillName.SpiritSpeak );
					}

					break;
				}
				case 1: // PoisonStrike them
				{
					if ( !c.Poisoned )
						spell = new PoisonStrikeSpell( m_Mobile, null );

					break;
				}
				case 2: // Deal some damage
				{
					spell = GetRandomDamageSpell();

					break;
				}
				case 3: // Set up a combo of attacks
				{
					if ( m_Mobile.Mana < 30 && m_Mobile.Mana > 15 )
					{
						if ( c.Paralyzed && !c.Poisoned )
						{
							m_Mobile.DebugSay( "I am going to meditate" );

							m_Mobile.UseSkill( SkillName.Meditation );
						}
						else if ( !c.Poisoned )
						{
							spell = new PoisonSpell( m_Mobile, null );
						}
					}
					else if ( m_Mobile.Mana > 30 && m_Mobile.Mana < 80 )
					{
						if ( Utility.Random( 2 ) == 0 && !c.Paralyzed && !c.Frozen && !c.Poisoned )
						{
							m_Combo = 0;
							spell = new PainSpikeSpell( m_Mobile, null );
						}
						else
						{
							m_Combo = 1;
							spell = new MindRotSpell( m_Mobile, null );
						}
					     
					}
				     break;
				}
				case 4: //Combo to soften our enemies with a powerful attack while we have max mana amounts
				{
					if ( m_Mobile.Mana > 80 )
					{
						if ( Utility.Random( 2 ) == 0 && !c.Paralyzed && !c.Frozen && !c.Poisoned ) 
						{
							m_Combo = 0;
							spell = new VengefulSpiritSpell ( m_Mobile, null );
						}
						else
						{
							m_Combo = 1;
							spell = new PoisonStrikeSpell ( m_Mobile, null );
						}
					}
				    break;
				}
			
			}

			return spell;
		}

		protected int m_Combo = -1;

		public virtual Spell DoCombo( Mobile c )
		{
			Spell spell = null;

			if ( m_Combo == 0 )
			{
				spell = new FlameStrikeSpell( m_Mobile, null );
				++m_Combo; // Move to next spell
			}
			else if ( m_Combo == 1 )
			{
				spell = new WitherSpell( m_Mobile, null );
				++m_Combo; // Move to next spell
			}
			else if ( m_Combo == 2 )
			{
				if ( !c.Poisoned )
					spell = new PoisonSpell( m_Mobile, null );

				++m_Combo; // Move to next spell
			}

			if ( m_Combo == 3 && spell == null )
			{
				switch ( Utility.Random( 3 ) )
				{
					default:
					case 0:
					{
						if ( c.Int < c.Dex )
							spell = new MindRotSpell( m_Mobile, null );
						else
							spell = new WitherSpell( m_Mobile, null );

						++m_Combo; // Move to next spell

						break;
					}
					case 1:
					{
						spell = new StrangleSpell( m_Mobile, null );
						m_Combo = -1; // Reset combo state
						break;
					}
					case 2:
					{
						spell = new WitherSpell( m_Mobile, null );
						m_Combo = -1; // Reset combo state
						break;
					}
				}
			}
			else if ( m_Combo == 4 && spell == null )
			{
				spell = new VengefulSpiritSpell( m_Mobile, null );
				m_Combo = -1;
			}

			return spell;
		}

		public override bool DoActionCombat()
		{
			Mobile c = m_Mobile.Combatant;
			m_Mobile.Warmode = true;

			if ( c == null || c.Deleted || !c.Alive || c.IsDeadBondedPet || !m_Mobile.CanSee( c ) || !m_Mobile.CanBeHarmful( c, false ) || c.Map != m_Mobile.Map )
			{
				// Our combatant is deleted, dead, hidden, or we cannot hurt them
				// Try to find another combatant

				if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
				{
					if ( m_Mobile.Debug )
						m_Mobile.DebugSay( "Something happened to my combatant, so I am going to fight {0}", m_Mobile.FocusMob.Name );

					m_Mobile.Combatant = c = m_Mobile.FocusMob;
					m_Mobile.FocusMob = null;
				}
				else
				{
					m_Mobile.DebugSay( "Something happened to my combatant, and nothing is around. I am on guard." );
					Action = ActionType.Guard;
					return true;
				}
			}

			if ( !m_Mobile.InLOS( c ) )
			{
				if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
				{
					m_Mobile.Combatant = c = m_Mobile.FocusMob;
					m_Mobile.FocusMob = null;
				}
			}

			if ( SmartAI && !m_Mobile.StunReady && m_Mobile.Skills[SkillName.Wrestling].Value >= 80.0 && m_Mobile.Skills[SkillName.Anatomy].Value >= 80.0 )
				EventSink.InvokeStunRequest( new StunRequestEventArgs( m_Mobile ) );

			if ( !m_Mobile.InRange( c, m_Mobile.RangePerception ) )
			{
				// They are somewhat far away, can we find something else?

				if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
				{
					m_Mobile.Combatant = m_Mobile.FocusMob;
					m_Mobile.FocusMob = null;
				}
				else if ( !m_Mobile.InRange( c, m_Mobile.RangePerception * 3 ) )
				{
					m_Mobile.Combatant = null;
				}

				c = m_Mobile.Combatant;

				if ( c == null )
				{
					m_Mobile.DebugSay( "My combatant has fled, so I am on guard" );
					Action = ActionType.Guard;

					return true;
				}
			}

			if ( !m_Mobile.Controled && !m_Mobile.Summoned )
			{
				if ( m_Mobile.Hits < m_Mobile.HitsMax * 20/100 )
				{
					// We are low on health, should we flee?

					bool flee = false;

					if ( m_Mobile.Hits < c.Hits )
					{
						// We are more hurt than them

						int diff = c.Hits - m_Mobile.Hits;

						flee = ( Utility.Random( 0, 100 ) > (10 + diff) ); // (10 + diff)% chance to flee
					}
					else
					{
						flee = Utility.Random( 0, 100 ) > 10; // 10% chance to flee
					}

					if ( flee )
					{
						if ( m_Mobile.Debug )
							m_Mobile.DebugSay( "I am going to flee from {0}", c.Name );

						Action = ActionType.Flee;
						return true;
					}
				}
			}

			if ( m_Mobile.Spell == null && DateTime.Now > m_NextCastTime && m_Mobile.InRange( c, 12 ) )
			{
				// We are ready to cast a spell

				Spell spell = null;
				Mobile toDispel = FindDispelTarget( true );

				if ( m_Mobile.Poisoned ) // Top cast priority is cure
				{
					spell = new CureSpell( m_Mobile, null );
				}
				else if ( toDispel != null ) // Something dispellable is attacking us
				{
					spell = DoDispel( toDispel );
				}
				else if ( SmartAI && m_Combo != -1 ) // We are doing a spell combo
				{
					spell = DoCombo( c );
				}
				else if ( SmartAI && (c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned ) // They have a heal spell out
				{
					spell = new PoisonStrikeSpell( m_Mobile, null );
				}
				else
				{
					spell = ChooseSpell( c );
				}

				// Now we have a spell picked
				// Move first before casting

				if ( SmartAI && toDispel != null )
				{
					if ( m_Mobile.InRange( toDispel, 10 ) )
						RunFrom( toDispel );
					else if ( !m_Mobile.InRange( toDispel, 12 ) )
						RunTo( toDispel );
				}
				else
				{
					RunTo( c );
				}

				if ( spell != null && spell.Cast() )
				{
					TimeSpan delay;

					if ( SmartAI || ( spell is DispelSpell ) )
					{
						delay = TimeSpan.FromSeconds( m_Mobile.ActiveSpeed );
					}
					else
					{
						double del = ScaleByNecromancy( 3.0 );
						double min = 6.0 - (del * 0.75);
						double max = 6.0 - (del * 1.25);

						delay = TimeSpan.FromSeconds( min + ((max - min) * Utility.RandomDouble()) );
					}

					m_NextCastTime = DateTime.Now + delay;
				}
			}
			else if ( m_Mobile.Spell == null || !m_Mobile.Spell.IsCasting )
			{
				RunTo( c );
			}

			return true;
		}

		public override bool DoActionGuard()
		{
			if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
			{
				if ( m_Mobile.Debug )
					m_Mobile.DebugSay( "I am going to attack {0}", m_Mobile.FocusMob.Name );

				m_Mobile.Combatant = m_Mobile.FocusMob;
				Action = ActionType.Combat;
			}
			else
			{
				if ( m_Mobile.Poisoned )
				{
					new CureSpell( m_Mobile, null ).Cast();
				}
				else if ( !m_Mobile.Summoned && (SmartAI || (ScaleByMagery( HealChance ) > Utility.RandomDouble())) )
				{
					if ( m_Mobile.Hits < (m_Mobile.HitsMax - 50) )
					{
						if ( !new GreaterHealSpell( m_Mobile, null ).Cast() )
							new HealSpell( m_Mobile, null ).Cast();
					}
					else if ( m_Mobile.Hits < (m_Mobile.HitsMax - 10) )
					{
						new HealSpell( m_Mobile, null ).Cast();
					}
					else
					{
						base.DoActionGuard();
					}
				}
				else
				{
					base.DoActionGuard();
				}
			}

			return true;
		}

		public override bool DoActionFlee()
		{
			Mobile c = m_Mobile.Combatant;

			if ( (m_Mobile.Mana > 20 || m_Mobile.Mana == m_Mobile.ManaMax) && m_Mobile.Hits > (m_Mobile.HitsMax / 2) )
			{
				m_Mobile.DebugSay( "I am stronger now, my guard is up" );
				Action = ActionType.Guard;
			}
			else if ( AquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true ) )
			{
				if ( m_Mobile.Debug )
					m_Mobile.DebugSay( "I am scared of {0}", m_Mobile.FocusMob.Name );

				RunFrom( m_Mobile.FocusMob );
				m_Mobile.FocusMob = null;

				if ( m_Mobile.Poisoned && Utility.Random( 0, 5 ) == 0 )
					new CureSpell( m_Mobile, null ).Cast();
			}
			else
			{
				m_Mobile.DebugSay( "Area seems clear, but my guard is up" );

				Action = ActionType.Guard;
				m_Mobile.Warmode = true;
			}

			return true;
		}

		public Mobile FindDispelTarget( bool activeOnly )
		{
			if ( m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel( m_Mobile ) || m_Mobile.AutoDispel )
				return null;

			if ( activeOnly )
			{
				ArrayList aggressed = m_Mobile.Aggressed;
				ArrayList aggressors = m_Mobile.Aggressors;

				Mobile active = null;
				double activePrio = 0.0;

				Mobile comb = m_Mobile.Combatant;

				if ( comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange( comb, 12 ) && CanDispel( comb ) )
				{
					active = comb;
					activePrio = m_Mobile.GetDistanceToSqrt( comb );

					if ( activePrio <= 2 )
						return active;
				}

				for ( int i = 0; i < aggressed.Count; ++i )
				{
					AggressorInfo info = (AggressorInfo)aggressed[i];
					Mobile m = (Mobile)info.Defender;

					if ( m != comb && m.Combatant == m_Mobile && m_Mobile.InRange( m, 12 ) && CanDispel( m ) )
					{
						double prio = m_Mobile.GetDistanceToSqrt( m );

						if ( active == null || prio < activePrio )
						{
							active = m;
							activePrio = prio;

							if ( activePrio <= 2 )
								return active;
						}
					}
				}

				for ( int i = 0; i < aggressors.Count; ++i )
				{
					AggressorInfo info = (AggressorInfo)aggressors[i];
					Mobile m = (Mobile)info.Attacker;

					if ( m != comb && m.Combatant == m_Mobile && m_Mobile.InRange( m, 12 ) && CanDispel( m ) )
					{
						double prio = m_Mobile.GetDistanceToSqrt( m );

						if ( active == null || prio < activePrio )
						{
							active = m;
							activePrio = prio;

							if ( activePrio <= 2 )
								return active;
						}
					}
				}

				return active;
			}
			else
			{
				Map map = m_Mobile.Map;

				if ( map != null )
				{
					Mobile active = null, inactive = null;
					double actPrio = 0.0, inactPrio = 0.0;

					Mobile comb = m_Mobile.Combatant;

					if ( comb != null && !comb.Deleted && comb.Alive && !comb.IsDeadBondedPet && CanDispel( comb ) )
					{
						active = inactive = comb;
						actPrio = inactPrio = m_Mobile.GetDistanceToSqrt( comb );
					}

					foreach ( Mobile m in m_Mobile.GetMobilesInRange( 12 ) )
					{
						if ( m != m_Mobile && CanDispel( m ) )
						{
							double prio = m_Mobile.GetDistanceToSqrt( m );

							if ( !activeOnly && (inactive == null || prio < inactPrio) )
							{
								inactive = m;
								inactPrio = prio;
							}

							if ( (m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio) )
							{
								active = m;
								actPrio = prio;
							}
						}
					}

					return active != null ? active : inactive;
				}
			}

			return null;
		}

		public bool CanDispel( Mobile m )
		{
			return ( m is BaseCreature && ((BaseCreature)m).Summoned && m_Mobile.CanBeHarmful( m, false ) && !((BaseCreature)m).IsAnimatedDead );
		}

		private static int[] m_Offsets = new int[]
			{
				-1, -1,
				-1,  0,
				-1,  1,
				 0, -1,
				 0,  1,
				 1, -1,
				 1,  0,
				 1,  1,

				-2, -2,
				-2, -1,
				-2,  0,
				-2,  1,
				-2,  2,
				-1, -2,
				-1,  2,
				 0, -2,
				 0,  2,
				 1, -2,
				 1,  2,
				 2, -2,
				 2, -1,
				 2,  0,
				 2,  1,
				 2,  2
			};

		private void ProcessTarget( Target targ )
		{
			bool isDispel = ( targ is DispelSpell.InternalTarget );
			bool isParalyze = ( targ is ParalyzeSpell.InternalTarget );
			bool isTeleport = ( targ is TeleportSpell.InternalTarget );
			bool teleportAway = false;

			Mobile toTarget;

			if ( isDispel )
			{
				toTarget = FindDispelTarget( false );

				if ( !SmartAI && toTarget != null )
					RunTo( toTarget );
				else if ( toTarget != null && m_Mobile.InRange( toTarget, 10 ) )
					RunFrom( toTarget );
			}
			else if ( SmartAI && (isParalyze || isTeleport) )
			{
				toTarget = FindDispelTarget( true );

				if ( toTarget == null )
				{
					toTarget = m_Mobile.Combatant;

					if ( toTarget != null )
						RunTo( toTarget );
				}
				else if ( m_Mobile.InRange( toTarget, 10 ) )
				{
					RunFrom( toTarget );
					teleportAway = true;
				}
				else
				{
					teleportAway = true;
				}
			}
			else
			{
				toTarget = m_Mobile.Combatant;

				if ( toTarget != null )
					RunTo( toTarget );
			}

			if ( (targ.Flags & TargetFlags.Harmful) != 0 && toTarget != null )
			{
				if ( (targ.Range == -1 || m_Mobile.InRange( toTarget, targ.Range )) && m_Mobile.CanSee( toTarget ) && m_Mobile.InLOS( toTarget ) )
				{
					targ.Invoke( m_Mobile, toTarget );
				}
				else if ( isDispel )
				{
					targ.Cancel( m_Mobile, TargetCancelType.Canceled );
				}
			}
			else if ( (targ.Flags & TargetFlags.Beneficial) != 0 )
			{
				targ.Invoke( m_Mobile, m_Mobile );
			}
			else if ( isTeleport && toTarget != null )
			{
				Map map = m_Mobile.Map;

				if ( map == null )
				{
					targ.Cancel( m_Mobile, TargetCancelType.Canceled );
					return;
				}

				int px, py;

				if ( teleportAway )
				{
					int rx = m_Mobile.X - toTarget.X;
					int ry = m_Mobile.Y - toTarget.Y;

					double d = m_Mobile.GetDistanceToSqrt( toTarget );

					px = toTarget.X + (int)(rx * (10 / d));
					py = toTarget.Y + (int)(ry * (10 / d));
				}
				else
				{
					px = toTarget.X;
					py = toTarget.Y;
				}

				for ( int i = 0; i < m_Offsets.Length; i += 2 )
				{
					int x = m_Offsets[i], y = m_Offsets[i + 1];

					Point3D p = new Point3D( px + x, py + y, 0 );

					LandTarget lt = new LandTarget( p, map );

					if ( (targ.Range == -1 || m_Mobile.InRange( p, targ.Range )) && m_Mobile.InLOS( lt ) && map.CanSpawnMobile( px + x, py + y, lt.Z ) && !SpellHelper.CheckMulti( p, map ) )
					{
						targ.Invoke( m_Mobile, lt );
						return;
					}
				}

				int teleRange = targ.Range;

				if ( teleRange < 0 )
					teleRange = 12;

				for ( int i = 0; i < 10; ++i )
				{
					Point3D randomPoint = new Point3D( m_Mobile.X - teleRange + Utility.Random( teleRange * 2 + 1 ), m_Mobile.Y - teleRange + Utility.Random( teleRange * 2 + 1 ), 0 );

					LandTarget lt = new LandTarget( randomPoint, map );

					if ( m_Mobile.InLOS( lt ) && map.CanSpawnMobile( lt.X, lt.Y, lt.Z ) && !SpellHelper.CheckMulti( randomPoint, map ) )
					{
						targ.Invoke( m_Mobile, new LandTarget( randomPoint, map ) );
						return;
					}
				}

				targ.Cancel( m_Mobile, TargetCancelType.Canceled );
			}
			else
			{
				targ.Cancel( m_Mobile, TargetCancelType.Canceled );
			}
		}
	}
}
Can somone help?
 
Top