asmrobot
2019-11-25 2aeab450471cb80b59002da7da80faf251a0c4f4
src/RichCreator/StateMachines/KillMonsterStateMachine.cs
@@ -2,14 +2,17 @@
using Emgu.CV.Structure;
using RichCreator.Dnf;
using RichCreator.Maps.Kalete;
using RichCreator.Models;
using RichCreator.StateMachines;
using RichCreator.Utility;
using RichCreator.Utility.Captures;
using RichCreator.Utility.CV;
using RichCreator.Utility.Dnf;
using RichCreator.Utility.InputControl;
using RichCreator.Utility.Maps;
using RichCreator.Utility.Skills;
using RichCreator.Utility.Structs;
using RichCreator.Utility.Utilitys;
using RichCreator.Utilitys;
using System;
using System.Collections.Generic;
@@ -27,61 +30,42 @@
        private MapInfo map;//地图
        private HouseInfo house;//当前房间
        private DnfRole role;//当前角色控制
        private Int32 preHouseIndex = 0;//上一房间编号
        private OutOfBounds outOfBounds;//禁区
        private bool isSuccess;//退出结果
        private ZTPoint roleLastPosition = ZTPoint.Empty;//角色最后位置
        private Int32 runningStep = RunningStep.None;//是否恢复的状态
        //当前状态
        private KillMonsterStates currentState = KillMonsterStates.Start;
        //是否截图屏幕
        private bool needCaptureScreen = false;
        //怪
        private ZTPoint[] stateMonsters;
        private System.Drawing.Bitmap bitmap = null;
        //原图
        private Image<Rgb, byte> image = null;
        //图像是否改变
        private bool imageIsChange = false;
        //色彩hsv
        private Image<Hsv, byte> hsvImage = null;
        #region Find Door Info
        //门坐标
        private ZTPoint stateDoorPosition;
        
        //离开的门朝向
        private Direction stateDoorLevelDirect = Direction.None;
        
        //屏幕定位点
        private ParametersPoint stateScreenLocation = new ParametersPoint();
        
        #endregion
        private KillMonsterStates currentState = KillMonsterStates.Start;//当前状态
        private bool needCaptureScreen = false;//是否截图屏幕
        private ZTPoint[] stateMonsters;//怪
        private Image<Rgb, byte> image = null;//原图
        private Image<Hsv, byte> hsvImage = null;//色彩hsv
        private ZTPoint state_DoorPosition;//门坐标
        private Direction state_DoorDirect = Direction.None;//门朝向
        private ParametersPoint stateScreenLocation = new ParametersPoint();//屏幕定位点
        private ZTPoint skillReleasePoint = ZTPoint.Empty;
        private HIDCode roleDirection = HIDCode.NoEvent;
        private bool tryEntryDoor = false;//是否尝试进门
        public KillMonsterStateMachine(MapInfo map,HouseInfo house, DnfRole role,Int32 preHouseIndex, Int32 runningStep)
        public KillMonsterStateMachine(MapInfo map,HouseInfo house, DnfRole role)
        {
            if (house.HousePathInfo.LoopPoint.Equals(ZTPoint.Empty))
            {
                throw new ArgumentOutOfRangeException("寻路中不存在循环点");
            }
            this.map = map;
            this.house = house;
            this.role = role;
            this.runningStep = runningStep;
            this.preHouseIndex = preHouseIndex;
            
            outOfBounds = new OutOfBounds(map.GameRect, role);
            hsvImage = new Image<Hsv, byte>(map.GameRect.End.X - map.GameRect.Start.X + 1, map.GameRect.End.Y - map.GameRect.Start.Y + 1);
        }
        private void SetState(KillMonsterStates current, bool capture)
        {
            currentState = current;
@@ -95,36 +79,30 @@
        /// <param name="cancellationToken"></param>
        /// <param name="timeoutMillSecond"></param>
        /// <returns></returns>
        public ZTResult Work(Int32 timeoutMillSecond)
        public ZTResult Work(Int32 timeoutMillSecond,Int32 fromHouseIndex,Int32 runningStep)
        {
            bool imageIsChange = false;//图像是否改变
            DateTime expireTime = DateTime.Now.AddMilliseconds(timeoutMillSecond);
            if (this.runningStep > RunningStep.None)
            {
                SetState(KillMonsterStates.FindMonster, true);
            }
            //定位方框列表
            MultiList<ZTRectangle, Int32> locationRectangles = new MultiList<ZTRectangle, int>();
            while (true)
            {
                if (map.CancelToken.IsCancellationRequested)
                {
                    G.Instance.DebugWriter("取消刷图");
                    this.role.StopMove();
                    this.role.StopMove("cancel");
                    return ZTResult.Cancel;
                }
                if (DateTime.Now > expireTime)
                {
                    G.Instance.DebugWriter("刷图超时");
                    this.role.StopMove();
                    this.role.StopMove("timeout");
                    return ZTResult.Timeout;
                }
                if (needCaptureScreen)
                {
                    using (bitmap = ScreenCapture.Instance.CaptureScreen())
                    using (System.Drawing.Bitmap bitmap = ScreenCapture.Instance.CaptureScreen())
                    {
                        if (image != null)
                        {
@@ -135,12 +113,15 @@
                        imageIsChange = true;
                    }
                }
                switch (currentState)
                {
                    case KillMonsterStates.Start:
                        //开始
                        this.map.EntryHousePrework(this.house.Index, this.preHouseIndex);
                        if (this.house.FromHouseIndex == fromHouseIndex)
                        {
                            this.map.EntryHousePrework(this.house.Index, fromHouseIndex);
                        }
                        SetState(KillMonsterStates.IsLastHouse, true);
                        break;
                    case KillMonsterStates.IsLastHouse:
@@ -151,14 +132,14 @@
                            SetState(KillMonsterStates.FindRole, false);
                            break;
                        }
                        if (this.house.Index == 15)
                        if (this.house.IsEnd)
                        {
                            SetState(KillMonsterStates.HasRewardWindow, false);
                        }
                        else
                        {
                            SetState(KillMonsterStates.IsOtherHouse, false);
                        }
                        }
                        break;
                    case KillMonsterStates.HasRewardWindow:
                        //是否有奖励界面
@@ -205,76 +186,90 @@
                        break;
                    case KillMonsterStates.FindRole:
                        //主角
                        CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
                        //定位点
                        if (!DnfCVHelper.GetLocationPoint(out locationRectangles, hsvImage, map.GameRect))
                        if (this.house.WithoutNumber.Count <= 0)
                        {
                            this.stateScreenLocation = DnfCVHelper.GetLocationPoint(image, map.GameRect);
                        }
                        else
                        {
                            this.stateScreenLocation = DnfCVHelper.GetLocationPoint(image, map.GameRect,this.house.WithoutNumber);
                        }
                        if (this.stateScreenLocation.Equals(ParametersPoint.Empty))
                        {
                            //找不到定位点
                            G.Instance.InfoWriter("找不到定位点");
                            SetState(KillMonsterStates.IsLastHouse, true);
                            break;
                        }
                        this.stateScreenLocation = new ParametersPoint(locationRectangles[0].Item1.GetCenterPoint(), locationRectangles[0].Item2);
                        ZTPoint rolePosition = DnfCVHelper.FindRole(hsvImage, map.GameRect);
                        if (rolePosition .Equals( ZTPoint.Empty))
                        CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
                        ZTPoint roleCBPosition = DnfCVHelper.FindRole(hsvImage, map.GameRect);
                        if (roleCBPosition.Equals(ZTPoint.Empty))
                        {
                            SetState(KillMonsterStates.FindRoleMove, false);
                            //未找到角色
                            if (!this.role.IsMoving)
                            {
                                SetState(KillMonsterStates.FindRoleMove, false);
                            }
                            else
                            {
                                SetState(KillMonsterStates.IsLastHouse, true);
                            }
                        }
                        else
                        {
                            if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.FindRoleMove))
                            if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
                            {
                                this.role.StopMove();
                                this.role.StopMove("update cb position");
                            }
                            role.UpdatePosition(rolePosition);
                            role.UpdatePosition(roleCBPosition);
                            SetState(KillMonsterStates.FindMonster, false);
                        }
                        break;
                    case KillMonsterStates.FindRoleMove:
                        //todo:让主角移动(原:有怪攻击一下,无怪移动一下)
                        FindRoleMove();
                        break;
                    case KillMonsterStates.FindMonster:
                        //找怪
                        this.stateMonsters = LindongCVHelper.FindMonster(hsvImage, map.GameRect);
                        //找怪
                        this.stateMonsters = DnfCVHelper.FindMonster(hsvImage, map.GameRect);
                        if (this.stateMonsters.Length > 0)
                        {
                            G.Instance.DebugWriter(string.Format("已找到{0}个怪", this.stateMonsters.Length));
                            SetState(KillMonsterStates.CalcAttackDistance, false);
                            G.Instance.DebugWriter(string.Format("找到{0}个怪", this.stateMonsters.Length));
                            SetState(KillMonsterStates.CalcAttackPoint, false);
                        }
                        else
                        {
                            if (this.role.IsMoveIntent(MoveIntent.AttackMove))
                            {
                                this.role.StopMove("find monster to pickup thing");
                            }
                            SetState(KillMonsterStates.PickupThing, false);
                        }
                        break;
                    case KillMonsterStates.PickupThing:
                        //拾取物品
                        SetState(KillMonsterStates.ToNextGatePoint, false);
                        //todo: PickupThing();
                        break;
                    case KillMonsterStates.ToNextGatePoint:
                        //移到进门点
                        SetState(KillMonsterStates.FindDoor, false);
                        //todo:ToNextGatePoint
                        PickupThing();
                        break;
                    case KillMonsterStates.FindDoor:
                        //查找门, 是否找到门
                        //查找门
                        if (this.house.IsEnd)
                        {
                            SetState(KillMonsterStates.IsLastHouse, true);
                            break;
                        }
                        FindDoor();
                        break;
                    case KillMonsterStates.EntryDoor:
                        //向门移动, 进门
                        EntryDoor();
                        break;
                    case KillMonsterStates.FindDoorMove:
                        //todo:找门移动
                        FindDoorMove();
                    case KillMonsterStates.ToLoop:
                        //巡逻
                        ToLoop();
                        break;
                    case KillMonsterStates.CalcAttackDistance:
                    case KillMonsterStates.CalcAttackPoint:
                        //判断使用何技能,计算攻击移动距离, 是否需要移动
                        CalcAttackDistance();
                        break;
@@ -283,23 +278,20 @@
                        ReleaseSkill();
                        break;
                    case KillMonsterStates.AttackMove:
                        //todo:攻击移动
                        //攻击移动
                        AttackMove();
                        break;
                    case KillMonsterStates.Exit:
                        //结束
                        G.Instance.DebugWriter("退出状态");
                        this.role.StopMove();
                        this.role.StopMove("exit");
                        if (this.isSuccess)
                        {
                            return ZTResult.Success;
                        }
                        return ZTResult.Failed;
                }
                
                G.Instance.DebugWriter("next state:" + currentState.ToString());
                G.Instance.DebugWriter($"next state:{currentState},capture screen:{needCaptureScreen}");
            }
        }
