asmrobot
2019-11-21 589ed88a5924a7494e21b95b6bbff5e46ff49ddd
src/RichCreator/Dnf/DnfRole.cs
@@ -2,8 +2,11 @@
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 System;
using System.Collections.Generic;
using System.Threading;
@@ -14,37 +17,61 @@
    /// </summary>
    public class DnfRole
    {
        private SpeedProvider speed;//速度
        private const Int32 PaddingLeft = 140;//左边框内边距
        private const Int32 PaddingRight = 140;//右边框内边距
        /// <summary>
        /// 角色脚部距色块中央的偏移
        /// </summary>
        public static readonly ZTPoint RoleFootOffset = new ZTPoint(0, 143);
        /// <summary>
        /// 角色身体中间距色块中央的偏移
        /// </summary>
        public static readonly ZTPoint RoleHalfOffset = new ZTPoint(0, 88);
        public DnfRole(ZTRectangle gameRect)
        {
            this.gameRect = gameRect;
            speed = SpeedProvider.Define;
            moveCancelToken = new CancellationTokenSource();
        }
        private SpeedProvider speed;//速度
        private HouseInfo house;//所在房间
        private ZTRectangle gameRect = ZTRectangle.Empty;
        private MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图
        private CancellationTokenSource moveCancelToken;//移动取消令牌
        /// <summary>
        /// 角色色块位置
        /// </summary>
        public ZTPoint RoleCBPosition { get; private set; }
        /// <summary>
        /// 角色脚部位置
        /// </summary>
        public ZTPoint Position
        {
            get
            {
                return CBToFootPosition(RoleCBPosition);
            }
        }
        /// <summary>
        /// 身体中间位置
        /// </summary>
        public ZTPoint HalfPosition
        {
            get
            {
                return CBToHalfPosition(RoleCBPosition);
            }
        }
        
        private Int32 minCenterLineY;
        private Int32 maxCenterLineY;
        private Int32 centerLineErrorRange = 35;//中间性可允许的误差
        private HouseInfo house;
        private ZTRectangle gameRect = ZTRectangle.Empty;
        private MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图
        private MoveMethod movingMethod = MoveMethod.Vertical;//移动方式,默认垂直移动
        private ZTSize movingDistance;//移动距离
        public ZTPoint Position { get; private set; }//角色位置
        /// <summary>
        /// 按下的键,0:横向,1:纵向
        /// </summary>
@@ -58,8 +85,6 @@
        public void SetHouse(HouseInfo house)
        {
            this.house = house;
            minCenterLineY = this.gameRect.End.Y + this.house.HouseCenterMoveLine - centerLineErrorRange;
            maxCenterLineY = this.gameRect.End.Y + this.house.HouseCenterMoveLine + centerLineErrorRange;
        }
        /// <summary>
@@ -74,10 +99,10 @@
        /// <summary>
        /// 更新位置
        /// </summary>
        /// <param name="position"></param>
        public void UpdatePosition(ZTPoint position)
        /// <param name="roleCBPosition"></param>
        public void UpdatePosition(ZTPoint roleCBPosition)
        {
            this.Position = position;
            this.RoleCBPosition = roleCBPosition;
        }
@@ -113,14 +138,56 @@
        /// <param name="moveDistance"></param>
        public void AttackMove(ZTSize moveDistance)
        {
            PutKey(moveDistance);
            PutDirectionKey(moveDistance);
            movingIntent = MoveIntent.AttackMove;
        }
        /// <summary>
        /// 攻击移动至
        /// </summary>
        /// <param name="skillReleasePoint"></param>
        public void AttackMoveTo(ZTPoint skillReleasePoint,ParametersPoint locationPoint)
        {
            //屏幕坐标转地图坐标
            ZTPoint start= this.house.ScreenToMapCoordinate(this.Position, locationPoint);
            ZTPoint end = this.house.ScreenToMapCoordinate(DnfRole.HalfToFootPosition(skillReleasePoint), locationPoint);
            List<ZTPoint> paths = this.house.FindPath(start, end);
            MovePaths(start, paths);
        }
        /// <summary>
        /// 移动到指定地图点
        /// </summary>
        public void MoveToMapPoint(ZTPoint start,ZTPoint end)
        {
            List<ZTPoint> paths = this.house.FindPath(start, end);
            MovePaths(start, paths);
        }
        /// <summary>
        /// 移动指定路径
        /// </summary>
        /// <param name="start"></param>
        /// <param name="paths"></param>
        public void MovePaths(ZTPoint start, List<ZTPoint> paths)
        {
            ZTPoint lastPoint = start;
            if (paths != null && paths.Count > 0)
            {
                for (int i = 0; i < paths.Count; i++)
                {
                    ZTPoint distance = paths[i].Sub(lastPoint);
                    this.SyncMove(distance);
                    lastPoint = paths[i];
                }
            }
        }
        private Int32 findRoleDir = 0;//寻找角色行走的方向
        private DateTime findRoleMoveTimeout = DateTime.MinValue;//方向移动过期时间
        private static HIDCode[][] dir = new HIDCode[][] { new HIDCode[] { HIDCode.LeftArrow ,HIDCode.NoEvent}, new HIDCode[] { HIDCode.NoEvent, HIDCode.UpArrow }, new HIDCode[] { HIDCode.RightArrow, HIDCode.NoEvent }, new HIDCode[] { HIDCode.NoEvent, HIDCode.DownArrow } };
        
        /// <summary>
@@ -140,23 +207,48 @@
                findRoleDir++;
                HIDCode[]  tempKeys = dir[findRoleDir % 4];
                Int32 stepms = 0, runms = 0;
                PutKey(out stepms, out runms, tempKeys[0], tempKeys[1], true);
                PutDirectionKey(out stepms, out runms, tempKeys[0], tempKeys[1], true);
                findRoleMoveTimeout = DateTime.Now.AddMilliseconds(speed.RandomMoveMillSecond);
            }
            //if (!IsMoving || (IsMoving && KeyIsChange(tempKeys)))
            //{
            //    //Int32 stepms = 0, runms = 0;
            //    //PutKey(out stepms, out runms, tempKeys[0], tempKeys[1], true);
            //}
            movingIntent = MoveIntent.FindRoleMove;
        }
        public void EntryDoorMove()
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.EntryDoor))
            {
                StopMove();
            }
        }
        public void ToLoopMove()
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.ToLoopPoint))
            {
                StopMove();
            }
        }
        public void ToNextGateMove()
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.ToNextGatePoint))
            {
                StopMove();
            }
        }
        /// <summary>
        /// 拾起物品移动
        /// </summary>
        public void PickupMove(ZTPoint rolePosition, ZTPoint thingItemPosition)
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.PickupMove))
            {
                StopMove();
            }
            ZTSize moveDistance = new ZTSize(thingItemPosition.X - rolePosition.X, thingItemPosition.Y - rolePosition.Y - 97);
            if (Math.Abs(moveDistance.Width) < 100 && Math.Abs(moveDistance.Height) < 100)
            {
@@ -168,39 +260,10 @@
            }
            //G.Instance.DebugWriter("pickup distance:" + moveDistance.ToString());
            PutKey(moveDistance);
            PutDirectionKey(moveDistance);
            movingIntent = MoveIntent.PickupMove;
        }
        /// <summary>
        /// 找门移动
        /// </summary>
        /// <param name="rolePosition"></param>
        public void FindDoorMove(ZTPoint rolePosition)
        {
            ComputeMoveInfo(rolePosition);
            HIDCode dirKey = HIDCode.NoEvent;
            switch (movingMethod)
            {
                case MoveMethod.ToLeft:
                    dirKey = HIDCode.LeftArrow;
                    break;
                case MoveMethod.ToRight:
                    dirKey = HIDCode.RightArrow;
                    break;
                case MoveMethod.Vertical:
                    dirKey = movingDistance.Height > 0 ? HIDCode.DownArrow : HIDCode.UpArrow;
                    break;
                case MoveMethod.Fixed:
                    SyncMove(new ZTPoint(movingDistance.Width,movingDistance.Height));
                    StopMove();
                    return;
            }
            PutKey(movingDistance);
            movingIntent = MoveIntent.FindDoorMove;
        }
        
        /// <summary>
        /// 同步移动指定距离
