private void IdleHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            if (npc.IsDead())
            {
                return;
            }
            NpcAiStateInfo        info = npc.GetAiStateInfo();
            AiData_PvpNpc_General data = GetAiData(npc);

            if (null != data)
            {
                npc.GetMovementStateInfo().IsMoving = false;
                if (data.PatrolPath.HavePathPoint)
                {
                    info.HomePos = npc.GetMovementStateInfo().GetPosition3D();
                    info.Time    = 0;
                    data.FoundPath.Clear();
                    ChangeToState(npc, (int)AiStateId.Patrol);
                }
                else
                {
                    ChangeToState(npc, (int)AiStateId.Combat);
                }
            }
        }
        private AiData_PvpNpc_General GetAiData(NpcInfo npc)
        {
            AiData_PvpNpc_General data = npc.GetAiStateInfo().AiDatas.GetData <AiData_PvpNpc_General>();

            if (null == data)
            {
                data = new AiData_PvpNpc_General();
                npc.GetAiStateInfo().AiDatas.AddData(data);
            }
            return(data);
        }
        protected override void OnStateLogicInit(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            NpcAiStateInfo        info = npc.GetAiStateInfo();
            AiData_PvpNpc_General data = GetAiData(npc);

            if (null != data)
            {
                info.Time = 0;
                npc.GetMovementStateInfo().IsMoving = false;
                info.HomePos = npc.GetMovementStateInfo().GetPosition3D();
                info.Target  = 0;
            }
        }
        private void PatrolHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            if (npc.IsDead())
            {
                return;
            }
            NpcAiStateInfo info = npc.GetAiStateInfo();

            info.Time += deltaTime;
            if (info.Time > 100)
            {
                info.Time = 0;
                AiData_PvpNpc_General data = GetAiData(npc);
                if (null != data)
                {
                    CharacterInfo interestestTarget = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY);
                    if (null != interestestTarget)
                    {
                        npc.GetMovementStateInfo().IsMoving = false;
                        NotifyNpcMove(npc);
                        info.Time   = 0;
                        info.Target = interestestTarget.GetId();
                        data.FoundPath.Clear();
                        ChangeToState(npc, (int)AiStateId.Pursuit);
                    }
                    else
                    {
                        ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D();
                        if (!data.PatrolPath.IsReached(srcPos))
                        {
                            PathToTargetWithoutObstacle(npc, data.FoundPath, data.PatrolPath.CurPathPoint, 100);
                        }
                        else
                        {
                            data.PatrolPath.UseNextPathPoint();
                            data.FoundPath.Clear();
                            if (!data.PatrolPath.HavePathPoint)
                            {
                                info.Time = 0;
                                ChangeToState(npc, (int)AiStateId.Idle);
                            }
                        }
                        info.HomePos = npc.GetMovementStateInfo().GetPosition3D();
                    }
                }
            }
        }
        private Vector3 GetHomePosition(NpcInfo npc, AiData_PvpNpc_General data)
        {
            Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D();
            Vector3 pt     = new Vector3();

            if (data.PatrolPath.GetNearstPoint(npc.SpatialSystem, npc.AvoidanceRadius, srcPos, ref pt))
            {
                if (!npc.SpatialSystem.GetCellMapView(npc.AvoidanceRadius).CanPass(pt))
                {
                    if (!AiLogicUtility.GetWalkablePosition(npc.SpatialSystem.GetCellMapView(npc.AvoidanceRadius), pt, srcPos, ref pt))
                    {
                        pt = srcPos;
                    }
                }
            }
            return(pt);
        }
        private void GoHomeHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            if (npc.IsDead())
            {
                return;
            }
            NpcAiStateInfo info = npc.GetAiStateInfo();

            info.Time += deltaTime;
            if (info.Time > 100)
            {
                info.Time = 0;
                AiData_PvpNpc_General data = GetAiData(npc);
                if (null != data)
                {
                    Vector3 targetPos            = info.HomePos;
                    ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D();
                    float powDistToHome          = Geometry.DistanceSquare(srcPos, info.HomePos);
                    if (powDistToHome <= 1)
                    {
                        npc.GetMovementStateInfo().IsMoving = false;
                        NotifyNpcMove(npc);
                        info.Time = 0;
                        data.FoundPath.Clear();
                        ChangeToState(npc, (int)AiStateId.Patrol);
                    }
                    else
                    {
                        PathToTargetWithoutObstacle(npc, data.FoundPath, targetPos, 100);

                        /*
                         * float angle = MathUtil.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z));
                         * npc.GetMovementStateInfo().SetFaceDir(angle);
                         * npc.GetMovementStateInfo().SetMoveDir(angle);
                         * npc.GetMovementStateInfo().TargetPosition = targetPos;
                         * npc.GetMovementStateInfo().IsMoving = true;
                         */
                    }
                }
            }
        }
        private void CombatHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            if (npc.IsDead())
            {
                return;
            }
            NpcAiStateInfo info = npc.GetAiStateInfo();

            info.Time += deltaTime;
            if (info.Time > 100)
            {
                AiData_PvpNpc_General data = GetAiData(npc);
                if (null != data)
                {
                    data.Time         += info.Time;
                    data.ThinkingTime += info.Time;
                    //ai配置参数  小兵思考时间
                    long thinkingTime = int.Parse(info.AiParam[2]);
                    //大于思考时间 重新选择新的目标
                    if (data.ThinkingTime > thinkingTime)
                    {
                        CharacterInfo interestestTarget = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY);
                        if (null != interestestTarget && info.Target != interestestTarget.GetId())
                        {
                            npc.GetMovementStateInfo().IsMoving = false;
                            NotifyNpcMove(npc);
                            info.Time         = 0;
                            data.Time         = 0;
                            data.ThinkingTime = 0;
                            info.Target       = interestestTarget.GetId();
                            return;
                        }
                    }
                    info.Time = 0;
                    bool          changeTarget = false;
                    CharacterInfo target       = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target);
                    if (null != target)
                    {
                        float dist       = (float)(npc.GetActualProperty().AttackRange *npc.AttackRangeCoefficient);
                        float distGoHome = (float)npc.GohomeRange;
                        ScriptRuntime.Vector3 targetPos = target.GetMovementStateInfo().GetPosition3D();
                        ScriptRuntime.Vector3 srcPos    = npc.GetMovementStateInfo().GetPosition3D();
                        float powDist       = Geometry.DistanceSquare(srcPos, targetPos);
                        float powDistToHome = Geometry.DistanceSquare(srcPos, info.HomePos);
                        if (powDist < dist * dist && npc.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D()))
                        {
                            float rps = npc.GetActualProperty().Rps;
                            if (rps > 0.001f && data.Time > 1000 / rps)
                            {
                                data.Time = 0;
                                float dir = Geometry.GetYAngle(new Vector2(srcPos.X, srcPos.Z), new Vector2(targetPos.X, targetPos.Z));
                                npc.GetMovementStateInfo().SetFaceDir(dir);
                                npc.GetMovementStateInfo().SetMoveDir(dir);
                                if (npc.CanShoot())
                                {
                                    aiCmdDispatcher.NpcFace(npc, this);
                                }
                            }
                        }
                        else if (powDistToHome < distGoHome * distGoHome)
                        {
                            npc.GetMovementStateInfo().IsMoving = false;
                            NotifyNpcMove(npc);
                            info.Time = 0;
                            data.FoundPath.Clear();
                            ChangeToState(npc, (int)AiStateId.Pursuit);
                        }
                        else
                        {
                            changeTarget = true;
                        }
                    }
                    else
                    {
                        changeTarget = true;
                    }
                    if (changeTarget)
                    {
                        data.FoundPath.Clear();
                        target = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY);
                        if (null != target)
                        {
                            npc.GetMovementStateInfo().IsMoving = false;
                            NotifyNpcMove(npc);
                            info.Time   = 0;
                            info.Target = target.GetId();
                            ChangeToState(npc, (int)AiStateId.Pursuit);
                        }
                        else
                        {
                            npc.GetMovementStateInfo().IsMoving = false;
                            NotifyNpcMove(npc);
                            info.Time    = 0;
                            info.HomePos = GetHomePosition(npc, data);
                            ChangeToState(npc, (int)AiStateId.GoHome);
                        }
                    }
                }
                else
                {
                    info.Time = 0;
                }
            }
        }
        private void PursuitHandler(NpcInfo npc, AiCommandDispatcher aiCmdDispatcher, long deltaTime)
        {
            if (npc.IsDead())
            {
                return;
            }
            NpcAiStateInfo info = npc.GetAiStateInfo();
            //ai配置参数
            long maxPursuitTime = int.Parse(info.AiParam[0]);
            long minPursuitTime = int.Parse(info.AiParam[1]);
            //
            bool goHome = false;

            info.Time += deltaTime;
            CharacterInfo         target = AiLogicUtility.GetSeeingLivingCharacterInfoHelper(npc, info.Target);
            AiData_PvpNpc_General data   = GetAiData(npc);

            if (null != target && info.Time <= maxPursuitTime && null != data)
            {
                if (info.Time >= minPursuitTime)
                {
                    //超过最小追击时间,尝试换攻击目标
                    CharacterInfo interestestTarget = GetInterestestTargetHelper(npc, CharacterRelation.RELATION_ENEMY);
                    if (null != interestestTarget && interestestTarget != target)
                    {
                        info.Time   = 0;
                        info.Target = interestestTarget.GetId();
                        data.FoundPath.Clear();
                        target = interestestTarget;
                    }
                }
                float   dist                 = (float)(npc.GetActualProperty().AttackRange *npc.AttackRangeCoefficient);
                float   distGoHome           = (float)npc.GohomeRange;
                Vector3 targetPos            = target.GetMovementStateInfo().GetPosition3D();
                ScriptRuntime.Vector3 srcPos = npc.GetMovementStateInfo().GetPosition3D();
                float powDist                = Geometry.DistanceSquare(srcPos, targetPos);
                float powDistToHome          = Geometry.DistanceSquare(srcPos, info.HomePos);
                if (powDist <= dist * dist && npc.SpatialSystem.CanShoot(npc.SpaceObject, target.GetMovementStateInfo().GetPosition3D()))
                {
                    npc.GetMovementStateInfo().IsMoving = false;
                    info.Time = 0;
                    ChangeToState(npc, (int)AiStateId.Combat);
                    NotifyNpcMove(npc);
                }
                else if (powDistToHome < distGoHome * distGoHome)
                {
                    if (AiLogicUtility.GetWalkablePosition(target, npc, ref targetPos))
                    {
                        PathToTargetWithoutObstacle(npc, data.FoundPath, targetPos, deltaTime);
                    }
                    else
                    {
                        npc.GetMovementStateInfo().IsMoving = false;
                        NotifyNpcMove(npc);
                    }
                }
                else
                {
                    goHome = true;
                }
            }
            else
            {
                goHome = true;
            }
            if (goHome)
            {
                npc.GetMovementStateInfo().IsMoving = false;
                NotifyNpcMove(npc);
                info.Time    = 0;
                info.HomePos = GetHomePosition(npc, data);
                data.FoundPath.Clear();
                ChangeToState(npc, (int)AiStateId.GoHome);
            }
        }