/**********************************************************
RunUO 2.0 AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by 
Filepath: scripts\_custom\engines\ML Peerless + misc areas\Dreadhorn\Custom Mobiles\DreadHorn.cs
Lines of code: 427
***********************************************************/


using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Engines.CannedEvil;
using System.Collections.Generic;
using Server.Targeting;

namespace Server.Mobiles
{
	public class DreadHorn : BaseCreature
	{
       private Timer m_Timer;
       Random rand = new Random(); 
       private int amount; 
       
		[Constructable]
		public DreadHorn() : base( AIType.AI_Super, FightMode.Closest, 18, 1, 0.2, 0.4 )
		{	
			Name = "Dread Horn";
			Body = 257;
			BaseSoundID = 0xA8;

			SetStr( 1281, 1305 );
			SetDex( 591, 815 );
			SetInt( 1226, 1250 );

			SetHits( 50000, 50000 );
			SetStam( 636, 945 );

			SetDamage( 15, 15 );

			SetDamageType( ResistanceType.Physical, 40 );
			SetDamageType( ResistanceType.Poison, 60 );

			SetResistance( ResistanceType.Physical, 40, 53 );
			SetResistance( ResistanceType.Fire, 50, 63 );
			SetResistance( ResistanceType.Cold, 50, 62 );
			SetResistance( ResistanceType.Poison, 67, 73 );
			SetResistance( ResistanceType.Energy, 60, 73 );

			SetSkill( SkillName.EvalInt, 100.0, 110.0 );
			SetSkill( SkillName.Poisoning, 115.0, 120.0);
			SetSkill( SkillName.Magery, 80.0, 98.0 );
			SetSkill( SkillName.Spellweaving, 115.0, 120.0 );
			SetSkill( SkillName.MagicResist, 110.0, 120.0 );
			SetSkill( SkillName.Tactics, 90.0, 110.0 );
			SetSkill( SkillName.Wrestling, 90.0, 115.5 );

			Fame = 24000;
			Karma = -24000;

			VirtualArmor = 75;
					

			m_Timer = new TeleportTimer( this );
			m_Timer.Start();
		}
		
		
		public override void OnThink()
		{
		
			//randomly lock combat to single target
			if(0.03>Utility.RandomDouble())
			{
			DebugSay("Locking target to combatant!");
			LockCombat(TimeSpan.FromMinutes(1+Utility.Random(3)));
			}
		
		base.OnThink();
		}		
		
		
		
