using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.Zone;
using CommonAI.Zone.Attributes;
using CommonAI.Zone.Helper;
using CommonLang;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonAI.Zone.Formula;
using System.Collections;
using CommonAI.ZoneClient.Agent;

namespace CommonAI.ZoneClient
{
    public partial class ZoneUnit : ZoneObject
    {
        public readonly SyncUnitInfo SyncInfo;
        public readonly UnitInfo Info;
        public readonly bool IsAttackRangeIncludeBodySize;

        // Status
        private int mHP;
        private int mMP;
        private int mSP;
        private int mMaxHP;
        private int mMaxMP;
        private int mMaxSP;
        private float mMoveSpeedSEC;
        private float mFastCastRate;
        private int mMoney;
        private string mName;
        private string mDisplayName;

        public string TemplateName { get { return Info.Name; } }
        public int TemplateID { get { return Info.ID; } }
        public override string Name { get { return mName; } }
        public override string DisplayName { get { return mDisplayName; } }
        public float BodySize { get { return Info.BodySize; } }
        public float BodyHitSize { get { return Info.BodyHitSize; } }
        public override float RadiusSize { get { return BodySize; } }

        public string Alias { get { return SyncInfo.Alias; } }
        public int Force { get { return SyncInfo.Force; } }
        public int HP { get { return mHP; } }
        public int MP { get { return mMP; } }
        public int SP { get { return mSP; } }
        public int MaxHP { get { return mMaxHP; } }
        public int MaxMP { get { return mMaxMP; } }
        public int MaxSP { get { return mMaxSP; } }
        public float MoveSpeedSEC { get { return mMoveSpeedSEC; } }
        public float TurnSpeedSEC { get { return mTurnSpeedSEC; } set { mTurnSpeedSEC = value; } }
        public float FastCastRate { get { return mFastCastRate; } }
        public int Money { get { return mMoney; } }
        public string PlayerUUID { get { return SyncInfo.PlayerUUID; } }
        public int Level { get { return SyncInfo.Level; } }
        public int Dummy_0 { get; private set; }
        public int Dummy_1 { get; private set; }
        public int Dummy_2 { get; private set; }
        public int Dummy_3 { get; private set; }
        public int Dummy_4 { get; private set; }
        public int Dummy_5 { get; private set; }



        public bool IsTurning
        {
            get { return mDirectionChange != mDirection; }
        }
        override public float Direction
        {
            get { return mDirection; }
            internal set
            {
                mDirectionChange = value;
                if (Info.UType == UnitInfo.UnitType.TYPE_BUILDING)
                {
                    mDirection = value;
                }
            }
        }

        public float ServerDirection { get { return mDirectionChange; } }
        public override float X { get { return mLocalPos.X; } }
        public override float Y { get { return mLocalPos.Y; } }
        public override bool TouchObj { get { return (mTouchObj) && (CurrentState != UnitActionStatus.Dead) && (mHP > 0); } }
        public override bool TouchMap { get { return mTouchMap; } }
        public bool IsStaticBlockable { get { return mIsStaticBlockable; } }
        virtual public bool IsActive { get { return (HP > 0); } }

        private bool mTouchObj;
        private bool mTouchMap;
        private bool mIsStaticBlockable;
        protected float mDirectionChange;
        protected float mTurnSpeedSEC;
        protected Vector2 mLocalPos = new Vector2();
        protected SyncPosEvent.UnitState mRemoteState;
        private State<UnitActionStatus> mState = new State<UnitActionStatus>(UnitActionStatus.Idle);
        private State<byte> mSubState = new State<byte>(0);
        protected HashMap<string, object> mEnvironmentVarMap = new HashMap<string, object>();
        private IVirtualClientUnit mVirtual;

        //新增技能Move标记(本地预演)
        protected bool mIsSkillMove;

        public IVirtualClientUnit Virtual { get { return mVirtual; } }

        public UnitActionStatus CurrentState
        {
            get { return mState.Value; }
        }
        public byte CurrentSubState
        {
            get { return mSubState.Value; }
        }

