public static string ScanMaterialName(InventorySection section, out Bitmap nameplate)
        {
            // Grab item name on right
            var refWidth  = 1280.0;
            var refHeight = Navigation.GetAspectRatio() == new Size(16, 9) ? 720.0 : 800.0;

            var width  = Navigation.GetWidth();
            var height = Navigation.GetHeight();

            var reference = new Rectangle(872, 80, 327, 37);

            // Nameplate is in the same place in 16:9 and 16:10
            var region = new RECT(
                Left:   (int)(reference.Left / refWidth * width),
                Top:    (int)(reference.Top / refHeight * height),
                Right:  (int)(reference.Right / refWidth * width),
                Bottom: (int)(reference.Bottom / refHeight * height));

            Bitmap bm = Navigation.CaptureRegion(region);

            nameplate = (Bitmap)bm.Clone();

            // Alter Image
            Scraper.SetGamma(0.2, 0.2, 0.2, ref bm);
            Bitmap n = Scraper.ConvertToGrayscale(bm);

            Scraper.SetInvert(ref n);

            string text = Scraper.AnalyzeText(n);

            text = Regex.Replace(text, @"[\W]", string.Empty).ToLower();

            //UI
            n.Dispose();
            bm.Dispose();

            if (section == InventorySection.CharacterDevelopmentItems)
            {
                return(Scraper.FindClosestDevelopmentName(text));
            }

            if (section == InventorySection.Materials)
            {
                return(Scraper.FindClosestMaterialName(text));
            }

            return(null);
        }
        public static void Scan_Materials(InventorySection section, ref HashSet <Material> materials)
        {
            if (!materials.Contains(new Material("Mora", 0)))
            {
                materials.Add(new Material("Mora", ScanMora()));
            }

            int scrollCount = 0;

            Material material         = new Material(null, 0);
            Material previousMaterial = new Material(null, -1);

            List <Rectangle> rectangles;
            int page = 0;

            // Keep scanning while not repeating any items names
            while (true)
            {
                int rows, cols;
                // Find all items on the screen
                (rectangles, cols, rows) = GetPageOfItems(section, page);

                // Remove last row. Sometimes the bottom of a page of items is caught which results
                // in a faded quantity that can't be parsed. Removing slightly increases the number of pages that
                // need to be scrolled but it's fine.
                var r = rectangles.Take(rectangles.Count() - cols).ToList();

                foreach (var rectangle in r)
                {
                    // Select Material
                    Navigation.SetCursorPos(Navigation.GetPosition().Left + rectangle.Center().X, Navigation.GetPosition().Top + rectangle.Center().Y);
                    Navigation.Click();
                    Navigation.SystemRandomWait(Navigation.Speed.SelectNextInventoryItem);

                    material.name  = ScanMaterialName(section, out Bitmap nameplate);
                    material.count = 0;

                    // Check if new material has been found
                    if (materials.Contains(material))
                    {
                        goto LastPage;
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(material.name))
                        {
                            // Scan Material Number
                            material.count = ScanMaterialCount(rectangle, out Bitmap quantity);
                            if (material.count == 0)
                            {
                                UserInterface.AddError($"Failed to parse quantity for {material.name}");
                                quantity.Save($"./logging/materials/{material.name}_Quantity.png");
                            }
                            materials.Add(material);
                            UserInterface.ResetCharacterDisplay();
                            UserInterface.SetMaterial(nameplate, quantity, material.name, material.count);

                            previousMaterial.name = material.name;
                        }
                    }
                    nameplate.Dispose();
                    Navigation.Wait(150);
                }

                Navigation.SetCursorPos(Navigation.GetPosition().Left + r.Last().Center().X, Navigation.GetPosition().Top + r.Last().Center().Y);
                Navigation.Click();
                Navigation.Wait(150);
                // Scroll to next page
                for (int i = 0; i < rows - 1; i++)
                {
                    scrollCount++;

                    // scroll down
                    for (int k = 0; k < 10; k++)
                    {
                        Navigation.sim.Mouse.VerticalScroll(-1);
                        // skip a scroll
                        if ((k == 7) && ((scrollCount % 3) == 0))
                        {
                            k++;
                            if (scrollCount % 9 == 0)
                            {
                                if (scrollCount == 18)
                                {
                                    scrollCount = 0;
                                }
                                else
                                {
                                    Navigation.sim.Mouse.VerticalScroll(-1);
                                }
                            }
                        }
                        Navigation.SystemRandomWait(Navigation.Speed.InventoryScroll);
                    }
                }
                Navigation.SystemRandomWait(Navigation.Speed.Normal);
                ++page;
            }