		public override bool OnBeforeDeath()
		{
			for ( int j = 0; j < 6; j++ )
			{
				PackItem(RandomMResources.Generate());	
			}
			
			for (int i = 0; i < Utility.RandomMinMax(1, 2); i++)
			{
				PackItem( new PetParrotStatue (Utility.RandomList(41, 495, 567, 48, 131, 75, 1001, 1169, 1155, 1164, 1160, 1162, 2210, 1324, 1157, 1364, 1156, 2101))); //Common hues/reward
			}
			
			if (0.15 >= Utility.RandomDouble())
				PackItem( new PetParrotStatue (Utility.RandomList(1281, 1158, 1266, 1150, 1167, 1109, 33, 1420, 1644, 1359))); //Uncommon 
			else if (0.05 >= Utility.RandomDouble())
				PackItem( new PetParrotStatue (Utility.RandomList(1166, 1165, 1172, 1168, 1175, 1152, 1161, 1151, 1154, 1153, 0, 1177)));//Rare reward hues

			switch ( Utility.Random( 75 ))
            {                                   
            	case 0: PackItem( new CrimsonCinture() ); break;   
            	case 12: PackItem( new DreadsFlute() ); break;     
			}
			
			switch ( Utility.Random( 5 ))
            {                                   
            	case 0: PackItem( new DreadMushroom() ); break;
            	case 1: PackItem( new DreadMushroom() ); break;    	
			}
			
			switch ( Utility.Random( 8 ))
            {                                   
            	case 2: PackItem( new DreadMushroom() ); break;
            	case 3: PackItem( new DreadMushroom() ); break; 	
			}
			
			switch ( Utility.Random( 40 ))
            {                                   
				case 0: PackItem( new MangledDreadHorn() ); break;
				case 1: PackItem( new MangledDreadHorn() ); break;
				case 2: PackItem( new MangledDreadHorn() ); break;
				case 3: PackItem( new MangledDreadHorn() ); break;
				case 4: PackItem( new MangledDreadHorn() ); break;
				case 5: PackItem( new MangledDreadHorn() ); break;
				case 6: PackItem( new MangledDreadHorn() ); break;
				case 7: PackItem( new MangledDreadHorn() ); break;
				case 8: PackItem( new MangledDreadHorn() ); break;
				case 9: PackItem( new MangledDreadHorn() ); break;
				case 10: PackItem( new MangledDreadHorn() ); break;
				case 11: PackItem( new MangledDreadHorn() ); break;
				case 12: PackItem( new MangledDreadHorn() ); break;
				case 13: PackItem( new MangledDreadHorn() ); break;
				case 14: PackItem( new MangledDreadHorn() ); break;
				case 15: PackItem( new MangledDreadHorn() ); break;
				case 16: PackItem( new HornOfDreadhorn () ); break;
				case 17: PackItem( new HornOfDreadhorn () ); break;
				case 18: PackItem( new HornOfDreadhorn () ); break;
				case 19: PackItem( new HornOfDreadhorn () ); break;
				case 20: PackItem( new HornOfDreadhorn () ); break;
				case 21: PackItem( new HornOfDreadhorn () ); break;
				case 22: PackItem( new HornOfDreadhorn () ); break;
            	case 23: PackItem( new HornOfDreadhorn () ); break; 
            	case 24: PackItem( new HornOfDreadhorn () ); break; 
            	case 25: PackItem( new HornOfDreadhorn () ); break; 
            	case 26: PackItem( new HornOfDreadhorn () ); break; 
				case 27: PackItem( new HornOfDreadhorn () ); break; 
				case 28: PackItem( new HornOfDreadhorn () ); break; 
				case 29: PackItem( new HornOfDreadhorn () ); break; 
				case 30: PackItem( new PristineDreadHorn() ); break;
				case 31: PackItem( new PristineDreadHorn() ); break;
				case 32: PackItem( new PristineDreadHorn() ); break;
			}
			
			switch ( Utility.Random( 7 ))
            {                                   
            	case 3: PackItem( new DreadHornHeart () ); break;     	
			}
			
			switch ( Utility.Random( 40 ))
            {                               
				case 10: PackItem( new DreadRevenge () ); break;		      	
			}
			
			switch ( Utility.Random( 32 ))
            {                                   
            	case 0: PackItem( new PlateOfHonorArms() ); break;
            	case 1: PackItem( new PlateOfHonorChest() ); break;
				case 2: PackItem( new PlateOfHonorGloves () ); break;
            	case 3: PackItem( new PlateOfHonorGorget () ); break;       
				case 4: PackItem( new PlateOfHonorHelm () ); break;		
				case 5: PackItem( new PlateOfHonorLegs () ); break;		
				case 6: PackItem( new AcolyteArms() ); break;
            	case 7: PackItem( new AcolyteChest() ); break;
				case 8: PackItem( new AcolyteGloves () ); break;	
				case 9: PackItem( new AcolyteLegs () ); break;	
				case 10: PackItem( new EvocaricusSword() ); break;
            	case 11: PackItem( new MalekisHonor() ); break;
				case 12: PackItem( new GrizzleArms() ); break;
            	case 13: PackItem( new GrizzleChest() ); break;
				case 14: PackItem( new GrizzleGloves () ); break;       
				case 15: PackItem( new GrizzleHelm () ); break;		
				case 16: PackItem( new PlateOfHonorLegs () ); break;
				case 17: PackItem( new MageArmorArms() ); break;
            	case 18: PackItem( new MageArmorChest() ); break;
				case 19: PackItem( new MageArmorGloves () ); break;	
				case 20: PackItem( new MageArmorLegs () ); break;                    
				case 21: PackItem( new MyrmidonArms() ); break;
            	case 22: PackItem( new MyrmidonChest() ); break;
				case 23: PackItem( new MyrmidonGloves () ); break;
            	case 24: PackItem( new MyrmidonGorget () ); break;       
				case 25: PackItem( new MyrmidonHelm () ); break;		
				case 26: PackItem( new MyrmidonLegs () ); break;		
				case 27: PackItem( new DeathEssenceArms() ); break;
            	case 28: PackItem( new DeathEssenceChest() ); break;
				case 29: PackItem( new DeathEssenceGloves () ); break;      
				case 30: PackItem( new DeathEssenceHelm () ); break;		
				case 31: PackItem( new DeathEssenceLegs () ); break;		
			}
			
			for ( int k = 0; k < Utility.RandomMinMax( 1, 3 ); k++ )
			{
				PackItem(new RandomTalisman());
			}
			
				
			if (0.8 >= Utility.RandomDouble()) PackItem( new DreadHornMane(1) );	
			
			if (0.4 >= Utility.RandomDouble()) 
			{
				switch (Utility.RandomMinMax(0, 2 ))
				{
					case 0: PackItem(Loot.RandomMPWeapon(90,110, 0));break;
					case 1: PackItem(Loot.RandomMPWeapon(90,110, 1));break;
					case 2: PackItem(Loot.RandomMPWeapon(90,110, 2));break;      		
				}
			}
				
			if (0.10 >= Utility.RandomDouble()) 
			{
				switch (Utility.RandomMinMax(0, 2 ))
				{
					case 0: PackItem(Loot.RandomMPWeapon(110,130, 0));break;
					case 1: PackItem(Loot.RandomMPWeapon(110,130, 1));break;
					case 2: PackItem(Loot.RandomMPWeapon(110,130, 2));break;      		
				}
			}
			
			if (0.05 >= Utility.RandomDouble())
			{
				switch (Utility.RandomMinMax(0, 2 ))
				{
					case 0: PackItem(Loot.RandomMPWeapon(130,150, 0));break;
					case 1: PackItem(Loot.RandomMPWeapon(130,150, 1));break;
					case 2: PackItem(Loot.RandomMPWeapon(130,150, 2));break;      		
				}
			}
			
			if (Map == Map.Felucca)
				amount = 12;
			else
				amount = 8;

			for (int n = 0; n < amount; n++)
			{
				switch (Utility.RandomMinMax(0, 5 ))
				{
					case 0: PackItem( new Taint(1));break;
					case 1: PackItem( new Muculent(1));break;
					case 2: PackItem( new Corruption(1));break;      		
					case 3: PackItem( new Blight (1));break;
					case 4: PackItem( new Scourge(1));break;
					case 5: PackItem( new Putrefaction(1));break;
				}
			}
			
			
			 for(int i=Utility.Random(4);i>0;i--) PackItem(RandomRecipe.Peerless());

		return base.OnBeforeDeath();
		}		
		

