using CommonAI.Zone.Formula;
using CommonLang;
using System;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
using CommonAI.Zone;
using CommonAI.Zone.Helper;
using XmdsCommonServer.XLS.Data;
using CommonAI.Zone.Instance;
using XmdsCommon.EditorData;
using XmdsCommonServer.Plugin.Units;
using static XmdsCommonSkill.Plugin.Skills.BattleParams;
using CommonAI.Data;
using static CommonAI.Zone.UnitInfo;
using XmdsCommon.Message;
using CommonLang.Log;
using System.Diagnostics;
using System.Collections.Generic;
using XmdsCommonServer.Plugin.Base;
using XmdsCommon.JSGModule.Interface;
using CommonAI.ZoneServer.JSGModule;

namespace XmdsCommonSkill.Plugin.Skills
{
    /// <summary>
    /// FileName: XmdsSkillBase.cs
    /// Author: Alex.Yu
    /// Corporation:... 
    /// Description: 
    /// DateTime: 2015/6/25 9:32:33
    /// </summary>

    #region 战斗数据.

    public class BattleParams
    {
        private static readonly ObjectPool<BattleParams> s_ListPool = new ObjectPool<BattleParams>(s_ListPool_OnCreate);

        private XmdsVirtual mAttacker;
        private XmdsVirtual mHitter;
        private AttackSource mSource;
        private GameSkill mGameSkill;
        private XmdsAttackProperties mProp;
        private XmdsVirtual.AtkResult mAtkResult;

        #region 计算结果.

        private int mThreatValue;                       //仇恨值

        private int mSkillDamagePer;                    //技能伤害百分百
        private int mSkillDamageModify;                 //技能伤害修改

        private int mFinalCritRate;                     //最终暴击率
        private int mFinalDamage;                       //最终伤害
        private int mHitAdd;                            //命中增加
        private int mCritAdd;                           //暴击增加
        private int mDamageModifyAdd;                   //伤害绝对值增加
        private int mSkillDamageAdd;                    //技能伤害增加
        private int mHitResult;                         //打击结果
        private int mHitDamge;                          //打击伤害
        private DamageType mDamageType = DamageType.Damage;

        #endregion


        private BattleParams() { }

        public static BattleParams AllocAutoRelease()
        {
            BattleParams ret = s_ListPool.Get();
            ret.ReSet();
            return ret;
        }

        private static BattleParams s_ListPool_OnCreate()
        {
            return new BattleParams();
        }

        public void ReSet()
        {
           // this.mHitUnits.Clear();
        }

        public void Dispose()
        {
            OnDispose();
            s_ListPool.Release(this);
        }

        private void OnDispose()
        {
            mAttacker = null;
            mHitter = null;
            mSource = null;
            mGameSkill = null;
            mProp = null;
            mThreatValue = 0;

            mSkillDamagePer = 0;
            mSkillDamageModify = 0;

            mFinalCritRate = 0;
            mFinalDamage = 0;
            mHitAdd = 0;
            mCritAdd = 0;
            mDamageModifyAdd = 0;
            mSkillDamageAdd = 0;

            mHitDamge = 0;
            mHitResult = 0;

            mDamageType = DamageType.Damage;
        }

        /// <summary>
        /// 攻击者.
        /// </summary>
        public XmdsVirtual Attacker
        {
            set { mAttacker = value; }
            get { return mAttacker; }
        }

        /// <summary>
        /// 被攻击者.
        /// </summary>
        public XmdsVirtual Hitter        { get { return mHitter;} set { mHitter = value;} }

        /// <summary>
        /// 攻击源信息.
        /// </summary>
        public AttackSource Source {
            get {return mSource;}

            set
            {
                mSource = value;
                mProp = (mSource.Attack.Properties as XmdsAttackProperties);
            }
        }

        /// <summary>
        /// 攻击信息.
        /// </summary>
        public XmdsAttackProperties AtkProp { get { return mProp; }}

        public XmdsVirtual.AtkResult AtkResult
        {
            get { return mAtkResult; }
            set { mAtkResult = value; }
        }

        /// <summary>
        /// 技能信息.
        /// </summary>
        public GameSkill GameSkill { get{return mGameSkill;} set { mGameSkill = value; } }

        /// <summary>
        /// 技能伤害百分比.
        /// </summary>
        public int SkillDamagePer { get { return mSkillDamagePer; } set{ mSkillDamagePer = value;} }

        /// <summary>
        /// 技能伤害绝对值.
        /// </summary>
        public int SkillDamageModify { get { return mSkillDamageModify; } set { mSkillDamageModify = value; } }

        /// <summary>
        /// 最终技能伤害.
        /// </summary>
        public int FinalSkillDamage { get { return mFinalDamage; } set { mFinalDamage = value; } }

        /// <summary>
        /// 最终暴击.
        /// </summary>
        public int FinalCritRate { get { return mFinalCritRate; } set { mFinalCritRate = value; } }

        /// <summary>
        /// 威胁值.
        /// </summary>
        public int ThreatValue { get { return mThreatValue; } set { mThreatValue = value; } }

        /// <summary>
        /// 暴击增加.
        /// </summary>
        public int CritAdd { get { return mCritAdd; } set { mCritAdd = value; } }

