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
|
{
|
/// <summary>
|
/// DNF角色
|
/// </summary>
|
public class DnfRole
|
{
|
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;
|
public MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图
|
private CancellationTokenSource moveCancelToken;//移动取消令牌
|
|
private Int32 findRoleDir = 0;//寻找角色行走的方向
|
private DateTime findRoleMoveTimeout = DateTime.MinValue;//方向移动过期时间
|
|
|
/// <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);
|
}
|
}
|
|
/// <summary>
|
/// 按下的键,0:横向,1:纵向
|
/// </summary>
|
private HIDCode[] pressKeys = new HIDCode[] { HIDCode.NoEvent, HIDCode.NoEvent };//当前按键
|
private bool isRun = false;//是否奔跑
|
|
/// <summary>
|
/// 设置当前房间信息
|
/// </summary>
|
/// <param name="house"></param>
|
public void SetHouse(HouseInfo house)
|
{
|
this.house = house;
|
toNextGate = true;
|
}
|
|
/// <summary>
|
/// 设置当前角色速度
|
/// </summary>
|
/// <param name="speed"></param>
|
public void SetSpeed(Int32 speed)
|
{
|
this.speed = new SpeedProvider(speed);
|
}
|
|
/// <summary>
|
/// 更新位置
|
/// </summary>
|
/// <param name="roleCBPosition"></param>
|
public void UpdatePosition(ZTPoint roleCBPosition)
|
{
|
this.RoleCBPosition = roleCBPosition;
|
}
|
|
private bool isMoving = false;
|
/// <summary>
|
/// 是否移动中
|
/// </summary>
|
public bool IsMoving
|
{
|
get
|
{
|
return isMoving;
|
//return pressKeys[0] != HIDCode.NoEvent || pressKeys[1] != HIDCode.NoEvent;
|
}
|
}
|
|
/// <summary>
|
/// 是否指定移动行为
|
/// </summary>
|
/// <param name="intent"></param>
|
/// <returns></returns>
|
public bool IsMoveIntent(MoveIntent intent)
|
{
|
if (IsMoving && movingIntent == intent)
|
{
|
return true;
|
}
|
return false;
|
}
|
|
/// <summary>
|
/// 攻击移动至
|
/// </summary>
|
/// <param name="skillReleasePoint"></param>
|
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<ZTPoint> 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);
|
}
|
|
/// <summary>
|
/// 查找主角移动
|
/// </summary>
|
/// <param name="moveDistance"></param>
|
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);
|
|
}
|
|
|
}
|
|
/// <summary>
|
/// 进门移动
|
/// </summary>
|
public void EntryDoorMove(ZTPoint doorScreenPosition, ParametersPoint screenLocation, Direction doorDirect)
|
{
|
//先到进门点
|
ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.Position, screenLocation);
|
ZTPoint nextGatePoint = this.house.GetNextGatePoint(doorDirect);
|
List<ZTPoint> 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;
|
/// <summary>
|
/// 移至巡逻点
|
/// </summary>
|
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<ZTPoint> 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);
|
}
|
|
/// <summary>
|
/// 拾起物品移动
|
/// </summary>
|
public void PickupMove(ZTPoint screenThingPosition,ParametersPoint screenLocation)
|
{
|
//屏幕坐标转地图坐标
|
ZTPoint start = this.house.ScreenToMapCoordinate(this.Position, screenLocation);
|
ZTPoint end = this.house.ScreenToMapCoordinate(screenThingPosition, screenLocation);
|
List<ZTPoint> 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);
|
}
|
}
|
|
/// <summary>
|
/// 同步移动指定距离
|
/// </summary>
|
/// <param name="distance"></param>
|
public void SyncMove(ZTPoint size)
|
{
|
ZTSize distance = new ZTSize(size.X, size.Y);
|
isMoving = true;
|
SyncMoveKeyPress(distance);
|
StopMove("sync move");
|
}
|
|
/// <summary>
|
/// 移动指定路径
|
/// </summary>
|
/// <param name="start"></param>
|
/// <param name="paths"></param>
|
/// <returns>true:完成移动,false:中间被打断</returns>
|
private bool MovePaths(ZTPoint start, List<ZTPoint> 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;
|
}
|
|
/// <summary>
|
/// 同步移动指定距离的按键
|
/// </summary>
|
/// <param name="distance"></param>
|
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);
|
}
|
}
|
|
|
/// <summary>
|
/// 停止移动
|
/// </summary>
|
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;
|
}
|
}
|
|
/// <summary>
|
/// 休眠
|
/// </summary>
|
/// <param name="millSecond"></param>
|
public void Sleep(Int32 millSecond)
|
{
|
Thread.Sleep(millSecond);
|
}
|
|
/// <summary>
|
/// 释放技能
|
/// </summary>
|
/// <param name="key"></param>
|
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 八方向移动
|
/// <summary>
|
/// 按下按键
|
/// </summary>
|
/// <param name="distance"></param>
|
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);
|
}
|
|
/// <summary>
|
/// 行走按键
|
/// </summary>
|
/// <param name="stepMS">已经步行ms</param>
|
/// <param name="runMS">已经奔跑ms</param>
|
/// <param name="horizontal">横向按键</param>
|
/// <param name="vertical">纵向按键</param>
|
/// <param name="isRun">是否奔跑</param>
|
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;
|
}
|
|
/// <summary>
|
/// 按钮是否变化
|
/// </summary>
|
/// <param name="pressKey"></param>
|
/// <returns></returns>
|
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
|
/// <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
|
|
|
}
|
}
|