        public ZoneUnit(UnitInfo info, SyncUnitInfo syn, ZoneLayer parent, AddUnitEvent add)
            : base(syn.ObjectID, parent)
        {
            this.SyncInfo = syn;
            this.mName = syn.Name;
            this.mDisplayName = TemplateManager.Factory.ToClientDisplayName(info, syn);
            this.Info = info;
            this.IsAttackRangeIncludeBodySize = parent.Templates.CFG.OBJECT_ATTACK_RANGE_INCLUDE_BODYSIZE;
            this.mPos.SetX(syn.x);
            this.mPos.SetY(syn.y);
            this.mMoveSpeedSEC = info.MoveSpeedSEC;
            this.mTurnSpeedSEC = float.IsNaN(info.TurnSpeedSEC) ? Templates.CFG.UNIT_TURN_SPEED_SEC : info.TurnSpeedSEC;
            this.mFastCastRate = 0;
            this.mLocalPos.SetX(syn.x);
            this.mLocalPos.SetY(syn.y);
            this.mDirection = this.mDirectionChange = syn.direction;
            this.mIsStaticBlockable = syn.IsStaticBlockable;
            this.mTouchObj = syn.IsTouchObj;
            this.mTouchMap = syn.IsTouchMap;
            this.mState.ChangeState((UnitActionStatus)syn.status);
            this.mSubState.ChangeState(syn.sub_status);
            this.mRemoteState.UnitMainState = (UnitActionStatus)syn.status;
            this.mRemoteState.UnitSubState = syn.sub_status;
            switch (Info.UType)
            {
                case UnitInfo.UnitType.TYPE_PET:
                case UnitInfo.UnitType.TYPE_TRIGGER:
                    mTouchObj = false;
                    break;
                case UnitInfo.UnitType.TYPE_BUILDING:
                    mTouchObj = (info.BodySize > 0);
                    break;
            }
            DoSync(syn.fields);
            InitSkills();
            //this.mVirtual = TemplateManager.Factory.CreateClientUnitVirtual(this);
        }

        public void SendPlayPetTeleport()
        {
            Parent.SendAction(new PlayPetTeleportAction());
        }

        protected override void Disposing()
        {
            base.Disposing();
            this.clearEvents();
            /*if (mVirtual != null)
            {
                mVirtual.OnDispose(this);
            }
            this.mVirtual = null;*/
            this.mBuffStatus.Clear();
            this.mChantingSkill = null;
            this.mCurrentSkillAction = null;
            this.mDamageTime = null;
            this.mHitFlyState = null;
            this.mLastLaunchSkill = null;
            this.mPickEvent = null;
            this.mEnvironmentVarMap.Clear();
            this.mSkillStatus.Clear();
        }

        protected internal override void OnAdded()
        {
            /*if (mVirtual != null)
            {
                mVirtual.OnInit(this);
            }*/
            this.SyncBuffStatus(SyncInfo.CurrentBuffStatus);
            base.OnAdded();
        }


        //--------------------------------------------------------------------------------
        #region State

        public override void SetClientLocalCurrentState(UnitActionStatus state, object evt)
        {
            this.SetCurrentState(state);
        }

        protected void SetCurrentState(ref SyncPosEvent.UnitState pos)
        {           
            this.SetCurrentState(pos.UnitMainState, pos.UnitSubState, null);
        }
        protected void SetCurrentState(UnitActionStatus state)
        {
            this.SetCurrentState(state, CurrentSubState, null);
        }
        protected void SetCurrentState(UnitActionStatus state, object evt)
        {
            this.SetCurrentState(state, CurrentSubState, evt);
        }
        protected void SetCurrentState(UnitActionStatus state, byte substate, object evt)
        {
            //不能移动切入,状态置成Idle(不应该有互斥状态存在 跑和不能移动)
            if (state == UnitActionStatus.Move && (substate & (byte)UnitActionSubStatus.CanNotMove) != 0)
            {
                state = UnitActionStatus.Idle;
            }

            if (mState.ChangeState(state))
            {
                if (mOnActionChanged != null)
                {
                    mOnActionChanged.Invoke(this, mState.Value, evt);
                }
            }
            SetCurrentSubState(substate);
        }
        protected void SetCurrentSubState(byte substate)
        {
            if (mSubState.ChangeState(substate))
            {
                if (mOnActionSubStatusChanged != null)
                {
                    mOnActionSubStatusChanged.Invoke(this, mSubState.Value, null);
                }
            }
        }