        /// <summary>
        /// 命中增加.
        /// </summary>
        public int HitAdd { get { return mHitAdd; } set { mHitAdd = value; } }

        /// <summary>
        /// 伤害绝对值增加.
        /// </summary>
        public int DamageModifyAdd { get { return mDamageModifyAdd; } set { mDamageModifyAdd = value; } }

        /// <summary>
        /// 使用计算公式类型.
        /// </summary>
        public DamageType UseDamageType { get { return mDamageType; } set { mDamageType = value; } }

        /// <summary>
        /// 技能伤害增加. 技能伤害固定值
        /// </summary>
        public int SkillDamageAdd { get { return mSkillDamageAdd; } set { mSkillDamageAdd = value; } }

        /// <summary>
        /// Hit结果,(伤害计算计算BUFF或其他异常状态作用最终效果.)
        /// </summary>
        public int HitResult { get { return mHitResult; } set { mHitResult = value; } }

        /// <summary>
        /// 打击伤害(FinalDamage经过暴击计算的值.)
        /// </summary>
        public int HitDamge { get  { return mHitDamge; } set { mHitDamge = value; } }
    }

    #endregion


    public abstract class XmdsSkillBase : UnitSkill
    {       
        /// <summary>
        /// 技能CD.
        /// </summary>
        protected static HashMap<int, XmdsSkillValue> mSkillCD = new HashMap<int, XmdsSkillValue>();
        /// <summary>
        /// 技能是否能自动释放.
        /// </summary>
        protected static HashMap<int, bool> mSkillCanAuto = new HashMap<int, bool>();

		#region 回调事件.

		public delegate void ScriptHandler(BattleParams param);
        public delegate bool ScriptHandler_Bool(BattleParams param);

        /// <summary>
        /// 计算闪避回调.
        /// </summary>
        protected ScriptHandler event_CalHitRateAdd;

        /// <summary>
        /// 计算暴击回调.
        /// </summary>
        protected ScriptHandler event_CalCritRateAdd;

        /// <summary>
        /// 计算技能伤害.
        /// </summary>
        protected ScriptHandler event_SkillDamagePer;

        /// <summary>
        /// 计算技能绝对值.
        /// </summary>
        protected ScriptHandler event_SkillDamageModify;

        /// <summary>
        /// 获取技能攻击类型(物理、魔法)
        /// </summary>
        protected ScriptHandler event_GetAttackType;

        /// <summary>
        /// 计算技能仇恨.
        /// </summary>
        protected ScriptHandler event_SkillThreatValue;

        /// <summary>
        /// 计算技能逻辑.
        /// </summary>
        protected ScriptHandler event_SkillLogic;

        /// <summary>
        /// 技能附加伤害加成.
        /// </summary>
        protected ScriptHandler event_DamageModifyAdd;

        /// <summary>
        /// 是否走伤害流程.
        /// </summary>                                           
        protected ScriptHandler event_UseDamageType;

        /// <summary>
        /// 总技能伤害加成.
        /// </summary>
        protected ScriptHandler event_SkillDamageAdd;

        /// <summary>
        /// 计算伤害之后的技能逻辑回调.
        /// </summary>
        protected ScriptHandler event_SkillLogicAfterCalDamage;

        /// <summary>
        /// 计算最终伤害修改
        /// </summary>
        protected ScriptHandler_Bool event_SkillFinalDamageModify;

        /// <summary>
        /// 计算招架结果类型
        /// </summary>
        protected ScriptHandler event_SkillAtkRtl;

		//技能破定值
		protected int mSkillBreakShieldValue;

        #endregion

        protected enum EventType : int
        {
            HitRateAdd = 1,                     //命中增加
            CritRateAdd = 2,                    //暴击几率增加
            DamagePer = 3,                      //--技能伤害
            DamageModify = 4,                   //--伤害修改
            AttackType = 5,                     //--攻击类型
            ThreadValue = 6,                    //--仇恨值
            SkillLogic = 7,                     //--技能逻辑
            DamageModifyAdd = 8,                //附加伤害
            UseFormluaType = 9,                 //走伤害流程
            SkillDamageAdd = 10,                //技能伤害加成
            SkillLogicAftercalDamage = 11,      //伤害计算之后逻辑回调
            SkillFinalDamageModify = 12,        //技能最终伤害修改
            GetCalAtkRlt = 13,                  //获得招架结果
        }

        protected void RegistEvent(EventType type, ScriptHandler callBack)
        {
            switch (type)
            {
                case EventType.AttackType:
                    event_GetAttackType = callBack;
                    break;
                case EventType.CritRateAdd:
                    event_CalCritRateAdd = callBack;
                    break;
                case EventType.HitRateAdd:
                    event_CalHitRateAdd = callBack;
                    break;
                case EventType.DamagePer:
                    event_SkillDamagePer = callBack;
                    break;
                case EventType.DamageModify:
                    event_SkillDamageModify = callBack;
                    break;
                case EventType.ThreadValue:
                    event_SkillThreatValue = callBack;
                    break;
                case EventType.SkillLogic:
                    event_SkillLogic = callBack;
                    break;
                case EventType.DamageModifyAdd:
                    event_DamageModifyAdd = callBack;
                    break;
                case EventType.UseFormluaType:
                    event_UseDamageType = callBack;
                    break;
                case EventType.SkillDamageAdd:
                    event_SkillDamageAdd = callBack;
                    break;
                case EventType.SkillLogicAftercalDamage:
                    event_SkillLogicAfterCalDamage = callBack;
                    break;
                case EventType.GetCalAtkRlt:
                    event_SkillAtkRtl = callBack;
                    break;
                default: break;
            }
        }

