using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using CommonAI.Zone.Formula;
using CommonLang;
using CommonLang.Log;
using System.Collections.Generic;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
using CommonAI.Zone.ZoneEditor;
using System.Diagnostics;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using XmdsCommonServer.XLS.Data;
using System;
using XmdsCommonServer.Plugin.Scene;
using CommonLang.Vector;
using CommonLang.Concurrent;
using CommonAI.Data;
using static CommonAI.Zone.Instance.InstanceUnit;
using CommonAI.data;
using XmdsCommonServer.Plugin.Base;
using XmdsCommonSkill.Plugin.CardSkill;

namespace XmdsCommonServer.Plugin
{
    /// <summary>
    /// FileName: XmdsVirtualUnit.cs
    /// </summary>
    public partial class XmdsVirtual : XmdsCommon.Plugin.VirtualUnitBase
	{
        private static AtomicInteger s_alloc_object_count = new AtomicInteger(0);
        /// <summary>
        /// 分配实例数量
        /// </summary>
        public static int AllocCount { get { return s_alloc_object_count.Value; } }
        #region Log.

        public static Logger log = LoggerFactory.GetDefLogger();
        public static void FormatLog(string txt, params object[] args)
        {
            if (args != null) { log.Debug(string.Format(txt, args)); }
            else { log.Debug(txt); }
        }

        public static void FormatLog(uint level, string txt, params object[] args)
        {
            if (args != null)
            {
                switch (level)
                {
                    case LoggerLevel.ERROR:
                        log.Error(string.Format(txt, args));
                        break;
                    case LoggerLevel.WARNNING:
                        log.Warn(string.Format(txt, args));
                        break;
                    default:
                        log.Debug(string.Format(txt, args));
                        break;
                }
            }
            else
            {
                switch (level)
                {
                    case LoggerLevel.ERROR:
                        log.Error(txt);
                        break;
                    case LoggerLevel.WARNNING:
                        log.Warn(txt);
                        break;
                    default:
                        log.Debug(txt);
                        break;
                }
            }
        }

		#endregion


		#region 战斗状态恢复配置.

		//血量恢复时间和系数,目前战中和非战中恢复速度一致.
		//HP回复频率.
		public static readonly int Coefficient_HPRebornTime = 5000;
		//战斗中HP回复系数.
		public static readonly float Coefficient_CombatHPReborn = 1f;

        #endregion

        readonly public UnitInfo mInfo;
        readonly public InstanceUnit mUnit;
        readonly public XmdsUnitProperties mProp;
        readonly public XmdsHateSystem mHateSystem;

        //是否完成初始化技能.
        protected bool mFinishSkillInit = false;
        public XmdsUnitProp MirrorProp;
        //脱战计时器.
        private TimeExpire<int> mOutOfCombatTime = null;
        //血量回复计时器.
        private TimeInterval<int> mHPRebornTimer = null;
		//定力值回复计时器.
		private TimeInterval<int> mMPRebornTimer = null;

		//出生点坐标.
		protected float mBirthPosX;
        protected float mBirthPosY;

        //坐骑状态.
        private bool mIsMounted = false;
        //是否在战斗状态.
        private BattleStatus mInCombatState = BattleStatus.None;
        //游戏服场景配置.
        public XmdsServerSceneData ServerSceneData = null;
        //隐身时队友是否可见.
        protected bool mTeamMemberVisible = true;
        public virtual bool TeamMemberVisible { get { return mTeamMemberVisible; } set { mTeamMemberVisible = value; } }

        //是否无敌.
        public bool IsInvincible { get; set; }
        //虚无状态无视技能.
        public bool NothingnessIgnoreSkill { get; set; }
        //虚无状态无视Buff效果.
        public bool NothingnessIgnoreBuff { get; set; }
        //虚无状态无视所有效果.
        public bool NothingnessIgnoreAll { get; set; }
		//恢复MP状态,不可打断
		public int mRecoverMPLeftTimes;

		//PVP触发的玩家id
		public string mPvpTriggerPlayerId;

        //战斗状态变更通知.
        public delegate void OnCombatChangeEvent(BattleStatus status);
        public event OnCombatChangeEvent OnHandleCombatChangeEvent
        {
            add { event_OnHandleCombatChangeEvent += value; }
            remove { event_OnHandleCombatChangeEvent -= value; }
        }

        protected event OnCombatChangeEvent event_OnHandleCombatChangeEvent;


        #region 属性变更.

        //操作指令申请计数.
        private int mPropChangeOperationCount = 0;
        //操作指令合集.
        private HashMap<int, PropChangeOperation> mPropChangeMap = new HashMap<int, PropChangeOperation>();

        protected PlayerBattlePropChangeEventB2C mBattlePropChangeEvt = null;

        private int mVirtualInventorySize = 0;
        #endregion

        #region 战斗状态变更原因.

        public const byte COMBATSTATE_CHANGE_REASON_DORESET = 1;

        #endregion

        public XmdsVirtual(InstanceUnit unit)
        {
            s_alloc_object_count++;
            mUnit = unit;
            mInfo = unit.Info;
            mProp = unit.Info.Properties as XmdsUnitProperties;
            mHateSystem = new XmdsHateSystem(this);
        }
        ~XmdsVirtual() { s_alloc_object_count--; }

        public void OnInit(InstanceUnit unit, bool pointLv)
        {
            UnitInfo info = unit.Info;

            FormatLog("- 初始化单位 : {0} - {0} ", unit.ID, unit.Name);

            Stopwatch sw = Stopwatch.StartNew();

            try
            {
				//出生点坐标.
				mBirthPosX = mUnit.X;
                mBirthPosY = mUnit.Y;
                //背包格子数.
                mVirtualInventorySize = mProp.ServerData.Prop.CurInventorySize;
				//非玩家,速度配置0
				if (mInfo.UType != UnitInfo.UnitType.TYPE_PLAYER && mProp.ServerData.Prop.MoveSpeed == 0)
				{
					mProp.ServerData.Prop.MoveSpeed = mInfo.MoveSpeedSEC;
				}

					//当前场景类型.
				InitSceneInfo();
                //子类初始化.
                Init(pointLv);
                //基础信息初始化.
                InitBaseData(mProp.ServerData.Prop);
                //坐骑信息记录.
                CheckMountStatus(mProp.ServerData.AvatarList);

				if (this.mCardModule == null)
				{
					this.CreateCreateCardModule();					
				}

				//初始化技能信息.
				InitSkillInfo(mProp.ServerData);

                //脱战计时器初始化.
                InitOutOfCombatTime();
                //初始化HP恢复计时器.
                InitRebornTimer();

                //(最后执行)同步给客户度信息.
                SyncClientData();
                //施放技能监听.
                mUnit.OnLaunchSkill += OnLaunchSkillHandler;
                //技能新增监听.
                mUnit.OnSkillAdded += OnSkillAddHandler;
                //技能移除监听.
                mUnit.OnSkillRemoved += OnSkillRemoveHandler;
                //技能变更监听.
                mUnit.OnStateChanged += OnStateChangedHandler;
                //物品时候时触发.
                mUnit.OnUseItem += MUnit_OnUseItem;

                mUnit.OnSkillHitTarget += OnSkillHitTargetHandler;
            }
			catch(Exception e)
			{
				log.Error("单位初始化异常:" + unit.Info.ID + ", " + e);
			}
            finally
            {
                sw.Stop();

                if (sw.ElapsedMilliseconds > 10)
                {
                    FormatLog("XmdsVirtual create overload , stopwatch time {0} > 10ms", sw.ElapsedMilliseconds);
                }

            }

        }

		private void MUnit_OnUseItem(InstanceUnit obj, ItemTemplate item, InstanceUnit item_creater)
		{
			BattleFunction battleFuntion = BattleFunction.GetInstance();
			if (item != null && battleFuntion != null)
			{
				int id = (item.Properties as XmdsItemProperties).TriggerFunctionID;
				if (id != 0)
				{
					battleFuntion.TriggrBattleFunction(id, this, this);
				}
			}
		}

		public void OnDispose(InstanceUnit owner)
        {
            Dispose();
        }

        /// <summary>
        /// 供子类重铸.
        /// </summary>
        protected virtual void Init(bool pointLv) { }

        public bool IsFinishSkillInit()
        {
            return mFinishSkillInit;
        }

        #region 常用API.

        protected virtual void SyncClientData()
        {
            //推属性变更计算.
            UnitPropRefresh();
            //第一次将全部属性推给客户端.
            SyncBattlePropsFields(PlayerBattlePropChangeEventB2C.MASK_ALL);
        }

        public int GetUnitLv()
        {
            if (this.mProp.ServerData.BaseInfo.UnitLv == 0)
            {
                return 1;
            }

            return this.mProp.ServerData.BaseInfo.UnitLv;
        }

        public int GetStateLv()
        {
            return this.mProp.ServerData.BaseInfo.StateLv;
        }

		// 神器id
        public int GetArtifactIndex()
        {
            return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex;
        }

