/**********************************************************
RunUO AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by Red Squirrel on Jan-01-2012 10:09:13pm
Filepath: scripts\events and scenarios\Halloween2011\Mobiles\SwampRotworm.cs
Lines of code: 213

Description: 

***********************************************************/


using System;
using Server;
using System.Collections;
using System.Collections.Generic;
using Server.Network;
using Server.Items;
using Server.Targeting;
using Server.Mobiles;

namespace Server.Mobiles
{
	[CorpseName( "a swamp rotworm corpse" )]
	public class SwampRotworm : BaseCreature
	{
		private DateTime AbsorbTimer; //Window of opportunity for rotworm to absorb a corpse and fully heal, once damaged
		private DateTime InBetweenDelayTimer; //Delay between ability to absorb corpses and fully heal
	
		[Constructable]
		public SwampRotworm() : base( AIType.AI_Super, FightMode.Closest, 10, 1, 0.3, 0.6 )
		{
			Name = "a rotworm";
			Body = 732;   
			Hue = 1164;

			SetStr( 222, 277 );
			SetDex( 75, 87 ); 
			SetInt( 16, 20 );

			SetHits( 356, 534 ); 

			SetDamage( 1, 5 ); 

			SetDamageType( ResistanceType.Physical, 100 );

			SetResistance( ResistanceType.Physical, 36, 43);
			SetResistance( ResistanceType.Fire, 30, 39 );
			SetResistance( ResistanceType.Cold, 28, 35 );
			SetResistance( ResistanceType.Poison, 65, 75 );
			SetResistance( ResistanceType.Energy, 25, 35 );

			SetSkill( SkillName.Anatomy, 0.0, 0.0 );
			SetSkill( SkillName.MagicResist, 25.0, 25.0 );
			SetSkill( SkillName.Tactics, 25.0, 25.0 );
			SetSkill( SkillName.Wrestling, 50.0, 50.0 );

			Fame = 6000;
			Karma = -6000;

			PackItem(new Gold(Utility.RandomMinMax( 26, 38 ))); 
			
			if(0.15 >= Utility.RandomDouble()) {
				switch ( Utility.Random( 3 ))
				{
					case 0: PackItem( new Bone() ); break;
					case 1: PackItem( new RibCage() ); break;
					case 2: PackItem( new BonePile() ); break;
				}
			}
		}
		
		public override void OnDeath( Container c )
		{
			if ( Utility.Random( 10 ) == 0 )
			{		
				Item item;

				switch ( Utility.Random( 1 ))
				{
								default:
					case 1: item = new RotwormSlime(); break;
							}

				c.DropItem( item );
			}

			base.OnDeath( c );
		}

		public override void GenerateLoot()
		{
			if (0.5 >= Utility.RandomDouble()) AddLoot( LootPack.Gems );
		}
		
		public override int GetAngerSound()
		{
			return 0x62A;
		}

		public override int GetIdleSound()
		{
			return 0x62D;
		}

		public override int GetAttackSound()
		{
			return 0x62A;
		}

		public override int GetHurtSound()
		{
			return 0x62C;
		}

		public override int GetDeathSound()
		{
			return 0x62B;
		}
		
		public override void OnThink()
		{
			if ( this.Alive && this!=null && (AbsorbTimer > DateTime.Now) && (InBetweenDelayTimer < DateTime.Now) && this.Hits != this.HitsMax) { 
				if (CorpseAbsorption(this)) {
					AbsorbTimer = DateTime.Now;
					
					//Rotworm will not absorb another corpse for a short time period, regardless of if it has been recently attacked
					InBetweenDelayTimer = DateTime.Now + TimeSpan.FromSeconds(3); 
				}
			}
			base.OnThink();		
		}
		
		public override void OnDamage( int amount, Mobile attacker, bool willKill ) 
		{
			if (attacker.Alive && attacker!=null && !IsBeingBloodPoisoned( attacker ) && 0.2 >= Utility.RandomDouble() && attacker.InRange( this, 2 )) {
				BeginBloodPoisoning( attacker, this );
			}
			
			//Rotworm will only absorb corpses if they were recently attacked
			AbsorbTimer = DateTime.Now + TimeSpan.FromSeconds(3); 
			
			base.OnDamage(amount, attacker, willKill);	
		}
		
		public override void OnGaveMeleeAttack(Mobile defender)
 		{
			base.OnGaveMeleeAttack (defender);
			
			if (defender.Alive && defender!=null && !IsBeingBloodPoisoned( defender ) && 0.05 >= Utility.RandomDouble() && defender.InRange( this, 2 )) {
				BeginBloodPoisoning( defender, this );
			}
		}