        protected void RegistEvent_Bool(EventType type, ScriptHandler_Bool callBack)
        {
            switch (type)
            {
                case EventType.SkillFinalDamageModify:
                    event_SkillFinalDamageModify = callBack;
                    break;
                default: break;
            }
        }

        public override int SkillID
        {
            get { return -1; }
        }

        protected override void OnBaseInit(GameSkill info, XmdsVirtual unit, ref SkillTemplate template)
        {
            //技能CD由配置表控制.
            template.CoolDownMS = this.GetTargetFormulaValue(info.SkillLevel, this.GetSkillCD(info.SkillID));

            //控制是否能自动施放.
            if (unit != null && unit.mUnit.IsPlayer && !this.IsCanAuto(info.SkillID))
            {
                info.AutoLaunch = false;
            }
            else if(info.SkillID != XmdsComSrvData.BOSS_CARD_SKILLID)
            {
                info.AutoLaunch = true;
            }

			OnInitConfig();
			OnInit(info, unit, ref template);
			this.mSkillBreakShieldValue = XmdsGlobalData.GetSkillBreakShieldValue(info.SkillID);
		}

        /// <summary>
        /// 初始化回调,用于子类重铸.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="unit"></param>
        /// <param name="template"></param>
        protected virtual void OnInit(GameSkill info, XmdsVirtual unit, ref SkillTemplate template)
        {

        }

		/** 敌伤害,友治疗,自动获取伤害类型 */
		protected CommonAI.Data.DamageType AutoGetDamageType(BattleParams param, CommonAI.Data.DamageType alliesDamageType = CommonAI.Data.DamageType.Heal)
		{
			if(param.Attacker.GetCurPKMode() == PKMode.All)
			{
				return (param.Attacker == param.Hitter) ? alliesDamageType : CommonAI.Data.DamageType.Damage;
			}			
			else if (param.Attacker.IsAllies(param.Hitter, true, true))
			{
				//和平模式下,只有队友才有加血
				return alliesDamageType;
			}
			else if (param.Attacker.GetCurPKMode() == PKMode.Peace && param.Hitter.IsPlayerUnit())
			{
				//和平模式下,非队友,无伤害
				return CommonAI.Data.DamageType.None;

			}

			return (param.Attacker == param.Hitter) ? alliesDamageType : CommonAI.Data.DamageType.Damage;
		}

		public override bool OnCallDamageProcess(XmdsVirtual attacker, XmdsVirtual hitter, AttackSource source, GameSkill gs, ref XmdsVirtual.AtkResult result, ref int damage)
        {
            BattleParams param = BattleParams.AllocAutoRelease();
            try
            { //param.AttackRlt = result.rlt;
                param.Attacker = attacker;
                param.Hitter = hitter;
                param.Source = source;
                param.GameSkill = gs;
                param.AtkResult = result;

                try
                {
                    param = OnDoSkillHitProcess(ref param);
                }
                catch (Exception error)
                {
                    LogError(string.Format("skill {0} attackUID:{1}, HitterUID: {2}, SceneID:{3} SceneUID:{4} OnCallDamageProcess error:{5} - {6}", 
						gs.SkillID, (attacker == null ? "anull" : attacker.mUnit.PlayerUUID), (hitter == null ? "hnull" : hitter.mUnit.PlayerUUID),
						(attacker == null ? -1 : attacker.mUnit.Parent.GetSceneID()), (attacker == null ? "snull" : attacker.mUnit.Parent.UUID), error.ToString(), error.StackTrace));
                }

                damage = param.HitResult;
				//System.Console.WriteLine("伤害:" + attacker.mUnit.ID + ", 伤害:" + damage);
                //仇恨系数.
                //result.ThreatValue = param.ThreatValue;
            }
            finally
            {
                param.Dispose();
            }
			result.breakShieldValue = CUtils.CastInt(this.mSkillBreakShieldValue * (1.0f + XmdsUnitProp.PER * attacker.MirrorProp.BreakShieldValue));
			return true;
        }

        #region 工具API.

        public virtual int GetTargetFormulaValue(int lv, int[] formula)
        {
            return XmdsBattleHelper.GetTargetFormulaValue(lv, formula, SkillID);
        }

        public virtual int GetTargetFormulaValue(int lv, XmdsSkillValue formula)
        {
            return formula.GetValue(lv);
        }

		public override int GetSkillValue(AbstractSkillType type) { return 0; }

		//public virtual int GetTargetValue(int lv, XmdsSkillValue value)
		//{
		//    bool invaild = false;

		//    int ret = value.GetValue(lv, out invaild);

		//    if (invaild)
		//    {
		//        LogError(SkillID, lv);
		//    }

