using RichCreator.Utility;
using RichCreator.Utility.Dnf;
using RichCreator.Utility.InputControl;
using RichCreator.Utility.Maps;
using RichCreator.Utility.Structs;
using System;
using System.Threading;
namespace RichCreator.Dnf
{
///
/// DNF角色
///
public class DnfRole
{
private SpeedProvider speed;//速度
private const Int32 PaddingLeft = 140;//左边框内边距
private const Int32 PaddingRight = 140;//右边框内边距
public DnfRole(ZTRectangle gameRect)
{
this.gameRect = gameRect;
speed = SpeedProvider.Define;
}
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; }//角色位置
///
/// 按下的键,0:横向,1:纵向
///
private HIDCode[] pressKeys = new HIDCode[] { HIDCode.NoEvent, HIDCode.NoEvent };//当前按键
private bool isRun = false;//是否奔跑
///
/// 设置当前房间信息
///
///
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;
}
///
/// 设置当前角色速度
///
///
public void SetSpeed(Int32 speed)
{
this.speed = new SpeedProvider(speed);
}
///
/// 更新位置
///
///
public void UpdatePosition(ZTPoint position)
{
this.Position = position;
}
///
/// 是否移动中
///
public bool IsMoving
{
get
{
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(ZTSize moveDistance)
{
PutKey(moveDistance);
movingIntent = MoveIntent.AttackMove;
}
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 } };
///
/// 查找主角移动
///
///
public void FindRoleMove()
{
if (IsMoving && !IsMoveIntent(MoveIntent.FindRoleMove))
{
StopMove();
}
if (DateTime.Now >= findRoleMoveTimeout)
{
//转换方向
findRoleDir++;
HIDCode[] tempKeys = dir[findRoleDir % 4];
Int32 stepms = 0, runms = 0;
PutKey(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 PickupMove(ZTPoint rolePosition, ZTPoint thingItemPosition)
{
ZTSize moveDistance = new ZTSize(thingItemPosition.X - rolePosition.X, thingItemPosition.Y - rolePosition.Y - 97);
if (Math.Abs(moveDistance.Width) < 100 && Math.Abs(moveDistance.Height) < 100)
{
//距离允许,就近距离移动并X
G.Instance.DebugWriter("distance ok");
SyncMove(new ZTPoint(moveDistance.Width,moveDistance.Height));
G.Instance.InputControl.PressKey(RandomUtils.G(400, 500), HIDCode.X);
return;
}
//G.Instance.DebugWriter("pickup distance:" + moveDistance.ToString());
PutKey(moveDistance);
movingIntent = MoveIntent.PickupMove;
}
///
/// 找门移动
///
///
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;
}
///
/// 同步移动指定距离
///
///
public void SyncMove(ZTPoint size)
{
ZTSize distance = new ZTSize(size.X, size.Y);
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;
}
PutKey(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)
{
PutKey(out stepms, out runms, horizontal, HIDCode.NoEvent, isRun);
Thread.Sleep(xtime);
}
if (ytime > 0)
{
PutKey(out stepms, out runms, HIDCode.NoEvent, vertical, false);
Thread.Sleep(ytime);
}
StopMove();
}
///
/// 停止移动
///
public void StopMove()
{
if (IsMoving)
{
//停止
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
pressKeys[0] = HIDCode.NoEvent;
pressKeys[1] = HIDCode.NoEvent;
isRun = false;
}
}
///
/// 休眠
///
///
public void Sleep(Int32 millSecond)
{
Thread.Sleep(millSecond);
}
///
/// 释放技能
///
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)
{
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;//最大未移动容忍毫秒数
///
/// 得到循环移动的距离
///
///
private void ComputeMoveInfo(ZTPoint rolePosition)
{
ZTRectangle limitRect = ZTRectangle.Empty;
//达到未移动阀值,可能有障碍物,先攻击,如果攻击后还是无效则上下左右移
if (rolePosition.Equals(this.roleLastPosition))
{
if (StaticTimerIsStart)
{
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;
}
}
}
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);
}
}
#region 八方向移动
///
/// 按下按键
///
///
private void PutKey(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;
PutKey(out stepms, out runms, horizontal, vertical, isRun);
}
///
/// 行走按键
///
/// 已经步行ms
/// 已经奔跑ms
/// 横向按键
/// 纵向按键
/// 是否奔跑
private void PutKey(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);
}
}
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);
}
else
{
G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical);
}
}
}
}
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 KeyIsChange(HIDCode[] pressKey)
{
if (pressKey == null || pressKey.Length != 2)
{
return true;
}
if (pressKeys[0] == pressKey[0] && pressKeys[1] == pressKey[1])
{
return false;
}
return true;
}
#endregion
}
}