		/***************************CORPSE ABSORPTION*********************************/
		/*****************************************************************************
		Mobile scans the area for items and checks to see if item is a corpse. If no 
		corpse is found, the procedure returns false. If a corpse is found and has not 
		been absorbed already (checks itemID for bones) then the mobile consumes the corpse 
	    (leaves bones) and is fully healed. The function returns true upon successful 
		corpse absorption.
		******************************************************************************/
		public static bool CorpseAbsorption ( Mobile m ) {
			Map map = m.Map;		
			ArrayList targets = new ArrayList();
				
			if ( map != null ) {
				IPooledEnumerable checkedItems = map.GetItemsInRange( new Point3D( m.Location ), 1 );

				foreach ( Item i in checkedItems ) {
					if ((Item)i is Corpse) {		
						Corpse c = i as Corpse;
						if (c.ItemID != 0xECA && c.ItemID != 0xECB && c.ItemID != 0xECC && c.ItemID != 0xECD && c.ItemID != 0xECE && c.ItemID != 0xECF && c.ItemID != 0xED0 && c.ItemID != 0xED1 && c.ItemID != 0xED2) {
							c.ProcessDelta();
							c.SendRemovePacket();
							c.ItemID = Utility.Random( 0xECA, 9 );
							m.Say(1111667); //* The rotworm absorbs the fleshy remains of the corpse *
							m.Hits = m.HitsMax;
							return true;
						}
					}
				}
				checkedItems.Free();
				return false;
			}
			else {
				return false;
			}			
		}
		
		/***************************BLOOD POISONING*********************************/
		/***************************************************************************
		Mobile inflicts the target with blood poisoning. Blood poisoning is a dot
		damage attack with intermittent damage. The damage done is resistable with
		the player's armor poison resistance value. On each blood poisoning 'tick',
		the player's combatant is wiped, requiring the player to retarget the
		mobile they are attacking while under the effects of blood poisoning
		****************************************************************************/
		private static Hashtable m_Table = new Hashtable();
		
		private class InternalTimer : Timer 
		{
			private Mobile m_From;
			private Mobile m_Mobile;
			private int m_Count;

			public InternalTimer( Mobile from, Mobile m ) : base( TimeSpan.FromSeconds( 2.0 ), TimeSpan.FromSeconds( 2.0 ) )
			{
				m_From = from;
				m_Mobile = m;
				Priority = TimerPriority.TwoFiftyMS;
			}

			protected override void OnTick()
			{
				if(m_Mobile==null || m_From == null) {			
					this.Stop();
					return;
				}
				
				BloodPoisoning( m_Mobile, m_From );

				if ( ++m_Count == 7 )
					EndBloodPoisoning( m_Mobile );
			}
		}
		
		public static void BeginBloodPoisoning( Mobile m, Mobile from )
		{
			m.SendLocalizedMessage( 1111672, "", 33 ); //"The rotworm has infected you with blood disease!" (Red Hue)
			m.FixedParticles( 0x373A, 1, 15, 9913, 67, 7, EffectLayer.Head );
			m.PlaySound( 0x213 );
	
			Timer t = (Timer)m_Table[m];

			if ( t != null )
				t.Stop();

			t = new InternalTimer( from, m );
			m_Table[m] = t;

			t.Start();
		}
		
		public static void BloodPoisoning( Mobile m, Mobile from )
		{
			if(m==null || from==null)return;
			
			if ( m.Alive ) {
				int damageGiven = AOS.Damage( m, from, Utility.RandomMinMax( 10, 20 ), 0, 0, 0, 100, 0 ); //On OSI, this damage doesn't actually interrupt damage
				m.Combatant = null;
			}
			else {
				EndBloodPoisoning( m );
			}
		}

		public static bool IsBeingBloodPoisoned( Mobile m )
		{
			return m_Table.Contains( m );
		}

		public static void EndBloodPoisoning( Mobile m )
		{
			if(m==null)return;
			
			Timer t = (Timer)m_Table[m];

			if ( t != null ) t.Stop();

			if(m_Table.Contains(m))	m_Table.Remove( m );

			m.SendLocalizedMessage( 1111673 ); //You no longer feel sick.
		}
		
		public override int Meat{ get{ return 2; } }
		public override FoodType FavoriteFood{ get{ return FoodType.Fish; } }
		public override bool CantbeSupreme { get { return true;} }
		public override bool CantbeParagon { get { return true;} }	

		public SwampRotworm( 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();
		}
	}
}