		//    return ret;
		//}

        private void LogError(int skill, int lv)
        {
            XmdsBattleHelper.LogError(string.Format("XmdsSkillBase get Value Error:skill id = {0} lv = {1}", skill, lv));
        }

        /// <summary>
        /// 算基础伤害.
        /// </summary>
        /// <param name="baseValue"></param>
        /// <param name="up"></param>
        /// <param name="lv"></param>
        /// <returns></returns>
        public virtual int CalDamagePer(int baseValue, int lv)
        {
			//return (lv - 1) + baseValue;
			return baseValue;
		}

        public virtual int CalDamagePer(XmdsSkillValue baseValue, int lv)
        {
			//return (lv - 1) + baseValue.GetValue(lv); ;
			return baseValue.GetValue(lv); ;
		}

        public virtual int GetThreatValue(int formulaID1, int formulaID2)
        {
            return 0;
        }

        #endregion

        #region 常态注册.

        protected override void OnRegistEvent()
        {
            RegistEvents();
        }

        private void RegistEvents()
        {
            this.RegistEvent(EventType.DamagePer, OnSkillDamagePerEvent);
            this.RegistEvent(EventType.DamageModify, OnskillDamageModifyEvent);
            this.RegistEvent(EventType.AttackType, OnAttackTypeEvent);
            this.RegistEvent(EventType.ThreadValue, OnThreatValueEvent);
            this.RegistEvent(EventType.SkillLogic, OnSkillLogicEvent);
            this.RegistEvent_Bool(EventType.SkillFinalDamageModify, OnSkillFinalDamageModifyEvent);
            this.RegistEvent(EventType.GetCalAtkRlt, OnGetCalAtkRlt);
			this.RegistEvent(EventType.SkillLogicAftercalDamage, OnSkillLogicAftercalDamage);
        }

        /// <summary>
        /// 得到仇恨.
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnThreatValueEvent(BattleParams param)
        {
            param.ThreatValue = 0;
        }

        /// <summary>
        /// 得到技能百分比.
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnSkillDamagePerEvent(BattleParams param)
        {

        }

        /// <summary>
        /// 得到技能伤害绝对值.
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnskillDamageModifyEvent(BattleParams param)
        {

        }

        /// <summary>
        /// 得到技能伤害类型.
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnAttackTypeEvent(BattleParams param)
        {

        }

        /// <summary>
        /// 技能特殊逻辑.
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnSkillLogicEvent(BattleParams param)
        {

        }

		protected virtual void OnSkillLogicAftercalDamage(BattleParams param)
		{

		}

		/// <summary>
		/// 技能固定伤害.(最终值)
		/// reture不执行具体伤害逻辑计算,直接使用给定的伤害值
		/// <param name="param"></param>
		protected virtual bool OnSkillFinalDamageModifyEvent(BattleParams param)
        {
            return false;
        }


        /// <summary>
        /// 获得招架结果类型
        /// </summary>
        /// <param name="param"></param>
        protected virtual void OnGetCalAtkRlt(BattleParams param)
        {

        }

        #endregion

        private void OnDispose()
        {
            event_CalHitRateAdd = null;
            event_CalCritRateAdd = null;
            event_SkillDamagePer = null;
            event_SkillDamageModify = null;
            event_GetAttackType = null;
            event_SkillThreatValue = null;
            event_SkillLogic = null;
            event_SkillDamageAdd = null;
            event_SkillLogicAfterCalDamage = null;
            event_SkillFinalDamageModify = null;
            event_UseDamageType = null;
            event_DamageModifyAdd = null;
        }

        #region 新计算流程.

        protected BattleParams OnDoSkillHitProcess(ref BattleParams param)
        {
            OnCalAtkRlt(param);

			//获得伤害类型.
			OnAttackType(param);

			//是否使用伤害公式.
			OnUseDamageFormula(param);

			//获得技能伤害百分比.
			OnGetSkillDamagePer(param);

            //获得技能固定伤害.
            OnGetSkillDamageModify(param);

            //获得技能仇恨系数.
            OnGetSkillThreatValue(param);          

            //技能逻辑调用.
            OnGetSkillLogic(param);

            //绝对伤害和计算伤害,只走一个
            if (!OnSkillFinalDamageModify(param))
            {
                switch (param.UseDamageType)
                {
                    case CommonAI.Data.DamageType.Damage:
                        OnGetDamage(param);
                        break;
                    case CommonAI.Data.DamageType.Heal:
                        OnGetHeal(param);
                        break;
                    case CommonAI.Data.DamageType.None:
                        param.FinalSkillDamage = 0;
                        break;
                    default: break;
                }

                //计算暴击效果.
                OnGetHitDamage(param);
            }          

            OnDispatchEvent(param);

            //计算伤害之后的回调.
            OnGetSkillLogicAfterCalDamage(param);

            //处理吸血效果
            if (param.UseDamageType == CommonAI.Data.DamageType.Damage && param.HitResult > 0)
            {
                ProcessAtkLeech(param);
            }

            return param;
        }

