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;
namespace RichCreator.Maps
{
///
/// 凛冬地图
///
public class SkillMap : MapInfo
{
///
/// 游戏区域
///
public ZTRectangle GameRect { get; set; }
public CancellationToken cancellationToken { get; set; }
///
/// 标题文字
///
private ZTRectangle titleRect = ZTRectangle.Empty;
///
/// lv字样
///
private ZTRectangle lvRect = ZTRectangle.Empty;
///
/// 向上滚动按钮
///
private ZTRectangle upKeyRect = ZTRectangle.Empty;
///
/// 向下滚动按钮
///
private ZTRectangle downKeyRect = ZTRectangle.Empty;
public override ZTResult Start(ZTRectangle gameRect, CancellationToken cancelToken, Int32 runningStep)
{
this.GameRect = gameRect;
this.cancellationToken = cancelToken;
WindowUtils.SetDnfToTop();
if (!OpenSkillWindow())
{
G.Instance.InfoWriter("打开技能窗口失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("技能窗口已打开");
//初始化
if (!InitSkills())
{
G.Instance.InfoWriter("初始化技能失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("技能已初始化");
//点顶端的技能
if (!SettingTopSkills())
{
G.Instance.InfoWriter("通用技能设置失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("通用技能已设置");
//点sp技能
if (!SettingSPSkills())
{
G.Instance.InfoWriter("SP技能设置失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("SP技能已设置");
//点tp技能
if (!SettingTPSkills())
{
G.Instance.InfoWriter("TP技能设置失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("TP技能已设置");
//点学习
if (!Studay())
{
G.Instance.InfoWriter("技能学习失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("技能已学习");
//技能摆放
if (!FormatSkillColumn())
{
G.Instance.InfoWriter("技能摆放失败");
return ZTResult.Failed;
}
G.Instance.InfoWriter("技能摆放成功");
CloseAllAlertWindow(this.cancellationToken, this.GameRect);
return ZTResult.Success;
}
///
/// 打开技能窗
///
///
///
///
///
///
private bool OpenSkillWindow()
{
bool isGray = false;
ZTRectangle innertitleRect=ZTRectangle.Empty, innerlvRect = ZTRectangle.Empty, innerupKeyRect = ZTRectangle.Empty, innerdownKeyRect = ZTRectangle.Empty;
for (int i = 0; i < 2; i++)
{
CloseAllAlertWindow(this.cancellationToken, this.GameRect);
G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration,HIDCode.K);
bool result=FuncUtils.TimeoutCancelableWrap(5000, this.cancellationToken, () => {
//识别技能窗
return SkillCVHelper.FindSkillWindow(out innertitleRect, out innerlvRect, out innerupKeyRect, out innerdownKeyRect,out isGray, this.GameRect);
});
if (result)
{
titleRect = innertitleRect;
lvRect = innerlvRect;
upKeyRect = innerupKeyRect;
downKeyRect = innerdownKeyRect;
if (isGray)
{
//如果当前选的是tp技能学习(tp技能学习的右侧滚动条跟sp右侧的不一样),则:
//选中sp技能学习
Utility.Structs.ZTPoint spPoint = new Utility.Structs.ZTPoint(lvRect.End.X + 55, lvRect.Start.Y - 80);
G.Instance.InputControl.MoveToAndClick(spPoint);
result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
//识别技能窗
return SkillCVHelper.FindCommonUpDownKey(out innerupKeyRect, out innerdownKeyRect, this.titleRect,this.GameRect);
},300);
if (!result)
{
continue;
}
upKeyRect = innerupKeyRect;
downKeyRect = innerdownKeyRect;
}
return true;
}
}
G.Instance.InfoWriter("打开技能对话框失败");
return false;
}
private bool InitSkills()
{
//点击初始化
Utility.Structs.ZTPoint initButton = new Utility.Structs.ZTPoint(this.upKeyRect.Start.X - 37, this.upKeyRect.Start.Y - 86);
G.Instance.InputControl.MoveToAndClick(initButton);
//是否已打开确认对话框
ZTRectangle notificationRect = ZTRectangle.Empty;
bool result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
return SkillCVHelper.ExistsNotificationText(out notificationRect,this.GameRect);
});
if (!result)
{
G.Instance.DebugWriter("公告未找到");
return false;
}
//点击确认
G.Instance.InputControl.Move(0, 0, true, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration);
G.Instance.InputControl.Move(0, 0, false, false, false);
Thread.Sleep(1000);
//是否已打开完毕对话框
result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
return SkillCVHelper.ExistsNotificationText(out notificationRect, this.GameRect);
});
if (!result)
{
G.Instance.DebugWriter("完毕公告未找到");
return false;
}
//点击确认
Utility.Structs.ZTPoint okPosition = new Utility.Structs.ZTPoint(notificationRect.GetCenterPoint().X, notificationRect.End.Y + 60);
G.Instance.InputControl.MoveToAndClick(okPosition);
Thread.Sleep(RandomUtils.G(500,800));
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 SettingTopSkills()
{
//物理暴击
Utility.Structs.ZTPoint skillPoint = new Utility.Structs.ZTPoint(lvRect.End.X + 200, lvRect.Start.Y - 42);
SettingSkill(skillPoint);
//物理背击
skillPoint = new Utility.Structs.ZTPoint(lvRect.End.X + 280, lvRect.Start.Y - 42);
SettingSkill(skillPoint);
return true;
}
///
/// 要点的技能列表
/// 内部为每个节所相对于节的相对位置
///
private List[] toAddLevelSkills = new List[] {
new List (){
new Utility.Structs.ZTPoint(762-346,450-237),//疾风之棍棒精通
},
new List (){
new Utility.Structs.ZTPoint(182,17),//朔风牵引
new Utility.Structs.ZTPoint(274,17),//流风决
new Utility.Structs.ZTPoint(481-251,342-262),//风鸣冲击
new Utility.Structs.ZTPoint(323,82),//游离之风
new Utility.Structs.ZTPoint(574-251,409-262),//双翼风刃
new Utility.Structs.ZTPoint(574-251,477-262),//风暴之眼
new Utility.Structs.ZTPoint(529-251,544-262),//真空旋风破
},
new List (){
new Utility.Structs.ZTPoint(432-251,275-329),//风暴之拳
new Utility.Structs.ZTPoint(479-251,342-329),//万象风龙阵
new Utility.Structs.ZTPoint(572-251,340-329),//御风之力
new Utility.Structs.ZTPoint(433-251,478-329),//风神决
new Utility.Structs.ZTPoint(526-251,475-329),//风卷残云
new Utility.Structs.ZTPoint(574-251,476-329),//游龙惊风破
new Utility.Structs.ZTPoint(431-251,542-329),//九霄风雷
new Utility.Structs.ZTPoint(663-295,545-331),//无限风域
}
};
///
/// 设置SP技能
///
///
private bool SettingSPSkills()
{
//选中sp技能学习
Utility.Structs.ZTPoint spPoint = new Utility.Structs.ZTPoint(lvRect.End.X + 55, lvRect.Start.Y - 80);
G.Instance.InputControl.MoveToAndClick(spPoint);
ZTRectangle numberLimitArea = new ZTRectangle(lvRect.Start.X-5,lvRect.End.Y,lvRect.End.X+21,lvRect.End.Y+340);
bool[] addedFlag = new bool[] {false,false,false };
bool isdown = true;
for (int i = 0; i < 4; i++)
{
for (int count = 0; count < 10; count++)
{
if (this.cancellationToken.IsCancellationRequested)
{
return false;
}
//是否有数字
bool result = FuncUtils.TimeoutCancelableWrap(1000, this.cancellationToken, () => {
return SkillCVHelper.HasNumberText(numberLimitArea);
}, 100);
if (!result)
{
continue;
}
//查找是否是某节,
Int32 numberSection = 0;
ZTRectangle sectionRect = ZTRectangle.Empty;
if (SkillCVHelper.IsNumberSections(out numberSection, out sectionRect, numberLimitArea))
{
if (!addedFlag[numberSection])
{
//没有添加,则循环把此节下的所有技能都加上
foreach (var item in toAddLevelSkills[numberSection])
{
SettingSkill(sectionRect.Start.Add(item));
}
addedFlag[numberSection] = true;
}
if (count == 0)
{
if (numberSection == 0)
{
//一开始是1区则向下
isdown = true;
}
if (numberSection == 2)
{
//一开始是3区则向上
isdown = false;
}
}
}
if (isdown)
{
G.Instance.InputControl.MoveToAndClick(downKeyRect.GetCenterPoint());
}
else
{
G.Instance.InputControl.MoveToAndClick(upKeyRect.GetCenterPoint());
}
}
if (addedFlag[0] == true && addedFlag[1] == true && addedFlag[2] == true)
{
return true;
}
isdown = !isdown;
}
return false;
}
///
/// 设置TP技能
///
///
private bool SettingTPSkills()
{
//选中tp技能学习
Utility.Structs.ZTPoint spPoint = new Utility.Structs.ZTPoint(lvRect.End.X + 253, lvRect.Start.Y - 80);
G.Instance.InputControl.MoveToAndClick(spPoint);
Utility.Structs.ZTPoint[] skills = new Utility.Structs.ZTPoint[] {
new Utility.Structs.ZTPoint(334-296,277-251),//1.第一行第一个
new Utility.Structs.ZTPoint(381-296,545-251),//2.第三行第二个
new Utility.Structs.ZTPoint(664-296,413-251),//3.第二行倒数第三个
new Utility.Structs.ZTPoint(567-296,410-251),//4.第二行倒数第五个
new Utility.Structs.ZTPoint(758-296,411-251),//5.第二行倒数第一个
};
for (int i = 0; i < skills.Length; i++)
{
SettingSkill(lvRect.Start.Add(skills[i]));
}
return true;
}
///
/// 学习
///
///
private bool Studay()
{
Utility.Structs.ZTPoint studayPoint = new Utility.Structs.ZTPoint(this.downKeyRect.Start.X-331,this.downKeyRect.End.Y+27);
G.Instance.InputControl.MoveToAndClick(studayPoint);
Thread.Sleep(1000);
//点击确认
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*3);
return true;
}
///
/// 设置技能
///
///
///
private bool SettingSkill(Utility.Structs.ZTPoint skillPoint)
{
//84,71
ZTRectangle limitRect = new ZTRectangle(skillPoint.X-84,skillPoint.Y-71,skillPoint.X+84,skillPoint.Y+71);
bool result = false;
ZTRectangle addSkillLevelButton = ZTRectangle.Empty;
//选中技能,试两次
int addTry = 0;
for (; addTry < 2; addTry++)
{
bool skillIsFull = false;
G.Instance.InputControl.MoveToAndClick(skillPoint);
Thread.Sleep(500);
result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
return SkillCVHelper.IsSelectSkill(out addSkillLevelButton, out skillIsFull, limitRect);
});
if (result)
{
if (skillIsFull)
{
return true;
}
break;
}
}
if (addTry >= 2)
{
return false;
}
//加技能点,试两次
for (addTry = 0; addTry < 2; addTry++)
{
G.Instance.InputControl.MoveToAndClick(addSkillLevelButton.GetCenterPoint());
result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
return SkillCVHelper.SkillIsFullLevel(limitRect);
});
if (result)
{
return true;
}
}
return false;
}
///
/// 格式化摆放技能栏
///
///
private bool FormatSkillColumn()
{
//打开已学技能窗
ZTRectangle studayTextRect = ZTRectangle.Empty;
if (!OpenStudaySkillWindow(out studayTextRect))
{
G.Instance.DebugWriter("未指开已学技能窗口");
return false;
}
//技能栏全部技能移动已学技能窗
if (!MoveSkillToStudayWindow(studayTextRect))
{
G.Instance.DebugWriter("移动至已学技能窗口失败");
return false;
}
//技能窗内容分步移
if (!MoveSkillToExpress(studayTextRect))
{
G.Instance.DebugWriter("移动至快捷栏失败");
return false;
}
return true;
}
///
/// 打开已学技能窗口
///
///
private bool OpenStudaySkillWindow(out ZTRectangle studayTextRect)
{
studayTextRect = ZTRectangle.Empty;
ZTRectangle innerstudyTextRect = ZTRectangle.Empty;
Utility.Structs.ZTPoint openwindowButton = new Utility.Structs.ZTPoint(this.titleRect.Start.X + 194, this.titleRect.Start.Y + 517);
for (int i = 0; i < 2; i++)
{
if (this.cancellationToken.IsCancellationRequested)
{
return false;
}
G.Instance.InputControl.MoveToAndClick(openwindowButton);
bool result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => {
return SkillCVHelper.StudaySkillWindowIsOpen(out innerstudyTextRect,this.GameRect);
}, 200);
if (result)
{
studayTextRect = innerstudyTextRect;
return true;
}
}
return false;
}
///
/// 从快捷栏向已学技能栏移动技能
///
///
private bool MoveSkillToStudayWindow(ZTRectangle studayTextRect)
{
ZTRectangle targetRect = GetStudaySkillRect(studayTextRect, 27);
for (int i = 0; i < 12; i++)
{
ZTRectangle expressRect = GetExpressSkillRect(i);
MoveSkill(expressRect.GetCenterPoint(), targetRect.GetCenterPoint());
}
return true;
}
///
/// 识别出来的技能索引和在技能快捷栏中的对应关系
/// 对应关系是-1的不放在快捷栏里
///
Dictionary skillToExpressMap = new Dictionary() {
{ 4 ,0},
{ 13,1},
{ 8 ,2},
{ 9 ,3},
{ 15,4},
{ 12,5},
{ 6 ,6},
{ 10,7},
{ 7 ,8},
{ 11,9},
{ 14,10},
{ 16,11}
};
///
/// 从已学技能栏向快捷栏移动技能
///
///
///
private bool MoveSkillToExpress(ZTRectangle studayTextRect)
{
int i = 0;
int count = 17;
while (i < count)
{
if (this.cancellationToken.IsCancellationRequested)
{
return false;
}
//获取位置,并将鼠标移到位置,显示出技能名
Utility.Structs.ZTPoint studayPoint = GetStudaySkillRect(studayTextRect, i).GetCenterPoint();
G.Instance.InputControl.MoveTo(studayPoint.X, studayPoint.Y, false, false, false);
Thread.Sleep(1000);
//识别
Int32 skillIndex = 0;//技能索引
ZTRectangle discenrnRect = new ZTRectangle(studayPoint.X - 150, this.GameRect.Start.Y, studayPoint.X, studayPoint.Y);
bool result = FuncUtils.TimeoutCancelableWrap(2000, this.cancellationToken, () => {
return SkillCVHelper.GetSkillName(out skillIndex, discenrnRect);
}, 200);
if (result)
{
if (skillToExpressMap.ContainsKey(skillIndex))
{
//要放到技能栏的位置
Utility.Structs.ZTPoint to = GetExpressSkillRect(skillToExpressMap[skillIndex]).GetCenterPoint();
MoveSkill(studayPoint, to);
count--;
continue;
}
}
else
{
G.Instance.DebugWriter("识别技能错误,index=" + i.ToString());
}
i++;
}
return true;
}
///
/// 移动技能
///
///
///
///
private bool MoveSkill(Utility.Structs.ZTPoint from, Utility.Structs.ZTPoint to)
{
//移动指定位置
G.Instance.InputControl.MoveTo(from.X, from.Y, false, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration*2);
//按下
G.Instance.InputControl.Move(0, 0, true, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration * 3);
//移到目标位置
G.Instance.InputControl.MoveTo(to.X, to.Y, true, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration*2);
//松开
G.Instance.InputControl.Move(0, 0, false, false, false);
Thread.Sleep(RandomUtils.MouseClickDuration * 2);
return true;
}
///
/// 得到快捷栏技能定位
///
///
///
private ZTRectangle GetExpressSkillRect(int index)
{
//x209,y488
Int32 row = index / 6;
Int32 col = index % 6;
int x = this.titleRect.Start.X + 209 + col * 33;
int y = this.titleRect.Start.Y + 488 + row * 33;
return new ZTRectangle(x, y, x + 33, y + 33);
}
///
/// 得到已学技能栏定位
///
///
///
///
private ZTRectangle GetStudaySkillRect(ZTRectangle studayTextRect, Int32 index)
{
//x:-122,y:44
Int32 row = index / 7;
Int32 col = index % 7;
int x = studayTextRect.Start.X + (-122) + col * 31;
int y = studayTextRect.Start.Y + 44 + row * 31;
return new ZTRectangle(x, y, x + 31, y + 31);
}
}
}