asmrobot
2019-11-25 2aeab450471cb80b59002da7da80faf251a0c4f4
sigle computer
4 files added
22 files modified
1546 ■■■■■ changed files
doc/流程图/杀怪KillMonster.vsd patch | view | raw | blame | history
src/RichCreator.Editor/MainWindow.xaml 2 ●●● patch | view | raw | blame | history
src/RichCreator.Editor/MainWindow.xaml.cs 24 ●●●●● patch | view | raw | blame | history
src/RichCreator.Utility/CV/DnfCVHelper.cs 244 ●●●●● patch | view | raw | blame | history
src/RichCreator.Utility/Dnf/MoveIntent.cs 3 ●●●● patch | view | raw | blame | history
src/RichCreator.Utility/Dnf/SpeedProvider.cs 42 ●●●● patch | view | raw | blame | history
src/RichCreator.Utility/Maps/HouseInfo.cs 10 ●●●● patch | view | raw | blame | history
src/RichCreator.Utility/Structs/ParametersPoint.cs 5 ●●●●● patch | view | raw | blame | history
src/RichCreator/Dnf/DnfRole.cs 338 ●●●●● patch | view | raw | blame | history
src/RichCreator/G.cs 14 ●●●●● patch | view | raw | blame | history
src/RichCreator/Images/down.png patch | view | raw | blame | history
src/RichCreator/Images/up.png patch | view | raw | blame | history
src/RichCreator/Jobs/DNFJob.cs 12 ●●●●● patch | view | raw | blame | history
src/RichCreator/Jobs/JobMonitor.cs 1 ●●●● patch | view | raw | blame | history
src/RichCreator/MainWindow.xaml 56 ●●●●● patch | view | raw | blame | history
src/RichCreator/MainWindow.xaml.cs 111 ●●●● patch | view | raw | blame | history
src/RichCreator/Maps/Kalete/KaleteMap.cs 103 ●●●● patch | view | raw | blame | history
src/RichCreator/Maps/Lindong/LindongMap.cs 40 ●●●● patch | view | raw | blame | history
src/RichCreator/Models/RunningModel.cs 4 ●●●● patch | view | raw | blame | history
src/RichCreator/Models/StateInfoItem.cs 31 ●●●●● patch | view | raw | blame | history
src/RichCreator/Models/StateProvider.cs 214 ●●●●● patch | view | raw | blame | history
src/RichCreator/RichCreator.csproj 4 ●●●● patch | view | raw | blame | history
src/RichCreator/StateMachines/KillMonsterStateMachine.cs 269 ●●●●● patch | view | raw | blame | history
src/RichCreator/configs/RichCreator.config 8 ●●●● patch | view | raw | blame | history
src/RichCreator/configs/kalete.txt 4 ●●●● patch | view | raw | blame | history
src/test/Program.cs 7 ●●●● patch | view | raw | blame | history
doc/流程图/杀怪KillMonster.vsd
Binary files differ
src/RichCreator.Editor/MainWindow.xaml
@@ -42,7 +42,7 @@
                <MenuItem Header="查找定位点" Click="FindLocationPoint_Click" />
                <MenuItem Header="查找物品" Click="FindThing_Click" />
                <Separator/>
                <MenuItem Header="测试找线" Click="FindLines" />
src/RichCreator.Editor/MainWindow.xaml.cs
@@ -409,7 +409,7 @@
            Image<Hsv, byte> hsv = new Image<Hsv, byte>(this.targetImage.Width, this.targetImage.Height);
            CvInvoke.CvtColor(this.targetImage, hsv, ColorConversion.Rgb2Hsv);
            Direction d;
            //List<ZTRectangle> rects = CVHelper.FindBlocks(hsv, new Hsv(165, 247, 175), new Hsv(173, 255, 230), new ZTSize(30, 30));
            Hsv minHsv = new Hsv(0, 0, 178);
@@ -427,6 +427,27 @@
            }
        }
        private void FindThing_Click(object sender, RoutedEventArgs e)
        {
            //转为hsv
            Image<Hsv, byte> hsv = new Image<Hsv, byte>(this.targetImage.Width, this.targetImage.Height);
            CvInvoke.CvtColor(this.targetImage, hsv, ColorConversion.Rgb2Hsv);
            ZTPoint[] things=DnfCVHelper.FindThings(hsv, new ZTRectangle(0, 0, this.targetImage.Width, this.targetImage.Height));
            int x, y, width, height;
            for (int i = 0; i < things.Length; i++)
            {
                x = things[i].X;
                y = things[i].Y;
                width = 25;
                height = 25;
                DrawRectangle(x, y, width, height, Colors.Green);
            }
        }
@@ -1150,6 +1171,7 @@
        //private void test_click(object sender, RoutedEventArgs e)
        //{
        //    string content = "%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3Cexchange%3E%3CErrCode%3E0%3C%2FErrCode%3E%3CErrMessage%3E%E6%88%90%E5%8A%9F%EF%BC%81%3C%2FErrMessage%3E%3Cbody1%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3850%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E7%99%BD%E7%BB%86%E8%83%9E%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody1%3E%3Cbody2%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3851%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E4%BA%9A%E7%A1%9D%E9%85%B8%E7%9B%90%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody2%3E%3Cbody3%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3852%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E6%AD%A3%E5%B8%B8%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E5%B0%BF%E8%83%86%E5%8E%9F%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody3%3E%3Cbody4%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3853%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E8%9B%8B%E7%99%BD%E8%B4%A8%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody4%3E%3Cbody5%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3854%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E5.0%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E4.5-8.0%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3EPH%E5%80%BC%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody5%3E%3Cbody6%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3855%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E5%B0%BF%E6%BD%9C%E8%A1%80%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody6%3E%3Cbody7%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3856%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E1.030%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E1.003-1.030%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E6%AF%94%E9%87%8D%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody7%3E%3Cbody8%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3857%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E2%2B%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E0-5.7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E6%8A%97%E5%9D%8F%E8%A1%80%E9%85%B8Vc%3C%2FItemName%3E%3CUnit%3Emmol%2FL%3C%2FUnit%3E%3C%2Fbody8%3E%3Cbody9%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3858%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E9%85%AE%E4%BD%93%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody9%3E%3Cbody10%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3859%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E8%83%86%E7%BA%A2%E7%B4%A0%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody10%3E%3Cbody11%3E%3CReportNo%3E15%3C%2FReportNo%3E%3CResultID%3E3860%3C%2FResultID%3E%3CTestNum%3E271%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170145%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A13%3A45%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A13%3A45%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FOptName%3E%3CCheckName%3E%E9%98%BF%E5%8D%9C%E6%9D%9C%E7%83%AD%E5%90%88%E6%9B%BC%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A15%3A46%3C%2FPrintTime%3E%3CLockBar%3E33700%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E-%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%E9%98%B4%E6%80%A7%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E8%91%A1%E8%90%84%E7%B3%96%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody11%3E%3Cbody12%3E%3CReportNo%3E16%3C%2FReportNo%3E%3CResultID%3E3881%3C%2FResultID%3E%3CTestNum%3E2%3C%2FTestNum%3E%3CTestDate%3E2019%2F4%2F17%3C%2FTestDate%3E%3CName%3E%E7%8E%8B%E5%88%9A%3C%2FName%3E%3CSex%3E%E5%A5%B3%3C%2FSex%3E%3CAge%3E26%E5%B2%81%3C%2FAge%3E%3CPid%3E130125199304015555%3C%2FPid%3E%3CDepartment%3E%3C%2FDepartment%3E%3CDoctor%3E%3C%2FDoctor%3E%3CPatType%3E%3C%2FPatType%3E%3CLCZD%3E%3C%2FLCZD%3E%3CBedNum%3E%3C%2FBedNum%3E%3CBarCode%3E1904170148%3C%2FBarCode%3E%3CSampleState%3E%E6%AD%A3%E5%B8%B8%3C%2FSampleState%3E%3CSample%3E%3C%2FSample%3E%3CTestTime%3E2019%2F4%2F17+23%3A23%3A21%3C%2FTestTime%3E%3CSampleDate%3E2019%2F4%2F17+23%3A23%3A21%3C%2FSampleDate%3E%3CComment%3E%3C%2FComment%3E%3COptName%3E%E5%B7%B4%E5%93%88%E5%B0%94%E5%8F%A4%E4%B8%BD%3C%2FOptName%3E%3CCheckName%3Eadmin%3C%2FCheckName%3E%3CPrintName%3E%3C%2FPrintName%3E%3CPrintTime%3E2019%2F4%2F17+23%3A24%3A43%3C%2FPrintTime%3E%3CLockBar%3E33717%3C%2FLockBar%3E%3CSCode%3E%E5%B8%B8%E8%A7%84%3C%2FSCode%3E%3CResult%3E%E5%AE%AB%E9%A2%88%E7%82%8E%3C%2FResult%3E%3CState%3E%3C%2FState%3E%3CLimit%3E%3C%2FLimit%3E%3CEName%3E%3C%2FEName%3E%3CItemName%3E%E5%AE%AB%E9%A2%88%3C%2FItemName%3E%3CUnit%3E%3C%2FUnit%3E%3C%2Fbody12%3E%3C%2Fexchange%3E";
src/RichCreator.Utility/CV/DnfCVHelper.cs
@@ -487,90 +487,6 @@
        }
        private const Int32 radisXMaxRange = 8;//x容差范围
        private const Int32 radisYMaxRange = 45;//y容差范围
        private const Int32 xLineMin = 46;//横向最小宽度
        private const Int32 yLineMin = 26;//纵向最小高度
        private const Int32 thingItemYOffset = 50;//查找的横线与物体垂直偏移
        //other remove:min:(0.0166666675359011,0.0584795325994492,0.564705908298492),max:(0.115740731358528,0.543589770793915,0.764705896377563)
        //min:(0.0454545430839062,0.148148149251938,0.454901963472366),max:(0.146666660904884,0.53804349899292,0.952941179275513)
        //边框颜色
        static ZTHsvFloatColor min = new ZTHsvFloatColor(0.0166f,  0.0584f, 0.5647f);
        static ZTHsvFloatColor max = new ZTHsvFloatColor(0.1467f, 0.5436f, 0.9530f);
        //other remove:min:(0,0.111111111938953,0.0666666701436043),max:(0.958333313465118,0.65625,0.129411771893501)
        //min:(0,0,0.0392156876623631),max:(0.833333313465118,1,0.219607844948769)
        //内部颜色
        static ZTHsvFloatColor innerMin = new ZTHsvFloatColor(0, 0f, 0.0392f);
        static ZTHsvFloatColor innerMax = new ZTHsvFloatColor(1, 1f, 0.2197f);
        /// <summary>
        /// 获取物品项点位
        /// </summary>
        /// <param name="image"></param>
        /// <param name="gameRect"></param>
        /// <returns></returns>
        public static List<Structs.ZTPoint> GetThingItemPoints(Image<Rgb, byte> image, ZTRectangle gameRect)
        {
            List<ZTLine> lines = CVHelper.FindLines(image, xLineMin,gameRect, Orientation.Horizontal, min, max);
            List<ZTLine> filterLines = new List<ZTLine>();
            List<Structs.ZTPoint> points = new List<Structs.ZTPoint>();
            Func<ZTLine, bool> existsLines = (line) =>
            {
                for (int i = 0; i < filterLines.Count; i++)
                {
                    //离得太近
                    if (Math.Abs(filterLines[i].Y - line.Y) <= 3)
                    {
                        //横坐标是否重合
                        if ((line.X + line.Length) < filterLines[i].X || line.X > (filterLines[i].X + filterLines[i].Length))
                        {
                            //未重合
                            continue;
                        }
                        return true;
                    }
                }
                return false;
            };
            ZTRectangle limit = ZTRectangle.Empty;
            ZTLine vline = ZTLine.Empty;
            //bool isLeft = true;
            for (int i = 0; i < lines.Count; i++)
            {
                ZTLine line = lines[i];
                //是否存在距离比较近的线
                if (existsLines(line))
                {
                    continue;
                }
                //查找左边
                //isLeft = true;
                limit = new ZTRectangle(line.X - radisXMaxRange, line.Y, line.X, line.Y + radisYMaxRange);
                if (!CVHelper.FindLine(out vline, image, yLineMin, limit, RichCreator.Utility.Structs.Orientation.Vertical, min, max))
                {
                    limit = new ZTRectangle(line.X + line.Length, line.Y, line.X + line.Length + radisXMaxRange, line.Y + radisYMaxRange);
                    if (!CVHelper.FindLine(out vline, image, yLineMin, limit, Orientation.Vertical, min, max))
                    {
                        continue;
                    }
                    //isLeft = false;
                }
                //内部是否黑色
                if (!CVHelper.InRange(image.Data, line.X + 3, line.Y + 3, innerMin, innerMax))
                {
                    continue;
                }
                filterLines.Add(line);
                points.Add(new Structs.ZTPoint(line.X + line.Length / 2, line.Y + thingItemYOffset));
            }
            return points;
        }
        #region Location Point 1
        private static readonly Hsv LocationPointMinHsv = new Hsv(0, 0, 0);