        #region 攻击逻辑结果计算.
        /// <summary>
        /// 计算攻击结果,闪避,暴击,命中.
        /// </summary>
        /// <param name="param"></param>
        private void OnCalAtkRlt(BattleParams param)
        {
            //外部已经赋值了, 就不需要再计算了
            if (param.Source.OutClientState != (byte)XmdsVirtual.UnitHitEventState.Normal)
            {
                return;
            }

            XmdsVirtual attacker = param.Attacker;
            XmdsVirtual hitter = param.Hitter;

            AttackSource atksource = param.Source;

            if (atksource.FromExpectTarget == SkillTemplate.CastTarget.Alias ||
                atksource.FromExpectTarget == SkillTemplate.CastTarget.AlliesExcludeSelf ||
                atksource.FromExpectTarget == SkillTemplate.CastTarget.AlliesIncludeSelf ||
                atksource.FromExpectTarget == SkillTemplate.CastTarget.PetForMaster ||
                attacker.GetPlayerUUID() == hitter.GetPlayerUUID())
            {
                //param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal;
                if (this.IsHealCritAttack(param))
                {
                    param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Crit;
                }
                else
                {
                    param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal;
                }
            }
            else
            {
                if (IsKillMonsterCrit(param))
                {
                    param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.KillMonsterCrit;
					//log.Info("斩妖暴击:" + attacker.mInfo.Name + ", " + hitter.mInfo.Name);
                }
                else
                {
                    if (this.IsCritAttack(param))
                    {
                        param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Crit;
                    }
                    else
                    {
                        param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal;
                    }
                }
            }

            //二次计算一下招架结果
            if (event_SkillAtkRtl != null)
            {
                event_SkillAtkRtl.Invoke(param);
            }
        }

        #region 是否斩妖的特殊暴击
        private bool IsKillMonsterCrit(BattleParams param)
        {
            XmdsInstancePlayer attacker = param.Attacker.mUnit as XmdsInstancePlayer;
            XmdsInstanceMonster hitter = param.Hitter.mUnit as XmdsInstanceMonster;

            int yaoQiLevel = param.Attacker.MirrorProp.YaoQiLevel;
            if (attacker != null && hitter != null && yaoQiLevel > 0)
            {
                HateSystem.HateInfo hateInfo = param.Hitter.mHateSystem.getHateInfo(param.Attacker.mUnit.ID);
                if (hateInfo != null && XmdsDataMgr.GetInstance().IsZhanYaoCrit(attacker, param.Hitter.mUnit.Level, yaoQiLevel,
                    ++hateInfo.hitNums, ref param.Source.OutClientStateExt))
                {
                    hateInfo.hitNums = 0;
                    return true;
                }
            }

            return false;
        }

        #endregion


        #region 是否暴击.

        private bool IsCritAttack(BattleParams param)
        {
			XmdsVirtual attacker = param.Attacker;
			XmdsVirtual hitter = param.Hitter;
			OnFinalCritHandler(param);


			//如果为普攻,并且下次普攻概率不为0,走这个概率
			if(param.GameSkill.SkillType == XmdsSkillType.normalAtk && param.Attacker.MirrorProp.NormalAtkCriteRate > 0)
			{
				return XmdsDamageCalculator.IsInRandomRange(param.Attacker.MirrorProp.NormalAtkCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER);
			}
			else
			{
				int critRate = attacker.MirrorProp.CritRate;

				if (attacker.IsPlayerUnit() && hitter.IsBoss())
				{
					critRate += attacker.MirrorProp.ToBossCritRate;
				}

				int finalCriteRate = critRate + param.CritAdd - hitter.MirrorProp.ResCritRate;
				param.FinalCritRate = finalCriteRate;

				return XmdsDamageCalculator.IsInRandomRange(finalCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER);
			}
        }

        private bool IsHealCritAttack(BattleParams param)
        {
            /*
            施法者的治疗暴击率 = 治疗暴击系数 * 施法者暴击 /(施法者暴击 + 施法者等级 * 100) +施法者.暴击率 + 被治疗者.受到治疗暴击率
            wuyonghui(吴永辉) 07-25 14:56:26
            最后个属性目前还没有,以后会有   (指的是“被治疗者.受到治疗暴击率”)
            */
            XmdsVirtual attacker = param.Attacker;

            float critRate = attacker.MirrorProp.CritRate * XmdsUnitProp.PER;

            OnFinalCritHandler(param);

            var finalCriteRate = (int)critRate + param.CritAdd;

            param.FinalCritRate = finalCriteRate;

            return XmdsDamageCalculator.IsInRandomRange(finalCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER);
        }

        private void OnFinalCritHandler(BattleParams param)
        {
            if (event_CalCritRateAdd != null)
            {
                event_CalCritRateAdd.Invoke(param);
            }
        }


        #endregion

        #endregion

        #region 技能攻击效果(逻辑、伤害).

        private void OnGetSkillDamagePer(BattleParams param)
        {

            if (event_SkillDamagePer != null)
            {
                event_SkillDamagePer.Invoke(param);
            }
        }

        private void OnGetSkillDamageModify(BattleParams param)
        {

            if (event_SkillDamageModify != null)
            {
                event_SkillDamageModify.Invoke(param);
            }

        }

