using RichCreator.Models; using RichCreator.Utility; 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; namespace RichCreator.Dnf { /// /// DNF角色 /// public class DnfRole { private const Int32 PaddingLeft = 140;//左边框内边距 private const Int32 PaddingRight = 140;//右边框内边距 /// /// 角色脚部距色块中央的偏移 /// public static readonly ZTPoint RoleFootOffset = new ZTPoint(0, 143); /// /// 角色身体中间距色块中央的偏移 /// 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; public MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图 private CancellationTokenSource moveCancelToken;//移动取消令牌 private Int32 findRoleDir = 0;//寻找角色行走的方向 private DateTime findRoleMoveTimeout = DateTime.MinValue;//方向移动过期时间 /// /// 角色色块位置 /// public ZTPoint RoleCBPosition { get; private set; } /// /// 角色脚部位置 /// public ZTPoint Position { get { return CBToFootPosition(RoleCBPosition); } } /// /// 身体中间位置 /// public ZTPoint HalfPosition { get { return CBToHalfPosition(RoleCBPosition); } } /// /// 按下的键,0:横向,1:纵向 /// private HIDCode[] pressKeys = new HIDCode[] { HIDCode.NoEvent, HIDCode.NoEvent };//当前按键 private bool isRun = false;//是否奔跑 /// /// 设置当前房间信息 /// /// public void SetHouse(HouseInfo house) { this.house = house; toNextGate = true; } /// /// 设置当前角色速度 /// /// public void SetSpeed(Int32 speed) { this.speed = new SpeedProvider(speed); } /// /// 更新位置 /// /// public void UpdatePosition(ZTPoint roleCBPosition) { this.RoleCBPosition = roleCBPosition; } private bool isMoving = false; /// /// 是否移动中 /// public bool IsMoving { get { return isMoving; //return pressKeys[0] != HIDCode.NoEvent || pressKeys[1] != HIDCode.NoEvent; } } /// /// 是否指定移动行为 /// /// /// public bool IsMoveIntent(MoveIntent intent) { if (IsMoving && movingIntent == intent) { return true; } return false; } /// /// 攻击移动至 /// /// public void AttackMove(ZTPoint skillReleasePoint, ParametersPoint screenLocation) { //屏幕坐标转地图坐标 ZTPoint start = this.house.ScreenToMapCoordinate(this.Position, screenLocation); ZTPoint end = this.house.ScreenToMapCoordinate(DnfRole.HalfToFootPosition(skillReleasePoint), screenLocation); List paths = this.house.FindPath(start, end); this.movingIntent = MoveIntent.AttackMove; isMoving = true; ThreadPool.QueueUserWorkItem((obj) => { this.MovePaths(start, paths, this.moveCancelToken.Token,"attack move"); }, null); } /// /// 查找主角移动 /// /// public void FindRoleMove() { if (DateTime.Now >= findRoleMoveTimeout) { //转换方向 findRoleDir++; ZTSize distance = ZTSize.Empty; switch (findRoleDir % 4) { case 0: //右 distance = new ZTSize(SpeedProvider.RandomMoveDistance, 0); break; case 1: //下 distance = new ZTSize(0,SpeedProvider.RandomMoveDistance); break; case 2: //左 distance = new ZTSize(-SpeedProvider.RandomMoveDistance, 0); break; case 3: //上 distance = new ZTSize(0,-SpeedProvider.RandomMoveDistance); break; } movingIntent = MoveIntent.FindRoleMove; isMoving = true; ThreadPool.QueueUserWorkItem((state) => { CancellationToken ctoken = (CancellationToken)state; this.SyncMoveKeyPress(distance); if (!ctoken.IsCancellationRequested) { //如果没有取消则停止 StopMove("find role mvoe"); } }, this.moveCancelToken.Token); } } /// /// 进门移动 /// public void EntryDoorMove(ZTPoint doorScreenPosition, ParametersPoint screenLocation, Direction doorDirect) { //先到进门点 ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.Position, screenLocation); ZTPoint nextGatePoint = this.house.GetNextGatePoint(doorDirect); List paths = this.house.FindPath(roleMapPoint, DnfRole.HalfToFootPosition(nextGatePoint)); //再到门后50像素 ZTPoint dp = this.house.ScreenToMapCoordinate(doorScreenPosition, screenLocation); ZTPoint doorPoint = DnfRole.HalfToFootPosition(dp); switch (doorDirect) { case Direction.Up: doorPoint = doorPoint.Add(0, -50); break; case Direction.Right: doorPoint = doorPoint.Add(50, 0); break; case Direction.Bottom: doorPoint = doorPoint.Add(0, 50); break; case Direction.Left: doorPoint = doorPoint.Add(-50, 0); break; } paths.Add(doorPoint); this.movingIntent = MoveIntent.EntryDoor; isMoving = true; this.MovePaths(roleMapPoint, paths, this.moveCancelToken.Token,"entry move"); } private bool toNextGate = true; private Int32 nextGate = 0; /// /// 移至巡逻点 /// public void LoopMove(ParametersPoint screenLocation) { ZTPoint start = ZTPoint.Empty, end = ZTPoint.Empty; ZTPoint halfMapPosition= this.house.ScreenToMapCoordinate(this.HalfPosition, screenLocation); ZTPoint footMapPosition= this.house.ScreenToMapCoordinate(this.Position, screenLocation); if (toNextGate) { //判断当前是否进门点 ZTPoint nextGatePoint=this.house.HousePathInfo.NextGates[nextGate].Point; ZTRectangle nextGateRect = new ZTRectangle(nextGatePoint.X - 20, nextGatePoint.Y - 20, nextGatePoint.X + 20, nextGatePoint.Y + 20); if (GeoHelper.IsInRect(halfMapPosition, nextGateRect)) { nextGate++; nextGate = nextGate % this.house.HousePathInfo.NextGates.Count; toNextGate = false; } } else { //判断当前是否在巡逻点 ZTPoint loopPoint = this.house.HousePathInfo.LoopPoint; ZTRectangle loopRect = new ZTRectangle(loopPoint.X - 20, loopPoint.Y - 20, loopPoint.X + 20, loopPoint.Y + 20); if (GeoHelper.IsInRect(footMapPosition, loopRect)) { toNextGate = true; } } if (toNextGate) { //向进门点移动 start = halfMapPosition; end=this.house.HousePathInfo.NextGates[nextGate].Point; G.Instance.InfoWriter($"nextgate->screen location:{screenLocation},start:{start},end:{end}"); } else { //向巡逻点移动 start = footMapPosition; end= this.house.HousePathInfo.LoopPoint; G.Instance.InfoWriter($"loop:screen location:{screenLocation},start:{start},end:{end}"); } List paths = this.house.FindPath(start,end); this.movingIntent = MoveIntent.ToLoop; isMoving = true; ThreadPool.QueueUserWorkItem((obj) => { this.MovePaths(start, paths, this.moveCancelToken.Token, "loop move"); }, null); } /// /// 拾起物品移动 /// public void PickupMove(ZTPoint screenThingPosition,ParametersPoint screenLocation) { //屏幕坐标转地图坐标 ZTPoint start = this.house.ScreenToMapCoordinate(this.Position, screenLocation); ZTPoint end = this.house.ScreenToMapCoordinate(screenThingPosition, screenLocation); List paths = this.house.FindPath(start, end); this.movingIntent = MoveIntent.PickupMove; isMoving = true; //未被打断移动至色块后,拾取 if (this.MovePaths(start, paths, this.moveCancelToken.Token,"pickup")) { G.Instance.InputControl.PressKey(RandomUtils.G(400, 500), HIDCode.X); } } /// /// 同步移动指定距离 /// /// public void SyncMove(ZTPoint size) { ZTSize distance = new ZTSize(size.X, size.Y); isMoving = true; SyncMoveKeyPress(distance); StopMove("sync move"); } /// /// 移动指定路径 /// /// /// /// true:完成移动,false:中间被打断 private bool MovePaths(ZTPoint start, List paths, CancellationToken cancelToken,string from) { ZTPoint lastPoint = start; if (paths != null && paths.Count > 0) { for (int i = 0; i < paths.Count; i++) { if (cancelToken.IsCancellationRequested) { break; } ZTPoint distance = paths[i].Sub(lastPoint); this.SyncMoveKeyPress(new ZTSize(distance.X, distance.Y)); lastPoint = paths[i]; } } if (!cancelToken.IsCancellationRequested) { //停止 StopMove("move path,"+from); return true; } return false; } /// /// 同步移动指定距离的按键 /// /// private void SyncMoveKeyPress(ZTSize distance) { HIDCode horizontal = HIDCode.NoEvent; HIDCode vertical = HIDCode.NoEvent; bool isRun = false; int runms, stepms; Int32 xsig = Math.Sign(distance.Width); Int32 ysig = Math.Sign(distance.Height); if (Math.Abs(distance.Width) >= speed.RunThresold) { isRun = true; } if (distance.Height > 0) { vertical = HIDCode.DownArrow; } if (distance.Height < 0) { vertical = HIDCode.UpArrow; } if (distance.Width > 0) { horizontal = HIDCode.RightArrow; } if (distance.Width < 0) { horizontal = HIDCode.LeftArrow; } PutDirectionKey(out stepms, out runms, horizontal, vertical, isRun); if (stepms > 0) { Int32 mdistance = (Int32)(stepms * speed.StepX); if (runms > 0) { mdistance += (Int32)(runms * speed.RunX); } distance = new ZTSize(distance.Width - xsig * mdistance, distance.Height); } int ytime = (Int32)(Math.Abs(distance.Height) / speed.StepY); Int32 xtime = (Int32)(Math.Abs(distance.Width) / speed.StepX); if (isRun) { xtime = (Int32)(Math.Abs(distance.Width) / speed.RunX); } Int32 mintime = Math.Min(xtime, ytime); if (xtime <= 0) { mintime = ytime; } if (ytime <= 0) { mintime = xtime; } Thread.Sleep(mintime); xtime -= mintime; ytime -= mintime; if (xtime > 0) { PutDirectionKey(out stepms, out runms, horizontal, HIDCode.NoEvent, isRun); Thread.Sleep(xtime); } if (ytime > 0) { PutDirectionKey(out stepms, out runms, HIDCode.NoEvent, vertical, false); Thread.Sleep(ytime); } } /// /// 停止移动 /// public void StopMove(string from) { if (IsMoving) { G.Instance.InfoWriter("stop move from:"+from); this.moveCancelToken.Cancel(); this.moveCancelToken = new CancellationTokenSource(); StateProvider.Instance.DirectionKey = "无"; G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false); pressKeys[0] = HIDCode.NoEvent; pressKeys[1] = HIDCode.NoEvent; isMoving = false; isRun = false; } } /// /// 休眠 /// /// public void Sleep(Int32 millSecond) { Thread.Sleep(millSecond); } /// /// 释放技能 /// /// public void ReleaseSkill(HIDCode key) { Int32 dur = RandomUtils.KeyPressDuration; G.Instance.InputControl.PressKey(dur, key); SkillInfo skill = SkillInfo.GetSkillInfo(key); if (skill != null) { Int32 subTime = (Int32)(skill.ReleaseWaitTime - dur); if (subTime > 0) { Sleep(subTime); } } } #region 八方向移动 /// /// 按下按键 /// /// private void PutDirectionKey(ZTSize distance) { HIDCode horizontal = HIDCode.NoEvent; HIDCode vertical = HIDCode.NoEvent; bool isRun = false; if (distance.Width < 0) { horizontal = HIDCode.LeftArrow; } if (distance.Width > 0) { horizontal = HIDCode.RightArrow; } if (Math.Abs(distance.Width) >= speed.RunThresold) { isRun = true; } if (distance.Height < 0) { vertical = HIDCode.UpArrow; } if (distance.Height > 0) { vertical = HIDCode.DownArrow; } Int32 stepms, runms; PutDirectionKey(out stepms, out runms, horizontal, vertical, isRun); } /// /// 行走按键 /// /// 已经步行ms /// 已经奔跑ms /// 横向按键 /// 纵向按键 /// 是否奔跑 private void PutDirectionKey(out Int32 stepMS, out Int32 runMS, HIDCode horizontal, HIDCode vertical, bool isRun) { stepMS = 0; runMS = 0; if (horizontal == vertical) { return; } if (horizontal == pressKeys[0] && vertical == pressKeys[1]) { return; } int keyCount = horizontal != HIDCode.NoEvent && vertical != HIDCode.NoEvent ? 2 : 1; Int32 tempwait = 0; if (isRun) { //跑 if (!this.isRun || horizontal != pressKeys[0]) { //如果之前没有跑,或跑的方向不一样,则开始跑 G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); tempwait = RandomUtils.KeyPressDuration; stepMS += tempwait; Thread.Sleep(tempwait); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false); Thread.Sleep(RandomUtils.KeyPressDuration); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); this.isRun = true; if (keyCount == 2) { tempwait = RandomUtils.KeyPressDuration; runMS += tempwait; Thread.Sleep(tempwait); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); //StateProvider.Instance.DirectionKey = "跑," + horizontal.ToString() + "," + vertical.ToString(); } //else //{ // StateProvider.Instance.DirectionKey = "跑," + horizontal.ToString(); //} } else { //奔跑方向不变 int afterKeyCount = pressKeys[0] != HIDCode.NoEvent && pressKeys[1] != HIDCode.NoEvent ? 2 : 1; if (afterKeyCount != keyCount) { //如果跟原来按键数量不一样 if (keyCount == 1) { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); //StateProvider.Instance.DirectionKey = "走," + horizontal.ToString(); } else { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); //StateProvider.Instance.DirectionKey = "走," + horizontal.ToString() + "," + vertical.ToString(); } } } } else { //走 if (keyCount == 1) { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal != HIDCode.NoEvent ? horizontal : vertical); } else { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); } } pressKeys[0] = horizontal; pressKeys[1] = vertical; } /// /// 按钮是否变化 /// /// /// private bool IsChangeOfKey(HIDCode[] pressKey) { if (pressKey == null || pressKey.Length != 2) { return true; } if (pressKeys[0] == pressKey[0] && pressKeys[1] == pressKey[1]) { return false; } return true; } #endregion #region role position convert /// /// 色块中央位置转为脚部位置 /// /// /// public static ZTPoint CBToFootPosition(ZTPoint cbPosition) { return cbPosition.Add(RoleFootOffset); } /// /// 色块中央位置转为人物中间位置 /// /// /// public static ZTPoint CBToHalfPosition(ZTPoint cbPosition) { return cbPosition.Add(RoleHalfOffset); } /// /// 脚部坐标到身份中央坐标转换 /// /// /// public static ZTPoint FootToHalfPosition(ZTPoint footPosition) { return footPosition.Sub(RoleFootOffset).Add(RoleHalfOffset); } /// /// 身体中央坐标到脚部坐标转换 /// /// /// public static ZTPoint HalfToFootPosition(ZTPoint halfPosition) { return halfPosition.Sub(RoleHalfOffset).Add(RoleFootOffset); } #endregion } }