@@ -730,7 +646,11 @@
        #endregion
        #region Location Point 2
        private static ColorArray LocationPoint = ColorArray.FromColorString(0, 0, "800,352,0,0,0$791,343,255,255,255$793,343,0,0,0$796,343,255,255,255$798,343,0,0,0$801,343,255,255,255$802,345,0,0,0$802,347,255,255,255$802,349,0,0,0$802,352,255,255,255$797,352,255,255,255$795,352,0,0,0$791,352,255,255,255$791,350,0,0,0$791,348,255,255,255$791,346,0,0,0$796,347,255,255,255$797,348,255,255,255");
        ////部分定位框数据
        //private static ColorArray LocationPoint = ColorArray.FromColorString(0, 0, "800,352,0,0,0$791,343,255,255,255$793,343,0,0,0$796,343,255,255,255$798,343,0,0,0$801,343,255,255,255$802,345,0,0,0$802,347,255,255,255$802,349,0,0,0$802,352,255,255,255$797,352,255,255,255$795,352,0,0,0$791,352,255,255,255$791,350,0,0,0$791,348,255,255,255$791,346,0,0,0$796,347,255,255,255$797,348,255,255,255");
        //全部定位框数据
        private static ColorArray LocationPoint = ColorArray.FromColorString(0, 0, "1629,368,255,255,255$1619,367,255,255,255$1620,367,255,255,255$1621,367,0,0,0$1622,367,0,0,0$1623,367,0,0,0$1624,367,255,255,255$1625,367,255,255,255$1626,367,0,0,0$1627,367,0,0,0$1628,367,0,0,0$1629,367,255,255,255$1630,367,255,255,255$1630,368,255,255,255$1628,368,0,0,0$1627,368,0,0,0$1626,368,0,0,0$1625,368,255,255,255$1624,368,255,255,255$1623,368,0,0,0$1622,368,0,0,0$1621,368,0,0,0$1620,368,255,255,255$1619,368,255,255,255$1619,369,0,0,0$1620,369,0,0,0$1629,369,0,0,0$1630,369,0,0,0$1630,370,0,0,0$1629,370,0,0,0$1620,370,0,0,0$1619,370,0,0,0$1619,371,255,255,255$1620,371,255,255,255$1621,371,0,0,0$1622,371,0,0,0$1623,371,0,0,0$1624,371,255,255,255$1625,371,255,255,255$1626,371,0,0,0$1627,371,0,0,0$1628,371,0,0,0$1629,371,255,255,255$1630,371,255,255,255$1630,372,255,255,255$1629,372,255,255,255$1628,372,0,0,0$1627,372,0,0,0$1626,372,0,0,0$1625,372,255,255,255$1624,372,255,255,255$1623,372,0,0,0$1622,372,0,0,0$1621,372,0,0,0$1620,372,255,255,255$1619,372,255,255,255$1619,373,0,0,0$1620,373,0,0,0$1629,373,0,0,0$1630,373,0,0,0$1630,374,0,0,0$1629,374,0,0,0$1620,374,0,0,0$1619,374,0,0,0$1619,375,255,255,255$1620,375,255,255,255$1621,375,0,0,0$1622,375,0,0,0$1623,375,0,0,0$1624,375,255,255,255$1625,375,255,255,255$1626,375,0,0,0$1627,375,0,0,0$1628,375,0,0,0$1629,375,255,255,255$1630,375,255,255,255$1630,376,255,255,255$1629,376,255,255,255$1628,376,0,0,0$1627,376,0,0,0$1626,376,0,0,0$1625,376,255,255,255$1624,376,255,255,255$1623,376,0,0,0$1622,376,0,0,0$1621,376,0,0,0$1620,376,255,255,255$1619,376,255,255,255");
        /// <summary>
        /// 获取定位点
        /// </summary>
@@ -742,29 +662,7 @@
            ZTRectangle rect = ZTRectangle.Empty;
            if (CVHelper.FindColorArray(out rect, image, LocationPoint, gameRect))
            {
                //获取定位标记,解析参数
                byte number = 0;
                bool bitValue = true;
                Int32 x = 0, y = 0;
                for (int bitIndex = 0; bitIndex <= 7; bitIndex++)
                {
                    //获取图像中存值的坐标
                    GetBitCoordinate(out x, out y, bitIndex);
                    //解析并设置值
                    if (!ParseBit(out bitValue, image, rect.Start.Add(x, y)))
                    {
                        return ParametersPoint.Empty;
                    }
                    else
                    {
                        number=SetBit(number, bitIndex, bitValue);
                    }
                }
                return new ParametersPoint(rect.GetCenterPoint(), number);
                return GetLocationPointParameter(image, rect);
            }
            return ParametersPoint.Empty;
@@ -787,6 +685,10 @@
            bool result = CVHelper.FindColorArray(out rect, image, LocationPoint, gameRect, (lpRect) => {
                ParametersPoint pp = GetLocationPointParameter(image, lpRect);
                if (pp.Equals( ParametersPoint.Empty))
                {
                    return false;
                }
                if (withoutNumber.ContainsKey(pp.Parameter))
                {
                    return false;
@@ -810,6 +712,11 @@
        /// <returns></returns>
        private static ParametersPoint GetLocationPointParameter(Image<Rgb,byte> image,ZTRectangle rect)
        {
            if (!VaildLocationRect(image, rect))
            {
                return ParametersPoint.Empty;
            }
            //获取定位标记,解析参数
            byte number = 0;
            bool bitValue = true;
@@ -834,7 +741,16 @@
            return new ParametersPoint(rect.GetCenterPoint(), number);
        }
        /// <summary>
        /// 验证定位点方块是否正常
        /// </summary>
        /// <param name="image"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        private static bool VaildLocationRect(Image<Rgb, byte> image, ZTRectangle rect)
        {
            return true;
        }
        /// <summary>
@@ -1161,5 +1077,115 @@
        #endregion
        #region Things
        private const Int32 radisXMaxRange = 8;//x容差范围
        private const Int32 radisYMaxRange = 45;//y容差范围
        private const Int32 xLineMin = 46;//横向最小宽度
        private const Int32 yLineMin = 26;//纵向最小高度
        private const Int32 thingItemYOffset = 50;//查找的横线与物体垂直偏移
        //other remove:min:(0.0166666675359011,0.0584795325994492,0.564705908298492),max:(0.115740731358528,0.543589770793915,0.764705896377563)
        //min:(0.0454545430839062,0.148148149251938,0.454901963472366),max:(0.146666660904884,0.53804349899292,0.952941179275513)
        //边框颜色
        static ZTHsvFloatColor min = new ZTHsvFloatColor(0.0166f, 0.0584f, 0.5647f);
        static ZTHsvFloatColor max = new ZTHsvFloatColor(0.1467f, 0.5436f, 0.9530f);
        //other remove:min:(0,0.111111111938953,0.0666666701436043),max:(0.958333313465118,0.65625,0.129411771893501)
        //min:(0,0,0.0392156876623631),max:(0.833333313465118,1,0.219607844948769)
        //内部颜色
        static ZTHsvFloatColor innerMin = new ZTHsvFloatColor(0, 0f, 0.0392f);
        static ZTHsvFloatColor innerMax = new ZTHsvFloatColor(1, 1f, 0.2197f);
        /// <summary>
        /// 获取物品项点位
        /// </summary>
        /// <param name="image"></param>
        /// <param name="gameRect"></param>
        /// <returns></returns>
        public static List<Structs.ZTPoint> GetThingItemPoints(Image<Rgb, byte> image, ZTRectangle gameRect)
        {
            List<ZTLine> lines = CVHelper.FindLines(image, xLineMin, gameRect, Orientation.Horizontal, min, max);
            List<ZTLine> filterLines = new List<ZTLine>();
            List<Structs.ZTPoint> points = new List<Structs.ZTPoint>();
            Func<ZTLine, bool> existsLines = (line) =>
            {
                for (int i = 0; i < filterLines.Count; i++)
                {
                    //离得太近
                    if (Math.Abs(filterLines[i].Y - line.Y) <= 3)
                    {
                        //横坐标是否重合
                        if ((line.X + line.Length) < filterLines[i].X || line.X > (filterLines[i].X + filterLines[i].Length))
                        {
                            //未重合
                            continue;
                        }
                        return true;
                    }
                }
                return false;
            };
            ZTRectangle limit = ZTRectangle.Empty;
            ZTLine vline = ZTLine.Empty;
            //bool isLeft = true;
            for (int i = 0; i < lines.Count; i++)
            {
                ZTLine line = lines[i];
                //是否存在距离比较近的线
                if (existsLines(line))
                {
                    continue;
                }
                //查找左边
                //isLeft = true;
                limit = new ZTRectangle(line.X - radisXMaxRange, line.Y, line.X, line.Y + radisYMaxRange);
                if (!CVHelper.FindLine(out vline, image, yLineMin, limit, RichCreator.Utility.Structs.Orientation.Vertical, min, max))
                {
                    limit = new ZTRectangle(line.X + line.Length, line.Y, line.X + line.Length + radisXMaxRange, line.Y + radisYMaxRange);
                    if (!CVHelper.FindLine(out vline, image, yLineMin, limit, Orientation.Vertical, min, max))
                    {
                        continue;
                    }
                    //isLeft = false;
                }
                //内部是否黑色
                if (!CVHelper.InRange(image.Data, line.X + 3, line.Y + 3, innerMin, innerMax))
                {
                    continue;
                }
                filterLines.Add(line);
                points.Add(new Structs.ZTPoint(line.X + line.Length / 2, line.Y + thingItemYOffset));
            }
            return points;
        }
        private static Hsv minThingHsv = new Hsv(25, 250, 250);
        private static Hsv maxThingHsv = new Hsv(29, 255, 255);
        private static ZTSize thingBlockSize = new ZTSize(20, 20);
        /// <summary>
        /// 查找所有物品的位置
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static Structs.ZTPoint[] FindThings(Image<Hsv, byte> image, ZTRectangle gameRect)
        {
            List<ZTRectangle> rects = CVHelper.FindBlocks(image, minThingHsv, maxThingHsv, thingBlockSize);
            Structs.ZTPoint[] monsterPoints = new Structs.ZTPoint[rects.Count];
            for (int i = 0; i < rects.Count; i++)
            {
                monsterPoints[i] = rects[i].GetCenterPoint().Add(gameRect.Start);
            }
            return monsterPoints;
        }
        #endregion
    }
}
src/RichCreator.Utility/Dnf/MoveIntent.cs
@@ -16,8 +16,7 @@
        AttackMove,//去攻击
        FindRoleMove,//找主角
        PickupMove,//去拾取
        ToNextGatePoint,//移至进门点
        ToLoopPoint,//移至巡逻点
        ToLoop,//移至巡逻点
        EntryDoor//进门
    }
}
src/RichCreator.Utility/Dnf/SpeedProvider.cs
@@ -11,6 +11,11 @@
    /// </summary>
    public class SpeedProvider
    {
        /// <summary>
        /// 随机移动距离
        /// </summary>
        public const Int32 RandomMoveDistance = 100;
        public static SpeedProvider Define = new SpeedProvider(1400);
        public SpeedProvider(Int32 speed)
        {
@@ -19,33 +24,33 @@
            double runPixelPerSpeedX = 0;//跑 X每个速度一秒移动的像素数
            if (speed <= 1109)
            {
                stepPixelPerSpeedX = 160d/1109d;
                stepPixelPerSpeedY = 127d/1109d;
                runPixelPerSpeedX =  260d/1109d;
                stepPixelPerSpeedX = 160d / 1109d;
                stepPixelPerSpeedY = 127d / 1109d;
                runPixelPerSpeedX = 260d / 1109d;
            }
            else if (speed > 1109 && speed <= 1151)
            {
                stepPixelPerSpeedX = 166.5d/1151d;
                stepPixelPerSpeedY = 131d/1151d;
                runPixelPerSpeedX = 267.7d/1151d;
                stepPixelPerSpeedX = 166.5d / 1151d;
                stepPixelPerSpeedY = 131d / 1151d;
                runPixelPerSpeedX = 267.7d / 1151d;
            }
            else if (speed > 1151 && speed <= 1256)
            {
                stepPixelPerSpeedX = 180d/1256d;
                stepPixelPerSpeedY = 142.5d/1256d;
                runPixelPerSpeedX = 284.5d/1256d;
                stepPixelPerSpeedX = 180d / 1256d;
                stepPixelPerSpeedY = 142.5d / 1256d;
                runPixelPerSpeedX = 284.5d / 1256d;
            }
            else if (speed > 1256 && speed <= 1400)
            {
                stepPixelPerSpeedX = 194.5d/1400d;
                stepPixelPerSpeedY = 156.5d/1400d;
                runPixelPerSpeedX = 320d/1400d;
                stepPixelPerSpeedX = 194.5d / 1400d;
                stepPixelPerSpeedY = 156.5d / 1400d;
                runPixelPerSpeedX = 320d / 1400d;
            }
            else
            {
                stepPixelPerSpeedX = 194.5d / 1400d;
                stepPixelPerSpeedY = 156.5d / 1400d;
                runPixelPerSpeedX = 320d/ 1400d;
                runPixelPerSpeedX = 320d / 1400d;
            }
            stepX = (stepPixelPerSpeedX * speed) / 1000;
@@ -53,19 +58,16 @@
            runX = (runPixelPerSpeedX * speed) / 800;
            RunThresold = stepX * RandomUtils.KeyPressDurationMax +runX * RandomUtils.KeyPressDurationMax+50;
            RandomMoveMillSecond = (Int32)(300 / stepX);
            RunThresold = stepX * RandomUtils.KeyPressDurationMax + runX * RandomUtils.KeyPressDurationMax + 50;
        }
        /// <summary>
        /// 开始跑的阀值
        /// </summary>
        public double RunThresold { get; private set; }
        //随机移动时间
        public Int32 RandomMoveMillSecond { get; private set; }
        private double stepX;
        /// <summary>
        /// 步行X轴速度
src/RichCreator.Utility/Maps/HouseInfo.cs
@@ -22,11 +22,12 @@
            InitPathInfo(null);
        }
        public HouseInfo(Int32 index,MapType mapType,bool isEnd, HIDCode[] skills,Int32[] withoutNumber)
        public HouseInfo(Int32 index,MapType mapType,bool isEnd, HIDCode[] skills,Int32[] withoutNumber,Int32 fromHouseIndex)
        {
            this.Index = index;
            this.MapType = mapType;
            this.IsEnd = isEnd;
            this.FromHouseIndex = fromHouseIndex;
            Skills = new SkillQueue();
            for (int i = 0; skills!=null&&i < skills.Length; i++)
@@ -51,12 +52,17 @@
            InitPathInfo(withoutNumber);
        }
        
        /// <summary>
        /// 房间编号
        /// </summary>
        public Int32 Index { get; set; }
        /// <summary>
        /// 来自房间索引
        /// </summary>
        public Int32 FromHouseIndex { get; set; }
        private Direction[] doorDirection = null;
        /// <summary>
        /// 门的位置