        private void OnGetSkillThreatValue(BattleParams param)
        {
            if (event_SkillThreatValue != null)
            {
                event_SkillThreatValue.Invoke(param);
            }
        }

        private void OnAttackType(BattleParams param)
        {
            if (event_GetAttackType != null)
            {
                event_GetAttackType.Invoke(param);
            }
        }

        private void OnGetSkillLogic(BattleParams param)
        {
            if (event_SkillLogic != null)
            {
                event_SkillLogic.Invoke(param);
            }
        }

        protected virtual void OnGetSkillLogicAfterCalDamage(BattleParams param)
        {
            if (event_SkillLogicAfterCalDamage != null)
            {
                event_SkillLogicAfterCalDamage.Invoke(param);
            }
        }

        //技能最终伤害调整
        private bool OnSkillFinalDamageModify(BattleParams param)
        {
            if (event_SkillFinalDamageModify != null)
            {
                return event_SkillFinalDamageModify.Invoke(param);
            }

            return false;
        }

        private void OnGetSkillDamageAdd(BattleParams param)
        {
            if (event_SkillDamageAdd != null)
            {
                event_SkillDamageAdd.Invoke(param);
            }

        }

        protected void OnGetDamage(BattleParams param)
        {
            XmdsVirtual attacker = param.Attacker;
            XmdsVirtual hitter = param.Hitter;

            OnGetDamageModifyAdd(param);

            int attackTemp = attacker.MirrorProp.GetFinalAttack(param.Hitter.mUnit.IsMonster);
            //计算面板物攻和技能加成效果.
            int attack = XmdsDamageCalculator.GetSkillDamage(attackTemp, param.SkillDamagePer, param.SkillDamageModify + param.DamageModifyAdd);
			if(attack <= 1 && attackTemp > 10)
			{
				string stackInfo = new StackTrace().ToString();
				XmdsVirtual.FormatLog(LoggerLevel.ERROR, "攻击异常 : {0}->{1}, dmgInfo:{2}, {3}, {4}, {5}, {6}", attackTemp, attack, 
					param.SkillDamagePer, param.SkillDamageModify, param.DamageModifyAdd, JSGModule.GetAttackSourceDes(param.Source), stackInfo);
			}
            OnGetSkillDamageAdd(param);            
            param.FinalSkillDamage = XmdsDamageCalculator.GetDamage(attack, attacker, hitter, param.Source) + param.SkillDamageAdd;
        }

        //治疗量计算.
        private void OnGetHeal(BattleParams param)
        {
            XmdsVirtual attacker = param.Attacker;
            XmdsVirtual hitter = param.Hitter;
            int attack = attacker.MirrorProp.MaxAttack;
            //计算面板魔攻和技能加成效果.
            attack = XmdsDamageCalculator.GetSkillDamage(attack, param.SkillDamagePer, param.SkillDamageModify + param.DamageModifyAdd);

			int v = attack;

			//治疗量.
			//v = CUtils.CastInt(attack * (param.Attacker.MirrorProp.HealEffect / XmdsDamageCalculator.PERER + 1));
			//受治疗量.
			//v = CUtils.CastInt(v * (hitter.MirrorProp.HealedEffect / XmdsDamageCalculator.PERER + 1));

			param.FinalSkillDamage = -v - param.SkillDamageAdd;

            //如果治疗效果计算等0,强制转为-1.
            if (param.FinalSkillDamage == 0)
            {
                param.FinalSkillDamage = -1;
            }
            else if (param.FinalSkillDamage > 0)
            {
                XmdsVirtual.FormatLog("治疗量计算异常值 = {0}", param.FinalSkillDamage);
            }
        }

        /** 处理技能,普攻吸血效果 */
        private void ProcessAtkLeech(BattleParams param)
        {
            //计算技能吸血和普攻吸血
            int damage = param.HitResult;
            if(damage <= 0)
            {
                return;
            }

            if (param.Attacker.mUnit.CurrentHP < param.Attacker.mUnit.MaxHP)
            {
                if (param.GameSkill.SkillType == XmdsSkillType.normalAtk)
                {
                    if (param.Attacker.MirrorProp.NormalAtkLeech > 0)
                    {
                        int addHP = CUtils.CastInt(damage * XmdsUnitProp.PER * param.Attacker.MirrorProp.NormalAtkLeech);
                        if (addHP > 0)
                            param.Attacker.mUnit.AddHP(addHP, param.Attacker.mUnit);
                    }
                }
                else if (param.GameSkill.SkillType == XmdsSkillType.active)
                {
                    if (param.Attacker.MirrorProp.ActiveAtkLeech > 0)
                    {
                        int addHP = CUtils.CastInt(damage * XmdsUnitProp.PER * param.Attacker.MirrorProp.ActiveAtkLeech);
                        if (addHP > 0)
                            param.Attacker.mUnit.AddHP(addHP, param.Attacker.mUnit);
                    }
                }
            }
        }