@@ -309,40 +301,68 @@
        /// </summary>
        private void FindRoleMove()
        {
            //if (this.stateMonsters != null && this.stateMonsters.Length > 0)
            //{
            //    this.role.StopMove();
            //    G.Instance.DebugWriter("找不到角色,Send X");
            //    G.Instance.InputControl.PressKey(1000, HIDCode.X);
            //    SetState(KillMonsterStates.FindRole, true);
            //    return;
            //}
            if (this.role.IsMoving)
            {
                if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
                {
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else
                {
                    //不是则停止
                    this.role.StopMove("find role other");
                }
            }
            this.role.FindRoleMove();
            SetState(KillMonsterStates.FindRole, true);
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        DateTime pickupTime = DateTime.MinValue;
        /// <summary>
        /// 拾取物品
        /// </summary>
        private void PickupThing()
        {
            //拾取物品,获取最近一个物品位置并步行过去
            ZTPoint thingItemPosition = GetNearlyThingItem(image, role.Position);
            if (!thingItemPosition .Equals( ZTPoint.Empty))
            {
                if (this.role.IsMoving && !this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
                {
                    this.role.StopMove();
                }
                this.role.PickupMove(this.role.Position, thingItemPosition);
                //return new KillMonsterStateResult(STATE_FindMonster, true);
            //拾取物品中,返回
            if (this.role.IsMoveIntent(MoveIntent.PickupMove))
            {
                SetState(KillMonsterStates.IsLastHouse, true);
                return;
            }
            if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
            ZTPoint screenThingPosition = GetNearlyThingItem(hsvImage, role.Position);
            //是否有物品
            if (!screenThingPosition.Equals(ZTPoint.Empty))
            {
                this.role.StopMove();
                //有其它移动,则停止
                if (this.role.IsMoving&&!this.role.IsMoveIntent(MoveIntent.PickupMove))
                {
                    this.role.StopMove("pickup moveing");
                }
                //第一次发现有物品后,等一秒再去拾取,防物品刚出来时的去错误的位置拾取
                if (pickupTime == DateTime.MinValue)
                {
                    pickupTime = DateTime.Now.AddSeconds(1);
                }
                if (pickupTime > DateTime.Now)
                {
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                ////todo:remove
                //hsvImage.Save(DateTime.Now.ToString("HH_mm_ss_fff")+"_" + Guid.NewGuid().ToString()+".png");
                this.role.PickupMove(screenThingPosition,this.stateScreenLocation);
                SetState(KillMonsterStates.IsLastHouse, true);
            }
            else
            {
                SetState(KillMonsterStates.FindDoor, false);
            }
        }
@@ -352,21 +372,38 @@
        private void FindDoor()
        {
            //查找真实的门
            this.stateDoorPosition = LindongCVHelper.FindDoor(out stateDoorLevelDirect, hsvImage, this.house.DoorDirection, map.GameRect);
            if (!this.stateDoorPosition .Equals(ZTPoint.Empty))
            Dictionary<ZTPoint,Direction> doors=ShikongzhimenCVHelper.FindDoor(hsvImage, this.house.DoorDirection, map.GameRect);
            this.state_DoorDirect = Direction.None;
            this.state_DoorPosition = ZTPoint.Empty;
            if (doors.Count > 0)
            {
                foreach (var door in doors)
                {
                    //门地图坐标
                    ZTPoint mapDoorPoint = this.house.ScreenToMapCoordinate(door.Key, this.stateScreenLocation);
                    //要进入门的允许区域
                    ZTPoint nextGatePoint = this.house.GetNextGatePoint(door.Value);
                    ZTRectangle doorRect = new ZTRectangle(nextGatePoint.X - 70, nextGatePoint.Y - 70, nextGatePoint.X + 70, nextGatePoint.Y + 70);
                    if (GeoHelper.IsInRect(mapDoorPoint, doorRect))
                    {
                        this.state_DoorDirect = door.Value;
                        this.state_DoorPosition = door.Key;
                        break;
                    }
                }
            }
            if (!this.state_DoorPosition.Equals(ZTPoint.Empty))
            {
                //找到门,向门移动  
                if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.FindDoorMove))
                {
                    this.role.StopMove();
                }
                G.Instance.InfoWriter("已找到门,位置:" + stateDoorPosition.ToString());
                SetState(KillMonsterStates.EntryDoor, false);
            }
            else
            {
                //未找到门,循环移动
                SetState(KillMonsterStates.FindDoorMove, false);
                //未找到门,巡逻
                SetState(KillMonsterStates.ToLoop, false);
            }
        }
@@ -375,122 +412,103 @@
        /// </summary>
        private void EntryDoor()
        {
            const Int32 XLevelOffset = 200;
            const Int32 YLevelOffset = 100;
            Int32 limitLine = 0;
            Int32 diff = 0;
            //传过来人物坐标和门的坐标,根据门的朝向计算人物走向
            switch (stateDoorLevelDirect)
            //已经开始进门
            if (this.role.IsMoving)
            {
                case Direction.Up:
                    //门在上方
                    limitLine = stateDoorPosition.Y + YLevelOffset;
                    if (role.Position.Y < limitLine)
                    {
                this.role.StopMove("entry door other moving");
            }
            const Int32 offsetX = 200;
            const Int32 offsetY = 100;
            ZTRectangle doorRect = new ZTRectangle(this.state_DoorPosition.X - offsetX, this.state_DoorPosition.Y - offsetY, this.state_DoorPosition.X + offsetX, this.state_DoorPosition.Y + offsetY);
            if (tryEntryDoor && GeoHelper.IsInRect(this.role.RoleCBPosition.Sub(DnfRole.RoleHalfOffset), doorRect))
            {
                //离门太近,先向外走,再向门走
                Int32 limitLine = 0;
                Int32 diff = 0;
                //传过来人物坐标和门的坐标,根据门的朝向计算人物走向
                switch (state_DoorDirect)
                {
                    case Direction.Up:
                        //门在上方
                        limitLine = state_DoorPosition.Y + offsetY;
                        //下移
                        this.role.SyncMove(new ZTPoint(0, limitLine - role.Position.Y));
                    }
                        //垂直对齐
                        diff = state_DoorPosition.X - role.Position.X;
                        this.role.SyncMove(new ZTPoint(diff, 0));
                        //移动y,进入
                        this.role.SyncMove(new ZTPoint(0, map.GameRect.Start.Y - role.Position.Y));
                        break;
                    //垂直对齐
                    diff = stateDoorPosition.X - role.Position.X;
                    this.role.SyncMove(new ZTPoint(diff, 0));
                    //移动y,进入
                    this.role.SyncMove(new ZTPoint(0, map.GameRect.Start.Y - role.Position.Y));
                    break;
                case Direction.Right:
                    //门在右侧
                    limitLine = stateDoorPosition.X - XLevelOffset;
                    if (role.Position.X > limitLine)
                    {
                    case Direction.Right:
                        //门在右侧
                        limitLine = state_DoorPosition.X - offsetX;
                        //如果角色位于门右侧,先向左移
                        this.role.SyncMove(new ZTPoint(limitLine - role.Position.X, 0));
                    }
                        //水平对齐
                        diff = state_DoorPosition.Y - role.Position.Y;
                        this.role.SyncMove(new ZTPoint(0, diff));
                        //移动x,进入
                        this.role.SyncMove(new ZTPoint(map.GameRect.End.X - role.Position.X, 0));
                        break;
                    //水平对齐
                    diff = stateDoorPosition.Y - role.Position.Y;
                    this.role.SyncMove(new ZTPoint(0, diff));
                    //移动x,进入
                    this.role.SyncMove(new ZTPoint(map.GameRect.End.X - role.Position.X, 0));
                    break;
                case Direction.Bottom:
                    //门在下方
                    limitLine = stateDoorPosition.Y - YLevelOffset;
                    if (role.Position.Y > limitLine)
                    {
                    case Direction.Bottom:
                        //门在下方
                        limitLine = state_DoorPosition.Y - offsetY;
                        //如果角色在门下方,先向上移
                        this.role.SyncMove(new ZTPoint(0, limitLine - role.Position.Y));
                    }
                        //垂直对齐
                        diff = state_DoorPosition.X - role.Position.X;
                        this.role.SyncMove(new ZTPoint(diff, 0));
                    //垂直对齐
                    diff = stateDoorPosition.X - role.Position.X;
                    this.role.SyncMove(new ZTPoint(diff, 0));
                        //移动y,进入
                        this.role.SyncMove(new ZTPoint(0, map.GameRect.End.Y - role.Position.Y));
                        break;
                    //移动y,进入
                    this.role.SyncMove(new ZTPoint(0, map.GameRect.End.Y - role.Position.Y));
                    break;
                case Direction.Left:
                    //门在左侧
                    limitLine = stateDoorPosition.X + XLevelOffset;
                    if (role.Position.X < limitLine)
                    {
                    case Direction.Left:
                        //门在左侧
                        limitLine = state_DoorPosition.X + offsetX;
                        //如果角色位于门左侧,先向右移
                        this.role.SyncMove(new ZTPoint(limitLine - role.Position.X, 0));
                    }
                        //水平对齐
                        diff = state_DoorPosition.Y - role.Position.Y;
                        this.role.SyncMove(new ZTPoint(0, diff));
                    //水平对齐
                    diff = stateDoorPosition.Y - role.Position.Y;
                    this.role.SyncMove(new ZTPoint(0, diff));
                    //移动x,进入
                    this.role.SyncMove(new ZTPoint(map.GameRect.Start.X - role.Position.X, 0));
                    break;
            }
            SetState(KillMonsterStates.IsLastHouse, true);
            return;
        }
        /// <summary>
        /// 找门移动
        /// </summary>
        private void FindDoorMove()
        {
            Int32 areaID = 0;
            if (this.outOfBounds.InOutOfBound(this.house.Index, role.Position, out areaID))
            {
                this.outOfBounds.MoveToCommonBound(areaID);
                        //移动x,进入
                        this.role.SyncMove(new ZTPoint(map.GameRect.Start.X - role.Position.X, 0));
                        break;
                }
                tryEntryDoor = false;
            }
            else
            {
                this.role.FindDoorMove(role.Position);
                this.role.EntryDoorMove(this.state_DoorPosition, this.stateScreenLocation, this.state_DoorDirect);
                tryEntryDoor = true;
            }
            SetState(KillMonsterStates.IsLastHouse, true);
            return;
        }
        private DateTime FindRoleLastNoMoveTime = DateTime.MaxValue;//最后没移动时间
        private bool FindRoleLastNoMoveStart = false;//没移动是否开始计时
        private ZTSize attackMoveDistance = ZTSize.Empty;
        private HIDCode roleDirection = HIDCode.NoEvent;
        /// <summary>
        /// 判断使用何技能,计算攻击移动距离, 是否需要移动
        /// </summary>
        private void CalcAttackDistance()
        {
            SkillInfo attackSkill = this.house.Skills.SyncPeek();
            
            //计算攻击移动距离
            bool needMove = false;
            attackMoveDistance = AttackRectangle.GetMoveDistance(map.GameRect, role.Position, stateMonsters, attackSkill, out roleDirection, out needMove);
            skillReleasePoint = AttackRectangle.GetAttackPoint(map.GameRect, role.HalfPosition, stateMonsters, attackSkill, out roleDirection, out needMove);
            if (!needMove)
            {
                G.Instance.DebugWriter(string.Format("不需移动直接发技能,距离:{0}", attackMoveDistance.ToString()));
                if (this.role.IsMoving)
                {
                    this.role.StopMove("calc attack");
                }
                G.Instance.DebugWriter(string.Format("不需移动直接发技能,距离:{0}", skillReleasePoint.ToString()));
                SetState(KillMonsterStates.ReleaseSkill, false);
            }
            else
@@ -498,25 +516,44 @@
                SetState(KillMonsterStates.AttackMove, false);
            }
        }
        /// <summary>
        /// 攻击移动
        /// </summary>
        private void AttackMove()
        {
            if (this.role.IsMoving)
            {
                if (this.role.IsMoveIntent(MoveIntent.AttackMove))
                {
                    //todo:添加如果是攻击移动中,如果怪物偏差太大则重新计算
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else
                {
                    //不是则停止
                    this.role.StopMove("attack move other");
                }
            }
            G.Instance.DebugWriter("attack move :" + skillReleasePoint.ToString() + ",role:" + role.Position.ToString() + ",monster1:" + stateMonsters[0].ToString() + ",skill:" + this.house.Skills.SyncPeek().Key.ToString());
            this.role.AttackMove(skillReleasePoint, this.stateScreenLocation);
            SetState(KillMonsterStates.FindRole, true);
        }
        /// <summary>
        /// 调整朝向, 释放技能
        /// </summary>
        private void ReleaseSkill()
        {
            SkillInfo skill = this.house.Skills.SyncDeQueue();
            this.roleLastPosition = ZTPoint.Empty;
            StateProvider.Instance.AttackKey = skill.Key;
            if (roleDirection != HIDCode.NoEvent)
            {
                G.Instance.InputControl.PressKey(100, roleDirection);
            }
            this.role.StopMove();
            if (skill.Key == HIDCode.X)
            {
                for (int i = 0; i < 5; i++)
@@ -528,47 +565,36 @@
            else
            {
                G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, skill.Key);
                Thread.Sleep((Int32)skill.ReleaseTime);
                Thread.Sleep((Int32)skill.ReleaseWaitTime);
            }
            G.Instance.DebugWriter(string.Format("发完技能,技能按键:{0},技能名称:{1}", skill.Key, skill.SkillName));
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        /// <summary>
        /// 攻击移动
        /// 巡逻
        /// </summary>
        private void AttackMove()
        private void ToLoop()
        {
            SkillInfo attackSkill = this.house.Skills.SyncPeek();
            //没有移动,可能有障碍物
            if (role.Position .Equals( this.roleLastPosition))
            //巡逻
            if (this.role.IsMoving)
            {
                if (FindRoleLastNoMoveStart && (DateTime.Now - FindRoleLastNoMoveTime).TotalMilliseconds > NoMoveMaxMillSecond)
                if (this.role.IsMoveIntent(MoveIntent.ToLoop))
                {
                    //开始计时 并且 超过最大未移动容忍时间
                    G.Instance.DebugWriter("find role no mvoe:" + role.Position.ToString());
                    this.role.StopMove();
                    G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.X);
                    FindRoleLastNoMoveTime = DateTime.Now;
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else if (!FindRoleLastNoMoveStart)
                else
                {
                    //没开始计时 则 开始计时
                    FindRoleLastNoMoveStart = true;
                    FindRoleLastNoMoveTime = DateTime.Now;
                    //不是则停止
                    this.role.StopMove("to loop other");
                }
            }
            else
            {
                //移动了 取消计时
                this.roleLastPosition = role.Position;
                FindRoleLastNoMoveStart = false;
            }
            G.Instance.DebugWriter("attack move :" + attackMoveDistance.ToString() + ",role:" + role.Position.ToString() + ",monster1:" + stateMonsters[0].ToString() + ",skill:" + attackSkill.Key.ToString());
            this.role.AttackMove(attackMoveDistance);
            SetState(KillMonsterStates.FindRole, true);
            this.role.LoopMove(this.stateScreenLocation);
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        #endregion
@@ -577,22 +603,22 @@
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public ZTPoint GetNearlyThingItem(Image<Rgb, byte> image, ZTPoint rolePosition)
        public ZTPoint GetNearlyThingItem(Image<Hsv, byte> image, ZTPoint rolePosition)
        {
            List<ZTPoint> points = DnfCVHelper.GetThingItemPoints(image, map.GameRect);
            if (points.Count <= 0)
            ZTPoint[] points = DnfCVHelper.FindThings(image, map.GameRect);
            if (points.Length <= 0)
            {
                return ZTPoint.Empty;
            }
            if (points.Count == 1)
            if (points.Length == 1)
            {
                return points[0];
            }
            double distance = 0;
            ZTPoint result = ZTPoint.Empty;
            for (int i = 0; i < points.Count; i++)
            for (int i = 0; i < points.Length; i++)
            {
                double temp = ZTImage.Utils.GetDistance(rolePosition.X, rolePosition.Y, points[i].X, points[i].Y);
                if (i == 0)
@@ -612,23 +638,23 @@
            return result;
        }
        
        /// <summary>
        /// 牌的位置
        /// </summary>
        private static readonly ZTPoint[] CardList = new ZTPoint[] {
            new ZTPoint(364,231),
            new ZTPoint(561,231),
            new ZTPoint(744,231),
            new ZTPoint(924,231),
            new ZTPoint(164,195),
            new ZTPoint(315,195),
            new ZTPoint(474,195),
            new ZTPoint(635,195),
            new ZTPoint(364,570),
            new ZTPoint(561,570),
            new ZTPoint(744,570),
            new ZTPoint(924,570),
            new ZTPoint(164,480),
            new ZTPoint(315,480),
            new ZTPoint(474,480),
            new ZTPoint(635,480),
        };
        /// <summary>
        /// 翻牌
        /// 1-4
@@ -643,7 +669,7 @@
            G.Instance.InputControl.MoveToAndClick(RandomUtils.PointRange(willPosition, 10));
            //判断黄金版是否可以翻
            if (DnfCVHelper.HasMowangqiyueCard(map.GameRect))
            if (DnfCVHelper.HasGoldCard(map.GameRect))
            {
                number = RandomUtils.G(5, 8);
                willPosition = map.GameRect.Start.Add(CardList[number - 1]);
@@ -652,7 +678,6 @@
        }
        
        /// <summary>
        /// 是否改变房间
        /// </summary>
@@ -671,8 +696,7 @@
            }
            return false;
        }
        /// <summary>
        /// 杀怪状态
        /// </summary>
@@ -689,11 +713,13 @@
            FindRoleMove,//让主角移动(原:有怪攻击一下,无怪移动一下)
            FindMonster,//找怪
            PickupThing,//拾取物品
            ToNextGatePoint,//移到进门点
            FindDoor,//查找门, 是否找到门
            EntryDoor,//向门移动, 进门
            FindDoorMove,//找门移动
            CalcAttackDistance,//判断使用何技能,计算攻击移动距离, 是否需要移动
            ToLoop,//巡逻
            CalcAttackPoint,//判断使用何技能,计算攻击移动距离, 是否需要移动
            ReleaseSkill,//调整朝向, 释放技能,
            AttackMove,//攻击移动
        }