context: /*
   * DAWN OF LIGHT - The first free open source DAoC server emulator
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   *
   */
  using System;
  using System.Collections.Generic;
  using System.Linq;
  
  using System.Text;
  using DOL.AI.Brain;
  using DOL.Database;
  using DOL.Events;
  using DOL.GS.Effects;
  using DOL.GS.PacketHandler;
  using DOL.GS.RealmAbilities;
  using DOL.GS.SkillHandler;
  using DOL.Language;
  
  using log4net;
  
  namespace DOL.GS.Spells
  {
  	/// <summary>
  	/// Default class for spell handler
  	/// should be used as a base class for spell handler
  	/// </summary>
  	public class SpellHandler : ISpellHandler
  	{
  		private static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  
  		/// <summary>
  		/// Maximum number of sub-spells to get delve info for.
  		/// </summary>
  		protected static readonly byte MAX_DELVE_RECURSION = 5;
  
  		protected DelayedCastTimer m_castTimer;
  		/// <summary>
  		/// The spell that we want to handle
  		/// </summary>
  		protected Spell m_spell;
  		/// <summary>
  		/// The spell line the spell belongs to
  		/// </summary>
  		protected SpellLine m_spellLine;
  		/// <summary>
  		/// The caster of the spell
  		/// </summary>
  		protected GameLiving m_caster;
  		/// <summary>
  		/// The target for this spell
  		/// </summary>
  		protected GameLiving m_spellTarget = null;
  		/// <summary>
  		/// Has the spell been interrupted
  		/// </summary>
  		protected bool m_interrupted = false;
  		/// <summary>
  		/// Delayedcast Stage
  		/// </summary>
  		public int Stage
  		{
  			get { return m_stage; }
  			set { m_stage = value; }
  		}
  		protected int m_stage = 0;
  		/// <summary>
  		/// Use to store Time when the delayedcast started
  		/// </summary>
  		protected long m_started = 0;
  		/// <summary>
  		/// Shall we start the reuse timer
  		/// </summary>
  		protected bool m_startReuseTimer = true;
  
  		public bool StartReuseTimer
  		{
  			get { return m_startReuseTimer; }
  		}
  
  		/// <summary>
  		/// Can this spell be queued with other spells?
  		/// </summary>
  		public virtual bool CanQueue
  		{
  			get { return true; }
  		}
  
  		/// <summary>
  		/// Does this spell break stealth on start of cast?
  		/// </summary>
  		public virtual bool UnstealthCasterOnStart
  		{
  			get { return true; }
  		}
  		
  		/// <summary>
  		/// Does this spell break stealth on Finish of cast?
  		/// </summary>
  		public virtual bool UnstealthCasterOnFinish
  		{
  			get { return true; }
  		}
  		
  		protected InventoryItem m_spellItem = null;
  
  		/// <summary>
  		/// Ability that casts a spell
  		/// </summary>
  		protected ISpellCastingAbilityHandler m_ability = null;
  
  		/// <summary>
  		/// Stores the current delve info depth
  		/// </summary>
  		private byte m_delveInfoDepth;
  
  		/// <summary>
  		/// AttackData result for this spell, if any
  		/// </summary>
  		protected AttackData m_lastAttackData = null;
  		/// <summary>
  		/// AttackData result for this spell, if any
  		/// </summary>
  		public AttackData LastAttackData
  		{
  			get { return m_lastAttackData; }
  		}
  
  		/// <summary>
  		/// The property key for the interrupt timeout
  		/// </summary>
  		public const string INTERRUPT_TIMEOUT_PROPERTY = "CAST_INTERRUPT_TIMEOUT";
  		/// <summary>
  		/// The property key for focus spells
  		/// </summary>
  		protected const string FOCUS_SPELL = "FOCUSING_A_SPELL";
  
  		protected bool m_ignoreDamageCap = false;
  
  		/// <summary>
  		/// Does this spell ignore any damage cap?
  		/// </summary>
  		public bool IgnoreDamageCap
  		{
  			get { return m_ignoreDamageCap; }
  			set { m_ignoreDamageCap = value; }
  		}
  
  		protected bool m_useMinVariance = false;
  
  		/// <summary>
  		/// Should this spell use the minimum variance for the type?
  		/// Followup style effects, for example, always use the minimum variance
  		/// </summary>
  		public bool UseMinVariance
  		{
  			get { return m_useMinVariance; }
  			set { m_useMinVariance = value; }
  		}
  		
  		/// <summary>
  		/// Can this SpellHandler Coexist with other Overwritable Spell Effect
  		/// </summary>
  		public virtual bool AllowCoexisting
  		{
  			get { return Spell.AllowCoexisting; }
  		}
  
  
  		/// <summary>
  		/// The CastingCompleteEvent
  		/// </summary>
  		public event CastingCompleteCallback CastingCompleteEvent;
  		//public event SpellEndsCallback SpellEndsEvent;
  
  		/// <summary>
  		/// spell handler constructor
  		/// <param name="caster">living that is casting that spell</param>
  		/// <param name="spell">the spell to cast</param>
  		/// <param name="spellLine">the spell line that spell belongs to</param>
  		/// </summary>
  		public SpellHandler(GameLiving caster, Spell spell, SpellLine spellLine)
  		{
  			m_caster = caster;
  			m_spell = spell;
  			m_spellLine = spellLine;
  		}
  
  		/// <summary>
  		/// Returns the string representation of the SpellHandler
  		/// </summary>
  		/// <returns></returns>
  		public override string ToString()
  		{
  			return new StringBuilder(128)
  				.Append("Caster=").Append(Caster == null ? "(null)" : Caster.Name)
  				.Append(", IsCasting=").Append(IsCasting)
  				.Append(", m_interrupted=").Append(m_interrupted)
  				.Append("\nSpell: ").Append(Spell == null ? "(null)" : Spell.ToString())
  				.Append("\nSpellLine: ").Append(SpellLine == null ? "(null)" : SpellLine.ToString())
  				.ToString();
  		}
  
  		#region Pulsing Spells
  
  		/// <summary>
  		/// When spell pulses
  		/// </summary>
  		public virtual void OnSpellPulse(PulsingSpellEffect effect)
  		{
  			if (Caster.IsMoving && Spell.IsFocus)
  			{
  				MessageToCaster("Your spell was cancelled.", eChatType.CT_SpellExpires);
  				effect.Cancel(false);
  				return;
  			}
  			if (Caster.IsAlive == false)
  			{
  				effect.Cancel(false);
  				return;
  			}
  			if (Caster.ObjectState != GameObject.eObjectState.Active)
  				return;
  			if (Caster.IsStunned || Caster.IsMezzed)
  				return;
  
  			// no instrument anymore = stop the song
  			if (m_spell.InstrumentRequirement != 0 && !CheckInstrument())
  			{
  				MessageToCaster("You stop playing your song.", eChatType.CT_Spell);
  				effect.Cancel(false);
  				return;
  			}
  
  
gt: 			if (Caster.Mana >= Spell.PulsePower)