        private void OnGetHitDamage(BattleParams param)
        {
            if (param.Source.OutClientState == (int)XmdsVirtual.UnitHitEventState.KillMonsterCrit)
            {
                param.HitDamge = CUtils.CastInt(param.FinalSkillDamage * (param.Source.OutClientStateExt * XmdsUnitProp.PER));
            }
            else if (param.Source.OutClientState == (int)XmdsVirtual.UnitHitEventState.Crit)
            {
				int criteDmgRate;
                if (param.UseDamageType == CommonAI.Data.DamageType.Heal)
					criteDmgRate = XmdsDamageCalculator.GetCritHealDamage(param.FinalSkillDamage, param.Attacker, param.Hitter);
                else
					criteDmgRate = XmdsDamageCalculator.GetCritDamage(param.FinalSkillDamage, param.Attacker, param.Hitter);

				//MMO-14871: 2021.3.30调整算法
				//2021.3.31暂时还原修改
				//criteDmgRate = criteDmgRate / 2 + 5000;
				if (criteDmgRate > XmdsDamageCalculator.PERER)
				{
					param.HitDamge = CUtils.CastInt(param.FinalSkillDamage / XmdsDamageCalculator.PERER * criteDmgRate);
				}
			}
            else
            {
                param.HitDamge = param.FinalSkillDamage;
            }
        }

        private void OnGetDamageModifyAdd(BattleParams param)
        {
            if (event_DamageModifyAdd != null)
            {
                event_DamageModifyAdd.Invoke(param);
            }
        }

        private void OnUseDamageFormula(BattleParams param)
        {
            if (event_UseDamageType != null)
            {
                event_UseDamageType.Invoke(param);
            }
        }

        private void OnDispatchEvent(BattleParams param)
        {
            int result = param.HitDamge;

            XmdsVirtual.AtkResult r = param.AtkResult;

            param.Attacker.DispatchHitEvents(ref result, param.Attacker, param.Hitter, param.Source,
                ref r, param.UseDamageType);

            param.HitResult = result;
        }
        #endregion

        #endregion

        #region 基础事件监听.

        protected override void OnBaseDataInit(XmdsSkillData data)
        {
            base.OnBaseDataInit(data);

            if (SkillID != -1)
            {
                if (data != null)
                {                   
					if(data.CDTime != null)
					{
						XmdsSkillValue skillCD;
						InitData(data, out skillCD, XmdsSkillData.XmdsSkillDataKey.CDTime);
						mSkillCD.Put(SkillID, skillCD);
					}

					if (data.canAuto != null)
					{						
						bool canAutoLunch = data.SkillType != (int)XmdsSkillType.cardSkill;
						if(canAutoLunch)
						{
							XmdsSkillValue skillCanAuto;
							InitData(data, out skillCanAuto, XmdsSkillData.XmdsSkillDataKey.canAuto);
							canAutoLunch = skillCanAuto == null ? false : (skillCanAuto.GetValue() == 1);
						}
						mSkillCanAuto.Put(SkillID, canAutoLunch);
					}

					if(data.TalentData != null && data.TalentData.Length > 0)
					{
						XmdsSkillValue talentInfo;
						InitData(data, out talentInfo, XmdsSkillData.XmdsSkillDataKey.TalentData);
						XmdsGlobalData.PutTalentData(SkillID, talentInfo);
					}
					
					if(data.BreakShieldValue > 0)
					{
						XmdsGlobalData.PutSkillBreakShieldValue(SkillID, data.BreakShieldValue);
					}					
				}
                else
                {
                    XmdsVirtual.FormatLog(string.Format("XmdsSkillBase get Value Error:skill id = {0}", SkillID));
                }
            }
        }

        private XmdsSkillValue GetSkillCD(int skillID)
        {
            XmdsSkillValue outSkillCD;
            mSkillCD.TryGetValue(skillID, out outSkillCD);
            return (outSkillCD == null) ? XmdsGlobalData.DefaultValue : outSkillCD;
        }

		private bool IsCanAuto(int skillID)
		{
			bool canAutoLaunch = false;
			mSkillCanAuto.TryGetValue(skillID, out canAutoLaunch);
			return canAutoLaunch;
        }

		/// <summary>
		/// MP预判断.
		/// </summary>
		/// <param name="skill"></param>
		/// <param name="launcher"></param>
		/// <returns></returns>
		protected override bool OnUnitLaunchSkillEvent(GameSkill skillInfo, ref InstanceUnit.SkillState skill, XmdsVirtual launcher, ref InstanceUnit.LaunchSkillParam param)
        {
            bool ret = true;

            //if (skill.ID == SkillID)
            //{
            //    if (ret == false)
            //    {
            //        //发送提示.
            //        launcher.SendMsgToClient(XmdsConstConfig.TIPS_MP_NOT_ENOUGH);
            //    }
            //}

            return ret;
        }

        #region 技能自动战斗检测.

        public override bool SkillAutoLaunchTest(InstanceUnit.SkillState ss, XmdsVirtual launcher)
        {
            if (OnSkillAutoLaunchTest(ss, launcher))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 技能自动战斗自定义检测.
        /// </summary>
        /// <param name="ss"></param>
        /// <param name="launcher"></param>
        /// <returns></returns>
        protected virtual bool OnSkillAutoLaunchTest(InstanceUnit.SkillState ss, XmdsVirtual launcher)
        {
            return true;
        }

        #endregion

        /// <summary>
        /// 技能施放完毕执行MP扣除.
        /// </summary>
        /// <param name="costEnergy"></param>
        /// <param name="attacker"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        protected override int OnUnitLaunchSkillOver(GameSkill info, XmdsVirtual attacker, InstanceUnit.SkillState state)
        {
            return 0;
        }

        #endregion
    }

