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); } }
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"); } } }