private void ScanCommands() { while (KeepScanning) { // Wait for listen to equal true Thread.Sleep(5); if (!Listen || ListenTo.Count == 0) { continue; } try { using (cg.LockHandler.SemiInteractive) { cg.UpdateScreen(); // Check if the chat updated #region Check For Chat Update DirectBitmap chatMarkup = Capture.Clone(Rectangles.LOBBY_CHATBOX); if (PreviousChatMarkup == null) { PreviousChatMarkup = chatMarkup; } else { if (PreviousChatMarkup.CompareTo(chatMarkup, 5, 98, DBCompareFlags.Multithread)) { chatMarkup.Dispose(); continue; } else { PreviousChatMarkup.Dispose(); PreviousChatMarkup = chatMarkup; } } #endregion foreach (LineInfo line in lineInfo) { foreach (int[] color in Chat.ChatColors) { if (Capture.CompareColor(MarkerX, line.Marker, color, Chat.ChatFade)) { string command = ""; int nameLength = -1; #if DEBUG List <LetterResult> letterInfos = new List <LetterResult>(); #endif for (int i = 0; i < line.Lines.Length; i++) { LineScanResult linescan = ScanLine(TextStart, ChatLength, line.Lines[i], color); command += linescan.Word; #if DEBUG letterInfos.AddRange(linescan.LetterInfos); #endif if (i == 0) { nameLength = linescan.NameLength; } } AddExecutedCommand(line.Lines[0], nameLength, color, command #if DEBUG , letterInfos #endif ); break; } } } } } catch (OverwatchClosedException) { } } // while // Dispose of resources used by this class. if (PreviousChatMarkup != null) { PreviousChatMarkup.Dispose(); } }
// 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) { using (cg.LockHandler.Interactive) { 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) { // 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. cg.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> /// Clicks an option. /// </summary> /// <param name="scanLocation">The location to scan for the option at.</param> /// <param name="markup">The markup of the option to scan for.</param> /// <returns>True if the option was found.</returns> public bool ClickOption(Point scanLocation, DirectBitmap markup) { return((bool)MenuOptionScan(scanLocation, OptionScanFlags.OpenMenu | OptionScanFlags.CloseIfNotFound | OptionScanFlags.ReturnFound | OptionScanFlags.Click, null, markup)); }
/// <summary> /// Clicks an option. /// </summary> /// <param name="slot">The slot to scan for the option at.</param> /// <param name="markup">The markup of the option to scan for.</param> /// <returns>True if the option was found.</returns> public bool ClickOption(int slot, DirectBitmap markup) { return(ClickOption(FindSlotLocation(slot), markup)); }
/// <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); } }
/// <summary> /// Scans for an option at the specified point. /// </summary> /// <param name="slot">The slot 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(int slot, OptionScanFlags flags, string saveMarkupsToFolder, DirectBitmap markup) { return(MenuOptionScan(FindSlotLocation(slot), flags, saveMarkupsToFolder, markup)); }
internal bool CompareTo(DirectBitmap other, int fade, double min, DBCompareFlags flags) { return(CompareTo(new Point(0, 0), other, fade, min, flags)); }
public bool IsIdenticle(DirectBitmap other) { return(Bytes.Length == other.Bytes.Length && Width == other.Width && Height == other.Height && Msvcrt.memcmp(Bytes, other.Bytes, Bytes.Length) == 0); }
internal SlotIdentity(DirectBitmap identity, int slot) : base(identity) { Slot = slot; }
private SlotIdentity GetSlotIdentity(int slot) { using (LockHandler.Passive) { if (!AllSlots.Contains(slot)) { return(null); } if (slot == 5 && OpenChatIsDefault) { Chat.CloseChat(); } if (slot == 0) { ResetMouse(); } Point origin = Point.Empty; int width = 0; int height = 0; if (IsSlotBlueOrRed(slot)) { width = 158; height = Distances.LOBBY_SLOT_HEIGHT; int comp = slot; if (IsSlotBlue(slot)) { origin = new Point(145, 239); } else if (IsSlotRed(slot)) { origin = new Point(372, 239); comp -= 6; } origin.Y += Distances.LOBBY_SLOT_DISTANCE * comp; } else if (IsSlotSpectatorOrQueue(slot)) { width = 158; height = Distances.LOBBY_SPECTATOR_SLOT_HEIGHT; origin = new Point(666, 245); int comp = slot; if (IsSlotSpectator(slot)) { origin.Y += FindSpectatorOffset(true); comp -= SpectatorID; } else if (IsSlotInQueue(slot)) { origin.Y -= Distances.LOBBY_QUEUE_OFFSET; comp -= QueueID; } origin.Y += Distances.LOBBY_SPECTATOR_SLOT_DISTANCE * comp; } UpdateScreen(); DirectBitmap identity = Capture.Clone(origin.X, origin.Y, width, height); if (slot == 5 && OpenChatIsDefault) { Chat.OpenChat(); } return(new SlotIdentity(identity, slot)); } }
public MapMarkup(DirectBitmap markup, params Map[] maps) { Markup = markup; Maps = maps; }
public const int Spectator_MarkInvitedWithPercentageChanged = 15; // 25% public InviteScanData(int slot, DirectBitmap markup) { Slot = slot; Markup = markup; }
/// <summary> /// Gets the slots that are invited. /// </summary> /// <returns>The list of slots invited.</returns> public List <int> GetInvitedSlots() { using (LockHandler.Interactive) { // Get all non-AI players List <int> players = GetSlots(SlotFlags.Blue | SlotFlags.Red | SlotFlags.Spectators | SlotFlags.Queue); // Close the chat if it is opened if (OpenChatIsDefault && players.Contains(5)) { Chat.CloseChat(); } List <InviteScanData> slotData = new List <InviteScanData>(); Stopwatch sw = new Stopwatch(); sw.Start(); double iterations = 0; while (sw.ElapsedMilliseconds <= InviteScanData.MSToScan) { UpdateScreen(); foreach (int slot in players) { // Get the data relating to the slot. InviteScanData previousSlotData = slotData.FirstOrDefault(v => v.Slot == slot); // Copy a 20x20 (10x10 if spectator) pixel square of the invite icon animation. Point scanAt = AddToSlotOrigin(IsSlotBlueOrRed(slot) ? InviteScanData.Origin : InviteScanData.SpectatorOrigin, slot, true); int range = IsSlotBlueOrRed(slot) ? InviteScanData.PlayerRange : InviteScanData.SpectatorRange; DirectBitmap markup = Capture.Clone(scanAt.X - range, scanAt.Y - range, range * 2, range * 2); // If there is no previous record of the animation for the slot, create it. if (previousSlotData == null) { slotData.Add(new InviteScanData(slot, markup)); } else { // If there is, compare it to the previous one. bool matching = previousSlotData.Markup.CompareTo(markup, InviteScanData.MarkupFade, InviteScanData.MarkupDifference, DBCompareFlags.Multithread); previousSlotData.Markup.Dispose(); previousSlotData.Markup = markup; if (!matching) { previousSlotData.Changes++; } } } iterations++; Thread.Sleep(20); } for (int i = 0; i < slotData.Count; i++) { slotData[i].Markup.Dispose(); } if (OpenChatIsDefault && players.Contains(5)) { Chat.OpenChat(); } return(slotData.Where(slot => slot.Changes / iterations * 100 > (IsSlotBlueOrRed(slot.Slot) ? InviteScanData.Player_MarkInvitedWithPercentageChanged : InviteScanData.Spectator_MarkInvitedWithPercentageChanged)) .Select(slot => slot.Slot).ToList()); } }