		//获得神器克制id
		public bool IsArtifactRestrain(UnitFateType fateType)
		{
			return ((int)fateType-1) == (((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex + 1) % 5;
		}

		//是否有神器
		public bool IsHasArtifact()
		{
			return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex != (int)ArtifactType.None;
		}

		//神器背饰id
		public int GetArtifactDefenceIndex()
		{
			return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactDefenceIndex;
		}

		protected void InitBaseInfo(XmdsUnitBaseInfo baseInfo)
        {
            //同步等级信息.
            mProp.ServerData.BaseInfo = baseInfo;
            this.mUnit.Level = mProp.ServerData.BaseInfo.UnitLv;
        }

        public HateSystem GetHateSystem()
        {
            return mHateSystem;
        }

        /// <summary>
        /// 获得攻击目标.
        /// </summary>
        /// <returns></returns>
        public virtual InstanceUnit GetAtkTarget(InstanceUnit target)
        {
            var unit_prop = target.Virtual as XmdsVirtual;
            return DispatchGetAtkUnitEvent(unit_prop).mUnit;
        }

        /// <summary>
        /// 物品触发单位加血效果.
        /// </summary>
        /// <param name="hp"></param>
        public int AddHPByItem(int hp)
        {
            int v = hp;

            this.mUnit.ReduceHP(-v, null, false, null);

            return v;
        }

        /// <summary>
        /// 女武神能量变更.
        /// </summary>
        /// <param name="value"></param>
        public void AddEnergyByItem(int value)
        {

        }

        /// <summary>
        /// 通知单位接收跳字事件.
        /// </summary>
        /// <param name="objID"></param>
        /// <param name="value"></param>
        public void SendHPChangeMessage(uint objID, int value)
        {
            BattleHintNumberB2C evt = new BattleHintNumberB2C();
            evt.Value = -value;
            evt.State = (byte)UnitHitEventState.Normal;
            evt.TargetObjID = this.mUnit.ID;
            this.mUnit.queueEvent(evt);
        }

        /// <summary>
        /// 通知单位接收能量变更跳字事件.
        /// </summary>
        /// <param name="objID"></param>
        /// <param name="value"></param>
        public void SendMPChangeMessage(uint objID, int value)
        {
            BattleHintNumberB2C evt = new BattleHintNumberB2C();
            evt.Value = -value;
            evt.State = (byte)UnitHitEventState.MP;
            evt.TargetObjID = this.mUnit.ID;
            this.mUnit.queueEvent(evt);
        }

        public void SendBattleHintNumberB2C(int Value, UnitHitEventState type, uint targetId = 0)
        {
            BattleHintNumberB2C evt = new BattleHintNumberB2C();
            evt.Value = Value;
            evt.State = (byte)type;
            evt.TargetObjID = targetId == 0 ? this.mUnit.ID : targetId;
            this.mUnit.queueEvent(evt);
        }

        /// <summary>
        /// 加血.
        /// </summary>
        /// <param name="hp">血量</param>
        /// <param name="sender">加血者</param>
        /// <param name="sendMsg">是否发送协议</param>
        public void AddHP(int hp, InstanceUnit sender = null, bool sendMsg = true, DamageSource dmgSrc = DamageSource.Def)
        {
            this.mUnit.ReduceHP(-hp, sender, sendMsg, null, false, dmgSrc);
        }

		public void AddHP(int hp, InstanceUnit sender, DamageSource dmgSrc)
		{
			this.mUnit.ReduceHP(-hp, sender, true, null, false, dmgSrc);
		}

		/// <summary>
		/// 加能量.
		/// </summary>
		/// <param name="mp"></param>
		/// <param name="sendMsg">是否发送协议</param>
		public void AddMP(int mp, InstanceUnit sender, bool sendMsg = true, bool force = false, AttackSource source = null)
        {
            this.mUnit.AddMP(mp, sender, force, false, source);
        }

		public void AddMP(int mp, InstanceUnit sender, AttackSource source)
		{
			this.mUnit.AddMP(mp, sender, true, false, source);
		}

		public bool IsCanReduceMP(bool force)
		{
			return force || mRecoverMPLeftTimes <= 0;
		}

        /// <summary>
        /// 获得角色原始属性.
        /// </summary>
        /// <returns></returns>
        public XmdsUnitProp GetOriginProp()
        {
            return mProp.ServerData.Prop;
        }

        /// <summary>
        /// 判断一定概率是否触发概率单位为万分比:填写1000表示百分之10.
        /// </summary>
        /// <param name="percent"></param>
        /// <returns></returns>
        public bool RandomPercent(int percent)
        {
            return XmdsDamageCalculator.IsInRandomRange(percent,
                this.mUnit.RandomN, (int)XmdsDamageCalculator.PERER);
        }

        protected virtual void Dispose()
        {
            DestorySkill();

            mOutOfCombatTime = null;
            mHPRebornTimer = null;
			mMPRebornTimer = null;
			OnHealEventHandle = null;
            event_OnCombatStateChangeHandle = null;
            event_OnHandleCombatChangeEvent = null;
            mBattlePropChangeEvt = null;

			if(this.mCardModule != null)
			{
				this.mCardModule.Dispose();
			}

            ClearRegistEvent();
            mHateSystem.Dispose();
        }

        /// <summary>
        /// 是否在异常状态内.
        /// </summary>
        /// <returns></returns>
        public bool IsInDebuffStatus()
        {
            bool ret = false;

            if (this.mUnit.IsStun || this.mUnit.IsSilent)
            {
                ret = true;
            }

            //取当前所有BUFF,判断如果有隐身BUFF立即解除该BUFF.
            using (var buffList = ListObjectPool<InstanceUnit.BuffState>.AllocAutoRelease())
            {
                this.mUnit.GetAllBuffStatus(buffList);

                if (buffList != null && buffList.Count > 0)
                {
                    for (int i = 0; i < buffList.Count; i++)
                    {
						if (XmdsInstanceUtils.IsControlBuff(buffList[i].Data))
						{
							return true;
						}                    
                    }
                }

            }
            return ret;
        }

        //移除控制buff
        public void RemoveControlBuff()
        {
            //取当前所有BUFF,判断如果有隐身BUFF立即解除该BUFF.
            using (var buffList = ListObjectPool<InstanceUnit.BuffState>.AllocAutoRelease())
            {
                //InstanceUnit.BuffState bfs = null;
                //XmdsBuffProperties prop = null;
                //BuffTemplate bt = null;

                this.mUnit.GetAllBuffStatus(buffList);

                if (buffList == null || buffList.Count <= 0)
                {
                    return;
                }

                for (int i = 0; i < buffList.Count; i++)
                {
					if (XmdsInstanceUtils.IsControlBuff(buffList[i].Data))
					{
						this.mUnit.removeBuff(buffList[i].Data.ID);
					}
                }
            }
        }

        protected bool IsBusy()
        {
            bool ret = false;

            if (this.mUnit.CurrentState != null &&
              (this.mUnit.CurrentState is InstanceUnit.StateSkill))// ||
                                                                   //(this.mUnit.CurrentState is InstanceUnit.StatePickObject))
            {
                ret = true;
            }

            return ret;
        }

        /// <summary>
        /// 向战斗服发送提示信息.
        /// </summary>
        /// <param name="msg"></param>
        public void SendMsgToClient(string msg)
        {
            if (msg != null)
            {
                ShowTipsEventB2C evt = new ShowTipsEventB2C();
                evt.Msg = msg;

                this.mUnit.queueEvent(evt);
            }
        }

		//单独给玩家发送消息,非广播
		public void SendMsgToPlayer(ObjectEvent evt, bool force = false)
		{
			this.mUnit.queueEvent(evt, force);
		}

		/// <summary>
		/// 获取当前可用背包格子数量.
		/// </summary>
		/// <returns></returns>
		public int GetInventorySize()
        {
            if (mProp != null)
            {
                return mProp.ServerData.Prop.CurInventorySize;
            }

            return 0;
        }

        public void SetInventorySize(int size)
        {
            if (mProp != null)
            {
                mProp.ServerData.Prop.CurInventorySize = size;
                VirtualInventorySize = size;
            }
        }

        public int VirtualInventorySize
        {
            get { return mVirtualInventorySize; }
            set { mVirtualInventorySize = value; }
        }

        /// <summary>
        /// 组队背包格子数.
        /// </summary>
        /// <returns></returns>
        public int GetTeamInventorySize()
        {
            if (mProp != null)
            {
                return mProp.ServerData.Prop.CurTeamInventorySize;
            }

            return 0;
        }

        public bool ContainBuff(bool isDebuff)
        {
            using (var buffList = ListObjectPool<InstanceUnit.BuffState>.AllocAutoRelease())
            {
                InstanceUnit.BuffState bfs = null;
                XmdsBuffProperties prop = null;
                BuffTemplate bt = null;

                this.mUnit.GetAllBuffStatus(buffList);

                if (buffList != null && buffList.Count > 0)
                {
                    for (int i = 0; i < buffList.Count; i++)
                    {
                        bfs = buffList[i];
                        bt = bfs.Data;
                        prop = bt.Properties as XmdsBuffProperties;

                        if (prop.Dispelled == false) { continue; }

                        if (bt.IsHarmful == isDebuff)
                        {
                            return true;
                        }

                    }
                }
            }

            return false;
        }

        /// <summary>
        /// 记录同步可视数据.
        /// 战斗服数据大致分为两块,一部分用作战斗计算使用,另一部分用作同步客户端表现相关信息,
        /// 当表现信息变更时,需要将数据同步给syncInfo,底层每次调用时时直接拿syncInfo来推送.
        /// </summary>
        protected void SyncPlayerVisibleData()
        {
            if (this.mUnit.VisibleInfo is PlayerVisibleDataB2C)
            {
                PlayerVisibleDataB2C pvd = this.mUnit.VisibleInfo as PlayerVisibleDataB2C;
                pvd.AvatarList = this.mProp.ServerData.AvatarList;
                pvd.BaseInfo = this.mProp.ServerData.BaseInfo;
                pvd.UnitPKInfo = this.mProp.ServerData.UnitPKInfo;
                pvd.UnitSceneInfo = this.mProp.ServerData.UnitSceneInfo;
            }

        }

        /// <summary>
        /// 当前场景信息初始化记录.
        /// </summary>
        protected virtual void InitSceneInfo()
        {
            EditorScene es = mUnit.Parent as EditorScene;
            XmdsSceneProperties zp = es.Data.Properties as XmdsSceneProperties;
            ServerSceneData = zp.ServerSceneData;
        }

        protected bool CalPKValue(XmdsVirtual target)
        {
            //特殊规则,跨服场景,击杀非本服玩家.
            if (this.mUnit.GetSceneType() >= CommonAI.Data.SceneType.CROSS_SERVER_NEW)
            {
                XmdsVirtual_Player r = target.GetPlayerUnit();

                if (r != null && this.GetServerID() != r.GetServerID())
                {
                    return false;
                }
            }

            return ServerSceneData.CalPKValue;
        }

        public virtual PKMode GetCurPKMode()
        {
            if (mProp.ServerData.UnitPKInfo != null)
            {
                return mProp.ServerData.UnitPKInfo.CurPKMode;
            }

            return PKMode.Peace;
        }

        /// <summary>
        /// 获得当前PK等级(判断是否为红名).
        /// </summary>
        /// <returns></returns>
        public virtual PKLevel GetCurPKLevel()
        {
            PKLevel ret = PKLevel.White;

            if (mProp != null && mProp.ServerData.UnitPKInfo != null)
            {
                ret = mProp.ServerData.UnitPKInfo.CurPKLevel;
            }

            return ret;
        }

        /// <summary>
        /// 服ID.
        /// </summary>
        /// <returns></returns>
        public virtual int GetServerID()
        {
            int ret = 0;

            if (this.mProp.ServerData != null && this.mProp.ServerData.BaseInfo != null)
            {
                ret = this.mProp.ServerData.BaseInfo.ServerID;
            }

            return ret;
        }

        /// <summary>
        /// 获得公会ID.
        /// </summary>
        /// <returns></returns>
        public virtual string GetGuildID()
        {
            string ret = null;

            if (this.mProp.ServerData != null && this.mProp.ServerData.BaseInfo != null)
            {
                ret = this.mProp.ServerData.BaseInfo.GuildID;
            }

            return ret;
        }

        /// <summary>
        /// 获得阵营ID
        /// </summary>
        /// <returns></returns>
        public virtual int GetForceID()
        {
            return this.mUnit.Force;
        }

        /// <summary>
        /// 获得单位ID(玩家返回UUID).
        /// </summary>
        /// <returns></returns>
        public virtual string GetPlayerUUID()
        {
            return mUnit.ID.ToString();
        }

        /// <summary>
        /// 重置功能,血量、buff、状态、技能全部变为初始状态.
        /// </summary>
        public void Reset()
        {
            //脱战.
            SetCombatState(BattleStatus.None, 1);

            //BUFF.
            this.mUnit.clearBuffs();

            //技能CD.
            this.mUnit.ClearAllSkillCD();

            //坐骑状态.
            this.TakeOffMount();

            //回血重置.
            if (mHPRebornTimer != null)
            {
                mHPRebornTimer.Reset();
            }

			if(mMPRebornTimer != null)
			{
				mMPRebornTimer.Reset();
			}

            this.mUnit.startRebirth();

            this.mUnit.CurrentHP = this.mUnit.MaxHP;
            this.mUnit.CurrentMP = this.mUnit.MaxMP;
        }
        /// <summary>
        /// 获取当前强度类型
        /// </summary>
        /// <returns></returns>
        public string GetCurSceneType()
        {
            return ServerSceneData.SceneHard;
        }

        /// <summary>
        /// 获取当前场景类型
        /// </summary>
        /// <returns></returns>
        public CommonAI.XmdsConstConfig.AreaType CurAreaType()
        {
            return ServerSceneData.CurAreaType;
        }

        protected virtual void OnHeal(XmdsVirtual attcker, int value, ref AtkResult result)
        {
            if (OnHealEventHandle != null)
            {
                OnHealEventHandle.Invoke(attcker, this, value, ref result);
            }
        }

        public void SendBattleFloatTipsEventB2C(BattleFloatTipsEventB2C evt)
        {
            if (evt != null)
            {
                this.mUnit.queueEvent(evt);
            }
        }

        public void SendBubbleTipsEventB2C(string msg)
        {
            if (!string.IsNullOrEmpty(msg))
            {
                var evt = new BubbleTipsEventB2C();
                evt.Msg = msg;
                this.mUnit.queueEvent(evt);
            }
        }
        /// <summary>
        /// 能否使用物品.
        /// </summary>
        /// <returns></returns>
        public bool CanUseItem()
        {
            bool ret = true;

            ret = (!this.mUnit.IsSilent);

            return ret;
        }

        /// <summary>
        /// 同步归属权信息.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="protype"></param>
        public virtual void SyncHeirsInfo(string name, int hpPercent, CommonAI.Data.XmdsUnitPro protype)
        {

        }

        /// <summary>
        /// 是否可被攻击.
        /// </summary>
        public virtual bool IsAttackable(XmdsVirtual attacker)
        {
            return true;
        }

        public virtual int GetVirtualTemplateID()
        {
            return mInfo.TemplateID;
        }

        /// <summary>
        /// 治愈效果,满血、满蓝.
        /// </summary>
        public virtual void DoCure()
        {
            this.AddHP(this.mUnit.MaxHP, null, false);
            this.AddMP(this.mUnit.MaxMP, null, false, true);
        }

        public bool SkillAutoLaunchTest(InstanceUnit.SkillState ss)
        {
            bool ret = false;

            UnitSkill us = XmdsBattleSkill.GetUnitSkill(ss.Data.ID); ;

            if (us != null)
            {
                ret = us.SkillAutoLaunchTest(ss, this);
            }

            return ret;
        }

        #endregion

        #region 基础事件.

        /// <summary>
        /// 角色本身的初始化.
        /// </summary>
        /// <param name="unit"></param>
        private void Unit_OnActivated(InstanceUnit unit)
        {
            mUnit.OnActivated -= Unit_OnActivated;
        }

        //主动移除技能.
        public GameSkill RemoveSkill(int skillID)
        {
            GameSkill skillData = this.SkillHelper.GetGameSkill(skillID);
            if (skillData == null)
            {
                return null;
            }
           
            if (skillData.SkillType == XmdsSkillType.passive || skillData.SkillType == XmdsSkillType.petGivePassive)
            {
                this.SkillHelper.RemovePassiveSkill(skillID);
                return null;
            }
            else
            {
                SkillState skillState = this.mUnit.getSkillState(skillID);
                this.SkillHelper.RemoveActiveSkill(skillID);
                return skillData;
            }
        }

        #endregion

        #region 安全区域

        private bool mIsInSafeArea = false;
        /// <summary>
        /// 是否在安全区域
        /// </summary>
        public bool IsInSafeArea(){ return mIsInSafeArea; }
        //跟新战斗区域状态
        private void UpdateAreaState(int intervalMS)
        {
            //var sa = mUnit.Parent.GetArea(mUnit.X, mUnit.Y);
            var sa = mUnit.CurrentArea;
            if (sa != null && sa.CurrentMapNodeValue == XmdsMapBlock.BLOCK_VALUE_SAFE)
            {
                this.mIsInSafeArea = true;
            }
            else
            {
                this.mIsInSafeArea = false;
            }
        }


        #endregion

        #region 战斗状态.

        /// <summary>
        /// 是否在战斗状态.
        /// </summary>
        public BattleStatus CombatState
        {
            get { return mInCombatState; }
        }

        public virtual void SetCombatState(BattleStatus value, byte reason = 0, String pvpTriggerPlayerId = "")
        {
            // 只有在空闲状态才允许设置技能展示状态
            if (value == BattleStatus.ReadyBattle && mInCombatState != BattleStatus.None)
            {
                return;
            }

			if (value != BattleStatus.None && mOutOfCombatTime != null)
			{
				mOutOfCombatTime.Reset();
			}

			if (mInCombatState != value)
            {
				if (value == BattleStatus.None)
                {
                    if (JudgeChangeCombatStateChange(value, reason))
                    {
                        mInCombatState = value;
                        CombatStateConnect(value, reason);
                        OnCombatStateChange(mInCombatState);

						//单位脱战了
						this.mUnit.Parent.cb_unitOutBattleCallBack(this.mUnit);
					}
                }
                else if (value > mInCombatState)//战斗状态等级不同.
                {
                    if (JudgeChangeCombatStateChange(value, reason))
                    {
                        mInCombatState = value;
                        CombatStateConnect(value, reason);
                        OnCombatStateChange(mInCombatState);
                    }
                }
            }

			if(mInCombatState == BattleStatus.PVP)
			{
				this.mPvpTriggerPlayerId = pvpTriggerPlayerId;
			}			
		}

        public bool IsInPVP()
        {
            return mInCombatState == BattleStatus.PVP ? true : false;
        }

        public bool IsInPVE()
        {
            return mInCombatState == BattleStatus.PVE ? true : false;
        }

		public BattleStatus GetBattleStatus()
		{
			return mInCombatState;
		}

		//坐骑状态变更.
		public bool IsMounted
        {
            set { mIsMounted = value; }
            get { return mIsMounted; }
        }

        private void CheckMountStatus(List<XmdsAvatarInfo> list)
        {
            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i].PartTag == XmdsAvatarInfo.XmdsAvatar.Ride_Equipment)
                    {
                        if (!string.IsNullOrEmpty(list[i].FileName))
                        {
                            //有坐骑信息.
                            IsMounted = true;
                            break;
                        }
                    }
                }
            }
        }

        //状态改变时候触发.
        protected virtual void OnCombatStateChange(BattleStatus status)
        {
            //脱战时,清空仇恨列表.
            if (status == BattleStatus.None && this.mUnit.IsDead() == false)
            {
                mHateSystem.Clear();

                if (event_OnCombatStateChangeHandle != null)
                {
                    event_OnCombatStateChangeHandle.Invoke(this, false);
                }

                FormatLog("{0}脱离战斗", mInfo.Name);
            }

            //状态变更时,需要同步告知客户端做响应表现.
            if (status != BattleStatus.None)
            {
                FormatLog("{0}进入战斗", mInfo.Name);
            }

            SyncUnitCombatState(status);

            if (event_OnHandleCombatChangeEvent != null)
            {
                event_OnHandleCombatChangeEvent.Invoke(status);
            }

            var scene = (mUnit.Parent as XmdsServerScene);
            scene.callback_OnCombatStateChange(this.mUnit, status);
        }

        protected virtual bool JudgeChangeCombatStateChange(BattleStatus status, byte reason)
        {
            bool ret = true;
            //默认为0,特殊情况不为0.
            if (reason != 0)
            {
                ret = true;
            }
            else
            {
                if (status == BattleStatus.None)
                {
                    //表示单位一旦开始追击不会退出战斗状态.
                    if (this.mUnit.Info.GuardRangeLimit == 0)
                    {
                        return false;
                    }
                }
            }

            return ret;
        }

        protected virtual void ChangeCombatStateFromAtk(XmdsVirtual target)
        {
            var s = target.IsPlayerUnit() ? BattleStatus.PVP : BattleStatus.PVE;
            SetCombatState(s, 0, target.mUnit.PlayerUUID);
        }

        protected virtual void CombatStateConnect(BattleStatus status, byte reason)
        {

        }

        public virtual void OnHitOthter(XmdsVirtual target)
        {

        }

        private void SyncUnitCombatState(BattleStatus status)
        {
            //改走通用字段.
            //mUnit.queueEvent(new CombatStateChangeEvent(mUnit.ID, status));

            //Dummy_0用来同步战斗状态.
            mUnit.Dummy_0 = (byte)status;
        }

        //脱战计时器.
        private void InitOutOfCombatTime()
        {
            if (mProp.IsUseCombatTimeCount == true)
            {
				if (this.mUnit.IsMonster)
				{
					mOutOfCombatTime = new TimeExpire<int>(XmdsConfig.Instance.OUTOF_BATTLE_MONSTER);
				}
				else
				{
					mOutOfCombatTime = new TimeExpire<int>(XmdsConfig.Instance.OUTOF_BATTLE_PLAYER);
				}                
            }
        }

        //更新脱战计时.
        private void UpdateOutOfCombatTime(int time)
        {
            if (mInCombatState != BattleStatus.None && mOutOfCombatTime != null && mOutOfCombatTime.Update(time))
            {
                SetCombatState(BattleStatus.None);
			}
        }

        #endregion

        #region 基础信息.

        protected void InitBaseData(XmdsUnitProp data)
        {
            //复制原始单位数据.

            MirrorProp = (XmdsUnitProp)data.Clone();

            this.mUnit.SetMaxHP(data.MaxHP, true);
            if (data.HP >= 0)
            {
                this.mUnit.CurrentHP = data.HP;
            }

			this.mUnit.MaxMP = data.ShieldValue;
			this.mUnit.CurrentMP = data.ShieldValue;

			SycSkillCdReduce();
            SycControledTimeReduce();

            SycMoveSpeed();
            SycAttackSpeed();
        }

        public void SycMoveSpeed()
        {
            this.mUnit.SetMoveSpeed(this.MirrorProp.MoveSpeed);
        }

        private void SycAttackSpeed()
        {
            this.mUnit.SetAttackSpeed(this.MirrorProp.AttackSpeed);
        }

        private void SycMaxHP()
        {
            mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
        }

        private void SycSkillCdReduce()
        {
            mUnit.SetSkillCdReduce(this.MirrorProp.SkillCD);
        }

        private void SycControledTimeReduce()
        {
            mUnit.SetControledTimeReduce(this.MirrorProp.CtrlTimeReduce);
        }

        #endregion

        #region 血量回复.

        private void InitRebornTimer()
        {
            if (mHPRebornTimer == null)
            {
                mHPRebornTimer = new TimeInterval<int>(Coefficient_HPRebornTime);
                mHPRebornTimer.FirstTimeEnable = false;
            }

			if(mMPRebornTimer == null)
			{
				mMPRebornTimer = new TimeInterval< int > (GlobalData.SHIELD_RECOVER_INTERVAL);
				mMPRebornTimer.FirstTimeEnable = false;
			}
        }

        private void UpdateHPReborn(int intervalMS)
        {
			try
			{
				if (MirrorProp.HPReborn > 0 && this.mUnit.CurrentHP < this.mUnit.MaxHP && mHPRebornTimer != null && !this.mUnit.IsDead())
				{
					if (mHPRebornTimer.Update(intervalMS))
					{
						if (mInCombatState != BattleStatus.None)
						{
							int v = CUtils.CastInt(MirrorProp.MaxHPReborn * Coefficient_CombatHPReborn);
							this.mUnit.AddHP(v, null);
						}
						else
						{
							this.mUnit.AddHP(MirrorProp.MaxHPReborn, null);
						}
					}
				}
			}
			catch(Exception e)
			{
				log.Error("UpdateHPReborn catch : " + this.mUnit.Info.ID + ", IsActive: " + this.mUnit.IsActive +
					", " + (mMPRebornTimer == null ? "timer null" : "OK") + ", " + e);
			}          
        }

		private void UpdateMPReborn(int intervalMS)
		{
			try
			{
				if(this.mRecoverMPLeftTimes > 0 && mMPRebornTimer != null && mMPRebornTimer.Update(intervalMS))
				{
					int addMP = 0;
					if(--this.mRecoverMPLeftTimes == 0)
					{
						addMP = this.mUnit.MaxMP - this.mUnit.CurrentMP;
					}
					else
					{
						addMP = this.mUnit.MaxMP / GlobalData.SHIELD_RECOVER_TIME;
					}

					this.AddMP(addMP, null);
				}
			}
			catch (Exception e)
			{
				log.Error("UpdateMPReborn catch : " + this.mUnit.Info.ID + ", IsActive: " + this.mUnit.IsActive + 
					", " + (mMPRebornTimer == null ? "timer null" : "OK") + ", " + e);
			}
		}

		public void StartRecoverMP(bool reset = false)
		{
			if (reset)
			{
				this.mRecoverMPLeftTimes = 0;
			}
			else
			{
				this.mRecoverMPLeftTimes = GlobalData.SHIELD_RECOVER_TIME;
			}			
		}

		#endregion

		#region Formula调用.

		public void OnUnitRemoved() { }
        public virtual int OnHit(XmdsVirtual attacker, AttackSource source)
        {
            AtkResult result = new AtkResult();

            //无敌直接免疫打击效果.
            if ((this.IsInvincible == true) && source.FromExpectTarget == SkillTemplate.CastTarget.Enemy)
            {
                attacker.OnHitOthter(this);
                //无敌时仇恨减为1.
                attacker.mHateSystem.SetHateInfo(this.mUnit.ID, 1);
                //攻击者进度战斗状态.
                attacker.ChangeCombatStateFromAtk(this);
                mHateSystem.OnHitted(attacker, this, 0, ref result);
                source.OutIsDamage = false;
                source.OutClientState = (int)UnitHitEventState.Immunity;
                return 0;
            }


            #region 特殊状态判断.

            if (this.NothingnessIgnoreBuff)
            {
                if (source.FromBuffState != null)
                {
                    return 0;
                }
            }

            if (this.NothingnessIgnoreSkill)
            {
                if (source.FromSkillState != null || source.FromSpellUnit != null)
                {
                    return 0;
                }
            }

            if (this.NothingnessIgnoreAll)
            {
                return 0;
            }

            #endregion

            int damage = this.On_hit_unit_vs_unit(attacker, this, source, ref result);

            if (damage < 0)
            {
                OnHeal(attacker, -damage, ref result);
                //加血.
                if (attacker.CombatState != BattleStatus.None) { SetCombatState(attacker.CombatState); }
            }
            else if(this.mUnit.ID != attacker.mUnit.ID)//自己对自己作用的不算
            {

                if (damage == 0 && source.OutClientState != (int)UnitHitEventState.Dodge)//增益、负面效果.
                {

                    if (source.FromExpectTarget == SkillTemplate.CastTarget.Enemy)//负面效果.
                    {
                        attacker.OnHitOthter(this);
                        //攻击者进度战斗状态.
                        attacker.ChangeCombatStateFromAtk(this);
                        mHateSystem.OnHitted(attacker, this, damage, ref result);
                        var v = attacker.IsPlayerUnit() ? BattleStatus.PVP : BattleStatus.PVE;

                        //单位被攻击,且从PVE状态转为PVP状态,
                        if (v == BattleStatus.PVP && CombatState != BattleStatus.PVP)
                        {
                            UnderAttackCheck(attacker);
                        }

                        SetCombatState(v, 0, attacker.mUnit.PlayerUUID);
                        //坐骑状态下检查受击影响.
                        MountOnHitCheck(attacker);
                        //判断异常状态(击倒击飞).
                        {
                            MountOnHit(source);
                        }
                    }
                    else //增益效果.
                    {
                        if (this != attacker)
                        {
                            //施术者或受攻击者双方互相影响.
                            if (this.CombatState != BattleStatus.None)
                            {
                                attacker.SetCombatState(this.CombatState);
                            }

                            if (attacker.CombatState != BattleStatus.None)
                            {
                                SetCombatState(attacker.CombatState);
                            }

                        }
                    }
                }
                else
                {
                    attacker.OnHitOthter(this);

                    //致命一击时候死亡状态不设置.
                    if (this.mUnit.CurrentHP - damage > 0)
                    {
                        var s = attacker.IsPlayerUnit() ? BattleStatus.PVP : BattleStatus.PVE;

                        //单位被攻击,且从PVE状态转为PVP状态,
                        if (s == BattleStatus.PVP && CombatState != BattleStatus.PVP)
                        {
                            UnderAttackCheck(attacker);
                        }

                        SetCombatState(s, 0, attacker.mUnit.PlayerUUID);
                    }

                    //攻击者进度战斗状态.
                    attacker.ChangeCombatStateFromAtk(this);
                    //仇恨值计算.
                    attacker.DispatchCalThreatValueEvent(this, source, ref result);
                    mHateSystem.OnHitted(attacker, this, damage, ref result);
                    //坐骑状态下检查受击影响.
                    MountOnHitCheck(attacker);
                    //判断异常状态(击倒击飞).
                    {
                        MountOnHit(source);
                    }

					//扣除定力
					if (this.mUnit.MaxMP > 0 && result.breakShieldValue > 0)
					{
						this.AddMP(-result.breakShieldValue, attacker.mUnit, source);
					}
                }

            }

            //if (damage == 0)
            //{
            //    source.OutIsDamage = false;
            //}

            return damage;
        }
        public virtual void OnUnitDead(XmdsVirtual killer)
        {
            //坐骑状态设置为false.
            TakeOffMount();
            //脱战.
            SetCombatState(BattleStatus.None, 1);

            if (mHateSystem != null)
            {
                mHateSystem.Clear();
            }


        }

        public virtual void OnKillUnit(XmdsVirtual dead)
        {

        }

        /// <summary>
        /// 是否属于玩家.
        /// </summary>
        /// <returns></returns>
        public virtual bool IsPlayerUnit()
        {
            return false;
        }

        /// <summary>
        /// 获取对应玩家单位.
        /// </summary>
        /// <returns></returns>
        public virtual XmdsVirtual_Player GetPlayerUnit()
        {
            return null;
        }

        public void OnHandleNetMessage(ObjectAction action)
        {
        }
        public void OnTriggerStart(InstanceUnit.TriggerState trigger, XmdsVirtual target)
        {

        }
        public virtual void OnUpdateTriggerSkill(int intervalMS, bool slowRefresh)
        {
            // 区域刷新 //
            UpdateAreaState(intervalMS);           
            //同步战斗属性协议.
            UpdateBattlePropsChangeEvt();
			
			//慢刷新,不必要每一帧都刷新
			if (slowRefresh)
			{
				int slowInterval = intervalMS * GlobalData.ZONE_UPDATE_SLOW;
				//计算是否脱战.
				UpdateOutOfCombatTime(slowInterval);
				//HP回复.
				UpdateHPReborn(slowInterval);
				UpdateMPReborn(slowInterval);

				//仇恨系统刷新.
				UpdateHateSystem(slowInterval);
			}

			//技能刷新.
			UpdateSkillHelper(intervalMS, slowRefresh);

			if (this.mCardModule != null)
			{
				this.mCardModule.Update(intervalMS, slowRefresh);
			}
		}

        public void OnBuffBegin(InstanceUnit.BuffState state, XmdsVirtual sender)
        {
            BuffTemplate template = state.Data;
            XmdsBuffProperties prop = template.Properties as XmdsBuffProperties;
            List<XmdsBuffVirtual> list = null;
            if (state.Tag != null)
            {
                list = state.Tag as List<XmdsBuffVirtual>;
            }

			//异常BUFF对坐骑状态有影响.
			MountOnBuffBegin(template);

			if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {

                    UnitBuff ub = list[i] as UnitBuff;
                    ub.BuffBegin(this, sender, state);
                }
            }

            DispatchBuffEvent(state, BuffEventType.Begin, null);
        }
        public void OnBuffUpdate(InstanceUnit.BuffState state, int time)
        {
            BuffTemplate template = state.Data;
            List<XmdsBuffVirtual> list = null;

            if (state.Tag != null)
            {
                list = state.Tag as List<XmdsBuffVirtual>;
            }

            if (list != null && list.Count != 0)
            {
                int count = 0;

                for (int i = 0; i < list.Count; i++)
                {
                    UnitBuff ub = list[i] as UnitBuff;
                    ub.BuffUpdate(this, state);
                    if (ub.IsInvaild())
                    {
                        count++;
                    }
                }

                if (count == list.Count)//当前BUFF所有能力都已失效,主动移出该BUFF.
                {
                    this.mUnit.removeBuff(template.ID);
                }
            }


        }
        public void OnBuffEnd(InstanceUnit.BuffState state, string result, bool replace)
        {

            BuffTemplate template = state.Data;
            XmdsBuffProperties prop = template.Properties as XmdsBuffProperties;
            List<XmdsBuffVirtual> list = null;

            if (state.Tag != null)
            {
                list = state.Tag as List<XmdsBuffVirtual>;
            }

            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    UnitBuff ub = list[i] as UnitBuff;
                    ub.BuffEnd(this, state, replace);
                }
            }

            DispatchBuffEvent(state, BuffEventType.End, result);
        }

        #endregion

        #region 属性能力重算.

        /// <summary>
        /// 刷新属性.
        /// </summary>
        protected void UnitPropRefresh(XmdsUnitProp prop = null)
        {
            if (prop == null)
            {
                XmdsUnitProp zup = GetOriginProp();
                this.MirrorProp = zup.Clone() as XmdsUnitProp;
            }
            else
            {
                this.MirrorProp = prop;
            }

            foreach (KeyValuePair<int, PropChangeOperation> kvp in mPropChangeMap)
            {
                ChangeProp(kvp.Value);
            }

            int srcHP = this.MirrorProp.MaxHP;

            // 更新虚拟属性,只影响数值,不计入显示和战力计算(也不在面板上显示)
            if(this.mProp.ServerData.PropExt != null && this.mUnit.IsPlayer)
            {
                this.MirrorProp.AddTo(this.mProp.ServerData.PropExt);
            }

            SycMaxHP();
            SycSkillCdReduce();
            SycControledTimeReduce();

            SycMoveSpeed();
            SycAttackSpeed();

            //隐藏属性导致玩家血量变了,同步最大血量ext
            if(this.MirrorProp.MaxHP != srcHP)
            {
                SyncBattlePropsFields(UnitAttributeType.SetMaxHP);
            }
        }

        private void ChangeProp(PropChangeOperation opt)
        {
            XmdsUnitProp zup = GetOriginProp();

            switch (opt.Type)
            {
                case UnitAttributeType.Defence:
                    if (opt.OpType == PropChangeOperation.OperateType.Percent)
                    {
                        this.MirrorProp.DefencePer += opt.Value;
                    }
                    else
                    {
                        this.MirrorProp.BaseDefence += opt.Value;
                    }
					//攻击异常日志
					if (this.MirrorProp.Defence > this.GetOriginProp().Defence * 3)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.Defence, this.GetOriginProp().Defence);
					}
					break;
                case UnitAttributeType.CritRate:
                    this.MirrorProp.CritRate += opt.Value;
                    break;
                case UnitAttributeType.MaxHP:
                    if (opt.OpType == PropChangeOperation.OperateType.Percent)
                    {
                        this.MirrorProp.HPPer += opt.Value;
                    }
                    else
                    {
                        this.MirrorProp.BaseMaxHP += opt.Value;
                    }
                    mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
					//攻击异常日志
					if (this.MirrorProp.MaxHP > this.GetOriginProp().MaxHP * 3)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.MaxHP, this.GetOriginProp().MaxHP);
					}
					break;
                case UnitAttributeType.Attack:
                    if (opt.OpType == PropChangeOperation.OperateType.Percent)
                    {
                        this.MirrorProp.AttackPer += opt.Value;
                    }
                    else
                    {
                        this.MirrorProp.BaseAttack += opt.Value;
                    }
					//攻击异常日志
					if (this.MirrorProp.MaxAttack > this.GetOriginProp().MaxAttack * 3)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.MaxAttack, this.GetOriginProp().MaxAttack);
					}
					break;
                case UnitAttributeType.HealedEffect:
                    this.MirrorProp.HealedEffect += opt.Value;
                    break;
                case UnitAttributeType.HealEffect:
                    this.MirrorProp.HealEffect += opt.Value;
                    break;
                case UnitAttributeType.PlayerDamageReduce:
                    this.MirrorProp.PlayerDamageReduce += opt.Value;
					// 免伤异常日志
					if(this.MirrorProp.PlayerDamageReduce > 10000)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.PlayerDamageReduce, opt.Value);
					}
                    break;				
				case UnitAttributeType.MoveSpeed:
                    this.MirrorProp.MoveSpeed += GetOpValueFloat(zup.MoveSpeed, opt.Value, opt.OpType);
					this.MirrorProp.VelocityAddition += opt.Value;
					break;
                case UnitAttributeType.PickupRange:
                    this.MirrorProp.pickupRange += GetOpValue(zup.pickupRange, opt.Value, opt.OpType);
                    break;
                case UnitAttributeType.AttackSpeed:
					this.MirrorProp.AttackSpeed += GetOpValue(zup.AttackSpeed, opt.Value, opt.OpType);
					break;
                case UnitAttributeType.SkillLanuchSpeed:
                    this.MirrorProp.SkillCD += GetOpValue(zup.SkillCD, opt.Value, opt.OpType);
                    break;
                case UnitAttributeType.ControlTimeReduce:
                    this.MirrorProp.CtrlTimeReduce += opt.Value;
                    break;
                case UnitAttributeType.SkillDamage:
                    this.MirrorProp.SkillDamageAdd += opt.Value;
                    break;
                case UnitAttributeType.IngoreDefence:
					if (opt.OpType == PropChangeOperation.OperateType.Percent)
					{
						this.MirrorProp.IgnoreDefensePer += opt.Value;
					}
					else
					{
						this.MirrorProp.BaseIgnoreDefense += opt.Value;
					}
                    break;
                case UnitAttributeType.SkillLeech:
                    this.MirrorProp.ActiveAtkLeech += opt.Value;
                    break;             
                case UnitAttributeType.CritDamage:
                    this.MirrorProp.CritDamage += opt.Value;
                    break;
                case UnitAttributeType.PlayerDamageAdd:
                    this.MirrorProp.PlayerDamageAdd += opt.Value;
					// 伤害增加异常日志
					if (this.MirrorProp.PlayerDamageAdd > 10000)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.PlayerDamageAdd, opt.Value);
					}
					break;
				case UnitAttributeType.MonsterDamageAdd:
					this.MirrorProp.monsterDamageAdd += opt.Value;
					break;
				case UnitAttributeType.MonsterDamageReduce:
					this.MirrorProp.monsterDamageReduce += opt.Value;
					break;
				case UnitAttributeType.AllDmgAdd:
					this.MirrorProp.AllDmgAdd += opt.Value;
					// 伤害增加异常日志
					if (this.MirrorProp.AllDmgAdd > 10000)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.AllDmgAdd, opt.Value);
					}
					break;
				case UnitAttributeType.AllDmgReduce:
					this.MirrorProp.AllDmgReduce += opt.Value;
					// 伤害增加异常日志
					if (this.MirrorProp.AllDmgReduce > 13000)
					{
						this.PrintAttrErrorInfo(opt.Type, this.MirrorProp.AllDmgReduce, opt.Value);
					}
					break;
				case UnitAttributeType.SetMaxHP:
                    this.MirrorProp.BaseMaxHP = opt.Value;
					break;
				case UnitAttributeType.CritRate_NormalAtk:
					this.MirrorProp.NormalAtkCriteRate += opt.Value;
					break;
				case UnitAttributeType.HPRecover:
					if (opt.OpType == PropChangeOperation.OperateType.Percent)
					{
						this.MirrorProp.HPRecoverPer += opt.Value;
					}
					else
					{
						this.MirrorProp.HPReborn += opt.Value;
					}
					break;
				case UnitAttributeType.EAttack_Gold:
					this.MirrorProp.ArtifactAttack[(int)ArtifactType.Gold] += opt.Value;
					break;
				case UnitAttributeType.EAttack_Wood:
					this.MirrorProp.ArtifactAttack[(int)ArtifactType.Wood] += opt.Value;
					break;
				case UnitAttributeType.EAttack_Water:
					this.MirrorProp.ArtifactAttack[(int)ArtifactType.Water] += opt.Value;
					break;
				case UnitAttributeType.EAttack_Fire:
					this.MirrorProp.ArtifactAttack[(int)ArtifactType.Fire] += opt.Value;
					break;
				case UnitAttributeType.EAttack_Soil:
					this.MirrorProp.ArtifactAttack[(int)ArtifactType.Soil] += opt.Value;
					break;
				case UnitAttributeType.EDefence_Gold:
					this.MirrorProp.ArtifactDefense[(int)ArtifactType.Gold] += opt.Value;
					break;
				case UnitAttributeType.EDefence_Wood:
					this.MirrorProp.ArtifactDefense[(int)ArtifactType.Wood] += opt.Value;
					break;
				case UnitAttributeType.EDefence_Water:
					this.MirrorProp.ArtifactDefense[(int)ArtifactType.Water] += opt.Value;
					break;
				case UnitAttributeType.EDefence_Fire:
					this.MirrorProp.ArtifactDefense[(int)ArtifactType.Fire] += opt.Value;
					break;
				case UnitAttributeType.EDefence_Soil:
					this.MirrorProp.ArtifactDefense[(int)ArtifactType.Soil] += opt.Value;
					break;
				case UnitAttributeType.ToBoss_CriteRate:
					this.MirrorProp.ToBossCritRate += opt.Value;
					break;
				case UnitAttributeType.ToBoss_CriteDamage:
					this.MirrorProp.ToBossCritDamage += opt.Value;
					break;
				case UnitAttributeType.MonsterRestraint_1:
					this.MirrorProp.MonsterRestraint[(int)UnitFateType.One - 1] += opt.Value;
					break;
				case UnitAttributeType.MonsterRestraint_2:
					this.MirrorProp.MonsterRestraint[(int)UnitFateType.Two - 1] += opt.Value;
					break;
				case UnitAttributeType.MonsterRestraint_3:
					this.MirrorProp.MonsterRestraint[(int)UnitFateType.Three - 1] += opt.Value;
					break;
				case UnitAttributeType.MonsterRestraint_4:
					this.MirrorProp.MonsterRestraint[(int)UnitFateType.Four - 1] += opt.Value;
					break;
				case UnitAttributeType.MonsterRestraint_5:
					this.MirrorProp.MonsterRestraint[(int)UnitFateType.Five - 1] += opt.Value;
					break;
				default:
                    break;
            }
        }

		private void PrintAttrErrorInfo(UnitAttributeType Type, int value1, int value2)
		{
#if JSG_DMG_LOG
			try
			{
				string stackInfo = new StackTrace().ToString();
				XmdsVirtual.FormatLog(LoggerLevel.ERROR, "属性异常异常 : UID:{0}, {1}, {2}, {3}, {4}", this.mUnit.PlayerUUID, Type, value1, value2, stackInfo);
			}
			catch(Exception e)
			{
				XmdsVirtual.FormatLog(LoggerLevel.ERROR, "PrintAttrErrorInfo异常:" + Type + ", " + value1 + ", " + value2 + ", " + e);
			}
#endif       
		}


        private int GetOpValue(float UnitProp, float changeValue, PropChangeOperation.OperateType type)
        {
            float ret = 0;

            if (type == PropChangeOperation.OperateType.Percent)
            {
                ret = UnitProp * (changeValue / XmdsDamageCalculator.PERER);
            }
            else
            {
                ret = changeValue;
            }

            return CUtils.CastInt(ret);
        }

		private float GetOpValueFloat(float UnitProp, float changeValue, PropChangeOperation.OperateType type)
		{
			float ret = 0;

			if (type == PropChangeOperation.OperateType.Percent)
			{
				ret = UnitProp * (changeValue / XmdsDamageCalculator.PERER);
			}
			else
			{
				ret = changeValue;
			}

			return ret;
		}

		public PropChangeOperation CreatePropChangeOpertation()
        {
            return new PropChangeOperation();
        }

		/** 被动改变数值 */
        public void ChangeMaxHP(int addValues)
        {
			mProp.ServerData.Prop.BaseMaxHP += addValues;
			mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
        }

		/** 被动改变攻击,除非死亡,否则不清除属性 */
		public void ChangeAttack(int addValues)
        {
			mProp.ServerData.Prop.BaseAttack += addValues;
			UnitPropRefresh();
		}

		/** 被动改变防御,除非死亡,否则不清除属性 */
		public void ChangeDefence(int addValues)
        {
			mProp.ServerData.Prop.BaseDefence += addValues;
			UnitPropRefresh();
        }

		/** 被动改变攻速,除非死亡,否则不清除属性 */
		public void ChangeAtkSpeed(int addValues)
        {
			mProp.ServerData.Prop.AttackSpeed += addValues;
			UnitPropRefresh();
		}

		/** 被动改变暴击伤害,除非死亡,否则不清除属性 */
		public void ChangeCriteDamage(int addValues)
		{
			mProp.ServerData.Prop.CritDamage += addValues;
			UnitPropRefresh();
		}

		/** 被动改变暴击率,除非死亡,否则不清除属性 */
		public void ChangeCriteRate(int addValues)
		{
			mProp.ServerData.Prop.CritRate += addValues;
			UnitPropRefresh();
		}

		/// <summary>
		/// 插入一条属性变更操作指令,返回id用来删除.
		/// </summary>
		/// <returns></returns>
		public int AddPropChangeOperation(PropChangeOperation opt)
        {
            int ret = 0;

            mPropChangeOperationCount++;

            ret = mPropChangeOperationCount;

            mPropChangeMap.Add(ret, opt);

            //立刻生效计算.
            UnitPropRefresh();

            SyncBattlePropsFields(opt.Type);

            return ret;
        }

        public bool UpdatePropChangeOperation(int OpID, PropChangeOperation opt)
        {
            if (mPropChangeMap.ContainsKey(OpID))
            {
                mPropChangeMap[OpID] = opt;
                //立刻生效计算.
                UnitPropRefresh();

                SyncBattlePropsFields(opt.Type);

                return true;
            }

            return false;
        }

        /// <summary>
        ///删除属性变更操作指令.
        /// </summary>
        public void RemovePropChangeOperation(int id)
        {
            PropChangeOperation opt;

            if (mPropChangeMap != null && mPropChangeMap.TryGetValue(id, out opt))
            {
                mPropChangeMap.Remove(id);
                SyncBattlePropsFields(opt.Type);
                UnitPropRefresh();
            }
            else
            {
                FormatLog("RemovePropChangeOperation Error");
            }
        }

        /// <summary>
        /// 操作指令.
        /// </summary>
        public struct PropChangeOperation
        {
            /// <summary>
            /// 操作属性.
            /// </summary>
            public UnitAttributeType Type;

            /// <summary>
            /// 操作值.
            /// </summary>
            public int Value;

            /// <summary>
            /// 操作类型.
            /// </summary>
            public OperateType OpType;

            /// <summary>
            /// 操作类型:值加减,百分比,
            /// </summary>
            public enum OperateType : byte
            {
                Value,
                Percent,
            }
        }

        /// <summary>
        /// 操作标识.
        /// </summary>
        public enum UnitAttributeType : Byte
        {
            None,                       //无.
            MoveSpeed,					//速度.
            Defence,					//防御.
            Attack,                     //最大攻击

			/**attention, 这里存在坑,之前增伤,减伤被改成玩家后,后来有需要所有的增伤,减伤,有新加了一个奇怪的东西。 容易混淆*/
			PlayerDamageAdd,            // 伤害加成(玩家之间)
			PlayerDamageReduce,			// 伤害减免(被改成玩家之间)
			MonsterDamageAdd,           // 怪物(妖兽)伤害增加
			MonsterDamageReduce,        // 怪物(妖兽)免伤
			AllDmgReduce,               // 所有伤害减免
			AllDmgAdd,                  // 单位增伤,IncAllDamage改成玩家之间导致新增一个奇怪所有增伤属性

			HealEffect,					//治疗效果.
            HealedEffect,				//受治疗效果.
            MaxHP,						//生命上限.
            CritRate,					//暴击率
            PickupRange,                //拾取距离
            AttackSpeed,                //攻速, 普攻冷却缩减
            SkillLanuchSpeed,           //技能冷却缩减
            ControlTimeReduce,          //控制时间改变,韧性
            SkillDamage,                //技能伤害
            IngoreDefence,              //无视防御
            SkillLeech,                 //技能吸血
            CritDamage,                 //暴击伤害
            
            SetMaxHP,                   //设置最大血量
			CritRate_NormalAtk,         //普攻暴击率(为实现技能效果加的)
			HPRecover,                  //生命恢复效果
			EAttack_Gold,
			EAttack_Wood,
			EAttack_Water,
			EAttack_Fire,
			EAttack_Soil,
			EDefence_Gold,
			EDefence_Wood,
			EDefence_Water,
			EDefence_Fire,
			EDefence_Soil,
			ToBoss_CriteRate,
			ToBoss_CriteDamage,
			MonsterRestraint_1,            // 命格克制
			MonsterRestraint_2,
			MonsterRestraint_3,
			MonsterRestraint_4,
			MonsterRestraint_5,			
		}


        // 数值上限
        public class GamePropLimit
        {
            public const int AttackSpeed_Down = -5000;              // 攻速下限
            public const int AttackSpeed_Up = 25000;                // 攻速上限
            public const int MoveSpeed = 4000;                      // 移速

            public const int SkillLaunchSpeed = 5000;               // 冷却缩减
            
            public const int DamageRemit = 5000;                    // 伤害减免
            public const int CtrlTimeReduce = 5000;                 // 韧性
            public const int SkillDamageAdd = 5000;                 // 技能伤害增幅
            public const int HealthAddition = 5000;                 // 治疗增幅
            public const int CtrlAddition = 5000;                   // 控制增幅
        }


        /// <summary>
        /// 同步客户端.
        /// </summary>
        private void UpdateBattlePropsChangeEvt()
        {
            if (mBattlePropChangeEvt != null)
            {
                GenBattlePropsFields(mBattlePropChangeEvt);
                SendBattlePropsChangeEvt(mBattlePropChangeEvt);
                mBattlePropChangeEvt = null;
            }
        }

        private ulong GetBattlePropFieldsMask(UnitAttributeType type)
        {
            ulong mask = 0;
            switch (type)
            {
                case UnitAttributeType.MaxHP:
                    mask = PlayerBattlePropChangeEventB2C.MASK_MAX_HP;
                    break;
                case UnitAttributeType.MoveSpeed:
                    mask = PlayerBattlePropChangeEventB2C.MASK_MOVE_SPEED | PlayerBattlePropChangeEventB2C.MASK_MOVE_SPEED_ADDITION;
					break;
                case UnitAttributeType.Attack:
                    mask = PlayerBattlePropChangeEventB2C.MASK_ATTACK;
                    break;
                case UnitAttributeType.IngoreDefence:
                    mask = PlayerBattlePropChangeEventB2C.MASK_IGNORE_DEFENSE_PER;
                    break;
                case UnitAttributeType.Defence:
                    mask = PlayerBattlePropChangeEventB2C.MASK_DEF;
                    break;
                case UnitAttributeType.CritRate:
                    mask = PlayerBattlePropChangeEventB2C.MASK_CRIT_RATE;
                    break;
                case UnitAttributeType.CritDamage:
                    mask = PlayerBattlePropChangeEventB2C.MASK_CRIT_DAMAGE;
                    break;
				case UnitAttributeType.PlayerDamageReduce:
                    mask = PlayerBattlePropChangeEventB2C.MASK_ALL_DAMAGE_REDUCE;
                    break;
                case UnitAttributeType.HealEffect:
                    mask = PlayerBattlePropChangeEventB2C.MASK_HEALEFFECT;
                    break;
                case UnitAttributeType.HealedEffect:
                    mask = PlayerBattlePropChangeEventB2C.MASK_HEALEDEFFECT;
                    break;
                case UnitAttributeType.AttackSpeed:
                    mask = PlayerBattlePropChangeEventB2C.MASK_ATTACK_SPEED;
                    break;
                case UnitAttributeType.SkillLanuchSpeed:
                    mask = PlayerBattlePropChangeEventB2C.MASK_SKILL_CD;
                    break;
                case UnitAttributeType.ControlTimeReduce:
                    mask = PlayerBattlePropChangeEventB2C.MASK_CTRLTIME_REDUCE;
                    break;
                case UnitAttributeType.SkillDamage:
                    mask = PlayerBattlePropChangeEventB2C.MASK_SKILLDAMAGE;
                    break;
                case UnitAttributeType.PlayerDamageAdd:
                    mask = PlayerBattlePropChangeEventB2C.MASK_INCALLDAMAGE;
                    break;
                case UnitAttributeType.SetMaxHP:
                    mask = PlayerBattlePropChangeEventB2C.MASK_MAX_HP_EXT;
                    break;
				case UnitAttributeType.SkillLeech:
					mask = PlayerBattlePropChangeEventB2C.MASK_ACTIVE_ATK_LEECH;
					break;
				case UnitAttributeType.HPRecover:
					mask = PlayerBattlePropChangeEventB2C.MASK_HP_REBORN;
					break;
				case UnitAttributeType.EAttack_Gold:
					mask = PlayerBattlePropChangeEventB2C.MASK_GOLD_ATTACK;
					break;
				case UnitAttributeType.EAttack_Wood:
					mask = PlayerBattlePropChangeEventB2C.MASK_WOOD_ATTACK;
					break;
				case UnitAttributeType.EAttack_Water:
					mask = PlayerBattlePropChangeEventB2C.MASK_WATER_ATTACK;
					break;
				case UnitAttributeType.EAttack_Fire:
					mask = PlayerBattlePropChangeEventB2C.MASK_FIRE_ATTACK;
					break;
				case UnitAttributeType.EAttack_Soil:
					mask = PlayerBattlePropChangeEventB2C.MASK_SOIL_ATTACK;
					break;
				case UnitAttributeType.EDefence_Gold:
					mask = PlayerBattlePropChangeEventB2C.MASK_GOLD_DEFENSE;
					break;
				case UnitAttributeType.EDefence_Wood:
					mask = PlayerBattlePropChangeEventB2C.MASK_WOOD_DEFENSE;
					break;
				case UnitAttributeType.EDefence_Water:
					mask = PlayerBattlePropChangeEventB2C.MASK_WATER_DEFENSE;
					break;
				case UnitAttributeType.EDefence_Fire:
					mask = PlayerBattlePropChangeEventB2C.MASK_FIRE_DEFENSE;
					break;
				case UnitAttributeType.EDefence_Soil:
					mask = PlayerBattlePropChangeEventB2C.MASK_SOIL_DEFENSE;
					break;
				case UnitAttributeType.ToBoss_CriteRate:
					mask = PlayerBattlePropChangeEventB2C.MASK_TOBOSS_CRIT_RATE;
					break;
				case UnitAttributeType.ToBoss_CriteDamage:
					mask = PlayerBattlePropChangeEventB2C.MASK_TOBOSS_CRIT_DAMAGE;
					break;
				case UnitAttributeType.MonsterRestraint_1:
					mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_1;
					break;
				case UnitAttributeType.MonsterRestraint_2:
					mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_2;
					break;
				case UnitAttributeType.MonsterRestraint_3:
					mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_3;
					break;
				case UnitAttributeType.MonsterRestraint_4:
					mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_4;
					break;
				case UnitAttributeType.MonsterRestraint_5:
					mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_5;
					break;
					//case UnitAttributeType.
					//mask = PlayerBattlePropChangeEventB2C.MASK_BREAK_SHIELD;
					//break;
				default:
                    break;
            }

            return mask;
        }

        private void SyncBattlePropsFields(UnitAttributeType type)
        {
            ulong mask = GetBattlePropFieldsMask(type);
            SyncBattlePropsFields(mask);
        }

        public virtual void SyncBattlePropsFields(ulong mask)
        {
            //该功能实现转移至player.
            //donothing.
        }


        private void GenBattlePropsFields(PlayerBattlePropChangeEventB2C evt)
        {
            XmdsUnitProp UseProp = this.MirrorProp; //this.GetOriginProp();
            evt.MaxHP = UseProp.MaxHP;
            evt.MoveSpeed = UseProp.MoveSpeed;
            evt.HPReborn = UseProp.HPReborn;
			
            //同步Attribute
            evt.HPPer = UseProp.HPPer;
            evt.Attack = UseProp.MaxAttack;
            evt.AttackPer = UseProp.AttackPer;
            evt.Def = UseProp.Defence;
            evt.DefPer = UseProp.DefencePer;
            evt.IgnoreDefensePer = UseProp.IgnoreDefensePer;
            evt.CritRate = UseProp.CritRate;
			evt.ResCritRate = UseProp.ResCritRate;

			evt.CritDamage = UseProp.CritDamage;
            evt.IncAllDamage = UseProp.PlayerDamageAdd;
            evt.AllDamageReduce = UseProp.PlayerDamageReduce;
            evt.CtrlTimeReduce = UseProp.CtrlTimeReduce;
            evt.SkillCD = UseProp.SkillCD;
            evt.HealEffect = UseProp.HealEffect;
            evt.HealedEffect = UseProp.HealedEffect;
            evt.SkillDamage = UseProp.SkillDamageAdd;
            evt.AttackSpeed = UseProp.AttackSpeed;
            evt.ControlUp = UseProp.ControlUp;

            evt.GoldAttack = UseProp.ArtifactAttack[(int)ArtifactType.Gold];
            evt.WoodAttack = UseProp.ArtifactAttack[(int)ArtifactType.Wood];
            evt.WaterAttack = UseProp.ArtifactAttack[(int)ArtifactType.Water];
            evt.FireAttack = UseProp.ArtifactAttack[(int)ArtifactType.Fire];
            evt.SoilAttack = UseProp.ArtifactAttack[(int)ArtifactType.Soil];

            evt.GoldDefense = UseProp.ArtifactDefense[(int)ArtifactType.Gold];
            evt.WoodDefense = UseProp.ArtifactDefense[(int)ArtifactType.Wood];
            evt.WaterDefense = UseProp.ArtifactDefense[(int)ArtifactType.Water];
            evt.FireDefense = UseProp.ArtifactDefense[(int)ArtifactType.Fire];
            evt.SoilDefense = UseProp.ArtifactDefense[(int)ArtifactType.Soil];

            evt.ToBossCritRate = UseProp.ToBossCritRate;
            evt.ToBossCritDamage = UseProp.ToBossCritDamage;

            evt.GoldRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Gold];
            evt.WoodRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Wood];
            evt.WaterRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Water];
            evt.FireRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Fire];
            evt.SoilRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Soil];

            evt.GoldResist = UseProp.ArtifactResist[(int)ArtifactType.Gold];
            evt.WoodResist = UseProp.ArtifactResist[(int)ArtifactType.Wood];
            evt.WaterResist = UseProp.ArtifactResist[(int)ArtifactType.Water];
            evt.FireResist = UseProp.ArtifactResist[(int)ArtifactType.Fire];
            evt.SoilResist = UseProp.ArtifactResist[(int)ArtifactType.Soil];

            evt.PvpKillValue = UseProp.KillValuePer;
            evt.YaoQiLevel = UseProp.YaoQiLevel;
            evt.NormalAtkLeech = UseProp.NormalAtkLeech;
            evt.ActiveAtkLeech = UseProp.ActiveAtkLeech;
            evt.ArtifactMainPer = UseProp.ArtifactMainPer;

            evt.FieldBossDamageAdd = UseProp.monsterDamageAdd;
            evt.MaxHPExt = this.MirrorProp.MaxHP;
            evt.DungeonMonsterDamageAdd = UseProp.monsterDamageReduce;
			evt.MoveSpeedAddition = UseProp.VelocityAddition;

			for(int i = 0; i < (int)UnitFateType.Five; i++)
			{
				evt.MonsterRestraint[i] = UseProp.MonsterRestraint[i];
			}

			//// 猎妖属性
			evt.monsterAtk = UseProp.monsterAtk;
			evt.monsterDef = UseProp.monsterDef;
			evt.monsterAtkPer = UseProp.monsterAtkPer;
			evt.monsterDefPer = UseProp.monsterDefPer;
		}

        private void UpdateHateSystem(int intervalMS)
        {
            if (mHateSystem != null)
            {
                //定期去除仇恨对象.
                mHateSystem.Update(intervalMS);
            }

        }

        private void SendBattlePropsChangeEvt(PlayerBattlePropChangeEventB2C evt)
        {
            this.mUnit.queueEvent(evt);
        }

        private void UnderAttackCheck(XmdsVirtual attacker)
        {
            //单位被攻击,且从PVE状态转为PVP状态,
            if (this is XmdsVirtual_Player)
            {
                var atk = attacker.GetPlayerUnit();

                if (atk != null)
                {
                    UnderAttackNotifyB2C evt = new UnderAttackNotifyB2C();
                    evt.AttackerID = atk.mUnit.ID;
                    evt.AttackerInfo = atk.mProp.ServerData.BaseInfo;
                    this.mUnit.queueEvent(evt);
                }
            }
        }

        public bool IsAllies(CommonAI.Zone.Formula.IVirtualUnit target, bool includeSelf = true, bool onlyForTeam = false)
        {
            XmdsVirtual unit = target as XmdsVirtual;
            if (unit == null)
            {
                return false;
            }

            return IsMember(unit, this.GetCurPKMode(), includeSelf, onlyForTeam);
        }

        public virtual int GetMaType() { return -1; }
		public virtual bool IsLvRepress() { return false; }

		public virtual bool IsBoss() { return false; }

		public virtual void doEvent(JSGCustomOpType value)  {}

		public virtual uint GetMasterID() { return 0; }

		public virtual InstanceUnit GetMasterUnit() { return null; }

		public virtual InstanceUnit GetPetUnit()
        {
            return null;
        }

        /// <summary>
		/// 下坐骑.
		/// </summary>
		public virtual void TakeOffMount()
        {
            if (mIsMounted == true)
            {
                SyncMountStatus(false);
            }
        }

		public int GetHealedEffect()
		{
			return this.MirrorProp.HealedEffect;
		}

		public int GetHealEffect()
		{
			return this.MirrorProp.HealEffect;
		}

		/** 获得单位职业 */
		public XmdsUnitPro GetUnitPro()
		{
			return this.mProp.ServerData.BaseInfo.ProType;
		}

		//性别: 0-男,1-女
		public int GetUnitSex()
		{
			return this.mProp.ServerData.BaseInfo.sex;
		}

		/** 获得宠物天赋加成 */
		public virtual int GetPetTalentAddition(UnitFateType type)
		{
			return ((XmdsUnitProp)mProp.ServerData.Prop).fateValue;
		}

		public UnitFateType GetUnitFateType()
		{
			return ((XmdsUnitProp)mProp.ServerData.Prop).fateType;
		}

		#endregion
	}
}