src/RichCreator.Utility/Structs/ParametersPoint.cs
@@ -36,5 +36,10 @@
            }
            return false;
        }
        public override string ToString()
        {
            return $"<{this.Point},{this.Parameter}>";
        }
    }
}
src/RichCreator/Dnf/DnfRole.cs
@@ -1,4 +1,5 @@
using RichCreator.Utility;
using RichCreator.Models;
using RichCreator.Utility;
using RichCreator.Utility.Dnf;
using RichCreator.Utility.InputControl;
using RichCreator.Utility.Maps;
@@ -24,26 +25,28 @@
        /// 角色脚部距色块中央的偏移
        /// </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();
            moveCancelToken = new CancellationTokenSource();
        }
        private SpeedProvider speed;//速度
        private HouseInfo house;//所在房间
        private ZTRectangle gameRect = ZTRectangle.Empty;
        private MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图
        private ZTRectangle gameRect = ZTRectangle.Empty;
        public MoveIntent movingIntent = MoveIntent.AttackMove;//移动意图
        private CancellationTokenSource moveCancelToken;//移动取消令牌
        private Int32 findRoleDir = 0;//寻找角色行走的方向
        private DateTime findRoleMoveTimeout = DateTime.MinValue;//方向移动过期时间
        /// <summary>
        /// 角色色块位置
@@ -71,13 +74,13 @@
                return CBToHalfPosition(RoleCBPosition);
            }
        }
        /// <summary>
        /// 按下的键,0:横向,1:纵向
        /// </summary>
        private HIDCode[] pressKeys = new HIDCode[] { HIDCode.NoEvent, HIDCode.NoEvent };//当前按键
        private bool isRun = false;//是否奔跑
        /// <summary>
        /// 设置当前房间信息
        /// </summary>
@@ -85,6 +88,7 @@
        public void SetHouse(HouseInfo house)
        {
            this.house = house;
            toNextGate = true;
        }
        /// <summary>
@@ -105,7 +109,7 @@
            this.RoleCBPosition = roleCBPosition;
        }
        private bool isMoving = false;
        /// <summary>
        /// 是否移动中
        /// </summary>
@@ -113,7 +117,8 @@
        {
            get
            {
                return pressKeys[0] != HIDCode.NoEvent || pressKeys[1] != HIDCode.NoEvent;
                return isMoving;
                //return pressKeys[0] != HIDCode.NoEvent || pressKeys[1] != HIDCode.NoEvent;
            }
        }
@@ -130,65 +135,24 @@
            }
            return false;
        }
        /// <summary>
        /// 攻击移动
        /// </summary>
        /// <param name="moveDistance"></param>
        public void AttackMove(ZTSize moveDistance)
        {
            PutDirectionKey(moveDistance);
            movingIntent = MoveIntent.AttackMove;
        }
        /// <summary>
        /// 攻击移动至
        /// </summary>
        /// <param name="skillReleasePoint"></param>
        public void AttackMoveTo(ZTPoint skillReleasePoint,ParametersPoint locationPoint)
        public void AttackMove(ZTPoint skillReleasePoint, ParametersPoint screenLocation)
        {
            //屏幕坐标转地图坐标
            ZTPoint start= this.house.ScreenToMapCoordinate(this.Position, locationPoint);
            ZTPoint end = this.house.ScreenToMapCoordinate(DnfRole.HalfToFootPosition(skillReleasePoint), locationPoint);
            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);
            MovePaths(start, paths);
        }
        /// <summary>
        /// 移动到指定地图点
        /// </summary>
        public void MoveToMapPoint(ZTPoint start,ZTPoint end)
        {
            List<ZTPoint> paths = this.house.FindPath(start, end);
            MovePaths(start, paths);
        }
        /// <summary>
        /// 移动指定路径
        /// </summary>
        /// <param name="start"></param>
        /// <param name="paths"></param>
        public void MovePaths(ZTPoint start, List<ZTPoint> paths)
        {
            ZTPoint lastPoint = start;
            if (paths != null && paths.Count > 0)
            this.movingIntent = MoveIntent.AttackMove;
            isMoving = true;
            ThreadPool.QueueUserWorkItem((obj) =>
            {
                for (int i = 0; i < paths.Count; i++)
                {
                    ZTPoint distance = paths[i].Sub(lastPoint);
                    this.SyncMove(distance);
                    lastPoint = paths[i];
                }
            }
                this.MovePaths(start, paths, this.moveCancelToken.Token,"attack move");
            }, null);
        }
        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 } };
        /// <summary>
        /// 查找主角移动
@@ -196,75 +160,160 @@
        /// <param name="moveDistance"></param>
        public void FindRoleMove()
        {
            if (IsMoving &&  !IsMoveIntent(MoveIntent.FindRoleMove))
            {
                StopMove();
            }
            if (DateTime.Now >= findRoleMoveTimeout)
            {
                //转换方向
                findRoleDir++;
                HIDCode[]  tempKeys = dir[findRoleDir % 4];
                Int32 stepms = 0, runms = 0;
                PutDirectionKey(out stepms, out runms, tempKeys[0], tempKeys[1], true);
                findRoleMoveTimeout = DateTime.Now.AddMilliseconds(speed.RandomMoveMillSecond);
                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);
            }
            
            movingIntent = MoveIntent.FindRoleMove;
        }
        public void EntryDoorMove()
        /// <summary>
        /// 进门移动
        /// </summary>
        public void EntryDoorMove(ZTPoint doorScreenPosition, ParametersPoint screenLocation, Direction doorDirect)
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.EntryDoor))
            //先到进门点
            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)
            {
                StopMove();
                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");
        }
        public void ToLoopMove()
        private bool toNextGate = true;
        private Int32 nextGate = 0;
        /// <summary>
        /// 移至巡逻点
        /// </summary>
        public void LoopMove(ParametersPoint screenLocation)
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.ToLoopPoint))
            {
                StopMove();
            }
        }
            ZTPoint start = ZTPoint.Empty, end = ZTPoint.Empty;
            ZTPoint halfMapPosition= this.house.ScreenToMapCoordinate(this.HalfPosition, screenLocation);
            ZTPoint footMapPosition= this.house.ScreenToMapCoordinate(this.Position, screenLocation);
        public void ToNextGateMove()
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.ToNextGatePoint))
            if (toNextGate)
            {
                StopMove();
            }
        }
                //判断当前是否进门点
                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 rolePosition, ZTPoint thingItemPosition)
        public void PickupMove(ZTPoint screenThingPosition,ParametersPoint screenLocation)
        {
            if (IsMoving && !IsMoveIntent(MoveIntent.PickupMove))
            //屏幕坐标转地图坐标
            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"))
            {
                StopMove();
            }
            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());
            PutDirectionKey(moveDistance);
            movingIntent = MoveIntent.PickupMove;
        }
        /// <summary>
        /// 同步移动指定距离
        /// </summary>
@@ -272,6 +321,50 @@
        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;
@@ -321,7 +414,7 @@
            {
                xtime = (Int32)(Math.Abs(distance.Width) / speed.RunX);
            }
            Int32 mintime = Math.Min(xtime, ytime);
            if (xtime <= 0)
            {
@@ -345,28 +438,25 @@
                PutDirectionKey(out stepms, out runms, HIDCode.NoEvent, vertical, false);
                Thread.Sleep(ytime);
            }
            //StopMove();
            G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false);
            pressKeys[0] = HIDCode.NoEvent;
            pressKeys[1] = HIDCode.NoEvent;
            isRun = false;
        }
        /// <summary>
        /// 停止移动
        /// </summary>
        public void StopMove()
        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;
            }
        }
@@ -379,7 +469,7 @@
        {
            Thread.Sleep(millSecond);
        }
        /// <summary>
        /// 释放技能
        /// </summary>
@@ -387,8 +477,8 @@
        public void ReleaseSkill(HIDCode key)
        {
            Int32 dur = RandomUtils.KeyPressDuration;
            G.Instance.InputControl.PressKey(dur,key);
            SkillInfo skill=SkillInfo.GetSkillInfo(key);
            G.Instance.InputControl.PressKey(dur, key);
            SkillInfo skill = SkillInfo.GetSkillInfo(key);
            if (skill != null)
            {
                Int32 subTime = (Int32)(skill.ReleaseWaitTime - dur);
@@ -398,7 +488,7 @@
                }
            }
        }
        #region 八方向移动
        /// <summary>
        /// 按下按键
@@ -482,7 +572,12 @@
                        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
@@ -495,10 +590,12 @@
                        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();
                        }
                    }
@@ -541,11 +638,10 @@
            }
            return true;
        }
        #endregion
        #region role position convert
        /// <summary>
        /// 色块中央位置转为脚部位置
src/RichCreator/G.cs
@@ -47,14 +47,16 @@
        private Action<string> infoWriter = null;
        private Action<Int64> remainTimeWriter = null;
        private Func<Int64,bool> cancelConfirm = null;
        private Action<Int32, string> updateState = null;
        private Action stopTaskUI = null;
        internal void EnableWriter(Action<string> debugWriter,Action<string> infoWriter, Action<Int64> remainWriter, Func< Int64, bool> cancelConfirm,Action stopTaskUI)
        internal void EnableWriter(Action<string> debugWriter,Action<string> infoWriter, Action<Int64> remainWriter, Func< Int64, bool> cancelConfirm,Action stopTaskUI,Action<Int32,string> updateState)
        {
            this.debugWriter = debugWriter;
            this.infoWriter = infoWriter;
            this.remainTimeWriter = remainWriter;
            this.cancelConfirm = cancelConfirm;
            this.stopTaskUI = stopTaskUI;
            this.updateState = updateState;
        }
        
        /// <summary>
