// Checks if an executed command should be added to the list of commands, then adds it. private string AddExecutedCommand(int y, int namelength, int[] seed, string command #if DEBUG , List <LetterResult> letterInfos #endif ) { #region Command Cleanup ListenTo ltd = null; int nameSeperator = command.IndexOf(']') + 2; if (nameSeperator == 1 || nameSeperator > command.Length) { return(command); } command = command.Substring(nameSeperator) .Trim(); string firstWord = command.Split(' ')[0]; #if DEBUG letterInfos.RemoveRange(0, nameSeperator); cg.DebugMenu?.ShowScan(letterInfos); #endif lock (ListenToAccessLock) foreach (ListenTo listenData in ListenTo) { if (listenData.Command == firstWord) { ltd = listenData; break; } } if (ltd == null || !ltd.Listen) { return(command); } #endregion #region Chat Identity // Store executor noise data in a bitmap. var executorscan = new Rectangle(0, y - 4, namelength, 6); DirectBitmap executor = Capture.Clone(executorscan); // Set name pixels to black and everything else to white for (int xi = 0; xi < executor.Width; xi++) { for (int yi = 0; yi < executor.Height; yi++) { if (executor.CompareColor(xi, yi, seed, Chat.ChatFade)) { executor.SetPixel(xi, yi, Color.Black); } else { executor.SetPixel(xi, yi, Color.White); } } } ChatIdentity ci = new ChatIdentity(executor); #endregion #region Profile and Friend Check bool isFriend = false; string name = null; PlayerIdentity pi = null; // If it was not found, pi is still null. Register the profile if _registerPlayerProfiles is true. if (ltd.GetNameAndProfile || ltd.CheckIfFriend) { Point openMenuAt = new Point(56, y); // Open the chat cg.Chat.OpenChat(); // Open the career profile cg.RightClick(openMenuAt, Timing.OPTION_MENU); // If the Send Friend Request option exists, they are not a friend. isFriend = !(bool)cg.Interact.MenuOptionScan(openMenuAt, OptionScanFlags.ReturnFound, null, Markups.SEND_FRIEND_REQUEST); if (ltd.GetNameAndProfile) { using (cg.LockHandler.Interactive) { // By default, the career profile option is selected and we can just press enter to open it. cg.KeyPress(Keys.Enter); // Wait for the career profile to load. WaitForCareerProfileToLoad(); // Get the player name name = cg.GetPlayerName(); // Take a screenshot of the career profile. DirectBitmap careerProfileSnapshot = Capture.Clone(Rectangles.LOBBY_CAREER_PROFILE); // Register the player identity. pi = new PlayerIdentity(careerProfileSnapshot); // Go back to the lobby. cg.GoBack(1); //cg.//ResetMouse(); // If opening the career profile failed, the state of the chat could be incorrect, // like being wrongly opened or wrongly closed because of when enter was pressed earlier. // This will fix it. cg.Chat.OpenChat(); if (!cg.OpenChatIsDefault) { cg.KeyPress(Keys.Enter); } } } else { cg.Interact.CloseOptionMenu(); } } #endregion CommandData commandData = new CommandData(command, GetChannelFromSeed(seed), ci, isFriend, name, pi); if (ltd.Callback != null) { ltd.Callback.Invoke(commandData); } else { commandData.ChatIdentity.Dispose(); commandData.PlayerIdentity?.Dispose(); } return(command); }
/// <summary> /// Scans for an option at the specified point. /// </summary> /// <param name="scanLocation">The location to scan at.</param> /// <param name="flags">The flags for scanning.</param> /// <param name="saveMarkupsToFolder">The location to save the markup of the scanned options. Set to null to ignore.</param> /// <param name="markup">The markup to scan for. Set to null to ignore.</param> /// <returns><para>Returns a bool determining if the option is found if <paramref name="markup"/> is not null and <paramref name="flags"/> has the <see cref="OptionScanFlags.ReturnFound"/> flag.</para> /// <para>Returns the location of the option if <paramref name="markup"/> is not null and <paramref name="flags"/> has the <see cref="OptionScanFlags.ReturnLocation"/> flag.</para></returns> public object MenuOptionScan(Point scanLocation, OptionScanFlags flags, string saveMarkupsToFolder, DirectBitmap markup) { if (saveMarkupsToFolder != null) { saveMarkupsToFolder = System.IO.Path.GetDirectoryName(saveMarkupsToFolder) + System.IO.Path.DirectorySeparatorChar; } using (cg.LockHandler.SemiInteractive) { if (scanLocation == Point.Empty) { if (flags.HasFlag(OptionScanFlags.ReturnFound)) { return(false); } else if (flags.HasFlag(OptionScanFlags.ReturnLocation)) { return(Point.Empty); } else { return(null); } } if (flags.HasFlag(OptionScanFlags.OpenMenu)) { cg.RightClick(scanLocation); } int xStart = scanLocation.X + 14, // X position to start scanning. yStart = 0, // Y position to start scanning. optionWidth = 79, // The width of the option. optionHeight = 6, // The height of the option. yIncrement = 1; // Pixel distance between options. int[] textcolor = new int[] { 169, 169, 169 }; int fade = 80; bool menuPointsDown = MenuPointsDown(scanLocation); if (menuPointsDown) // The menu points down. { yStart = scanLocation.Y + 12; } else // The menu points up. { yStart = scanLocation.Y - 18; yIncrement = -yIncrement; } cg.UpdateScreen(); var options = new List <Tuple <Point, int> >(); int optionIndex = 0; for (int y = yStart; optionHeight < y && y < cg.Capture.Height - optionHeight; y += yIncrement) { bool oob = false; while (!(oob = optionHeight > y || y > cg.Capture.Height - optionHeight) && !Capture.CompareColor(xStart, y + (menuPointsDown ? 1 : -optionHeight), textcolor, fade + 20)) { y += yIncrement; } // If the y is out of range of the bitmap, stop scanning the options. if (oob || !Capture.CompareColor(xStart - 8, y, new int[] { 67, 67, 68 }, 30)) { break; } int percent = 0; if (markup != null) { int success = 0; int total = 0; for (int xi = 0; xi < markup.Width; xi++) { for (int yi = 0; yi < markup.Height; yi++) { total++; bool bmpPixelIsBlack = Capture.CompareColor(xStart + xi, y + yi, new int[] { 170, 170, 170 }, 80); bool markupPixelIsBlack = markup.GetPixel(xi, yi) == Color.FromArgb(0, 0, 0); if (bmpPixelIsBlack == markupPixelIsBlack) { success++; } } } percent = (int)(Convert.ToDouble(success) / Convert.ToDouble(total) * 100); } // Get bitmap of option if (saveMarkupsToFolder != null) { DirectBitmap work = Capture.Clone(xStart, y, optionWidth, optionHeight); for (int xi = 0; xi < work.Width; xi++) { for (int yi = 0; yi < work.Height; yi++) { if (work.CompareColor(xi, yi, textcolor, fade)) { work.SetPixel(xi, yi, Color.Black); } else { work.SetPixel(xi, yi, Color.White); } } } work.Save($@"{saveMarkupsToFolder}Option Markup-{optionIndex}.png"); work.Dispose(); } #if DEBUG if (cg.DebugMenu != null) { Console.WriteLine($"{optionIndex} - {percent}%"); } #endif options.Add(new Tuple <Point, int>(new Point(xStart, y), percent)); optionIndex++; } Point optionLocation = Point.Empty; if (markup != null && options.Count > 0) { optionLocation = options.Where(o => o.Item2 > 75).OrderByDescending(o => o.Item2).FirstOrDefault()?.Item1 ?? Point.Empty; } if (flags.HasFlag(OptionScanFlags.Click)) { SelectMenuOption(optionLocation); } // Close the menu. if (flags.HasFlag(OptionScanFlags.CloseMenu) || (flags.HasFlag(OptionScanFlags.CloseIfNotFound) && optionLocation == Point.Empty)) { CloseOptionMenu(); } if (flags.HasFlag(OptionScanFlags.ReturnFound)) { return(optionLocation != Point.Empty); } else if (flags.HasFlag(OptionScanFlags.ReturnLocation)) { return(optionLocation); } return(null); } }