		public override void GenerateLoot()
		{
			AddLoot( LootPack.AosUltraRich, 2 );
			AddLoot( LootPack.AosSuperBoss, 2);
			AddLoot( LootPack.FilthyRich, 3 );
		}

		public override bool AutoDispel{ get{ return true; } }
		public override double AutoDispelChance{ get{ return 0.3; } }
		public override Poison HitPoison{ get{ return Poison.Lethal; } }
		public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
		public override bool NoFlee { get { return true; } }
		public override bool IsMLCreature { get { return true;} }
		public override bool IsMLBoss { get { return true;} }
		public override int ArcaneLevel{ get{ return 2; } }
		public override int SuperAI_DelayMax{ get{ return 0; } }
 

		private static readonly double[] m_Offsets = new double[]
			{
				Math.Cos( 000.0 / 180.0 * Math.PI ), Math.Sin( 000.0 / 180.0 * Math.PI ),
				Math.Cos( 040.0 / 180.0 * Math.PI ), Math.Sin( 040.0 / 180.0 * Math.PI ),
				Math.Cos( 080.0 / 180.0 * Math.PI ), Math.Sin( 080.0 / 180.0 * Math.PI ),
				Math.Cos( 120.0 / 180.0 * Math.PI ), Math.Sin( 120.0 / 180.0 * Math.PI ),
				Math.Cos( 160.0 / 180.0 * Math.PI ), Math.Sin( 160.0 / 180.0 * Math.PI ),
				Math.Cos( 200.0 / 180.0 * Math.PI ), Math.Sin( 200.0 / 180.0 * Math.PI ),
				Math.Cos( 240.0 / 180.0 * Math.PI ), Math.Sin( 240.0 / 180.0 * Math.PI ),
				Math.Cos( 280.0 / 180.0 * Math.PI ), Math.Sin( 280.0 / 180.0 * Math.PI ),
				Math.Cos( 320.0 / 180.0 * Math.PI ), Math.Sin( 320.0 / 180.0 * Math.PI ),
			};
			


		public override void OnDeath( Container c )
		{
			base.OnDeath( c );
		}
		
		[CommandProperty( AccessLevel.GameMaster )]
		public override int ManaMax{ get{ return 5000; } }

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

		public override void OnAfterDelete()
		{

			base.OnAfterDelete();
		}
		