@@ -101,6 +103,16 @@
        }
        /// <summary>
        /// 更新状态
        /// </summary>
        /// <param name="index"></param>
        /// <param name="text"></param>
        public void UpdateState(Int32 index, string text)
        {
            this.updateState(index, text);
        }
        /// <summary>
        /// 停止任务
        /// </summary>
        public void StopTaskUI()
src/RichCreator/Images/down.png
src/RichCreator/Images/up.png
src/RichCreator/Jobs/DNFJob.cs
@@ -76,22 +76,24 @@
            for (; roleIndex < config.RoleCount; roleIndex++)
            {
                RunningModel.UpdateRoleIndex(roleIndex+1);
                if (cancellationToken.IsCancellationRequested)
                {
                    return ZTResult.Cancel;
                }
                DateTime playOneRoleStartTime = DateTime.Now;
                DateTime startRoleTime = DateTime.Now;
                G.Instance.InfoWriter($"Play Role:{roleIndex+1}");
                playResult = PlayRole(cancellationToken, roleIndex, startGameButtonRect);
                StateProvider.Instance.PreRoleTime = (Int32)(DateTime.Now - startRoleTime).TotalSeconds;
                StateProvider.Instance.RoleTimePassed = 0;
                if (playResult != ZTResult.Success)
                {
                    G.Instance.InfoWriter($"角色刷图失败,第{roleIndex+1}个角色");
                    return playResult;
                }
                Int32 playOneRoleTotalSecond = (Int32)(DateTime.Now - playOneRoleStartTime).TotalSeconds;
                G.Instance.InfoWriter($"角色刷图完成,用时:{(playOneRoleTotalSecond / 60)}分{(playOneRoleTotalSecond % 60)}秒");
                G.Instance.InfoWriter($"角色刷图完成");
            }
            
            RunningModel.UpdateRoleIndex(1);
src/RichCreator/Jobs/JobMonitor.cs
@@ -85,6 +85,7 @@
            for (; accountIndex < accountCount; accountIndex++)
            {
                RunningModel.UpdateAccountIndex(accountIndex+1);
                if (runningStep < RunningStep.SelectRole)
                {
                    string username, password;
src/RichCreator/MainWindow.xaml
@@ -9,7 +9,7 @@
        ResizeMode="NoResize"
        Loaded="Window_Loaded"
        Unloaded="Window_Unloaded"
        Title="富豪自动创造机" Height="250" Width="800" WindowStartupLocation="CenterScreen">
        Title="富豪自动创造机" SizeToContent="Height"  Width="800" WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <Style TargetType="Border" x:Key="RowBorderStyle">
            <Setter Property="BorderBrush" Value="Gray"/>
@@ -32,13 +32,31 @@
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <TextBox Grid.Row="0" AcceptsReturn="True" TextWrapping="Wrap" IsReadOnly="True" x:Name="LogTB" VerticalScrollBarVisibility="Auto"/>
                        <Grid Grid.Row="0">
                            <TextBox x:Name="LogTB" AcceptsReturn="True" TextWrapping="Wrap" IsReadOnly="True" VerticalScrollBarVisibility="Auto" Visibility="Collapsed" Height="200"/>
                            <Button x:Name="LogTBClearBtn" Content="清空"  Padding="15 0 15 0" Margin="5" Click="ClearLog_Click" VerticalAlignment="Top" HorizontalAlignment="Right" Visibility="Collapsed" />
                            <Button Background="Transparent" BorderThickness="0" Click="LogTBExpand_Click" VerticalAlignment="Top">
                                <Image Source="Images/down.png" Height="20" />
                            </Button>
                        </Grid>
                        <Grid Grid.Row="1">
                            <ListBox Grid.Column="1" x:Name="StateList" Height="30" >
                                <ListBox.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <StackPanel Orientation="Horizontal" />
                                    </ItemsPanelTemplate>
                                </ListBox.ItemsPanel>
                            </ListBox>
                        </Grid>
                        <Grid Grid.Row="2">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
@@ -52,33 +70,6 @@
                            </StackPanel>
                            <TextBlock x:Name="debugMessage" Grid.Column="1" VerticalAlignment="Center" Text="" Margin="12 0 " />
                            <StackPanel Orientation="Horizontal"  Grid.Column="2" HorizontalAlignment="Right">
                                <!--<Button Content="test" Click="Button_Click" />
                            <ComboBox SelectedIndex="0" x:Name="d">
                                <ComboBoxItem >向上</ComboBoxItem>
                                <ComboBoxItem >向下</ComboBoxItem>
                            </ComboBox>
                            <ComboBox SelectedIndex="0" x:Name="v">
                                <ComboBoxItem >0.1</ComboBoxItem>
                                <ComboBoxItem >0.2</ComboBoxItem>
                                <ComboBoxItem >0.3</ComboBoxItem>
                                <ComboBoxItem >0.4</ComboBoxItem>
                                <ComboBoxItem >0.5</ComboBoxItem>
                                <ComboBoxItem >0.6</ComboBoxItem>
                                <ComboBoxItem >0.7</ComboBoxItem>
                                <ComboBoxItem >0.8</ComboBoxItem>
                                <ComboBoxItem >0.9</ComboBoxItem>
                                <ComboBoxItem >1</ComboBoxItem>
                                <ComboBoxItem >2</ComboBoxItem>
                                <ComboBoxItem >3</ComboBoxItem>
                                <ComboBoxItem >4</ComboBoxItem>
                                <ComboBoxItem >5</ComboBoxItem>
                                <ComboBoxItem >6</ComboBoxItem>
                                <ComboBoxItem >7</ComboBoxItem>
                                <ComboBoxItem >8</ComboBoxItem>
                                <ComboBoxItem >9</ComboBoxItem>
                            </ComboBox>
                            <Button Content="移动"  Padding="15 0 15 0" Margin="5" Click="TestMoveClick" />-->
                                <ComboBox SelectedIndex="0" x:Name="taskName" VerticalAlignment="Center">
                                    <ComboBoxItem >凛冬</ComboBoxItem>
                                    <ComboBoxItem >卡勒特</ComboBoxItem>
@@ -89,12 +80,11 @@
                                    <ComboBoxItem>读角色位置</ComboBoxItem>
                                    <ComboBoxItem>移动进门</ComboBoxItem>
                                </ComboBox>
                                <Button Content="清空"  Padding="15 0 15 0" Margin="5" Click="ClearLog_Click" />
                                <Button Content="运行(Home)"  Padding="15 0 15 0" Margin="5" Click="Run_Click" x:Name="RunningButton" />
                                <Button Content="运行"  Padding="15 0 15 0" Margin="5" Click="Run_Click" x:Name="RunningButton" />
                            </StackPanel>
                        </Grid>
                    </Grid>
                </Border>
            </TabItem>
src/RichCreator/MainWindow.xaml.cs
@@ -22,6 +22,7 @@
using RichCreator.Maps.Kalete;
using ZTImage.Collections;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
namespace RichCreator
{
@@ -34,7 +35,7 @@
        public MainWindow()
        {
            InitializeComponent();
            G.Instance.EnableWriter(this.writeDebug, this.writeInfo, this.writeRemainTime, this.CancelConfirm,this.stopTaskUI);
            G.Instance.EnableWriter(this.writeDebug, this.writeInfo, this.writeRemainTime, this.CancelConfirm,this.stopTaskUI,this.updateState);
            viewModel = new ConfigViewModel();
            this.DataContext = viewModel;
        }
@@ -121,6 +122,36 @@
        private void ClearLog_Click(object sender, RoutedEventArgs e)
        {
            this.LogTB.Text = string.Empty;
        }
        /// <summary>
        /// 折叠日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LogTBExpand_Click(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            Image img = btn.Content as Image;
            BitmapImage bitmap = null;
            if (this.LogTB.Visibility == Visibility.Collapsed)
            {
                //当前是隐藏状态
                this.LogTB.Visibility = Visibility.Visible;
                this.LogTBClearBtn.Visibility = Visibility.Visible;
                //todo:让日志图像设为up.png
                bitmap = new BitmapImage(new Uri("pack://application:,,,/Images/up.png"));
            }
            else
            {
                this.LogTB.Visibility = Visibility.Collapsed;
                this.LogTBClearBtn.Visibility = Visibility.Collapsed;
                //todo:让日志图像设为down.png
                bitmap = new BitmapImage(new Uri("pack://application:,,,/Images/down.png"));
            }
            img.Source = bitmap;
        }
        /// <summary>
@@ -297,46 +328,40 @@
        /// </summary>
        private void TestToNextDoor()
        {
            ZTRectangle gameRect = ZTRectangle.Empty;
            WindowUtils.GetDnfRect(out gameRect);
            //ZTRectangle gameRect = ZTRectangle.Empty;
            //WindowUtils.GetDnfRect(out gameRect);
            HouseInfo house = new HouseInfo(1, MapType.Kalete, false, null,null);
            DnfRole role = new DnfRole(gameRect);
            role.SetHouse(house);
            //HouseInfo house = new HouseInfo(1, MapType.Kalete, false, null,null);
            //DnfRole role = new DnfRole(gameRect);
            //role.SetHouse(house);
            Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y );
            Task.Run(() => {
                WindowUtils.SetDnfToTop();
                Thread.Sleep(10);
            //Image<Hsv, byte> hsvImage = new Image<Hsv, byte>(gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y );
            //Task.Run(() => {
            //    WindowUtils.SetDnfToTop();
            //    Thread.Sleep(10);
                Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
                image.ROI = new System.Drawing.Rectangle(gameRect.Start.X, gameRect.Start.Y, gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y);
                CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
                image.ROI = System.Drawing.Rectangle.Empty;
            //    Image<Rgb, byte> image = ScreenCapture.Instance.CaptureScreenReturnImage();
            //    image.ROI = new System.Drawing.Rectangle(gameRect.Start.X, gameRect.Start.Y, gameRect.End.X - gameRect.Start.X, gameRect.End.Y - gameRect.Start.Y);
            //    CvInvoke.CvtColor(image, hsvImage, Emgu.CV.CvEnum.ColorConversion.Rgb2Hsv);
            //    image.ROI = System.Drawing.Rectangle.Empty;
                
                //定位点
                ParametersPoint locationCoor = DnfCVHelper.GetLocationPoint(image, gameRect);
                if (locationCoor.Equals(ParametersPoint.Empty))
                {
                    //找不到定位点
                    G.Instance.InfoWriter("找不到定位点");
                    return;
                }
            //    //定位点
            //    ParametersPoint locationCoor = DnfCVHelper.GetLocationPoint(image, gameRect);
            //    if (locationCoor.Equals(ParametersPoint.Empty))
            //    {
            //        //找不到定位点
            //        G.Instance.InfoWriter("找不到定位点");
            //        return;
            //    }
                
                ZTPoint rolePosition = DnfCVHelper.FindRole(hsvImage, gameRect);
                role.UpdatePosition(rolePosition);
            //    ZTPoint rolePosition = DnfCVHelper.FindRole(hsvImage, gameRect);
            //    role.UpdatePosition(rolePosition);
                ZTPoint start=house.ScreenToMapCoordinate(DnfRole.CBToHalfPosition(rolePosition), locationCoor);
                ZTPoint roleFootPosition = house.ScreenToMapCoordinate(role.Position, locationCoor);
                ZTPoint ngp = DnfRole.HalfToFootPosition(house.HousePathInfo.NextGates[0].Point);
                role.MoveToMapPoint(roleFootPosition, ngp);
                G.Instance.InfoWriter($"测试进入下一关的门完成");
            });
            //    role.ToNextGateMove(locationCoor, house.HousePathInfo.NextGates[0].Point);
            //    G.Instance.InfoWriter($"测试进入下一关的门完成");
            //});
        }
@@ -521,6 +546,19 @@
        }
        /// <summary>
        /// 更新指定状态
        /// </summary>
        /// <param name="index"></param>
        /// <param name="text"></param>
        private void updateState(Int32 index, string text)
        {
            this.Dispatcher.BeginInvoke((Action)(() =>
            {
                this.StateList.Items[index] = text;
            }));
        }
        /// <summary>
        /// 开始任务UI设置
        /// </summary>
        private void startTaskUI()
