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技能学习 ZTPoint spPoint = new 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() { //点击初始化 ZTPoint initButton = new 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); //是否已打开完毕对话框 result = FuncUtils.TimeoutCancelableWrap(3000, this.cancellationToken, () => { return SkillCVHelper.ExistsNotificationText(out notificationRect, this.GameRect); }); if (!result) { G.Instance.DebugWriter("完毕公告未找到"); return false; } //点击确认 ZTPoint okPosition = new ZTPoint(notificationRect.GetCenterPoint().X, notificationRect.End.Y + 70); 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() { //物理暴击 ZTPoint skillPoint = new ZTPoint(lvRect.End.X + 200, lvRect.Start.Y - 42); SettingSkill(skillPoint); //物理背击 skillPoint = new ZTPoint(lvRect.End.X + 280, lvRect.Start.Y - 42); SettingSkill(skillPoint); return true; } /// /// 要点的技能列表 /// 内部为每个节所相对于节的相对位置 /// private List[] toAddLevelSkills = new List[] { new List (){ new ZTPoint(762-346,450-237),//疾风之棍棒精通 }, new List (){ new ZTPoint(182,17),//朔风牵引 new ZTPoint(274,17),//流风决 new ZTPoint(481-251,342-262),//风鸣冲击 new ZTPoint(323,82),//游离之风 new ZTPoint(574-251,409-262),//双翼风刃 new ZTPoint(574-251,477-262),//风暴之眼 new ZTPoint(529-251,544-262),//真空旋风破 }, new List (){ new ZTPoint(432-251,275-329),//风暴之拳 new ZTPoint(479-251,342-329),//万象风龙阵 new ZTPoint(572-251,340-329),//御风之力 new ZTPoint(433-251,478-329),//风神决 new ZTPoint(526-251,475-329),//风卷残云 new ZTPoint(574-251,476-329),//游龙惊风破 new ZTPoint(431-251,542-329),//九霄风雷 new ZTPoint(663-295,545-331),//无限风域 } }; /// /// 设置SP技能 /// /// private bool SettingSPSkills() { //选中sp技能学习 ZTPoint spPoint = new 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技能学习 ZTPoint spPoint = new ZTPoint(lvRect.End.X + 253, lvRect.Start.Y - 80); G.Instance.InputControl.MoveToAndClick(spPoint); ZTPoint[] skills = new ZTPoint[] { new ZTPoint(334-296,277-251),//1.第一行第一个 new ZTPoint(381-296,545-251),//2.第三行第二个 new ZTPoint(664-296,413-251),//3.第二行倒数第三个 new ZTPoint(567-296,410-251),//4.第二行倒数第五个 new 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() { ZTPoint studayPoint = new 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(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; ZTPoint openwindowButton = new 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; } //获取位置,并将鼠标移到位置,显示出技能名 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)) { //要放到技能栏的位置 ZTPoint to = GetExpressSkillRect(skillToExpressMap[skillIndex]).GetCenterPoint(); MoveSkill(studayPoint, to); count--; continue; } } else { G.Instance.DebugWriter("识别技能错误,index=" + i.ToString()); } i++; } return true; } /// /// 移动技能 /// /// /// /// private bool MoveSkill(ZTPoint from, 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); } } }