using RichCreator.Utility;
using RichCreator.Utility.Captures;
using RichCreator.Utility.CV;
using RichCreator.Utility.InputControl;
using RichCreator.Utility.Structs;
using RichCreator.Utility.Utilitys;
using Emgu.CV;
using Emgu.CV.Structure;
using RichCreator.Jobs;
using RichCreator.Jobs.StateMachines;
using System;
using System.Collections.Generic;
using System.Threading;
using RichCreator.Utility.Maps;
using RichCreator.Utility.Skills;
using RichCreator.Dnf;
namespace RichCreator.Maps.Lindong
{
///
/// 凛冬地图
///
public class LindongMap : MapInfo
{
public LindongMap(ZTRectangle gameRect, CancellationToken cancelToken) :base(MapType.Lingdong,gameRect,cancelToken)
{
this.MiniMap = new LindongMiniMap(gameRect);
this.Role = new DnfRole(gameRect);
}
///
/// 角色
///
public DnfRole Role { get; set; }
///
/// 地图的所有房间
/// NextIndex=-1,完成
/// NextIndex=-2,出错
///
private static readonly HouseInfo[] Houses = new HouseInfo[] {
new HouseInfo (0 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Right } },
new HouseInfo (1 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Bottom } },
new HouseInfo (2 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (3 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (4 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Bottom } },
new HouseInfo (5 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (6 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (7 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (8 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-148,DoorDirection=new[]{Direction.Right,Direction.Bottom } },
new HouseInfo (9 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-300,DoorDirection=new[]{Direction.Right,Direction.Bottom } },
new HouseInfo (10,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Bottom } },
new HouseInfo (11,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Left } },
new HouseInfo (12,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-220,DoorDirection=new[]{Direction.Right } },
new HouseInfo (13,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-320,DoorDirection=new[]{Direction.Right } },
new HouseInfo (14,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-320,DoorDirection=new[]{Direction.Right } },
new HouseInfo (15,MapType.Lingdong,true ,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Right } },
new HouseInfo (16,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Up } },
new HouseInfo (17,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Up } },
new HouseInfo (18,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Up } },
new HouseInfo (19,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X}){HouseCenterMoveLine=-250,DoorDirection=new[]{Direction.Up } }
};
private Int32 runningStep = RunningStep.None;
///
/// 开始
///
///
///
///
///
public override ZTResult Start(Int32 runningStep)
{
this.runningStep = runningStep;
WindowUtils.SetDnfToTop();
if (runningStep < RunningStep.War)
{
if (!MoveToSunan())
{
return ZTResult.Failed;
}
if (!MoveToShikongzhimen())
{
return ZTResult.Failed;
}
if (!MoveToChoiceTaskPage())
{
return ZTResult.Failed;
}
if (!IntoTaskRoom())
{
return ZTResult.Failed;
}
G.Instance.InfoWriter("成功进入副本");
}
while (true)
{
//重复刷,直到疲劳值不够了
if (this.CancelToken.IsCancellationRequested)
{
return ZTResult.Cancel;
}
DateTime startHouse = DateTime.Now;
ZTResult killResult = KillMonster();
if (killResult==ZTResult.Success)
{
//捡东西
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.V);
Thread.Sleep(1000);
for (int i = 0; i < 5; i++)
{
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.X);
Thread.Sleep(RandomUtils.KeyPressDuration * 3);
}
//卖装备并关闭商店
SaleEquipment();
Int32 houseTotalSecond = (Int32)(DateTime.Now - startHouse).TotalSeconds;
G.Instance.InfoWriter("单次刷图成功,用时:"+(houseTotalSecond/60)+"分"+(houseTotalSecond%60)+"秒");
//查询疲劳值
Int32 pilaozhi =DnfCVHelper.GetPiLaoZhi(this.GameRect);
G.Instance.InfoWriter("疲劳值:" + pilaozhi);
if (pilaozhi <= 0)
{
ExitToTown();
return ZTResult.Success;
}
ReplayGame();
continue;
}
else
{
return killResult;
}
}
}
///
/// 是否进入打怪地图
///
///
public override bool IsEntryMap()
{
//查找顶端凛冬文字
bool findResult = FuncUtils.TimeoutCancelableWrap(2 * 60 * 1000, CancelToken, () => {
using (Image image = ScreenCapture.Instance.CaptureScreenReturnImage())
{
return LindongCVHelper.ExistLingdongText(image, this.GameRect);
}
}, 10);
//if (!findResult)
//{
// G.Instance.InfoWriter("未找到进入凛冬的文字");
//}
//else
//{
// G.Instance.InfoWriter("进入凛冬");
//}
return findResult;
}
///
/// esc退到城镇
///
private void ExitToTown()
{
G.Instance.DebugWriter("返回城镇");
Utility.Structs.ZTPoint point = new Utility.Structs.ZTPoint(this.GameRect.End.X - 124, this.GameRect.Start.Y + 146);
G.Instance.InputControl.MoveToAndClick(point);
Thread.Sleep(5000);
}
///
/// 点击再次挑战
///
private void ReplayGame()
{
G.Instance.DebugWriter("重新挑战");
Utility.Structs.ZTPoint point = new Utility.Structs.ZTPoint(this.GameRect.End.X - 132, this.GameRect.Start.Y + 90);
G.Instance.InputControl.MoveToAndClick(point);
}
///
/// 刷房间
///
///
private ZTResult KillMonster()
{
bool ret = false;
if (!IsEntryMap())
{
G.Instance.InfoWriter("未找到进入凛冬");
return ZTResult.Failed;
}
G.Instance.InfoWriter("进入凛冬");
Int32 preHouseIndex = -1;
Int32 houseIndex = -1;
//技能加成
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Space);
//循环刷房间
while (true)
{
preHouseIndex = houseIndex;
//看房间号
ret = this.MiniMap.GetCurrentHouseIndexWaitTimeout(out houseIndex, null, this.CancelToken, 3 * 1000);
if (!ret)
{
G.Instance.InfoWriter("未找到人物所在房间");
return ZTResult.Failed;
}
G.Instance.InfoWriter("进入房间->" + houseIndex.ToString());
HouseInfo houseInfo = Houses[houseIndex];
this.Role.SetHouse(houseInfo);
DateTime startTime = DateTime.Now;
KillMonsterStateMachine kmsm = new KillMonsterStateMachine(this, houseInfo,this.Role, preHouseIndex,this.runningStep);
ZTResult smresult = kmsm.Work( 5 * 60 * 1000);
Int32 roomTotalSecond = (Int32)(DateTime.Now - startTime).TotalSeconds;
G.Instance.InfoWriter("房间刷完,用时:" + (roomTotalSecond / 60) + "分" + (roomTotalSecond % 60) + "秒");
runningStep = RunningStep.None;
if (smresult == ZTResult.Success)
{
if (houseInfo.IsEnd)
{
//所有房间刷完
return ZTResult.Success;
}
//刷其它房间
continue;
}
else
{
return smresult;
}
}
}
///
/// 步行到素喃
///
///
private bool MoveToSunan()
{
bool result = FuncUtils.NoChangeRetryCallWrap(
() =>
{
WindowUtils.SetDnfToTop();
CloseAllAlertWindow(this.CancelToken, this.GameRect);
//向下走出赛丽亚的房间 ,走向素喃
G.Instance.InputControl.PressKey(2000, HIDCode.DownArrow);
},
() =>
{
G.Instance.InfoWriter("检测是否进入素喃");
result = FuncUtils.TimeoutCancelableWrap(10000, this.CancelToken, () => {
return LindongCVHelper.IsInSunan(this.GameRect);
});
if (!result)
{
G.Instance.InfoWriter("进入素喃失败");
return false;
}
G.Instance.InfoWriter("进入素喃成功");
return true;
},
() =>
{
return DnfCVHelper.IsInSaiLiYaHouse(this.GameRect);
});
return result;
}
///
/// 步行至时空之门
///
///
private bool MoveToShikongzhimen()
{
bool result= FuncUtils.NoChangeRetryCallWrap(() =>
{
//打开地图
Utility.Structs.ZTPoint mapButtonPosition = new Utility.Structs.ZTPoint(this.GameRect.End.X - 14, this.GameRect.Start.Y + 16);
G.Instance.InputControl.MoveToAndClick(mapButtonPosition);
Thread.Sleep(1000);
//点到副本之前的地图
Utility.Structs.ZTPoint mapPrePosition = new Utility.Structs.ZTPoint(this.GameRect.Start.X + 382, this.GameRect.Start.Y + 252);
G.Instance.InputControl.MoveToAndClick(mapPrePosition);
//关闭地图框
CloseAllAlertWindow(this.CancelToken, this.GameRect);
},
() =>
{
//检测是否进入时空之门
return FuncUtils.TimeoutCancelableWrap(15000, this.CancelToken, () =>
{
CloseAllAlertWindow(this.CancelToken, this.GameRect);
return LindongCVHelper.IsInShikongzhimen(this.GameRect);
});
},
() =>
{
//检测是否还在素喃
return FuncUtils.TimeoutCancelableWrap(3000, this.CancelToken, () => {
CloseAllAlertWindow(this.CancelToken, this.GameRect);
return LindongCVHelper.IsInSunan(this.GameRect);
});
});
Thread.Sleep(5000);
return result;
}
///
/// 步行到任务选择和正式开打页面
///
///
private bool MoveToChoiceTaskPage()
{
bool result = false;
//右走进选择副本界面
G.Instance.InputControl.PressKey(1500, HIDCode.LeftArrow);
G.Instance.InfoWriter("检测是否打开选择副本界面");
result = FuncUtils.TimeoutCancelableWrap(10000, this.CancelToken, () => {
Image image = ScreenCapture.Instance.CaptureScreenReturnImage();
return LindongCVHelper.IsInChoiceTaskPage(image, this.GameRect);
});
if (!result)
{
G.Instance.InfoWriter("进入打开选择副本界面失败");
return false;
}
G.Instance.InfoWriter("打开选择副本界面成功");
return true;
}
///
/// 进入指定房间
///
///
private bool IntoTaskRoom()
{
bool result = false;
//选择凛冬
G.Instance.InfoWriter("开始选择凛冬");
Int32 nandu = 0;
if (!SelectLindong(out nandu))
{
G.Instance.InfoWriter("选择凛冬失败");
return false;
}
G.Instance.InfoWriter("选择凛冬成功,难度:"+nandu);
if (nandu != 4)
{
G.Instance.InfoWriter("开始选择难度");
result=SelectNandu(nandu);
if (!result)
{
G.Instance.InfoWriter("选择难度失败");
return false;
}
G.Instance.InfoWriter("选择难度成功");
}
//开始
G.Instance.InputControl.PressKey(80, HIDCode.Space);
return true;
}
///
/// 关闭所有弹出窗
///
///
///
///
private void CloseAllAlertWindow(CancellationToken cancelToken, ZTRectangle gameRect)
{
while (!cancelToken.IsCancellationRequested)
{
//G.Instance.InputControl.MoveTo(gameRect.Start.X,gameRect.Start.Y, false, false, false);
//Thread.Sleep(10);
//截图
Image image = ScreenCapture.Instance.CaptureScreenReturnImage();
ZTRectangle closeButtonRect = ZTRectangle.Empty;
if (!DnfCVHelper.GetAlertWindow(out closeButtonRect, image, gameRect))
{
return;
}
G.Instance.InputControl.MoveToAndClick(closeButtonRect.GetCenterPoint());
Thread.Sleep(500);
}
}
///
/// 选择凛冬
///
///
private bool SelectLindong(out Int32 nandu)
{
Image image = ScreenCapture.Instance.CaptureScreenReturnImage();
if (LindongCVHelper.GetChoiceLingdongNandu(out nandu, image, this.GameRect))
{
return true;
}
G.Instance.InputControl.MoveToAndClick(new Utility.Structs.ZTPoint(this.GameRect.Start.X + 508, this.GameRect.Start.Y + 552));
Thread.Sleep(5000);
image = ScreenCapture.Instance.CaptureScreenReturnImage();
if (LindongCVHelper.GetChoiceLingdongNandu(out nandu, image, this.GameRect))
{
return true;
}
return false;
}
///
/// 选择难度
///
///
///
///
private bool SelectNandu(Int32 nandu)
{
Int32 count = 4 - nandu;
for (int i = 0; i < Math.Abs(count); i++)
{
if (count < 0)
{
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.LeftArrow);
}
else
{
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
}
Thread.Sleep(400);
}
Image image = ScreenCapture.Instance.CaptureScreenReturnImage();
if (!LindongCVHelper.GetChoiceLingdongNandu(out nandu, image, this.GameRect))
{
return false;
}
if (nandu == 4)
{
return true;
}
return false;
}
///
/// 出售装备
///
///
private bool SaleEquipment()
{
//卖装备并关闭商店
ZTRectangle closeButtonRect = ZTRectangle.Empty;
ZTRectangle saleButtonRect = ZTRectangle.Empty;
if (!DnfCVHelper.HasSaleButton(out saleButtonRect, out closeButtonRect, this.GameRect))
{
return false;
}
//卖装备
G.Instance.InfoWriter("出售装备");
G.Instance.InputControl.MoveToAndClick(saleButtonRect.GetCenterPoint());
//得到装备文字位置
ZTRectangle equipmentTextRect = ZTRectangle.Empty;
bool result = FuncUtils.TimeoutCancelableWrap(5000, this.CancelToken, () => {
Int32 status = 0;
if (DnfCVHelper.GetEquipmentSelectStatus(out equipmentTextRect, out status, this.GameRect))
{
if (status == 1)
{
return true;
}
G.Instance.InputControl.MoveToAndClick(equipmentTextRect.GetCenterPoint());
}
return false;
});
if (!result)
{
G.Instance.InfoWriter("装备文字未取到");
return false;
}
//开始点,每格步进30
ZTPoint startPoint = new Utility.Structs.ZTPoint( equipmentTextRect.End.X-30, equipmentTextRect.End.Y+9);
List points = DnfCVHelper.GetEquipmentIndexs(startPoint);
for (int i = 0; i < points.Count; i++)
{
Int32 index = points[i];
int row = index / 8;
int col = index % 8;
int x = col * 30+15;
int y = row * 30+15;
//点窗格
G.Instance.InputControl.MoveToAndClick(new Utility.Structs.ZTPoint(startPoint.X + x, startPoint.Y + y));
Thread.Sleep(500);
//点确定
G.Instance.InputControl.Move(0, 0, true, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration);
G.Instance.InputControl.Move(0, 0, false, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration);
}
G.Instance.DebugWriter("equipment:" +ZTImage.Utils.ConcatString(points.ToArray(),","));
Thread.Sleep(RandomUtils.KeyPressDuration);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Escape);
return true;
}
public override void EntryHousePrework(int houseIndex, int preHouseIndex)
{
//移动和发招
switch (houseIndex)
{
case 2:
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.LeftArrow);
this.Role.SyncMove(new ZTPoint(-110, 0));
G.Instance.InputControl.PressKeys(HIDCode.LeftArrow, HIDCode.G);
break;
case 1:
this.Role.SyncMove(new ZTPoint(-480, 80));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.W);
break;
case 5:
//G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.R);
Thread.Sleep(1000);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.T);
break;
case 4:
this.Role.SyncMove(new ZTPoint(-1150, -50));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.E);
//Thread.Sleep(1000);
//G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.E);
break;
case 8:
this.Role.SyncMove(new ZTPoint(-100, 110));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.G);
//Thread.Sleep(300);
//G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Z);
break;
case 9:
this.Role.SyncMove(new ZTPoint(325, 65));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.R);
Thread.Sleep(1000);
this.Role.SyncMove(new ZTPoint(300, 0));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.T);
break;
case 10:
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Q);
break;
case 12:
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.R);
Thread.Sleep(1000);
this.Role.SyncMove(new ZTPoint(-110, 0));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.T);
break;
case 13:
if (preHouseIndex == 12)
{
this.Role.SyncMove(new ZTPoint(600, 150));
}
else
{
this.Role.SyncMove(new ZTPoint(-300, 200));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.RightArrow);
}
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Q);
Thread.Sleep(1000);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.E);
break;
case 14:
if (preHouseIndex == 13)
{
this.Role.SyncMove(new ZTPoint(400, 0));
}
else
{
this.Role.SyncMove(new ZTPoint(0, 100));
}
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.W);
break;
case 15:
this.Role.SyncMove(new ZTPoint(600, 0));
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.H);
Thread.Sleep(5000);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Y);
break;
case 18:
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.W);
break;
}
}
}
}