@@ -584,6 +622,12 @@
            }
            //初始状态
            for (Int32 i = 0; i < StateProvider.States.Length; i++)
            {
                this.StateList.Items.Add(StateProvider.States[i].HeaderText+":"+ StateProvider.States[i].Value);
            }
        }
@@ -594,5 +638,6 @@
            IntPtr intPtr = (new WindowInteropHelper(this)).Handle;
            SystemHotKey.UnRegHotKey(intPtr, hotKeyID);
        }
    }
}
src/RichCreator/Maps/Kalete/KaleteMap.cs
@@ -2,6 +2,7 @@
using Emgu.CV.Structure;
using RichCreator.Dnf;
using RichCreator.Jobs.StateMachines;
using RichCreator.Models;
using RichCreator.Utility;
using RichCreator.Utility.Captures;
using RichCreator.Utility.CV;
@@ -32,29 +33,30 @@
        /// NextIndex=-2,出错
        /// </summary>
        private static readonly HouseInfo[] Houses = new HouseInfo[] {
            new HouseInfo (0 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (1 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (2 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (3 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (4 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (5 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (6 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (7 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (8 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},new int[]{20,21,22,23 }),
            new HouseInfo (9 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (10,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (11,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (12,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (13,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (14,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (15,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (16,MapType.Kalete,true ,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (17,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (18,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (19,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null)
            new HouseInfo (0 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (1 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (2 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (3 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (4 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (5 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (6 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,1),
            new HouseInfo (7 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,6),
            new HouseInfo (8 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},new int[]{20,21,22,23 },7),
            new HouseInfo (9 ,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (10,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (11,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (12,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,13),
            new HouseInfo (13,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,8),
            new HouseInfo (14,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (15,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (16,MapType.Kalete,true ,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,17),
            new HouseInfo (17,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,12),
            new HouseInfo (18,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0),
            new HouseInfo (19,MapType.Kalete,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,0)
        };
        
        private Int32 runningStep = RunningStep.None;
        private DateTime startRoleTime = DateTime.Now;
        /// <summary>
        /// 开始
@@ -66,12 +68,8 @@
        public override ZTResult Start(Int32 runningStep)
        {
            this.runningStep = runningStep;
            WindowUtils.SetDnfToTop();
            WindowUtils.SetDnfToTop();
            if (runningStep < RunningStep.War)
            {
                if (!MoveToSunan())
@@ -104,10 +102,10 @@
                {
                    return ZTResult.Cancel;
                }
                DateTime startHouse = DateTime.Now;
                ZTResult killResult = KillMonster();
                DateTime startMapTime = DateTime.Now;
                ZTResult killResult = KillOfMap();
                StateProvider.Instance.RoleTimePassed = (Int32)(DateTime.Now - startRoleTime).TotalSeconds;
                StateProvider.Instance.PreMapTime= (Int32)(DateTime.Now - startMapTime).TotalSeconds;
                if (killResult == ZTResult.Success)
                {
                    //捡东西
@@ -118,17 +116,13 @@
                        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) + "秒");
                    G.Instance.InfoWriter("单次刷图完成");
                    //查询疲劳值
                    Int32 pilaozhi = DnfCVHelper.GetPiLaoZhi(this.GameRect);
                    G.Instance.InfoWriter("疲劳值:" + pilaozhi);
                    if (pilaozhi <= 0)
                    {
@@ -223,28 +217,26 @@
        /// 刷房间
        /// </summary>
        /// <returns></returns>
        private ZTResult KillMonster()
        private ZTResult KillOfMap()
        {
            bool ret = false;
            DateTime startMapTime = DateTime.Now;
            if (!IsEntryMap())
            {
                G.Instance.InfoWriter("未找到进入凛冬");
                G.Instance.InfoWriter("未找到进入卡勒特");
                return ZTResult.Failed;
            }
            G.Instance.InfoWriter("进入卡勒特");
            Int32 preHouseIndex = -1;
            Int32 houseIndex = -1;
            G.Instance.InfoWriter("进入卡勒特");
            Int32 houseIndex = -1;
            //技能加成
            G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.Space);
            //循环刷房间
            while (true)
            {
                preHouseIndex = houseIndex;
                DateTime startHouseTime = DateTime.Now;
                Int32 fromHouseIndex = houseIndex;
                //看房间号
                ret = this.MiniMap.GetCurrentHouseIndexWaitTimeout(out houseIndex, null, this.CancelToken, 3 * 1000);
                if (!ret)
@@ -253,15 +245,20 @@
                    return ZTResult.Failed;
                }
                G.Instance.InfoWriter("进入房间->" + houseIndex.ToString());
                StateProvider.Instance.HouseIndex = houseIndex;
                G.Instance.InfoWriter($"进入房间({houseIndex})");
                HouseInfo houseInfo = Houses[houseIndex];
                this.Role.SetHouse(houseInfo);
                DateTime startTime = DateTime.Now;
                KillMonsterStateMachine kmsm = new KillMonsterStateMachine(this, houseInfo,this.Role);
                ZTResult smresult = kmsm.Work(2 * 60 * 1000,preHouseIndex,this.runningStep);
                Int32 roomTotalSecond = (Int32)(DateTime.Now - startTime).TotalSeconds;
                G.Instance.InfoWriter("房间刷完,用时:" + (roomTotalSecond / 60) + "分" + (roomTotalSecond % 60) + "秒");
                ZTResult smresult = kmsm.Work(2 * 60 * 1000,fromHouseIndex,this.runningStep);
                G.Instance.InfoWriter($"房间刷完({houseIndex})");
                StateProvider.Instance.RoleTimePassed = (Int32)(DateTime.Now - startRoleTime).TotalSeconds;
                StateProvider.Instance.MapTimePassed= (Int32)(DateTime.Now - startMapTime).TotalSeconds;
                StateProvider.Instance.PreHouseTime = (Int32)(DateTime.Now - startHouseTime).TotalSeconds;
                runningStep = RunningStep.None;
                if (smresult == ZTResult.Success)
src/RichCreator/Maps/Lindong/LindongMap.cs
@@ -33,26 +33,26 @@
        /// NextIndex=-2,出错
        /// </summary>
        private static readonly HouseInfo[] Houses = new HouseInfo[] {
            new HouseInfo (0 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (1 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (2 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (3 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (4 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (5 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (6 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (7 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (8 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (9 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (10,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (11,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (12,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (13,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (14,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (15,MapType.Lingdong,true ,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (16,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (17,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (18,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null),
            new HouseInfo (19,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null)
            new HouseInfo (0 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (1 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (2 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (3 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (4 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (5 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (6 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (7 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (8 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (9 ,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (10,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (11,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (12,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (13,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (14,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (15,MapType.Lingdong,true ,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (16,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (17,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (18,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1),
            new HouseInfo (19,MapType.Lingdong,false,new HIDCode[] { HIDCode.A,HIDCode.D,HIDCode.X},null,-1)
        };
        
        private Int32 runningStep = RunningStep.None;
src/RichCreator/Models/RunningModel.cs
@@ -24,6 +24,8 @@
        public static void UpdateAccountIndex(Int32 accountIndex)
        {
            StateProvider.Instance.AccountIndex = accountIndex;
            var config = ConfigHelper.GetInstance<RunningModel>();
            config.AccountIndex = accountIndex;
            ConfigHelper.SetInstance<RunningModel>(config);
@@ -39,6 +41,8 @@
        public static void UpdateRoleIndex(Int32 roleIndex)
        {
            StateProvider.Instance.RoleIndex = roleIndex;
            var config = ConfigHelper.GetInstance<RunningModel>();
            config.RoleIndex = roleIndex;
            ConfigHelper.SetInstance<RunningModel>(config);
src/RichCreator/Models/StateInfoItem.cs
New file
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RichCreator.Models
{
    /// <summary>
    /// 状态基类
    /// </summary>
    public class StateInfoItem
    {
        public StateInfoItem(string key, string headerText, string value)
        {
            this.Key = key;
            this.HeaderText = headerText;
            this.Value = value;
        }
        public int Index { get; set; }
        public string Key { get; set; }
        public string HeaderText { get; set; }
        public string Value { get; set; }
    }
}
src/RichCreator/Models/StateProvider.cs
New file
@@ -0,0 +1,214 @@
using RichCreator.Utility.InputControl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RichCreator.Models
{
    /// <summary>
    /// 状态信息
    /// </summary>
    public class StateProvider
    {
        private StateProvider()
        { }
        /// <summary>
        /// 支持的状态
        /// </summary>
        public static readonly StateInfoItem[] States = new StateInfoItem[] {
            new StateInfoItem ("AccountIndex","账号","-1"),
            new StateInfoItem ("RoleIndex","角色","-1"),
            new StateInfoItem ("HouseIndex","房间","-1"),
            new StateInfoItem("PreRoleTime","前角色","0m0s"),
            new StateInfoItem ("RoleTimePassed","角色","0m0s"),
            new StateInfoItem ("PreMapTime","前图","0m0s"),
            new StateInfoItem ("MapTimePassed","本图","0m0s"),
            new StateInfoItem ("PreHouseTime","前房","0m0s")
            //new StateInfoItem ("DirectionKey","方向按键","无"),
            //new StateInfoItem ("AttackKey","攻击按键","无")
        };
        private Dictionary<string, StateInfoItem> stateDic = new Dictionary<string, StateInfoItem>();
        private void SetValue(string key, string value)
        {
            if (!stateDic.ContainsKey(key))
            {
                return;
            }
            StateInfoItem item = stateDic[key];
            item.Value = value;
            //更新值
            G.Instance.UpdateState(item.Index, item.HeaderText + ":" + value);
        }
        private static StateProvider instance = null;
        private static object lockHelper = new object();
        public static StateProvider Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (lockHelper)
                    {
                        if (instance == null)
                        {
                            instance = new StateProvider();
                            ///所有状态添加到字典中
                            for (int i = 0; i < States.Length; i++)
                            {
                                States[i].Index = i;
                                if (!instance.stateDic.ContainsKey(States[i].Key))
                                {
                                    instance.stateDic.Add(States[i].Key, States[i]);
                                }
                            }
                        }
                    }
                }
                return instance;
            }
        }
        /// <summary>
        /// 当前账号
        /// </summary>
        public Int32 AccountIndex
        {
            set
            {
                SetValue("AccountIndex", value.ToString());
            }
        }
        /// <summary>
        /// 角色索引
        /// </summary>
        public int RoleIndex
        {
            set
            {
                SetValue("RoleIndex", value.ToString());
            }
        }
        /// <summary>
        /// 房间索引
        /// </summary>
        public Int32 HouseIndex
        {
            set
            {
                SetValue("HouseIndex", value.ToString());
            }
        }
        /// <summary>
        /// 前角色所花时间
        /// </summary>
        public Int32 PreRoleTime
        {
            set
            {
                SetValue("PreRoleTime", (value / 60) + "m" + (value % 60) + "s");
            }
        }
        /// <summary>
        /// 角色已用时间
        /// </summary>
        public Int32 RoleTimePassed
        {
            set
            {
                SetValue("RoleTimePassed", (value / 60) + "m" + (value % 60) + "s");
            }
        }
        /// <summary>
        /// 上一次地图时间
        /// </summary>
        public Int32 PreMapTime
        {
            set
            {
                SetValue("PreMapTime", (value / 60) + "m" + (value % 60) + "s");
            }
        }
        /// <summary>
        /// 刷图已用时间
        /// </summary>
        public Int32 MapTimePassed
        {
            set
            {
                SetValue("MapTimePassed", (value / 60) + "m" + (value % 60) + "s");
            }
        }
        /// <summary>
        /// 刷上一个房间所有时间
        /// </summary>
        public Int32 PreHouseTime
        {
            set
            {
                SetValue("PreHouseTime", (value / 60) + "m" + (value % 60) + "s");
            }
        }
        /// <summary>
        /// 方向按键
        /// </summary>
        public string DirectionKey
        {
            set
            {
                SetValue("DirectionKey", value);
            }
        }
        /// <summary>
        /// 攻击按键
        /// </summary>
        public HIDCode AttackKey
        {
            set
            {
                SetValue("AttackKey", value.ToString());
            }
        }
        ///// <summary>
        ///// 角色位置
        ///// </summary>
        //public Int32 RolePosition
        //{
        //    set
        //    {
        //    }
        //}
        ///// <summary>
        ///// 怪物位置
        ///// </summary>
        //public Int32 MonsterPosition
        //{
        //    set
        //    {
        //    }
        //}
    }
}
src/RichCreator/RichCreator.csproj
@@ -107,6 +107,8 @@
    <Compile Include="Dnf\DnfRole.cs" />
    <Compile Include="Dnf\IMiniMap.cs" />
    <Compile Include="Dnf\MapInfo.cs" />
    <Compile Include="Models\StateInfoItem.cs" />
    <Compile Include="Models\StateProvider.cs" />
    <Compile Include="Utilitys\GameUtils.cs" />
    <Compile Include="Maps\Kalete\KaleteMap.cs" />
    <Compile Include="Maps\Kalete\KaleteMiniMap.cs" />
@@ -197,6 +199,8 @@
      <SubType>Designer</SubType>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Resource Include="Images\down.png" />
    <Resource Include="Images\up.png" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
src/RichCreator/StateMachines/KillMonsterStateMachine.cs
@@ -2,10 +2,12 @@
using Emgu.CV.Structure;
using RichCreator.Dnf;
using RichCreator.Maps.Kalete;
using RichCreator.Models;
using RichCreator.StateMachines;
using RichCreator.Utility;
using RichCreator.Utility.Captures;
using RichCreator.Utility.CV;
using RichCreator.Utility.Dnf;
using RichCreator.Utility.InputControl;
using RichCreator.Utility.Maps;
using RichCreator.Utility.Skills;
@@ -51,6 +53,11 @@
        public KillMonsterStateMachine(MapInfo map,HouseInfo house, DnfRole role)
        {
            if (house.HousePathInfo.LoopPoint.Equals(ZTPoint.Empty))
            {
                throw new ArgumentOutOfRangeException("寻路中不存在循环点");
            }
            this.map = map;
            this.house = house;
            this.role = role;
@@ -72,10 +79,9 @@
        /// <param name="cancellationToken"></param>
        /// <param name="timeoutMillSecond"></param>
        /// <returns></returns>
        public ZTResult Work(Int32 timeoutMillSecond,Int32 preHouseIndex,Int32 runningStep)
        public ZTResult Work(Int32 timeoutMillSecond,Int32 fromHouseIndex,Int32 runningStep)
        {
            bool imageIsChange = false;//图像是否改变
            Int32 nextGate = 0;
            DateTime expireTime = DateTime.Now.AddMilliseconds(timeoutMillSecond);
            
            while (true)
@@ -83,14 +89,14 @@
                if (map.CancelToken.IsCancellationRequested)
                {
                    G.Instance.DebugWriter("取消刷图");
                    this.role.StopMove();
                    this.role.StopMove("cancel");
                    return ZTResult.Cancel;
                }
                if (DateTime.Now > expireTime)
                {
                    G.Instance.DebugWriter("刷图超时");
                    this.role.StopMove();
                    this.role.StopMove("timeout");
                    return ZTResult.Timeout;
                }
@@ -112,7 +118,10 @@
                {
                    case KillMonsterStates.Start:
                        //开始
                        this.map.EntryHousePrework(this.house.Index, preHouseIndex);
                        if (this.house.FromHouseIndex == fromHouseIndex)
                        {
                            this.map.EntryHousePrework(this.house.Index, fromHouseIndex);
                        }
                        SetState(KillMonsterStates.IsLastHouse, true);
                        break;
                    case KillMonsterStates.IsLastHouse:
@@ -136,7 +145,6 @@
                        //是否有奖励界面
                        if (DnfCVHelper.IsJiangli(image, map.GameRect))
                        {
                            G.Instance.InfoWriter("has jiangli");
                            SetState(KillMonsterStates.TurnAroundCard, false);
                        }
                        else
@@ -178,7 +186,6 @@
                        break;
                    case KillMonsterStates.FindRole:
                        //主角
                        //定位点
                        if (this.house.WithoutNumber.Count <= 0)
                        {
@@ -201,26 +208,32 @@
                        ZTPoint roleCBPosition = DnfCVHelper.FindRole(hsvImage, map.GameRect);
                        if (roleCBPosition.Equals(ZTPoint.Empty))
                        {
                            SetState(KillMonsterStates.FindRoleMove, false);
                            //未找到角色
                            if (!this.role.IsMoving)
                            {
                                SetState(KillMonsterStates.FindRoleMove, false);
                            }
                            else
                            {
                                SetState(KillMonsterStates.IsLastHouse, true);
                            }
                        }
                        else
                        {
                            if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.FindRoleMove))
                            if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
                            {
                                this.role.StopMove();
                                this.role.StopMove("update cb position");
                            }
                            role.UpdatePosition(roleCBPosition);
                            SetState(KillMonsterStates.FindMonster, false);
                        }
                        break;
                    case KillMonsterStates.FindRoleMove:
                        //todo:让主角移动(原:有怪攻击一下,无怪移动一下)
                        FindRoleMove();
                        break;
                    case KillMonsterStates.FindMonster:
                        //找怪
                        //找怪
                        this.stateMonsters = DnfCVHelper.FindMonster(hsvImage, map.GameRect);
                        if (this.stateMonsters.Length > 0)
                        {
                            G.Instance.DebugWriter(string.Format("找到{0}个怪", this.stateMonsters.Length));
@@ -228,13 +241,16 @@
                        }
                        else
                        {
                            if (this.role.IsMoveIntent(MoveIntent.AttackMove))
                            {
                                this.role.StopMove("find monster to pickup thing");
                            }
                            SetState(KillMonsterStates.PickupThing, false);
                        }
                        break;
                    case KillMonsterStates.PickupThing:
                        //拾取物品
                        //todo: PickupThing();
                        SetState(KillMonsterStates.FindDoor, false);
                        PickupThing();
                        break;
                    case KillMonsterStates.FindDoor:
                        //查找门
@@ -249,39 +265,9 @@
                        //向门移动, 进门
                        EntryDoor();
                        break;
                    case KillMonsterStates.InNextGatePoint:
                        //是否在进门点
                        ParametersPoint nextGatePoint = ParametersPoint.Empty;
                        ZTPoint rmhp=this.house.ScreenToMapCoordinate(this.role.HalfPosition, this.stateScreenLocation);
                        if (this.house.IsInNextGatePoint(out nextGatePoint,rmhp))
                        {
                            SetState(KillMonsterStates.ToLoopPoint, false);
                        }
                        else
                        {
                            //不在进门点
                            SetState(KillMonsterStates.ToNextGatePoint, false);
                        }
                        break;
                    case KillMonsterStates.ToNextGatePoint:
                        //移到进门点
                        ZTPoint rmp = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
                        ZTPoint ngp = DnfRole.HalfToFootPosition(this.house.HousePathInfo.NextGates[nextGate].Point);
                        this.role.MoveToMapPoint(rmp, ngp);
                        nextGate++;
                        nextGate = nextGate % this.house.HousePathInfo.NextGates.Count;
                        SetState(KillMonsterStates.IsLastHouse, true);
                        break;
                    case KillMonsterStates.ToLoopPoint:
                        //移动到循环点
                        if (!this.house.HousePathInfo.LoopPoint.Equals(ZTPoint.Empty))
                        {
                            //开始移动
                            ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
                            this.role.MoveToMapPoint(roleMapPoint, this.house.HousePathInfo.LoopPoint);
                        }
                        SetState(KillMonsterStates.IsLastHouse, true);
                    case KillMonsterStates.ToLoop:
                        //巡逻
                        ToLoop();
                        break;
                    case KillMonsterStates.CalcAttackPoint:
                        //判断使用何技能,计算攻击移动距离, 是否需要移动
@@ -292,13 +278,12 @@
                        ReleaseSkill();
                        break;
                    case KillMonsterStates.AttackMove:
                        //todo:攻击移动
                        //攻击移动
                        AttackMove();
                        break;
                    case KillMonsterStates.Exit:
                        //结束
                        G.Instance.DebugWriter("退出!~");
                        this.role.StopMove();
                        this.role.StopMove("exit");
                        if (this.isSuccess)
                        {
                            return ZTResult.Success;
@@ -306,7 +291,7 @@
                        return ZTResult.Failed;
                }
                
                G.Instance.DebugWriter("next state:" + currentState.ToString());
                G.Instance.DebugWriter($"next state:{currentState},capture screen:{needCaptureScreen}");
            }
        }
@@ -316,32 +301,69 @@
        /// </summary>
        private void FindRoleMove()
        {
            if (this.role.IsMoving)
            {
                if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
                {
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else
                {
                    //不是则停止
                    this.role.StopMove("find role other");
                }
            }
            this.role.FindRoleMove();
            SetState(KillMonsterStates.FindRole, true);
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        DateTime pickupTime = DateTime.MinValue;
        /// <summary>
        /// 拾取物品
        /// </summary>
        private void PickupThing()
        {
            ////拾取物品,获取最近一个物品位置并步行过去
            //ZTPoint thingItemPosition = GetNearlyThingItem(image, role.Position);
            //if (!thingItemPosition .Equals( ZTPoint.Empty))
            //{
            //    if (this.role.IsMoving && !this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
            //    {
            //        this.role.StopMove();
            //    }
            //拾取物品中,返回
            if (this.role.IsMoveIntent(MoveIntent.PickupMove))
            {
                SetState(KillMonsterStates.IsLastHouse, true);
                return;
            }
            //    this.role.PickupMove(this.role.Position, thingItemPosition);
            //    //return new KillMonsterStateResult(STATE_FindMonster, true);
            //}
            ZTPoint screenThingPosition = GetNearlyThingItem(hsvImage, role.Position);
            //是否有物品
            if (!screenThingPosition.Equals(ZTPoint.Empty))
            {
                //有其它移动,则停止
                if (this.role.IsMoving&&!this.role.IsMoveIntent(MoveIntent.PickupMove))
                {
                    this.role.StopMove("pickup moveing");
                }
            //if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
            //{
            //    this.role.StopMove();
            //}
                //第一次发现有物品后,等一秒再去拾取,防物品刚出来时的去错误的位置拾取
                if (pickupTime == DateTime.MinValue)
                {
                    pickupTime = DateTime.Now.AddSeconds(1);
                }
                if (pickupTime > DateTime.Now)
                {
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                ////todo:remove
                //hsvImage.Save(DateTime.Now.ToString("HH_mm_ss_fff")+"_" + Guid.NewGuid().ToString()+".png");
                this.role.PickupMove(screenThingPosition,this.stateScreenLocation);
                SetState(KillMonsterStates.IsLastHouse, true);
            }
            else
            {
                SetState(KillMonsterStates.FindDoor, false);
            }
        }
        /// <summary>
@@ -363,20 +385,15 @@
                    //要进入门的允许区域
                    ZTPoint nextGatePoint = this.house.GetNextGatePoint(door.Value);
                    ZTRectangle doorRect = new ZTRectangle(nextGatePoint.X - 70, nextGatePoint.Y - 70, nextGatePoint.X + 70, nextGatePoint.Y + 70);
                    G.Instance.InfoWriter("has door:" + mapDoorPoint.ToString()+",rect:"+doorRect.ToString());
                    if (GeoHelper.IsInRect(mapDoorPoint, doorRect))
                    {
                        G.Instance.InfoWriter("in door");
                        this.state_DoorDirect = door.Value;
                        this.state_DoorPosition = door.Key;
                        break;
                    }
                }
            }
            
            if (!this.state_DoorPosition.Equals(ZTPoint.Empty))
            {
@@ -385,8 +402,8 @@
            }
            else
            {
                //未找到门,是否存进门点
                SetState(KillMonsterStates.InNextGatePoint, false);
                //未找到门,巡逻
                SetState(KillMonsterStates.ToLoop, false);
            }
        }
@@ -395,12 +412,19 @@
        /// </summary>
        private void EntryDoor()
        {
            //已经开始进门
            if (this.role.IsMoving)
            {
                this.role.StopMove("entry door other moving");
            }
            const Int32 offsetX = 200;
            const Int32 offsetY = 100;
            ZTRectangle doorRect = new ZTRectangle(this.state_DoorPosition.X - offsetX, this.state_DoorPosition.Y - offsetY, this.state_DoorPosition.X + offsetX, this.state_DoorPosition.Y + offsetY);
            if (tryEntryDoor && GeoHelper.IsInRect(this.role.RoleCBPosition, doorRect))
            if (tryEntryDoor && GeoHelper.IsInRect(this.role.RoleCBPosition.Sub(DnfRole.RoleHalfOffset), doorRect))
            {
                //离门太近,先向外走,再向门走
                Int32 limitLine = 0;
                Int32 diff = 0;
                //传过来人物坐标和门的坐标,根据门的朝向计算人物走向
@@ -460,32 +484,7 @@
            }
            else
            {
                //先到进门点
                ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
                ZTPoint nextGatePoint = this.house.GetNextGatePoint(this.state_DoorDirect);
                List<ZTPoint> paths = this.house.FindPath(roleMapPoint, DnfRole.HalfToFootPosition(nextGatePoint));
                //再到门后50像素
                ZTPoint dp = this.house.ScreenToMapCoordinate(this.state_DoorPosition, this.stateScreenLocation);
                ZTPoint doorPoint = DnfRole.HalfToFootPosition(dp);
                switch (this.state_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.role.MovePaths(roleMapPoint, paths);
                this.role.EntryDoorMove(this.state_DoorPosition, this.stateScreenLocation, this.state_DoorDirect);
                tryEntryDoor = true;
            }
@@ -505,6 +504,10 @@
            skillReleasePoint = AttackRectangle.GetAttackPoint(map.GameRect, role.HalfPosition, stateMonsters, attackSkill, out roleDirection, out needMove);
            if (!needMove)
            {
                if (this.role.IsMoving)
                {
                    this.role.StopMove("calc attack");
                }
                G.Instance.DebugWriter(string.Format("不需移动直接发技能,距离:{0}", skillReleasePoint.ToString()));
                SetState(KillMonsterStates.ReleaseSkill, false);
            }
@@ -519,8 +522,24 @@
        /// </summary>
        private void AttackMove()
        {
            if (this.role.IsMoving)
            {
                if (this.role.IsMoveIntent(MoveIntent.AttackMove))
                {
                    //todo:添加如果是攻击移动中,如果怪物偏差太大则重新计算
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else
                {
                    //不是则停止
                    this.role.StopMove("attack move other");
                }
            }
            G.Instance.DebugWriter("attack move :" + skillReleasePoint.ToString() + ",role:" + role.Position.ToString() + ",monster1:" + stateMonsters[0].ToString() + ",skill:" + this.house.Skills.SyncPeek().Key.ToString());
            this.role.AttackMoveTo(skillReleasePoint,this.stateScreenLocation);
            this.role.AttackMove(skillReleasePoint, this.stateScreenLocation);
            SetState(KillMonsterStates.FindRole, true);
        }
        
@@ -529,9 +548,8 @@
        /// </summary>
        private void ReleaseSkill()
        {
            this.role.StopMove();
            SkillInfo skill = this.house.Skills.SyncDeQueue();
            StateProvider.Instance.AttackKey = skill.Key;
            if (roleDirection != HIDCode.NoEvent)
            {
                G.Instance.InputControl.PressKey(100, roleDirection);
@@ -553,6 +571,31 @@
            G.Instance.DebugWriter(string.Format("发完技能,技能按键:{0},技能名称:{1}", skill.Key, skill.SkillName));
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        /// <summary>
        /// 巡逻
        /// </summary>
        private void ToLoop()
        {
            //巡逻
            if (this.role.IsMoving)
            {
                if (this.role.IsMoveIntent(MoveIntent.ToLoop))
                {
                    //进行中,则返回
                    SetState(KillMonsterStates.IsLastHouse, true);
                    return;
                }
                else
                {
                    //不是则停止
                    this.role.StopMove("to loop other");
                }
            }
            this.role.LoopMove(this.stateScreenLocation);
            SetState(KillMonsterStates.IsLastHouse, true);
        }
        #endregion
        /// <summary>
@@ -560,22 +603,22 @@
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public ZTPoint GetNearlyThingItem(Image<Rgb, byte> image, ZTPoint rolePosition)
        public ZTPoint GetNearlyThingItem(Image<Hsv, byte> image, ZTPoint rolePosition)
        {
            List<ZTPoint> points = DnfCVHelper.GetThingItemPoints(image, map.GameRect);
            if (points.Count <= 0)
            ZTPoint[] points = DnfCVHelper.FindThings(image, map.GameRect);
            if (points.Length <= 0)
            {
                return ZTPoint.Empty;
            }
            if (points.Count == 1)
            if (points.Length == 1)
            {
                return points[0];
            }
            double distance = 0;
            ZTPoint result = ZTPoint.Empty;
            for (int i = 0; i < points.Count; i++)
            for (int i = 0; i < points.Length; i++)
            {
                double temp = ZTImage.Utils.GetDistance(rolePosition.X, rolePosition.Y, points[i].X, points[i].Y);
                if (i == 0)
@@ -672,9 +715,7 @@
            PickupThing,//拾取物品
            FindDoor,//查找门, 是否找到门
            EntryDoor,//向门移动, 进门
            InNextGatePoint,//是否在进门点
            ToNextGatePoint,//移至进门点
            ToLoopPoint,//移至巡逻点
            ToLoop,//巡逻
            
src/RichCreator/configs/RichCreator.config
@@ -5,11 +5,11 @@
  <StartWaitSecond>300</StartWaitSecond>
    <RoleCount>10</RoleCount>
  <NotificationWechat>true</NotificationWechat>
  <UserName1>2228607100</UserName1>
    <Password1>a5m1nf0g00d</Password1>
  <!--<UserName1>2228607100</UserName1>
    <Password1>a5m1nf0g00d</Password1>-->
  <!--<UserName1>1258493488</UserName1>
    <Password1>cc11111111</Password1>-->
  <UserName1>1258493488</UserName1>
    <Password1>cc11111111</Password1>
    <!--<UserName2>2228607100</UserName2>
    <Password2>a5m1nf0g00d</Password2>-->
    <UserName3></UserName3>
src/RichCreator/configs/kalete.txt
@@ -1,5 +1,5 @@
//0
{"Width":896,"Height":686,"Obstacles":[{"Points":[{"X":2,"Y":320},{"X":460,"Y":310},{"X":493,"Y":319},{"X":556,"Y":334},{"X":668,"Y":344},{"X":759,"Y":330},{"X":873,"Y":308},{"X":893,"Y":300},{"X":891,"Y":1},{"X":2,"Y":3}],"Length":10},{"Points":[{"X":2,"Y":552},{"X":71,"Y":545},{"X":76,"Y":427},{"X":165,"Y":439},{"X":166,"Y":521},{"X":253,"Y":559},{"X":703,"Y":550},{"X":703,"Y":521},{"X":823,"Y":513},{"X":834,"Y":568},{"X":893,"Y":559},{"X":893,"Y":684},{"X":4,"Y":683}],"Length":13}],"LocationPoints":[{"Point":{"X":797,"Y":348},"Parameter":0},{"Point":{"X":671,"Y":348},"Parameter":1},{"Point":{"X":547,"Y":348},"Parameter":2},{"Point":{"X":423,"Y":348},"Parameter":3},{"Point":{"X":298,"Y":347},"Parameter":4},{"Point":{"X":172,"Y":348},"Parameter":5},{"Point":{"X":47,"Y":348},"Parameter":6}],"FindPathPoints":[{"X":51,"Y":392},{"X":438,"Y":418},{"X":775,"Y":400}],"LoopPoint":{"X":0,"Y":0},"FindPathLines":[{"P1":{"X":51,"Y":392},"P2":{"X":775,"Y":400}},{"P1":{"X":438,"Y":418},"P2":{"X":775,"Y":400}},{"P1":{"X":438,"Y":418},"P2":{"X":51,"Y":392}}],"NextGates":[{"Point":{"X":833,"Y":348},"Parameter":1}],"PathGuides":[]}
{"Width":896,"Height":686,"Obstacles":[{"Points":[{"X":2,"Y":320},{"X":460,"Y":310},{"X":493,"Y":319},{"X":556,"Y":334},{"X":668,"Y":344},{"X":759,"Y":330},{"X":873,"Y":308},{"X":893,"Y":300},{"X":891,"Y":1},{"X":2,"Y":3}],"Length":10},{"Points":[{"X":2,"Y":552},{"X":71,"Y":545},{"X":76,"Y":427},{"X":165,"Y":439},{"X":166,"Y":521},{"X":253,"Y":559},{"X":703,"Y":550},{"X":703,"Y":521},{"X":823,"Y":513},{"X":834,"Y":568},{"X":893,"Y":559},{"X":893,"Y":684},{"X":4,"Y":683}],"Length":13}],"LocationPoints":[{"Point":{"X":797,"Y":348},"Parameter":0},{"Point":{"X":671,"Y":348},"Parameter":1},{"Point":{"X":547,"Y":348},"Parameter":2},{"Point":{"X":423,"Y":348},"Parameter":3},{"Point":{"X":298,"Y":347},"Parameter":4},{"Point":{"X":172,"Y":348},"Parameter":5},{"Point":{"X":47,"Y":348},"Parameter":6}],"FindPathPoints":[{"X":51,"Y":392},{"X":438,"Y":418},{"X":775,"Y":400}],"LoopPoint":{"X":142,"Y":385},"FindPathLines":[{"P1":{"X":51,"Y":392},"P2":{"X":775,"Y":400}},{"P1":{"X":438,"Y":418},"P2":{"X":775,"Y":400}},{"P1":{"X":438,"Y":418},"P2":{"X":51,"Y":392}}],"NextGates":[{"Point":{"X":833,"Y":348},"Parameter":1}],"PathGuides":[]}
//1
{"Width":896,"Height":720,"Obstacles":[{"Points":[{"X":2,"Y":541},{"X":291,"Y":563},{"X":406,"Y":615},{"X":411,"Y":685},{"X":0,"Y":683}],"Length":5},{"Points":[{"X":88,"Y":475},{"X":158,"Y":514},{"X":246,"Y":512},{"X":295,"Y":523},{"X":356,"Y":534},{"X":421,"Y":524},{"X":413,"Y":473},{"X":336,"Y":455},{"X":267,"Y":445},{"X":215,"Y":426},{"X":148,"Y":431},{"X":103,"Y":442}],"Length":12},{"Points":[{"X":49,"Y":332},{"X":181,"Y":302},{"X":180,"Y":258},{"X":271,"Y":250},{"X":347,"Y":275},{"X":425,"Y":288},{"X":543,"Y":321},{"X":655,"Y":357},{"X":793,"Y":343},{"X":858,"Y":326},{"X":890,"Y":345},{"X":893,"Y":4},{"X":4,"Y":1},{"X":0,"Y":307}],"Length":14},{"Points":[{"X":560,"Y":716},{"X":591,"Y":586},{"X":644,"Y":566},{"X":792,"Y":559},{"X":825,"Y":535},{"X":879,"Y":535},{"X":895,"Y":542},{"X":894,"Y":718}],"Length":8}],"LocationPoints":[{"Point":{"X":86,"Y":391},"Parameter":10},{"Point":{"X":211,"Y":390},"Parameter":11},{"Point":{"X":337,"Y":390},"Parameter":12},{"Point":{"X":465,"Y":391},"Parameter":13},{"Point":{"X":590,"Y":391},"Parameter":14},{"Point":{"X":716,"Y":390},"Parameter":15},{"Point":{"X":841,"Y":391},"Parameter":16},{"Point":{"X":467,"Y":531},"Parameter":20},{"Point":{"X":467,"Y":473},"Parameter":21},{"Point":{"X":468,"Y":414},"Parameter":22},{"Point":{"X":467,"Y":354},"Parameter":23},{"Point":{"X":468,"Y":295},"Parameter":24},{"Point":{"X":467,"Y":237},"Parameter":25},{"Point":{"X":468,"Y":176},"Parameter":26},{"Point":{"X":468,"Y":119},"Parameter":27},{"Point":{"X":469,"Y":59},"Parameter":28}],"FindPathPoints":[{"X":159,"Y":370},{"X":343,"Y":346},{"X":547,"Y":388},{"X":445,"Y":416},{"X":470,"Y":558},{"X":215,"Y":534},{"X":38,"Y":480}],"LoopPoint":{"X":208,"Y":312},"FindPathLines":[{"P1":{"X":159,"Y":370},"P2":{"X":343,"Y":346}},{"P1":{"X":159,"Y":370},"P2":{"X":445,"Y":416}},{"P1":{"X":445,"Y":416},"P2":{"X":547,"Y":388}},{"P1":{"X":343,"Y":346},"P2":{"X":547,"Y":388}},{"P1":{"X":343,"Y":346},"P2":{"X":445,"Y":416}},{"P1":{"X":159,"Y":370},"P2":{"X":547,"Y":388}},{"P1":{"X":445,"Y":416},"P2":{"X":470,"Y":558}},{"P1":{"X":215,"Y":534},"P2":{"X":470,"Y":558}},{"P1":{"X":38,"Y":480},"P2":{"X":159,"Y":370}},{"P1":{"X":38,"Y":480},"P2":{"X":215,"Y":534}}],"NextGates":[{"Point":{"X":468,"Y":571},"Parameter":2}],"PathGuides":[]}
//2
@@ -15,7 +15,7 @@
//7
{"Width":896,"Height":720,"Obstacles":[{"Points":[{"X":891,"Y":674},{"X":328,"Y":675},{"X":320,"Y":630},{"X":310,"Y":560},{"X":226,"Y":520},{"X":120,"Y":510},{"X":5,"Y":494},{"X":0,"Y":513},{"X":1,"Y":719},{"X":893,"Y":718}],"Length":10},{"Points":[{"X":2,"Y":314},{"X":160,"Y":304},{"X":269,"Y":346},{"X":458,"Y":349},{"X":508,"Y":367},{"X":611,"Y":386},{"X":725,"Y":381},{"X":746,"Y":358},{"X":805,"Y":353},{"X":878,"Y":333},{"X":894,"Y":322},{"X":891,"Y":2},{"X":1,"Y":2}],"Length":13}],"LocationPoints":[{"Point":{"X":797,"Y":407},"Parameter":0},{"Point":{"X":672,"Y":406},"Parameter":1},{"Point":{"X":546,"Y":407},"Parameter":2},{"Point":{"X":422,"Y":405},"Parameter":3},{"Point":{"X":297,"Y":406},"Parameter":4},{"Point":{"X":172,"Y":408},"Parameter":5},{"Point":{"X":48,"Y":407},"Parameter":6},{"Point":{"X":87,"Y":391},"Parameter":10},{"Point":{"X":212,"Y":390},"Parameter":11},{"Point":{"X":339,"Y":390},"Parameter":12},{"Point":{"X":464,"Y":391},"Parameter":13},{"Point":{"X":590,"Y":391},"Parameter":14},{"Point":{"X":716,"Y":391},"Parameter":15},{"Point":{"X":842,"Y":391},"Parameter":16}],"FindPathPoints":[{"X":181,"Y":388},{"X":770,"Y":419},{"X":499,"Y":552}],"LoopPoint":{"X":200,"Y":396},"FindPathLines":[{"P1":{"X":181,"Y":388},"P2":{"X":770,"Y":419}},{"P1":{"X":499,"Y":552},"P2":{"X":770,"Y":419}},{"P1":{"X":499,"Y":552},"P2":{"X":181,"Y":388}}],"NextGates":[{"Point":{"X":834,"Y":410},"Parameter":1}],"PathGuides":[]}
//8
{"Width":1120,"Height":600,"Obstacles":[{"Points":[{"X":0,"Y":322},{"X":58,"Y":329},{"X":218,"Y":398},{"X":239,"Y":367},{"X":206,"Y":326},{"X":253,"Y":310},{"X":295,"Y":303},{"X":317,"Y":181},{"X":325,"Y":28},{"X":315,"Y":4},{"X":1,"Y":5}],"Length":11},{"Points":[{"X":486,"Y":313},{"X":630,"Y":311},{"X":709,"Y":314},{"X":818,"Y":340},{"X":936,"Y":334},{"X":1030,"Y":337},{"X":1061,"Y":309},{"X":1103,"Y":200},{"X":1113,"Y":3},{"X":322,"Y":2},{"X":320,"Y":143},{"X":463,"Y":153}],"Length":12},{"Points":[{"X":1118,"Y":510},{"X":968,"Y":506},{"X":823,"Y":526},{"X":810,"Y":590},{"X":1117,"Y":598}],"Length":5}],"LocationPoints":[{"Point":{"X":1023,"Y":334},"Parameter":0},{"Point":{"X":898,"Y":334},"Parameter":1},{"Point":{"X":773,"Y":333},"Parameter":2},{"Point":{"X":648,"Y":334},"Parameter":3},{"Point":{"X":522,"Y":334},"Parameter":4},{"Point":{"X":399,"Y":334},"Parameter":5},{"Point":{"X":272,"Y":334},"Parameter":6},{"Point":{"X":149,"Y":334},"Parameter":7},{"Point":{"X":90,"Y":417},"Parameter":10},{"Point":{"X":216,"Y":417},"Parameter":11},{"Point":{"X":342,"Y":416},"Parameter":12},{"Point":{"X":467,"Y":416},"Parameter":13},{"Point":{"X":593,"Y":417},"Parameter":14},{"Point":{"X":719,"Y":417},"Parameter":15},{"Point":{"X":844,"Y":415},"Parameter":16},{"Point":{"X":970,"Y":417},"Parameter":17},{"Point":{"X":289,"Y":420},"Parameter":20},{"Point":{"X":289,"Y":360},"Parameter":21},{"Point":{"X":289,"Y":301},"Parameter":22},{"Point":{"X":288,"Y":241},"Parameter":23},{"Point":{"X":289,"Y":182},"Parameter":24},{"Point":{"X":289,"Y":123},"Parameter":25},{"Point":{"X":289,"Y":63},"Parameter":26},{"Point":{"X":290,"Y":5},"Parameter":27}],"FindPathPoints":[{"X":159,"Y":419},{"X":409,"Y":415},{"X":687,"Y":409},{"X":929,"Y":431}],"LoopPoint":{"X":813,"Y":372},"FindPathLines":[{"P1":{"X":159,"Y":419},"P2":{"X":409,"Y":415}},{"P1":{"X":409,"Y":415},"P2":{"X":687,"Y":409}},{"P1":{"X":687,"Y":409},"P2":{"X":929,"Y":431}},{"P1":{"X":409,"Y":415},"P2":{"X":929,"Y":431}},{"P1":{"X":159,"Y":419},"P2":{"X":687,"Y":409}}],"NextGates":[{"Point":{"X":288,"Y":453},"Parameter":2}],"PathGuides":[]}
{"Width":1120,"Height":600,"Obstacles":[{"Points":[{"X":0,"Y":322},{"X":58,"Y":329},{"X":218,"Y":398},{"X":239,"Y":367},{"X":206,"Y":326},{"X":253,"Y":310},{"X":295,"Y":303},{"X":317,"Y":181},{"X":325,"Y":28},{"X":315,"Y":4},{"X":1,"Y":5}],"Length":11},{"Points":[{"X":486,"Y":313},{"X":630,"Y":311},{"X":709,"Y":314},{"X":818,"Y":340},{"X":936,"Y":334},{"X":1030,"Y":337},{"X":1061,"Y":309},{"X":1103,"Y":200},{"X":1113,"Y":3},{"X":322,"Y":2},{"X":320,"Y":143},{"X":463,"Y":153}],"Length":12},{"Points":[{"X":1118,"Y":510},{"X":968,"Y":506},{"X":823,"Y":526},{"X":810,"Y":590},{"X":1117,"Y":598}],"Length":5}],"LocationPoints":[{"Point":{"X":1023,"Y":334},"Parameter":0},{"Point":{"X":898,"Y":334},"Parameter":1},{"Point":{"X":773,"Y":333},"Parameter":2},{"Point":{"X":648,"Y":334},"Parameter":3},{"Point":{"X":522,"Y":334},"Parameter":4},{"Point":{"X":399,"Y":334},"Parameter":5},{"Point":{"X":272,"Y":334},"Parameter":6},{"Point":{"X":149,"Y":334},"Parameter":7},{"Point":{"X":90,"Y":417},"Parameter":10},{"Point":{"X":216,"Y":417},"Parameter":11},{"Point":{"X":342,"Y":416},"Parameter":12},{"Point":{"X":467,"Y":416},"Parameter":13},{"Point":{"X":593,"Y":417},"Parameter":14},{"Point":{"X":719,"Y":417},"Parameter":15},{"Point":{"X":844,"Y":415},"Parameter":16},{"Point":{"X":970,"Y":417},"Parameter":17},{"Point":{"X":289,"Y":420},"Parameter":20},{"Point":{"X":289,"Y":360},"Parameter":21},{"Point":{"X":289,"Y":301},"Parameter":22},{"Point":{"X":288,"Y":241},"Parameter":23},{"Point":{"X":289,"Y":182},"Parameter":24},{"Point":{"X":289,"Y":123},"Parameter":25},{"Point":{"X":289,"Y":63},"Parameter":26},{"Point":{"X":290,"Y":5},"Parameter":27}],"FindPathPoints":[{"X":159,"Y":419},{"X":409,"Y":415},{"X":687,"Y":409},{"X":929,"Y":431}],"LoopPoint":{"X":813,"Y":372},"FindPathLines":[{"P1":{"X":159,"Y":419},"P2":{"X":409,"Y":415}},{"P1":{"X":409,"Y":415},"P2":{"X":687,"Y":409}},{"P1":{"X":687,"Y":409},"P2":{"X":929,"Y":431}},{"P1":{"X":409,"Y":415},"P2":{"X":929,"Y":431}},{"P1":{"X":159,"Y":419},"P2":{"X":687,"Y":409}}],"NextGates":[{"Point":{"X":288,"Y":453},"Parameter":2}],"PathGuides":[{"Polygon":{"Points":[{"X":1001,"Y":340},{"X":999,"Y":251},{"X":1062,"Y":247},{"X":1054,"Y":341}],"Length":4},"Target":{"X":1025,"Y":347}},{"Polygon":{"Points":[{"X":975,"Y":342},{"X":974,"Y":253},{"X":1007,"Y":253},{"X":1002,"Y":343}],"Length":4},"Target":{"X":989,"Y":342}},{"Polygon":{"Points":[{"X":949,"Y":261},{"X":978,"Y":263},{"X":979,"Y":345},{"X":940,"Y":342},{"X":935,"Y":262}],"Length":5},"Target":{"X":955,"Y":342}},{"Polygon":{"Points":[{"X":1052,"Y":317},{"X":1056,"Y":260},{"X":1081,"Y":265},{"X":1074,"Y":314}],"Length":4},"Target":{"X":1065,"Y":331}}]}
//9
{"Width":1120,"Height":600,"Obstacles":[{"Points":[{"X":2,"Y":323},{"X":87,"Y":301},{"X":248,"Y":296},{"X":353,"Y":332},{"X":424,"Y":355},{"X":736,"Y":362},{"X":953,"Y":343},{"X":952,"Y":296},{"X":1019,"Y":313},{"X":1105,"Y":357},{"X":1117,"Y":357},{"X":1116,"Y":1},{"X":0,"Y":1}],"Length":13},{"Points":[{"X":156,"Y":595},{"X":182,"Y":540},{"X":252,"Y":491},{"X":407,"Y":472},{"X":468,"Y":507},{"X":708,"Y":507},{"X":753,"Y":473},{"X":912,"Y":443},{"X":1013,"Y":476},{"X":1106,"Y":495},{"X":1118,"Y":597}],"Length":11}],"LocationPoints":[{"Point":{"X":89,"Y":417},"Parameter":10},{"Point":{"X":216,"Y":416},"Parameter":11},{"Point":{"X":341,"Y":418},"Parameter":12},{"Point":{"X":469,"Y":418},"Parameter":13},{"Point":{"X":593,"Y":415},"Parameter":14},{"Point":{"X":718,"Y":418},"Parameter":15},{"Point":{"X":845,"Y":417},"Parameter":16},{"Point":{"X":970,"Y":415},"Parameter":17},{"Point":{"X":1097,"Y":416},"Parameter":18}],"FindPathPoints":[{"X":233,"Y":364},{"X":142,"Y":457},{"X":1026,"Y":368}],"LoopPoint":{"X":944,"Y":399},"FindPathLines":[{"P1":{"X":233,"Y":364},"P2":{"X":1026,"Y":368}},{"P1":{"X":142,"Y":457},"P2":{"X":1026,"Y":368}},{"P1":{"X":142,"Y":457},"P2":{"X":233,"Y":364}}],"NextGates":[{"Point":{"X":73,"Y":416},"Parameter":3}],"PathGuides":[]}
//10
src/test/Program.cs
@@ -189,8 +189,6 @@
        static void Main(string[] args)
        {
            Image<Rgb, byte> image = RichCreator.Utility.Captures.ScreenCapture.Instance.CaptureScreenReturnImage();
            int i = 0;
            ZTImage.Diagnostics.CodeTimer.Timer("test", 100000, () => {
@@ -234,6 +232,11 @@
            Console.ReadKey();
        }
        
    }
}