		public override void OnDamage( int amount, Mobile attacker, bool willKill ) 
		{
		
		if (0.1 > Utility.RandomDouble() && 0.1 > Utility.RandomDouble() )
		{
			ArrayList list = new ArrayList();

			foreach ( Mobile m in this.GetMobilesInRange( 20 ) )
			{
				if ( m == this || !ShouldHarm( m ) || !this.InLOS( m ) )
					continue;

				if ( m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned || ((BaseCreature)m).Team != this.Team) )
					list.Add( m );
				else if ( m.Player )
					list.Add( m );
			}
			
			this.Say( 1075081 );

			if(attacker!=null)
			{
				foreach ( Mobile m in list )
				{
					ExpireTimer timer = (ExpireTimer)DiscordanceTable[m];

					if ( timer != null )
					{
						timer.DoExpire();
					}
					//else if ( timer == null && this.InLOS( attacker ))
					//{
					//}

					List<ResistanceMod> mods = new List<ResistanceMod>();
					
					double penalty = 0;
					penalty = -(attacker.PhysicalResistance - 20); 
					mods.Add( new ResistanceMod( ResistanceType.Physical,(int)penalty));
					penalty = -(attacker.FireResistance - 20);
					mods.Add( new ResistanceMod( ResistanceType.Fire,(int)penalty));
					penalty = -(attacker.ColdResistance - 20);
					mods.Add( new ResistanceMod( ResistanceType.Cold,(int)penalty));
					penalty = -(attacker.PoisonResistance - 20);
					mods.Add( new ResistanceMod( ResistanceType.Poison,(int)penalty));
					penalty = -(attacker.EnergyResistance - 20);
					mods.Add( new ResistanceMod( ResistanceType.Energy,(int)penalty));
					
					for ( int i = 0; i < mods.Count; ++i )
						m.AddResistanceMod( mods[i] );

					m.FixedEffect( 0x3779, 10, 25 );

					timer = new ExpireTimer( m, mods, TimeSpan.FromSeconds( 45 ) ); //Discord lasts 45 Seconds
					timer.Start();
					DiscordanceTable[m] = timer;
				}
			}
		}
			base.OnDamage(amount, attacker, willKill );			
		}
		
		private static Hashtable DiscordanceTable = new Hashtable();

		private class ExpireTimer : Timer
		{
			private Mobile m_Mobile;
			private List<ResistanceMod> m_Mods;

			public ExpireTimer( Mobile m, List<ResistanceMod> mods, TimeSpan delay ) : base( delay )
			{
				m_Mobile = m;
				m_Mods = mods;
				Priority = TimerPriority.TwoFiftyMS;
			}

			public void DoExpire()
			{
				for ( int i = 0; i < m_Mods.Count; ++i )
					m_Mobile.RemoveResistanceMod( m_Mods[i] );

				Stop();
				DiscordanceTable.Remove( m_Mobile );
			}

			protected override void OnTick()
			{
				m_Mobile.SendMessage( "You resistances return to normal" );
				DoExpire();
			}
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 0 ); // version

		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();

			switch ( version )
			{
				case 0:
				{

					m_Timer = new TeleportTimer( this );
					m_Timer.Start();

					break;
				}
			}
		}
		
		private class TeleportTimer : Timer
		{
			private Mobile m_Owner;

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

			public TeleportTimer( Mobile owner ) : base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 5.0 ) )
			{
				m_Owner = owner;
				Priority=TimerPriority.TwoFiftyMS;
			}

			protected override void OnTick()
			{
				if ( m_Owner.Deleted )
				{
					Stop();
					return;
				}

				Map map = m_Owner.Map;

				if ( map == null )
					return;

				if ( 0.25 < Utility.RandomDouble() )
					return;

				Mobile toTeleport = null;

				foreach ( Mobile m in m_Owner.GetMobilesInRange( 16 ) )
				{
					if ( m != m_Owner && m.Player && m_Owner.ShouldHarm( m ) && m_Owner.InLOS( m ) && !m_Owner.InRange(m,6) )
					{
						toTeleport = m;
						break;
					}
				}

				if ( toTeleport != null )
				{
					int offset = Utility.Random( 8 ) * 2;

					Point3D to = m_Owner.Location;

					for ( int i = 0; i < m_Offsets.Length; i += 2 )
					{
						int x = m_Owner.X + m_Offsets[(offset + i) % m_Offsets.Length];
						int y = m_Owner.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length];

						if ( map.CanSpawnMobile( x, y, m_Owner.Z ) )
						{
							to = new Point3D( x, y, m_Owner.Z );
							break;
						}
						else
						{
							int z = map.GetAverageZ( x, y );

							if ( map.CanSpawnMobile( x, y, z ) )
							{
								to = new Point3D( x, y, z );
								break;
							}
						}
					}

					Mobile m = toTeleport;

					Point3D from = m.Location;

					m.Location = to;

					Server.Spells.SpellHelper.Turn( m_Owner, toTeleport );
					Server.Spells.SpellHelper.Turn( toTeleport, m_Owner );

					m.ProcessDelta();

					Effects.SendLocationParticles( EffectItem.Create( from, m.Map, EffectItem.DefaultDuration ), 0x3728, 10, 10, 2023 );
					Effects.SendLocationParticles( EffectItem.Create(   to, m.Map, EffectItem.DefaultDuration ), 0x3728, 10, 10, 5023 );

					m.PlaySound( 0x1FE );

					m_Owner.Combatant = toTeleport;
					
					if(0.2>Utility.RandomDouble() && !m_Owner.CombatLocked())
					{
					m_Owner.DebugSay("Locking target to teleported mobile!");
					m_Owner.LockCombat(TimeSpan.FromMinutes(1+Utility.Random(3)));
					}
				}
			}
		}
	}
}