        #endregion

        //--------------------------------------------------------------------------------

        override internal protected void Update()
        {
            int intervalMS = Parent.CurrentIntervalMS;
            if (mHitFlyState != null && mHitFlyState.Update(intervalMS))
            {
                mHitFlyState = null;
            }
            UpdatePos(intervalMS);
            UpdateDamage(intervalMS);
            UpdateSkills(intervalMS);
            UpdateBuffs(intervalMS);
            UpdatePickEvent(intervalMS);
        }

        protected internal override void UpdateAI()
        {
            int intervalMS = Parent.CurrentIntervalMS;
            updateSkillAction(intervalMS);
        }

        protected internal virtual void UpdatePos(int intervalMS)
        {
            if (mDirection != mDirectionChange)
            {
                mDirection = MoveHelper.DirectionChange(
                    mDirectionChange,
                    mDirection,
                    mTurnSpeedSEC,
                    intervalMS);
            }
            if (Parent.ActorSyncMode != SyncMode.ForceByServer)
            {
                if (!FixPos(intervalMS, mLocalPos, mPos))
                {
                    if(CurrentState == UnitActionStatus.Move && mRemoteState.UnitMainState != UnitActionStatus.Move)
                    {
                        this.SetCurrentState(ref mRemoteState);
                    }
                }
                else
                {
                    //if(this is ZoneActor)
                    //    CommonLang.Log.ClientLog.LogWarning(">>UpdatePos:{0},{1}-->{2},{3}", mLocalPos.X, mLocalPos.Y, mPos.X, mPos.Y);
                }
            }
        }

        public override void ForceSyncPos(float x, float y)
        {
			//YXJDebug.logWarning("{0}>>ForceSyncPos:{1},{2}", Name, x, y);
			this.mPos.SetX(x);
			this.mPos.SetY(y);
            this.mLocalPos.SetX(x);
            this.mLocalPos.SetY(y);
        }
        public override void SyncPos(ref SyncPosEvent.UnitState pos)
        {
            this.mRemoteState = pos;
            if (Parent.ActorSyncMode == SyncMode.ForceByServer)
            {
                this.SetCurrentState(ref mRemoteState);
            }
            else
            {
                var rst = mRemoteState;
                if (CurrentState == UnitActionStatus.Move && mRemoteState.UnitMainState == UnitActionStatus.Idle)
                {
                    if (IsNeedFixPos(mLocalPos, mPos))
                    {
                        rst.UnitMainState = UnitActionStatus.Move;
                    }
                }
                this.SetCurrentState(ref rst);
            }
        }