    public abstract class XmdsPassiveSkillBase : UnitPassiveSkill
    {
        /// <summary>
        ///计时器.
        /// </summary>
        private TimeExpire<int> mTimer = null;
        private bool mIsCD = false;
        /// <summary>
        /// CD减少时间.
        /// </summary>
        private int mDecreaseTotalTimeMS = 0;


        public override int SkillID
        {
            get { return -1; }
        }

        protected bool IsCD
        {
            set { mIsCD = true; }
            get { return mIsCD; }
        }

        /// <summary>
        /// 获得主技能ID.
        /// </summary>
        /// <returns></returns>
        public virtual int GetMainSkillID()
        {
            return -1;
        }

        protected override void OnUpdate(int intervalMS, bool slowRefresh)
        {
            //计时器刷新.
            TimerUpdate(intervalMS);
            base.OnUpdate(intervalMS, slowRefresh);
        }

		protected void GetNearUnitInfo(XmdsVirtual virInfo, float range, ref int alliesCount, ref int enemyCount)
        {
            int alliesCountTemp = 0;
            int enemyCountTemp = 0;
            using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
            {
                virInfo.mUnit.Parent.getObjectsRoundRange<InstanceUnit>(
                    (obj, dx, dy, dr) =>
                    {
                        var u = obj as InstanceUnit;
                        if (u.Virtual is XmdsVirtual_Player && CMath.includeRoundPoint(dx, dy, dr, u.X, u.Y))
                        {
                            //己方单位.
                            if (virInfo.mUnit.Force == u.Force)
                            {
                                alliesCountTemp++;
                            }
                            else
                            {
                                enemyCountTemp++;
                            }
                        }

                        return true;
                    },
                    virInfo.mUnit.X,
                    virInfo.mUnit.Y,
                    range,
                    list, virInfo.mUnit.AoiStatus);
            }

            alliesCount = alliesCountTemp;
            enemyCount = enemyCountTemp;
        }

		protected List<InstanceUnit> GetNearUnitList(XmdsVirtual virInfo, float range, bool includeSelf = false, int pointForce = 0)
		{
			List<InstanceUnit> list = new List<InstanceUnit>();
			virInfo.mUnit.Parent.getObjectsRoundRange<InstanceUnit>(
				(obj, dx, dy, dr) =>
				{
					if(!includeSelf && obj == virInfo.mUnit)
					{
						return false;
					}
					
					var u = obj as InstanceUnit;
					if (pointForce > 0 && u.Force != pointForce)
					{
						return false;
					}

					return CMath.includeRoundPoint(dx, dy, dr, u.X, u.Y);
				},
				virInfo.mUnit.X,
				virInfo.mUnit.Y,
				range,
				list, virInfo.mUnit.AoiStatus);

			return list;
		}

		public override int GetCDPassTime()
        {
            if (mTimer != null)
            {
                return mTimer.PassTimeMS;
            }

            return 0;
        }

        public override int GetCDTotalTime()
        {
            if (mTimer != null)
            {
                return mTimer.TotalTimeMS;
            }

            return 0;
        }

        public override void SetCDPassTime(int timeMS)
        {
            if (mTimer != null)
            {
                mTimer.Update(timeMS);
            }
        }


		public override int GetSkillValue(AbstractSkillType type) { return 0; }

		#region Timer相关.

		protected void SetTimer(int timeMS)
        {
            int t = timeMS - GetDecreaseTotalTimeMS();

            t = Math.Max(1000, t);

            if (mTimer == null)
            {
                mTimer = new TimeExpire<int>(t);
            }
            else
            {
                mTimer.Reset(t);
            }
        }
        /// <summary>
        /// 设置CD为true,重算CD.
        /// </summary>
        protected void RestartTimer()
        {
            mIsCD = true;
            if (mTimer != null)
            {
                mTimer.Reset();
            }
        }
        protected void TimerUpdate(int intervalMS)
        {
            if (mTimer != null)
            {
                if (mIsCD == true && mTimer.Update(intervalMS))
                {
                    mIsCD = false;
                }
            }
        }
        public virtual int GetTargetFormulaValue(int lv, int[] formula)
        {
            return XmdsBattleHelper.GetTargetFormulaValue(lv, formula, SkillID);
        }
        public virtual int GetTargetFormulaValue(int lv, XmdsSkillValue formula)
        {
            return formula.GetValue(lv);
        }

        public override void SetDecreaseTotalTimeMS(int timeMS)
        {
            mDecreaseTotalTimeMS = timeMS;
        }

        public override int GetDecreaseTotalTimeMS()
        {
            return mDecreaseTotalTimeMS;
        }

        private void LogError(int skill, int lv)
        {
            XmdsBattleHelper.LogError(string.Format("XmdsPassiveSkillBase get Value Error:skill id = {0} lv = {1}", skill, lv));
        }

        #endregion


    }
}