@@ -241,7 +304,7 @@
                horizontal = HIDCode.LeftArrow;
            }
            PutKey(out stepms, out runms, horizontal, vertical, isRun);
            PutDirectionKey(out stepms, out runms, horizontal, vertical, isRun);
            if (stepms > 0)
            {
                Int32 mdistance = (Int32)(stepms * speed.StepX);
@@ -258,9 +321,7 @@
            {
                xtime = (Int32)(Math.Abs(distance.Width) / speed.RunX);
            }
            Int32 mintime = Math.Min(xtime, ytime);
            if (xtime <= 0)
            {
@@ -276,15 +337,20 @@
            ytime -= mintime;
            if (xtime > 0)
            {
                PutKey(out stepms, out runms, horizontal, HIDCode.NoEvent, isRun);
                PutDirectionKey(out stepms, out runms, horizontal, HIDCode.NoEvent, isRun);
                Thread.Sleep(xtime);
            }
            if (ytime > 0)
            {
                PutKey(out stepms, out runms, HIDCode.NoEvent, vertical, false);
                PutDirectionKey(out stepms, out runms, HIDCode.NoEvent, vertical, false);
                Thread.Sleep(ytime);
            }
            StopMove();
            //StopMove();
            G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
            pressKeys[0] = HIDCode.NoEvent;
            pressKeys[1] = HIDCode.NoEvent;
            isRun = false;
        }
        
        /// <summary>
@@ -294,6 +360,9 @@
        {
            if (IsMoving)
            {
                this.moveCancelToken.Cancel();
                this.moveCancelToken = new CancellationTokenSource();
                //停止
                G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
                pressKeys[0] = HIDCode.NoEvent;
@@ -310,181 +379,23 @@
        {
            Thread.Sleep(millSecond);
        }
        /// <summary>
        /// 释放技能
        /// </summary>
        /// <param name="key"></param>
        public void ReleaseSkill(HIDCode key)
        {
            ReleaseSkill(key, 0);
        }
        public void ReleaseSkill(HIDCode key, Int32 skillTimeout)
        {
            Int32 dur = RandomUtils.KeyPressDuration;
            G.Instance.InputControl.PressKey(dur,key);
            Int32 subTime = skillTimeout - dur;
            if (subTime > 0)
            SkillInfo skill=SkillInfo.GetSkillInfo(key);
            if (skill != null)
            {
                Thread.Sleep(subTime);
            }
        }
        private ZTPoint roleLastPosition = ZTPoint.Empty;
        private bool StaticTimerIsStart = false;//静止计时是否开始
        private Int32 StaticTimerCounter = 0;//静止计时计数器
        private DateTime DetectLastNoMoveTime = DateTime.MaxValue;//最后没移动时间
        private const Int32 NoMoveMaxMillSecond = 2000;//最大未移动容忍毫秒数
        /// <summary>
        /// 得到循环移动的距离
        /// </summary>
        /// <returns></returns>
        private void ComputeMoveInfo(ZTPoint rolePosition)
        {
            ZTRectangle limitRect = ZTRectangle.Empty;
            //达到未移动阀值,可能有障碍物,先攻击,如果攻击后还是无效则上下左右移
            if (rolePosition.Equals(this.roleLastPosition))
            {
                if (StaticTimerIsStart)
                Int32 subTime = (Int32)(skill.ReleaseWaitTime - dur);
                if (subTime > 0)
                {
                    if ((DateTime.Now - DetectLastNoMoveTime).TotalMilliseconds > NoMoveMaxMillSecond)
                    {
                        G.Instance.DebugWriter($"find door not move,role position:{rolePosition.ToString()}");
                        this.StopMove();
                        if (StaticTimerCounter == 0)
                        {
                            //清除障碍物
                            G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.X);
                        }
                        else
                        {
                            //无法清除障碍物,随机移动一下
                            switch (StaticTimerCounter % 4)
                            {
                                case 0:
                                    G.Instance.DebugWriter("random up");
                                    //上
                                    movingDistance = new ZTSize(0, -300);
                                    break;
                                case 1:
                                    //右
                                    movingDistance = new ZTSize(600, 0);
                                    break;
                                case 2:
                                    //下
                                    movingDistance = new ZTSize(0, 300);
                                    break;
                                case 3:
                                    //左
                                    movingDistance = new ZTSize(-600, 0);
                                    break;
                            }
                            movingMethod = MoveMethod.Fixed;
                        }
                        StaticTimerCounter++;
                        DetectLastNoMoveTime = DateTime.Now;
                        if (StaticTimerCounter > 1)
                        {
                            return;
                        }
                    }
                    Sleep(subTime);
                }
                else if (!StaticTimerIsStart)
                {
                    //没开始计时 则 开始计时
                    StaticTimerIsStart = true;
                    DetectLastNoMoveTime = DateTime.Now;
                }
            }
            else
            {
                //移动了 取消计时
                this.roleLastPosition = rolePosition;
                StaticTimerIsStart = false;
                StaticTimerCounter = 0;
            }
            if (!IsMoving)
            {
                //刚开始移动
                movingMethod = MoveMethod.Vertical;
            }
            if (movingMethod == MoveMethod.Vertical && rolePosition.Y >= minCenterLineY && rolePosition.Y <= maxCenterLineY)
            {
                //不需要上下移动,计算左右
                if (this.house.DoorDirection[0] == Direction.Left)
                {
                    movingMethod = MoveMethod.ToLeft;
                }
                else if (this.house.DoorDirection[0] == Direction.Right)
                {
                    movingMethod = MoveMethod.ToRight;
                }
                else
                {
                    //计算是向左还是右,哪边大往哪边
                    if (rolePosition.X > (this.gameRect.Start.X + (this.gameRect.End.X - this.gameRect.Start.X) / 2))
                    {
                        //左边空间大
                        movingMethod = MoveMethod.ToLeft;
                    }
                    else
                    {
                        movingMethod = MoveMethod.ToRight;
                    }
                }
            }
            if (movingMethod == MoveMethod.ToLeft)
            {
                //计算左边界范围
                limitRect = new ZTRectangle(gameRect.Start.X, gameRect.Start.Y, gameRect.Start.X + PaddingLeft, gameRect.End.Y);
                //判断是否到左边界
                if (RichCreator.Utilitys.Utils.IsInRect(rolePosition, limitRect))
                {
                    //到左边界就向右走
                    movingMethod = MoveMethod.ToRight;
                    movingDistance = new ZTSize(gameRect.End.X - rolePosition.X, 0);
                }
                else
                {
                    //没到继续向左走
                    movingMethod = MoveMethod.ToLeft;
                    movingDistance = new ZTSize(limitRect.Start.X - rolePosition.X, 0);
                }
            }
            else if (movingMethod == MoveMethod.ToRight)
            {
                //计算右边界范围
                limitRect = new ZTRectangle(gameRect.End.X - PaddingRight, gameRect.Start.Y, gameRect.End.X, gameRect.End.Y);
                //判断是否到右边界
                if (Utilitys.Utils.IsInRect(rolePosition, limitRect))
                {
                    //到右边界就向左走
                    G.Instance.InfoWriter($"in limit rect,role position:{rolePosition.ToString()},limit:{limitRect.ToString()}");
                    movingMethod = MoveMethod.ToLeft;
                    movingDistance = new ZTSize(gameRect.Start.X - rolePosition.X, 0);
                }
                else
                {
                    //没到继续向右走
                    movingMethod = MoveMethod.ToRight;
                    movingDistance = new ZTSize(gameRect.End.X - rolePosition.X, 0);
                }
            }
            else
            {
                //向点移动
                Int32 targetY = gameRect.End.Y + this.house.HouseCenterMoveLine;
                movingDistance = new ZTSize(0, targetY - rolePosition.Y);
            }
        }
        
@@ -493,7 +404,7 @@
        /// 按下按键
        /// </summary>
        /// <param name="distance"></param>
        private void PutKey(ZTSize distance)
        private void PutDirectionKey(ZTSize distance)
        {
            HIDCode horizontal = HIDCode.NoEvent;
            HIDCode vertical = HIDCode.NoEvent;
@@ -523,7 +434,7 @@
            }
            Int32 stepms, runms;
            PutKey(out stepms, out runms, horizontal, vertical, isRun);
            PutDirectionKey(out stepms, out runms, horizontal, vertical, isRun);
        }
        /// <summary>
@@ -534,7 +445,7 @@
        /// <param name="horizontal">横向按键</param>
        /// <param name="vertical">纵向按键</param>
        /// <param name="isRun">是否奔跑</param>
        private void PutKey(out Int32 stepMS, out Int32 runMS, HIDCode horizontal, HIDCode vertical, bool isRun)
        private void PutDirectionKey(out Int32 stepMS, out Int32 runMS, HIDCode horizontal, HIDCode vertical, bool isRun)
        {
            stepMS = 0;
            runMS = 0;
@@ -617,7 +528,7 @@
        /// </summary>
        /// <param name="pressKey"></param>
        /// <returns></returns>
        private bool KeyIsChange(HIDCode[] pressKey)
        private bool IsChangeOfKey(HIDCode[] pressKey)
        {
            if (pressKey == null || pressKey.Length != 2)
            {
@@ -630,7 +541,51 @@
            }
            return true;
        }
        #endregion
        
        #region role position convert
        /// <summary>
        /// 色块中央位置转为脚部位置
        /// </summary>
        /// <param name="cbPosition"></param>
        /// <returns></returns>
        public static ZTPoint CBToFootPosition(ZTPoint cbPosition)
        {
            return cbPosition.Add(RoleFootOffset);
        }
        /// <summary>
        /// 色块中央位置转为人物中间位置
        /// </summary>
        /// <param name="cbPosition"></param>
        /// <returns></returns>
        public static ZTPoint CBToHalfPosition(ZTPoint cbPosition)
        {
            return cbPosition.Add(RoleHalfOffset);
        }
        /// <summary>
        /// 脚部坐标到身份中央坐标转换
        /// </summary>
        /// <param name="footPosition"></param>
        /// <returns></returns>
        public static ZTPoint FootToHalfPosition(ZTPoint footPosition)
        {
            return footPosition.Sub(RoleFootOffset).Add(RoleHalfOffset);
        }
        /// <summary>
        /// 身体中央坐标到脚部坐标转换
        /// </summary>
        /// <param name="halfPosition"></param>
        /// <returns></returns>
        public static ZTPoint HalfToFootPosition(ZTPoint halfPosition)
        {
            return halfPosition.Sub(RoleHalfOffset).Add(RoleFootOffset);
        }
        #endregion