LastPage:
            // scroll down as much as possible
            for (int i = 0; i < 20; i++)
            {
                Navigation.sim.Mouse.VerticalScroll(-1);
                Navigation.SystemRandomWait(Navigation.Speed.InventoryScroll);
            }

            Navigation.Wait(500);

            (rectangles, _, _) = GetPageOfItems(section, page);
            bool passby = true;

            for (int i = rectangles.Count - 1; i >= 0; i--)             // Click through but backwards to short-circuit after new materials
            {
                // Select Material
                Rectangle rectangle = rectangles[i];
                Navigation.SetCursorPos(Navigation.GetPosition().Left + rectangle.Center().X, Navigation.GetPosition().Top + rectangle.Center().Y);
                Navigation.Click();
                Navigation.SystemRandomWait(Navigation.Speed.SelectNextInventoryItem);

                material.name  = ScanMaterialName(section, out Bitmap nameplate);
                material.count = 0;

                if (materials.Contains(material) && passby)
                {
                    continue;
                }

                if (!materials.Contains(material))
                {
                    if (!string.IsNullOrEmpty(material.name))
                    {
                        // Scan Material Number
                        material.count = ScanMaterialCount(rectangle, out Bitmap quantity);
                        if (material.count == 0)
                        {
                            UserInterface.AddError($"Failed to parse quantity for {material.name}");
                            quantity.Save($"./logging/materials/{material.name}_Quantity.png");
                        }
                        materials.Add(material);
                        UserInterface.ResetCharacterDisplay();
                        UserInterface.SetMaterial(nameplate, quantity, material.name, material.count);
                        passby = false;                         // New material found so break on next old material
                        quantity.Dispose();
                    }
                }
                else
                {
                    nameplate.Dispose();
                    break;
                }
                Navigation.Wait(150);
            }
        }
Exemple #3
0
 static Inventory()
 {
     _config = ((InventorySection)(System.Configuration.ConfigurationManager.GetSection("Inventory")));
 }
 private static (List <Rectangle> rectangles, int cols, int rows) GetPageOfItems(InventorySection section, int page)
 {
     // Screenshot of inventory
     using (Bitmap screenshot = Navigation.CaptureWindow())
     {
         try
         {
             var(rectangles, cols, rows) = ProcessScreenshot(screenshot);
             if (cols != 8 || rows < 4)
             {
                 // Generated rectangles
                 screenshot.Save($"./logging/materials/{section}Inventory{page}.png");
                 using (Graphics g = Graphics.FromImage(screenshot))
                     rectangles.ForEach(r => g.DrawRectangle(new Pen(Color.Green, 3), r));
                 screenshot.Save($"./logging/materials/{section}Inventory{page}_{cols}x{rows}.png");
             }
             return(rectangles, cols, rows);
         }
         catch (Exception)
         {
             screenshot.Save($"./logging/materials/{section}Inventory{page}.png");
             throw new Exception($"Insufficient items found in {section} inventory");
         }
     }
 }
 static Inventory()
 {
     _config = ((InventorySection)(System.Configuration.ConfigurationManager.GetSection("Inventory")));
 }