/// <summary> /// Waits for the furnace crafting popup to appear /// </summary> /// <returns>true if the popup is found</returns> public bool WaitForPopup(int timeout) { const int popupTitleHash = 842393; Color[,] screen; Stopwatch watch = new Stopwatch(); watch.Start(); long titleHash; int left = Left + 144; int right = Left + 344; int top = Top + 4; int bottom = Top + 23; while (watch.ElapsedMilliseconds < timeout) { if (BotProgram.StopFlag) { return(false); } screen = ScreenScraper.GetRGB(ScreenScraper.CaptureWindow()); screen = ImageProcessing.ScreenPiece(screen, left, right, top, bottom); titleHash = ImageProcessing.ColorSum(screen); if (Numerical.CloseEnough(popupTitleHash, titleHash, 0.001)) { return(true); } } return(false); }
/// <summary> /// Checks a piece of the screen against an expected value for approximate equivalence /// </summary> /// <param name="image">full image of the game screen</param> /// <param name="left">left bound of the piece of the screen to check</param> /// <param name="right">right bound of the piece of the screen to check</param> /// <param name="top">top bound of the piece of the screen to check</param> /// <param name="bottom">bottom bound of the piece of the screen to check</param> /// <param name="expectedColorSum">the expected color sum of the piece of the screen</param> /// <param name="tolerance">allowed deviation of the actual value from the expected value</param> /// <returns></returns> public static bool ScreenPieceCheck(Color[,] image, int left, int right, int top, int bottom, long expectedColorSum, double tolerance) { Color[,] screenPiece = ScreenPiece(image, left, right, top, bottom); long colorSum = ColorSum(screenPiece); return(Numerical.CloseEnough(expectedColorSum, colorSum, tolerance)); }
/// <summary> /// Waits for the "Enter amount:" prompt to appear over the chat box /// </summary> /// <param name="timeout">Gives up after the max wait time has elapsed</param> /// <returns>true if the prompt appears</returns> public static bool WaitForEnterAmount(Process rsClient, int timeout) { Point screenSize = ScreenScraper.GetWindowSize(rsClient); const int asterisk = 91235; const int left = 252; const int right = 265; int top = screenSize.Y - 81; int bottom = screenSize.Y - 69; Color[,] screen; Stopwatch watch = new Stopwatch(); watch.Start(); long asteriskHash; while (watch.ElapsedMilliseconds < timeout) { if (BotProgram.StopFlag) { return(false); } screen = ScreenScraper.GetRGB(ScreenScraper.CaptureWindow()); screen = ImageProcessing.ScreenPiece(screen, left, right, top, bottom); asteriskHash = ImageProcessing.ColorSum(screen); if (Numerical.CloseEnough(asterisk, asteriskHash, 0.01)) { return(true); } } return(false); }
/// <summary> /// Determines if the client is logged into world 385 (F2P) or world 386 (P2P). /// Also identifies worlds 358 and 368 as bot worlds. /// Assumes that the client is logged into the game. /// </summary> /// /// <param name="readWindow">Set to true to force a new screen read</param> /// <returns>true if the client is logged into world 385 or 386</returns> protected bool LoggedIntoBotWorld(bool readWindow = false) { Screen.MakeSureWindowHasBeenRead(readWindow); Inventory.OpenLogout(); SafeWaitPlus(1000, 150); Screen.ReadWindow(); if (!Screen.WorldSwitcherIsOpen()) { ClickWorldSwitcher(); SafeWaitPlus(1500, 500); Screen.ReadWindow(); } Stopwatch watch = new Stopwatch(); watch.Start(); while (!Screen.WorldSwitcherIsOpen() && (watch.ElapsedMilliseconds < 3000) && !StopFlag) { ClickWorldSwitcher(); SafeWait(600, 200); Screen.ReadWindow(); } int left = Screen.Width - 84; int right = left + 30; int top = Screen.Height - 297; int bottom = top + 20; long colorSum = ImageProcessing.ColorSum(Vision.ScreenPiece(left, right, top, bottom)); bool freeBotWorld = Numerical.CloseEnough(120452, colorSum, 0.00001); bool memberBotWorld = Numerical.CloseEnough(121998, colorSum, 0.00001); return(memberBotWorld || freeBotWorld); }
/// <summary> /// Responds to a given dialog body hash /// </summary> /// <param name="bodyHash">total number of text pixels in a dialog box body</param> protected bool ProcessDialog(long bodyCount) { if (Numerical.CloseEnough(16029632, bodyCount, _hashPrecision)) //"Yes<br>No" - title:"Convert the planks for 2500 coins?" { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(16029168, bodyCount, _hashPrecision)) //"Yes<br>No" - title:"Convert the planks for 6250 coins?" { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(16023580, bodyCount, _hashPrecision)) //"Yes<br>No" - title:"Convert the planks for 12500 coins?" { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(16021762, bodyCount, _hashPrecision)) //"Yes<br>No" - title:"Convert the planks for 37500 coins?" { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15831076, bodyCount, _hashPrecision)) //"Take to sawmill: 25 x logs<br>"Something else..." { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15801599, bodyCount, _hashPrecision)) //"Take to sawmill: 25 x Oak logs<br>"Something else..." { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15790514, bodyCount, _hashPrecision)) //"Take to sawmill: 25 x Teak logs<br>"Something else..." { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15741143, bodyCount, _hashPrecision)) //"Take to sawmill: 25 x Mahogany logs<br>"Something else..." { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15774502, bodyCount, _hashPrecision)) //"Serve...<br>Go to the bank...<br>Go to the sawmill<br>Greet guests<br>You're fired" { StartSawmillTask(); } else if (Numerical.CloseEnough(15989089, bodyCount, _hashPrecision)) //"Sawmill<br>Bank<br>Never mind" { Keyboard.WriteNumber(1); } else if (Numerical.CloseEnough(15959844, bodyCount, _hashPrecision) || Numerical.CloseEnough(16167022, bodyCount, _hashPrecision)) //"Enter amount:" { Keyboard.WriteNumber(25); SafeWaitPlus(50, 25); Keyboard.Enter(); } else if (Numerical.CloseEnough(15768332, bodyCount, _hashPrecision)) //"Okay, here's 10,000 coins.<br>I'll pay you later.<br>You're fired!" { Keyboard.WriteNumber(1); } else { return(false); } return(true); //one of the conditions was met }
public void CloseEnoughTest1(long[] targets, long test, double tolerance, bool close) { List <long> targetList = new List <long>(); foreach (long target in targets) { targetList.Add(target); } Assert.AreEqual(Numerical.CloseEnough(targetList, test, tolerance), close); }
/// <summary> /// Determines if "Click here to continue is showing" /// </summary> /// <returns>true if the player can push space to continue a dialog</returns> protected bool ContinueBar() { int left = 233; int right = left + 144; int top = Screen.Height - 59; int bottom = top + 10; bool[,] continueBar = Vision.ColorFilterPiece(ContinueBarBlue, left, right, top, bottom); int textSize = ImageProcessing.MatchCount(continueBar); return(Numerical.CloseEnough(285, textSize, 0.01)); }
/// <summary> /// Determines if one of the two bot worlds is selected on the login screen. /// Assumes that the client is on the login screen. /// </summary> /// <param name="readWindow">Set to true to force a new screen read</param> /// <returns>true if the world is set to 385 or 386. May also hit on 358 and 368</returns> public bool LoginSetForBotWorld(bool readWindow = false) { MakeSureWindowHasBeenRead(readWindow); Point loginOffset = LoginScreenOffset(); int left = Center.X - 323 + loginOffset.X; int right = left + 30; int top = 466 + loginOffset.Y; int bottom = top + 14; long colorSum = ImageProcessing.ColorSum(ImageProcessing.ScreenPiece(Value, left, right, top, bottom)); bool freeBotWorld = Numerical.CloseEnough(LOGIN_BOT_WORLD_385, colorSum, 0.0005); bool memberBotWorld = Numerical.CloseEnough(LOGIN_BOT_WORLD_386, colorSum, 0.00005); return(memberBotWorld || freeBotWorld); }
/// <summary> /// Get the demon butler to take oak logs to the sawmill /// </summary> /// <returns>true if successful</returns> protected override bool Construct() { Inventory.OpenOptions(false); Point houseOptions = Probability.GaussianCircle(HouseOptionsLocation(), 5, 0, 360, 12); Mouse.Move(houseOptions.X, houseOptions.Y); if (WaitForTeleport()) { return(false); } if (!WaitFor(IsAtHouse) || !CallServant() || !InitiateDemonDialog()) { return(false); } long lastBody = 0; long dialogBody = 0; Stopwatch watch = new Stopwatch(); watch.Start(); while (!StopFlag && (watch.ElapsedMilliseconds < 30000) && AnyDialog(true)) { dialogBody = DialogHash(false); if (!Numerical.CloseEnough(dialogBody, lastBody, _hashPrecision)) { if (ContinueBar()) { Keyboard.Space(); } else { if (ProcessDialog(dialogBody)) { lastBody = dialogBody; } } } SafeWait(200); } return(!AnyDialog(false)); }
/// <summary> /// Eats a bite of rock cake if hitpoints are above 1 /// </summary> /// <returns>true if a bite of rock cake is taken</returns> protected bool Hitpoints() { if (TimeSinceLastOverload < overloadDrainTime || Numerical.CloseEnough(overloadBoostTime, TimeSinceLastOverload, 0.02)) { return(false); //an overload might be taking effect or wearing off } const double oneHitpoint = 0.035714285714285712; RectangleBounds hitpoints = Minimap.HitpointsDigitsArea(); double redHitpointsMatch = Vision.FractionalMatchPiece(HitpointsRed, hitpoints.Left, hitpoints.Right, hitpoints.Top, hitpoints.Bottom); if (Numerical.WithinRange(redHitpointsMatch, oneHitpoint, 0.01 * oneHitpoint) || (Minimap.Hitpoints() > 0.25)) { return(false); //hitpoints are already at 1 or an overload has just worn off and hitpoints are no longer red } Inventory.RightClickInventoryOption(0, 0, 1, false); //guzzle rock cake SafeWaitPlus(1000, 250); return(true); }
/// <summary> /// Determines if the dialog box is showing for the "Un-note the banknotes?" title /// </summary> /// <returns></returns> protected bool UnNoteTheBanknotes() { long titleHash = DialogTitleHash(); return(Numerical.CloseEnough(4090128, titleHash, _titleHashPrecision)); }
public void CloseEnoughTest(long target, long test, double tolerance, bool close) { Assert.AreEqual(Numerical.CloseEnough(target, test, tolerance), close); }