        public override void SyncPos(ref SyncPosEvent.UnitPos pos)
        {
            bool bMoved = mPos.X != pos.X || mPos.Y != pos.Y;
            base.mPos.SetX(pos.X);
            base.mPos.SetY(pos.Y);
            this.mDirectionChange = pos.Direction;
            this.mDirection = MoveHelper.DirectionChange(
                mDirectionChange,
                mDirection,
                mTurnSpeedSEC,
                Parent.CurrentIntervalMS);
            if (Parent.IsSyncZ) { this.Z = pos.Z; }
            if (Parent.ActorSyncMode == SyncMode.ForceByServer)
            {
                //YXJDebug.logWarning(">>{0}>syncPos:{0},{1}-->forceByServerMode", Name, pos.X, pos.Y);
                mLocalPos.SetX(pos.X);
                mLocalPos.SetY(pos.Y);
            }
            else
            {
                var rst = mRemoteState;
                if (CurrentState == UnitActionStatus.Move && rst.UnitMainState == UnitActionStatus.Idle)
                {
                    rst.UnitMainState = UnitActionStatus.Move;
                }
                else if(bMoved && CurrentState == UnitActionStatus.Idle && rst.UnitMainState == UnitActionStatus.Idle && rst.UnitSubState == 0)
                {
                    //新创建的单位,丢失了move状态信息,打个补丁
                    rst.UnitMainState = UnitActionStatus.Move;
                }
                else if(rst.UnitMainState == UnitActionStatus.Skill)
                {
                    if ((rst.UnitSubState & (byte)UnitActionSubStatus.ChargeAtkIdle) != 0)
                    {
                       //YXJDebug.logDebug(">>下发SyncPosEvent的状态不对(蓄力idle中移动)");
                    }
                    else if((rst.UnitSubState & (byte)UnitActionSubStatus.Mocking) != 0)
                    {
                    }
                    else
                    {
                        //YXJDebug.logWarning(">>{0}>skill状态中syncPos, curState:{1}/{2}-->{3}/{4}", Name, (int)CurrentState, (int)CurrentSubState, (int)mRemoteState.UnitMainState, (int)mRemoteState.UnitSubState);
                    }
                }
                //YXJDebug.logWarning(">>{0}>UnitsyncPos, curState:{1}/{2}-->{3}/{4}, x:{5},y:{6}", Name, (int)CurrentState, (int)CurrentSubState, (int)mRemoteState.UnitMainState, (int)mRemoteState.UnitSubState, pos.X, pos.Y);
                this.SetCurrentState(ref rst);
            }
        }
        /// <summary>
        /// 修正本地坐标//
        /// </summary>
        public bool FixPos(int intervalMS, Vector2 local_pos, IVector2 remote_pos)
        {
            float fdistance = MathVector.getDistance(local_pos, remote_pos);
            if (fdistance > 0)
            {
                float dspeed = MoveHelper.GetDistance(intervalMS, MoveSpeedSEC);
                if (fdistance >= Parent.AsyncUnitPosModifyMaxRange)
                {
                    local_pos.SetX(remote_pos.X);
                    local_pos.SetY(remote_pos.Y);
                    return true;
                }
                else if (fdistance <= dspeed)
                {
                    //local_pos.x = remote_pos.X;
                    //local_pos.y = remote_pos.Y;
                    return false;
                }
                else if (CurrentState == UnitActionStatus.Move)
                {
                    float db = dspeed;
                    MathVector.moveTo(local_pos, remote_pos.X, remote_pos.Y, db);
                    return true;
                }
                else
                {
                    float db = dspeed * fdistance;
                    MathVector.moveTo(local_pos, remote_pos.X, remote_pos.Y, db);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 是否需要修正坐标
        /// </summary>
        /// <returns></returns>
        public bool IsNeedFixPos(Vector2 local_pos, IVector2 remote_pos)
        {
            float fdistance = MathVector.getDistance(local_pos, remote_pos);
            return fdistance >= Parent.MinStep;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="smooth">是否慢慢转身</param>
        public void SetDirection(float direction, bool smooth = true)
        {
            if (smooth)
            {
                mDirectionChange = direction;
            }
            else
            {
                mDirectionChange = direction;
                mDirection = direction;
            }
        }
        public float GetDeadTimeCD()
        {
            if (mDeadTime != null)
            {
                return mDeadTime.Percent;
            }
            return 0;
        }

        override internal protected void DoEvent(ObjectEvent e)
        {
            if (e is UnitDamageEvent)
            {
                DoDamage(e as UnitDamageEvent);
            }
            else if (e is UnitLaunchSkillEvent)
            {
                DoLaunchSkill(e as UnitLaunchSkillEvent);
            }
            else if (e is UnitSkillActionChangeEvent)
            {
                DoChangeAction(e as UnitSkillActionChangeEvent);
            }
            else if (e is UnitDeadEvent)
            {
                DoDead(e as UnitDeadEvent);
            }
            else if (e is UnitLaunchBuffEvent)
            {
                DoLaunchBuff(e as UnitLaunchBuffEvent);
            }
            else if(e is BuffDataNotify)
            {
                SyncBuffOverlayLevel(e as BuffDataNotify);
            }
            else if (e is SyncUnitBuffState)
            {
                DoRemoveOverlayLevelBuff(e as SyncUnitBuffState);
            }
            else if (e is UnitStopBuffEvent)
            {
                DoStopBuff(e as UnitStopBuffEvent);
            }
            else if (e is UnitFieldChangedEvent)
            {
                DoSync(e as UnitFieldChangedEvent);
            }
            else if (e is UnitStartPickObjectEvent)
            {
                DoStartPick(e as UnitStartPickObjectEvent);
            }
            else if (e is UnitStopPickObjectEvent)
            {
                DoStopPick(e as UnitStopPickObjectEvent);
            }
            else if (e is UnitJumpEvent)
            {
                DoJump(e as UnitJumpEvent);
            }
            else if (e is UnitForceSyncPosEvent)
            {
                DoForceSyncPosEvent(e as UnitForceSyncPosEvent);
            }
            else if (e is UnitChantSkillEvent)
            {
                DoUnitChantSkillEvent(e as UnitChantSkillEvent);
            }
            else if (e is UnitSyncMultiTimeLine)
            {
                DoUnitSyncMultiTimeLine(e as UnitSyncMultiTimeLine);
            }
            //----------------------- player ----------------------//
            else if (e is PlayerCDEvent)
            {
                DoSkillCDChanged(e as PlayerCDEvent);
            }
            else if (e is PlayerSkillChangedEvent)
            {
                DoSkillChanged(e as PlayerSkillChangedEvent);
            }
            else if (e is PlayerSkillAddedEvent)
            {
                DoSkillAdded(e as PlayerSkillAddedEvent);
            }
            else if (e is PlayerSkillRemovedEvent)
            {
                DoSkillRemoved(e as PlayerSkillRemovedEvent);
            }
            else if (e is PlayerSkillTimeChangedEvent)
            {
                DoPlayerSkillTimeChangedEvent(e as PlayerSkillTimeChangedEvent);
            }
            else if (e is PlayerSyncEnvironmentVarEvent)
            {
                DoSyncUnitVarEvent(e as PlayerSyncEnvironmentVarEvent);
            }
            else if (e is PlayerSkillStopEvent)
            {
                DoPlayerSkillStopEvent(e as PlayerSkillStopEvent);
            }
            else if (e is PlayerScriptCommandEvent)
            {
                DoPlayerScriptCommandEvent(e as PlayerScriptCommandEvent);
            }
            else if (e is PlayerSkillActiveChangedEvent)
            {
                DoPlayerSkillActiveChangedEvent(e as PlayerSkillActiveChangedEvent);
            }
            //----------------------- player ----------------------//
            //新增技能层数的协议
            else if (e is PlayerSkillUseTimeChangedEvent)
            {
                DoPlayerSkillUseTimeChangedEvent(e as PlayerSkillUseTimeChangedEvent);
            }
            else if (e is UnitStealthInfo)
            {
                DoUnitStealthInfo(e as UnitStealthInfo);
            }
        }

        protected virtual void DoUnitStealthInfo(UnitStealthInfo e)
        {
            if (mOnSetStealtState != null)
                mOnSetStealtState(e.stealth, e.flag);
        }

        protected virtual void DoForceSyncPosEvent(UnitForceSyncPosEvent e)
        {
            //YXJDebug.logWarning(">{0}:{1}>>DoForceSyncPosEvent:{2},{3}, state:{4},{5}", ObjectID,Name, e.X, e.Y, e.UnitMainState, e.UnitSubState);
            if(this.Parent != null && this.Parent.IsSceneDujie() && e.UnitMainState == (byte)UnitActionStatus.Move)
            {
                //YXJDebug.logWarning(">IgnoreForceSyncPos_u@move: {0}{1}, state:{2},{3}", ObjectID, Name, e.UnitMainState, e.UnitSubState);
                return;
            }
            if (!mIsSkillMove)
            {
                mLocalPos.SetX(e.X);
                mLocalPos.SetY(e.Y);
            }
            mPos.SetX(e.X);
            mPos.SetY(e.Y);
            mDirection = mDirectionChange = e.Direction;

            mRemoteState.UnitMainState = (UnitActionStatus)e.UnitMainState;
            mRemoteState.UnitSubState = e.UnitSubState;
            this.SetCurrentState((UnitActionStatus)e.UnitMainState, e.UnitSubState, e);

        }
        protected virtual void DoSync(UnitFieldChangedEvent syn)
        {
            if ((syn.mask & UnitFieldChangedEvent.MASK_HP) != 0)
            {
                if (mHP != syn.currentHP)
                {
                    int old = mHP;
                    this.mHP = syn.currentHP;
                    if (mOnHPChanged != null)
                    {
                        mOnHPChanged.Invoke(this, old, syn.currentHP);
                    }
                }
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_MP) != 0)
            {
                if (mMP != syn.currentMP)
                {
                    int old = mMP;
                    this.mMP = syn.currentMP;
                    if (mOnMPChanged != null)
                    {
                        mOnMPChanged.Invoke(this, old, syn.currentMP);
                    }
                }
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_MAX_HP) != 0)
            {
                if (this.mMaxHP != syn.maxHP)
                {
                    int old = mMaxHP;
                    this.mMaxHP = syn.maxHP;
                    if (mOnMaxHPChanged != null)
                    {
                        mOnMaxHPChanged.Invoke(this, old, syn.maxHP);
                    }
                }
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_MAX_MP) != 0)
            {
                if (this.mMaxMP != syn.maxMP)
                {
                    int old = mMaxMP;
                    this.mMaxMP = syn.maxMP;
                    if (mOnMaxMPChanged != null)
                    {
                        mOnMaxMPChanged.Invoke(this, old, syn.maxMP);
                    }
                }
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_SP) != 0)
            {
                this.mSP = syn.currentSP;
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_MAX_SP) != 0)
            {
                this.mMaxSP = syn.maxSP;
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_SPEED) != 0) { this.mMoveSpeedSEC = syn.currentSpeed; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_FCR) != 0) { this.mFastCastRate = syn.currentFCR; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_MONEY) != 0)
            {
                if (mMoney != syn.currentMoney)
                {
                    int old = this.mMoney;
                    this.mMoney = syn.currentMoney;
                    if (mOnMoneyChanged != null)
                    {
                        mOnMoneyChanged.Invoke(this, old, syn.currentMoney);
                    }
                }
            }
            if ((syn.mask & UnitFieldChangedEvent.MASK_LEVEL) != 0) { this.SyncInfo.Level = syn.level; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_0) != 0) { this.Dummy_0 = syn.dummy_0; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_1) != 0) { this.Dummy_1 = syn.dummy_1; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_2) != 0) { this.Dummy_2 = syn.dummy_2; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_3) != 0) { this.Dummy_3 = syn.dummy_3; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_4) != 0) { this.Dummy_4 = syn.dummy_4; }
            if ((syn.mask & UnitFieldChangedEvent.MASK_DUMMY_5) != 0) { this.Dummy_5 = syn.dummy_5; }
        }
        protected virtual void DoSyncUnitVarEvent(PlayerSyncEnvironmentVarEvent e)
        {
            mEnvironmentVarMap[e.Key] = e.Value;
        }
        protected virtual void DoPlayerScriptCommandEvent(PlayerScriptCommandEvent e)
        {
            if (mOnScriptCommand != null)
            {
                mOnScriptCommand.Invoke(this, e.message);
            }
        }
        //--------------------------------------------------------------------------------

        /// <summary>
        /// 获得当前单位服务端可同步环境变量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object GetEnvironmentVar(string key)
        {
            return mEnvironmentVarMap.Get(key);
        }

        /// <summary>
        /// 获得当前单位服务端可同步环境变量列表
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IEnumerable<string> ListEnvironmentVars()
        {
            return mEnvironmentVarMap.Keys;
        }

        //--------------------------------------------------------------------------------



        //--------------------------------------------------------------------------------

        #region Delegate
        public enum SkillOption
        {
            Init,
            Reset,
            Add,
            Remove,
            ActiveChange
        }
        public delegate void OnSetStealtStateHandler(byte stealth, short flag);
        public delegate void OnSkillChangedHandler(SkillOption op, ZoneUnit unit, int baseSkillID, params int[] skills);
        public delegate void OnActionStatusChangedHandler(ZoneUnit unit, UnitActionStatus status, object evt);
        //新增子状态
        public delegate void OnActionSubStatusChangedHandler(ZoneUnit unit, byte status, object evt);
        public delegate void OnMoneyChangedHandler(ZoneUnit unit, int oldMoney, int newMoney);
        //public delegate void OnChantSkillHandler(ZoneUnit unit, SkillState skill, UnitChantSkillEvent evt);
        public delegate void OnChantSkillHandler(ZoneUnit unit, UnitChantSkillEvent evt, TimeExpire<SkillTemplate> timeExpire);
        public delegate void OnLaunchSkillHandler(ZoneUnit unit, SkillState skill, UnitLaunchSkillEvent evt);
        public delegate void OnHPChangedHandler(ZoneUnit unit, int oldHP, int newHP);
        public delegate void OnMPChangedHandler(ZoneUnit unit, int oldMP, int newMP);
        public delegate void OnMaxHPChangedHandler(ZoneUnit unit, int oldMaxHP, int newMaxHP);
        public delegate void OnMaxMPChangedHandler(ZoneUnit unit, int oldMaxMP, int newMaxMP);
        public delegate void OnStartPickObjectHandler(ZoneUnit unit, TimeExpire<UnitStartPickObjectEvent> start);
        public delegate void OnStopPickObjectHandler(ZoneUnit unit, UnitStopPickObjectEvent stop);
        public delegate void OnSkillActionChangedHandler(ZoneUnit unit, SkillState skill, byte index);
        public delegate void OnBuffAddedHandler(ZoneUnit unit, BuffState buff);
        public delegate void OnBuffChangedHandler(ZoneUnit unit, BuffState buff);
        public delegate void OnBuffRemovedHandler(ZoneUnit unit, BuffState buff);
        public delegate void OnRemoveBuffByOverlayLevelHandler(ZoneUnit unit, BuffState buff);
        public delegate void OnScriptCommandHandler(ZoneUnit unit, string msg);
        public delegate void OnSkillActionStartHandler(ZoneUnit unit, ISkillAction action);

        //客户端技能预演事件
        public delegate void OnClientSkillSimulationHandler(ZoneUnit unit, SimulationSkillEnum type);

        private OnSetStealtStateHandler mOnSetStealtState;
        private OnSkillChangedHandler mOnSkillChanged;
        private OnActionStatusChangedHandler mOnActionChanged;
        //新增子状态
        private OnActionSubStatusChangedHandler mOnActionSubStatusChanged;
        private OnMoneyChangedHandler mOnMoneyChanged;
        private OnChantSkillHandler mOnChantSkill;
        private OnLaunchSkillHandler mOnLaunchSkill;
        private OnHPChangedHandler mOnHPChanged;
        private OnMPChangedHandler mOnMPChanged;
        private OnMaxHPChangedHandler mOnMaxHPChanged;
        private OnMaxMPChangedHandler mOnMaxMPChanged;
        private OnStartPickObjectHandler mOnStartPickObject;
        private OnStopPickObjectHandler mOnStopPickObject;
        private OnSkillActionChangedHandler mOnSkillActionChanged;
        private OnBuffAddedHandler mOnBuffAdded;
        private OnBuffRemovedHandler mOnBuffRemoved;
        private OnBuffChangedHandler mOnBuffChanged;
        private OnRemoveBuffByOverlayLevelHandler mOnRemoveBuffByOverlayLeveled;
        private OnScriptCommandHandler mOnScriptCommand;
        private OnSkillActionStartHandler mOnSkillActionStart;
        private OnClientSkillSimulationHandler mOnClientSkillSimulation;

        private void clearEvents()
        {
            this.mOnSetStealtState = null;
            this.mOnSkillChanged = null;
            this.mOnActionChanged = null;
            this.mOnMoneyChanged = null;
            this.mOnChantSkill = null;
            this.mOnLaunchSkill = null;
            this.mOnHPChanged = null;
            this.mOnMPChanged = null;
            this.mOnMaxHPChanged = null;
            this.mOnMaxMPChanged = null;
            this.mOnStartPickObject = null;
            this.mOnStopPickObject = null;
            this.mOnSkillActionChanged = null;
            this.mOnBuffAdded = null;
            this.mOnBuffChanged = null;
            this.mOnBuffRemoved = null;
            this.mOnScriptCommand = null;
            this.mOnSkillActionStart = null;
            this.mOnRemoveBuffByOverlayLeveled = null;
            this.mOnClientSkillSimulation = null;
        }

        [EventTriggerDescAttribute("草丛隐身状态改变触发")]
        public event OnSetStealtStateHandler OnSetStealtState { add { mOnSetStealtState += value; } remove { mOnSetStealtState -= value; } }
        [EventTriggerDescAttribute("单位持有技能发生变化时触发")]
        public event OnSkillChangedHandler OnSkillChanged { add { mOnSkillChanged += value; } remove { mOnSkillChanged -= value; } }
        [EventTriggerDescAttribute("单位状态发生变化时触发")]
        public event OnActionStatusChangedHandler OnActionChanged { add { mOnActionChanged += value; } remove { mOnActionChanged -= value; } }
        [EventTriggerDescAttribute("单位子状态发生变化时触发")]
        public event OnActionSubStatusChangedHandler OnActionSubStatusChanged { add { mOnActionSubStatusChanged += value; } remove { mOnActionSubStatusChanged -= value; } }
        [EventTriggerDescAttribute("单位金币发生变化时触发")]
        public event OnMoneyChangedHandler OnMoneyChanged { add { mOnMoneyChanged += value; } remove { mOnMoneyChanged -= value; } }
        [EventTriggerDescAttribute("单位开始吟唱时触发")]
        public event OnChantSkillHandler OnChantSkill { add { mOnChantSkill += value; } remove { mOnChantSkill -= value; } }
        [EventTriggerDescAttribute("单位释放技能时触发")]
        public event OnLaunchSkillHandler OnLaunchSkill { add { mOnLaunchSkill += value; } remove { mOnLaunchSkill -= value; } }

        [EventTriggerDescAttribute("HP变化")]
        public event OnHPChangedHandler OnHPChanged { add { mOnHPChanged += value; } remove { mOnHPChanged -= value; } }
        [EventTriggerDescAttribute("MP变化")]
        public event OnMPChangedHandler OnMPChanged { add { mOnMPChanged += value; } remove { mOnMPChanged -= value; } }

        [EventTriggerDescAttribute("MaxHP变化")]
        public event OnMaxHPChangedHandler OnMaxHPChanged { add { mOnMaxHPChanged += value; } remove { mOnMaxHPChanged -= value; } }
        [EventTriggerDescAttribute("MaxMP变化")]
        public event OnMaxMPChangedHandler OnMaxMPChanged { add { mOnMaxMPChanged += value; } remove { mOnMaxMPChanged -= value; } }


        [EventTriggerDescAttribute("单位开始检取物品")]
        public event OnStartPickObjectHandler OnStartPickObject { add { mOnStartPickObject += value; } remove { mOnStartPickObject -= value; } }
        [EventTriggerDescAttribute("单位完成/结束检取物品")]
        public event OnStopPickObjectHandler OnStopPickObject { add { mOnStopPickObject += value; } remove { mOnStopPickObject -= value; } }
        [EventTriggerDescAttribute("单位技能动作发生变化")]
        public event OnSkillActionChangedHandler OnSkillActionChanged { add { mOnSkillActionChanged += value; } remove { mOnSkillActionChanged -= value; } }

        [EventTriggerDescAttribute("单位添加BUFF")]
        public event OnBuffAddedHandler OnBuffAdded { add { mOnBuffAdded += value; } remove { mOnBuffAdded -= value; } }
        [EventTriggerDescAttribute("单位BUFF状态改变")]
        public event OnBuffChangedHandler OnBuffChanged { add { mOnBuffChanged += value; } remove { mOnBuffChanged -= value; } }
        [EventTriggerDescAttribute("单位移除BUFF")]
        public event OnBuffRemovedHandler OnBuffRemoved { add { mOnBuffRemoved += value; } remove { mOnBuffRemoved -= value; } }

        [EventTriggerDescAttribute("移除层buff(剑雨新增)")]
        public event OnRemoveBuffByOverlayLevelHandler OnRemoveBuffByOverlayLevel { add { mOnRemoveBuffByOverlayLeveled += value; } remove { mOnRemoveBuffByOverlayLeveled -= value; } }

        [EventTriggerDescAttribute("服务端通知客户端执行指定脚本代码")]
        public event OnScriptCommandHandler OnScriptCommand { add { mOnScriptCommand += value; } remove { mOnScriptCommand -= value; } }

        [EventTriggerDescAttribute("技能动作开始")]
        public event OnSkillActionStartHandler OnSkillActionStart { add { mOnSkillActionStart += value; } remove { mOnSkillActionStart -= value; } }

        [EventTriggerDescAttribute("客户端技能模拟")]
        public event OnClientSkillSimulationHandler OnClickSkillSimulationEvent { add { mOnClientSkillSimulation += value; } remove { mOnClientSkillSimulation -= value; } }

        #endregion




    }



}