/**********************************************************
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\CarrionCreeper.cs
Lines of code: 205

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 carrion creeper corpse" )]
	public class CarrionCreeper : BaseCreature
	{
		private DateTime DrainCorpseTimer; //Window of opportunity for carrion creeper to drain a corpse and fully heal, once damaged
		private DateTime InBetweenDelayTimer; //Delay between ability to drain corpses and fully heal
	
		[Constructable]
		public CarrionCreeper() : base( AIType.AI_Super, FightMode.Aggressor, 10, 1, 0.3, 0.6 )
		{
			Name = "a carrion creeper";
			Body = 727;   
			Hue = 2207;   

			SetStr( 401, 473 );
			SetDex( 78, 91 ); 
			SetInt( 18, 24 );

			SetHits( 643, 800 ); 

			SetDamage( 11, 17 ); 

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

			SetResistance( ResistanceType.Physical, 52, 55);
			SetResistance( ResistanceType.Fire, 42, 50 );
			SetResistance( ResistanceType.Cold, 29, 31 );
			SetResistance( ResistanceType.Poison, 69, 75 );
			SetResistance( ResistanceType.Energy, 26, 30 );

			SetSkill( SkillName.Anatomy, 0.0, 0.0 );
			SetSkill( SkillName.MagicResist, 35.0, 37.0 );
			SetSkill( SkillName.Tactics, 97.0, 102.0 );
			SetSkill( SkillName.Wrestling, 100.0, 107.0 );

			Fame = 11000;
			Karma = -11000;

			PackItem(new Gold(Utility.RandomMinMax( 294, 337 ))); 
			
			if(0.4 >= 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 CarrionCreeperSpine(); break;
							}

				c.DropItem( item );
			}

			base.OnDeath( c );
		}


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

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

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

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

		public override int GetDeathSound()
		{
			return 0x5DD;
		}
		
		public override void OnThink()
		{
			if ( this.Alive && this!=null && (DrainCorpseTimer > DateTime.Now) && (InBetweenDelayTimer < DateTime.Now) && this.Hits != this.HitsMax) { 
				if (CorpseDrain(this)) {
					DrainCorpseTimer = DateTime.Now;
					
					//Carrion Creeper will not drain 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 ) 
		{
			//Creeper will only drain corpses if they were recently attacked
			DrainCorpseTimer = DateTime.Now + TimeSpan.FromSeconds(3); 
			
			base.OnDamage(amount, attacker, willKill);	
		}
		
		public override void OnGaveMeleeAttack(Mobile defender)
 		{
			if (defender.Alive && defender!=null && 0.45 >= Utility.RandomDouble() && defender.InRange( this, 2 )) {
				
				if (SwampRotworm.IsBeingBloodPoisoned( defender )) {
					defender.SendMessage("The carrion creeper is repulsed by your diseased blood"); 
				}
				else {
					defender.SendMessage("The carrion creeper drains you to replenish its health"); 
					this.Hits += Utility.RandomMinMax( 11, 17 );
				}
			}
			
			if (defender.Alive && defender!=null && 0.05 >= Utility.RandomDouble() && defender.InRange( this, 2 )) {
				WeakeningAnemia( defender );
			}
			
			base.OnGaveMeleeAttack (defender);
		}

		/***************************CORPSE DRAIN**************************************/
		/*****************************************************************************
		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 CorpseDrain ( 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.Channeled == false) {
							c.Channeled = true;
							c.Hue = 0x835;
							m.Say("The carrion creeper drains a nearby corpse to heal itself"); //* The bloodworm drains blood from a nearby corpse to heal itself.*
							m.Hits = m.HitsMax;
							return true;
						}
					}
				}
				checkedItems.Free();
				return false;
			}
			else {
				return false;
			}			
		}
		
		/************************WEAKENING ANEMIA***********************************/
		/***************************************************************************
		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
		****************************************************************************/
		
		public static void WeakeningAnemia( Mobile defender )
		{
			ExpireTimer timer = (ExpireTimer)m_Table[defender];
			List<StatMod> mods = new List<StatMod>();
			
			if ( timer == null ) {
				int effect = -40;
			
				mods.Add( new StatMod( StatType.Str, "Str", (int)effect, TimeSpan.Zero ) );
				mods.Add( new StatMod( StatType.Dex, "Dex", (int)effect, TimeSpan.Zero ) );
				mods.Add( new StatMod( StatType.Int, "Int", (int)effect, TimeSpan.Zero ) );
			
				for ( int i = 0; i < mods.Count; ++i )
					defender.AddStatMod( mods[i] );
			
				defender.SendMessage("The carrion creeper's bite weakens you. You have become anemic"); 
				defender.FixedParticles( 0x373A, 1, 15, 9913, 67, 7, EffectLayer.Head );
				defender.PlaySound( 0x1ED );
				defender.Stam = 0;
			
				timer = new ExpireTimer( defender, mods, TimeSpan.FromSeconds( 13 ) ); 
				timer.Start();
				m_Table[defender] = timer;
			}
		}
		
		private static Hashtable m_Table = new Hashtable();

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

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

			public void DoExpire()
			{
				m_Mobile.RemoveStatMod( "Str" ); 
				m_Mobile.RemoveStatMod( "Dex" ); 
				m_Mobile.RemoveStatMod( "Int" ); 


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

			protected override void OnTick()
			{
				DoExpire();
				m_Mobile.SendLocalizedMessage( 1111670 ); //"You recover from your anemia." 
			}
		}
	
		public override FoodType FavoriteFood{ get{ return FoodType.Meat; } }
		public override bool CantbeSupreme { get { return true;} }
		public override bool CantbeParagon { get { return true;} }	

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