├── .gitignore ├── FAQ.md ├── LICENSE ├── README.md ├── ch_bot_lib.ahk ├── ch_sw1ft_bot.ahk ├── common_setups.md ├── images ├── ancient_eye_click.png ├── ascend.png ├── cid.png ├── clan_collect.png ├── clan_fight.png ├── clan_fight_again.png ├── clan_raid.png ├── clickable.png ├── clickable_bag.png ├── clickable_cake.png ├── clickable_candy.png ├── clickable_cane.png ├── clickable_egg.png ├── clickable_fish.png ├── clickable_heart.png ├── coin.png ├── combat_tab.png ├── dk.png ├── dk_g.png ├── farm.png ├── gilded.png ├── gilded_button.png ├── gog.png ├── guide │ ├── ancient_eye_click.png │ ├── ancient_settings.png │ ├── autohotkey.png │ ├── bot_settings.png │ ├── browserTopMargin.png │ ├── ch_settings.png │ ├── display_settings.png │ ├── dl_bot.png │ ├── error_msg.png │ ├── gilded.png │ ├── gildedRanger.png │ ├── kumawakamaru.png │ ├── lib_settings.png │ ├── logs.png │ ├── monitor_true_color.png │ ├── playstyle.png │ ├── siyalatas.png │ ├── start_bot.png │ ├── taskbar.png │ └── unzip_bot.png ├── hire.png ├── max.png ├── max_lvl.png ├── progression.png ├── quality.png ├── skill.png ├── skill_bar.png ├── skill_dimmed.png ├── skill_locked.png ├── smile.png ├── solomon.png ├── top_corner_alt_mmb.png ├── upgrades.png ├── way_of_kings.png ├── way_of_the_chef.png └── yes.png ├── logs └── .gitignore ├── monster_clicker.ahk ├── system ├── DO NOT EDIT THESE FILES.txt ├── ancients_optimizer_loader.html ├── ch_bot_default_settings.ahk ├── ch_bot_lib_default_settings.ahk ├── monster_clicker_default_settings.ahk └── wm_messages.ahk └── tools └── combo_tester.ahk /.gitignore: -------------------------------------------------------------------------------- 1 | ch_bot_lib_settings.ahk 2 | ch_bot_settings.ahk 3 | monster_clicker_settings.ahk 4 | -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | ## Speed Run 4 | 5 | **Q:** Not supported any more? 6 | **A:** No, sadly not. Highly repetitive and predictable runs died when Iris was removed. This together with the fact, that the new Transcendent Power speeds up your game progression a great deal, makes it even more difficult to script something even remotely decent when you have no visual cues to guide you. RIP Speed Run, 2015 -- 2016 :( 7 | 8 | ## Vision Run 9 | 10 | **Q:** I get a "Start failed (state = 0)!" warning, what's wrong? 11 | **A1:** Make sure the CH browser window is at 100% zoom. 12 | **A2:** In Windows, use standard 100% (96 DPI) display scaling in (32 bit) True Color 13 | 14 | **Q:** The bot only level heroes 2 levels at a time, not 200, why? 15 | **A1:** The bot fails to focus and Ctrl click. Usually this can be fixed by slightly re-sizing the browser window and hit Alt+F6. 16 | 17 | **Q:** Why isn't the Steam client supported? 18 | **A:** The Vision run utilizes the level shown in the browser client title bar. Something the Steam client lacks. 19 | 20 | **Q:** Can it run in the background? 21 | **A:** No. The image recognition functionality requires it to be visible at all times. 22 | 23 | **Q:** The monitor power savings seems to cause issues! 24 | **A:** Either enable the `noSleep` bot setting, or turn the power savings off. 25 | 26 | **Q:** Changing the settings files do nothing!? 27 | **A:** Make sure you are __NOT__ editing the system default settings. See the __Step-by-step Guide__ in the [README](README.md). 28 | 29 | **Q:** The bot seem to miss-click, do I need to update any coordinates? 30 | **A1:** If you have moved or re-sized the client window, just hit Alt+F6 and try again. 31 | **A2:** Make sure the `browserTopMargin` setting is correct. See the __Step-by-step Guide__ in the [README](README.md). 32 | 33 | **Q:** I have focus issues, why? 34 | **A1:** You need to run CH in one browser (e.g. Opera), then do your normal surfing in another (e.g. Chrome). 35 | **A2:** Make sure the CH window IS NOT focused when you start a run. 36 | **A3:** A trick to get focus back, is to left-click and *draw some boxes* on your desktop. 37 | 38 | **Q:** Why do I get an error when trying to run one of the script files? 39 | **A:** Make sure you have the latest version of both [AutoHotkey][] and the bot. 40 | 41 | **Q:** With `saveBeforeAscending` enabled, the bot don't click save after changing the file name. 42 | **A:** Change the `saveButtonClassNN` setting 43 | 44 | **Q:** With `saveBeforeAscending` enabled, the bot changes the file name, but Windows fails to see this and tries to save with the default `clickerHeroSave.txt` name. 45 | **A:** Change the `saveMode` setting 46 | 47 | **Q:** Can the bot farm Hero Souls while I’m AFK? 48 | **A:** Yes, set the `autoAscend` option to `true`. 49 | 50 | **Q1:** Can I turn off sounds? 51 | **Q2:** Can I move the text splash windows? 52 | **A1:** Yes. Under __Optional Settings__, you’ll find the __Look & Feel__ section. The monster clicker has similar settings. 53 | 54 | **Q:** I just can’t get the bot to work and none of the answers above did help. What should I do? 55 | **A:** Ask me on [Reddit][home]. Also link me a [Pastebin][] with the contents of today's log file in the logs folder. 56 | 57 | [AutoHotkey]: http://ahkscript.org/ 58 | [home]: https://www.reddit.com/r/ClickerHeroes/comments/4phxdg/clicker_heroes_sw1ft_bot/?sort=new 59 | [Pastebin]: http://pastebin.com/ 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 swiftb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clicker Heroes Sw1ft Bot 2 | 3 | A game bot for [Clicker Heroes][Reddit]. 4 | 5 | ## Overview 6 | 7 | * [Features](#general-features) 8 | * [Minimum recommended game state](#minimum-recommended-game-state) 9 | * [Step-by-step Guide](#step-by-step-guide) 10 | * [Troubleshooting](#troubleshooting) 11 | * [Known issues](#known-issues) 12 | * [Hotkeys](#main-hotkeys) 13 | * [Questions or comments?](#questions-or-comments) 14 | 15 | ## General Features 16 | 17 | * Automated Hero Souls farming 18 | * Vision Run loop (Ctrl+F1) 19 | - Supports idle, hybrid and active play 20 | - Finds gilded heroes/rangers automatically 21 | - Picks up *clickables* without breaking idle 22 | - Automatic switches from idle to active in hybrid mode 23 | - Automatic ascensions 24 | - Automatic reload/restart/resume 25 | - Option to auto-save before ascending 26 | - Option to auto-level Solomon after ascending 27 | - **Limitations:** Only supported in the CH browser client (in low quality). The window must also be visible in the foreground 28 | * Hotkeys for raiding 29 | * Separate active _monster clicker_ script 30 | - Built in click speed throttle (when mouse enters window) 31 | - Remotely operated by the main bot script 32 | * Supports user defined skill combos (see `tools/combo_tester.ahk`) 33 | * Monitored _click safety zones_ preventing bot misclicks 34 | * Logging to file 35 | 36 | ### Minimum recommended game state 37 | 38 | * Two world ascensions to get the Buy Available Upgrades button 39 | - **Recommendation:** Save 100 rubies and buy two Quick Ascension's @ Lvl 10 after every Transcension. 40 | 41 | ## Step-by-step Guide 42 | 43 | **1.** Start Clicker Heroes in your browser and set the graphics quality to low. Click the *wrench* and make sure these three options are unchecked: 44 |  45 | 46 | **2.** Download and install the latest version of [AutoHotkey][] 47 |  48 | 49 | **3.** Download the [latest bot release][] from GitHub: 50 |  51 | 52 | **4.** Extract the bot zip file: 53 |  54 | 55 | **5.** Double-click the `ch_sw1ft_bot.ahk` file to start the bot: 56 |  57 | Unless you run Clicker Heroes in the Opera browser, you will get the following error message: 58 |  59 | This is expected. 60 | 61 | In your taskbar you should see two green **H** icons. One for the bot, one for separate monster clicker: 62 |  63 | 64 | Unless they already exist, three user settings files will be created: 65 |  66 | 67 | **6.** Open the `ch_bot_lib_settings.ahk` file: 68 |  69 | **Important!** Use a decent text editor, like [Sublime Text][] or [Notepad++][] when you configure this bot. 70 | 71 | * If needed, change the `browser` name. 72 | * Make sure the Clicker Heroes window have focus, then click Ctrl+Middle Mouse Button dead center in the ancient tab eye like this: 73 |  74 | * Update the `browserTopMargin` according to the pop-up window: 75 |  76 | * Save and reload the script with Alt+F5. 77 | 78 | **Test hotkeys:** 79 | 80 | * Ctrl+Alt+F1 should scroll down to the bottom, then back up 81 | * Ctrl+Alt+F2 should switch between all used tabs 82 | 83 | If any of these two fail, check the [Troubleshooting](#troubleshooting) section and the [FAQ](FAQ.md) for possible solutions. 84 | 85 | **7.** Open the `ch_bot_settings.ahk` file: 86 |  87 | 88 | * With e.g. a lvl 90,000 Siyalatas: 89 |  90 | Following the [regilding chart][], you should be gilded on Moloch: 91 |  92 | Then you would set `gildedRanger` to 11. 93 | 94 | * Depending on your playstyle, you set `endLvlIdle` and `endLvlActive` differently: 95 |  96 | 97 | * The settings for `chronos`, `kumawakamaru` and `vaagur`: 98 |  99 | Should match your in-game values: 100 |  101 | 102 | Recommended optional settings: 103 | 104 | * Set `autoAscend` to "true" 105 | * Set `saveBeforeAscending` to "true" 106 | * Set `noSleep` to "true" 107 | 108 | **8.** Save and reload with Alt+F5, then start the Vision Run with Ctrl+F1. 109 | 110 | In the logs folder: 111 |  112 | 113 | Open today's log file. The most important bits here are: 114 | 115 | DEBUG browser = Opera 116 | DEBUG browserTopMargin = 216 117 | DEBUG gildedRanger = Moloch 118 | DEBUG endLvlIdle = 99999 119 | DEBUG endLvlActive = 100000 120 | DEBUG chronos = 11.36 121 | DEBUG kumawakamaru = -2.59 122 | DEBUG vaagur = -39.71 123 | INFO Recommended transitional hero(es): Banana > Alabaster 124 | 125 | Make sure these match with your settings. Also put 1 gild on the recommended transitional hero(es). 126 | 127 | ## Troubleshooting 128 | 129 | * Keep your mouse pointer outside the Clicker Heroes window to avoid *click speed throttling*. 130 | * Use a separate web browser for web surfing while running the script. 131 | * Make sure your browser window is not zoomed in or out, and is at 100% viewing size. 132 | * In Windows: 133 | - Set display scaling to 100% (96 DPI) 134 |  135 | - Use True Color (32 bit) 136 |  137 | - If your account don't have administrator rights, you might have to start the script by right-clicking it and select **Run as Administrator**. 138 | 139 | ## Known issues 140 | 141 | * Active power savings settings turning off your monitor(s), can cause issues with AHK's image recognition. To combat this, you can enable the `noSleep` bot setting. 142 | * The script can't handle any extra _stuff_ on the left side, e.g. a bookmark list. 143 | 144 | ## Vision Run Error States 145 | 146 | | State | Error | Solution | 147 | | ----- | ----- | -------- | 148 | -2 | No Clicker Heroes window found | Open the client 149 | -1 | Vision, but not in browser | Use the browser client 150 | 0 | Vision, but not finding anything | In Windows, use standard 100% (96 DPI) display scaling in (32 bit) True Color 151 | 152 | ## Main Hotkeys 153 | 154 | | Hotkey | Function | 155 | | ------ | -------- | 156 | Ctrl+F1 | Start the Vision Run loop 157 | Ctrl+F3 | Reload and restart Vision Run loop 158 | Pause | Pause/unpause the script 159 | Alt+Pause | Abort any active run or initiated ascension 160 | Shift+Pause | Schedule a stop after finishing the current run 161 | Alt+F5 | Reload the script (needed after configuration changes) 162 | Shift+Ctrl+F5 | Schedule a script reload after finishing the current run, then restart it 163 | Alt+F6 | Re-initialize coordinates (needed after moving or re-sizing the client window) 164 | 165 | #### Supplementary Hotkeys 166 | 167 | These hotkeys can be executed while a Vision run is active. 168 | 169 | | Hotkey | Function | 170 | | ------ | -------- | 171 | Ctrl+Esc | Suspend/Unsuspend all other Hotkeys 172 | Ctrl+F11 | Autosave the game 173 | Win+F6 | Raid once for free 174 | Win+F7 | One paid raid 175 | Win+F8 | `raidAttempts` paid raids 176 | Shift+Ctrl+F1 | Toggle the `autoAscend` flag 177 | Shift+Ctrl+F6 | Toggle the `playNotificationSounds` flag 178 | Shift+Ctrl+F7 | Toggle the `playWarningSounds` flag 179 | Shift+Ctrl+F11 | Toggle the `saveBeforeAscending` flag 180 | 181 | ## Questions or comments? 182 | 183 | Check the [FAQ](FAQ.md) or visit the original script [home][] on Reddit. 184 | 185 | [Reddit]: https://www.reddit.com/r/ClickerHeroes/ 186 | [AutoHotkey]: http://ahkscript.org/ 187 | [home]: https://www.reddit.com/r/ClickerHeroes/comments/4phxdg/clicker_heroes_sw1ft_bot/?sort=new 188 | [latest bot release]: https://github.com/swiftb/clicker-heroes-sw1ft-bot/releases/latest 189 | [regilding chart]: https://redd.it/3frj62 190 | [Sublime Text]: https://www.sublimetext.com/ 191 | [Notepad++]: https://notepad-plus-plus.org/ -------------------------------------------------------------------------------- /ch_bot_lib.ahk: -------------------------------------------------------------------------------- 1 | ; ----------------------------------------------------------------------------------------- 2 | ; Clicker Heroes Sw1ft Bot Lib 3 | ; by Sw1ftb 4 | ; ----------------------------------------------------------------------------------------- 5 | 6 | CoordMode, Pixel, Screen 7 | 8 | libVersion=4.0 9 | 10 | winName := "Clicker Heroes" 11 | 12 | exitThread := false 13 | 14 | chWinId := "" 15 | 16 | ; All the script coordinates are based on these four default dimensions. 17 | chWidth := 1136 18 | chHeight := 640 19 | chMargin := 8 20 | chTopMargin := 30 21 | 22 | chTotalWidth := chWidth + chMargin * 2 23 | chTotalHeight := chHeight + chMargin + chTopMargin 24 | 25 | ; Calculated 26 | xScreenL := 0 27 | yScreenT := 0 28 | xScreenR := 0 29 | yScreenB := 0 30 | 31 | ; Calculated 32 | leftMarginOffset := 0 33 | topMarginOffset := 0 34 | 35 | ; Calculated 36 | aspectRatio := 1 37 | 38 | zzz := 175 ; sleep delay (in ms) after a click 39 | lvlUpDelay := 6 ; time (in seconds) between lvl up clicks 40 | coinPickUpDelay := 5 ; time (in seconds) needed to pick up all coins from a clickable 41 | 42 | scrollDelay := 325 ; base delay (in ms) 43 | scrollClickDelay := 20 ; delay per click (in ms) 44 | 45 | dialogBoxClass := "#32770" 46 | 47 | blueColor := 0x60BEFF 48 | yellowColor := 0xFECB00 49 | dimmedYellowColor := 0x7E6500 50 | goldColor := 0xFFB423 51 | brightGoldColor := 0xFFD911 52 | 53 | severityLevels := {"OFF":0, "WARN":1, "USER":2, "INFO":3, "DEBUG":4, "TRACE":5} 54 | 55 | gameModes := {"INIT":0, "PROGRESSING":1, "FARMING":2, "FIGHTING":3} 56 | 57 | ; -- Images ------------------------------------------------------------------------------- 58 | 59 | ; Combat zone offsets 60 | CZTO := 170 61 | CZLO := 500 62 | CZBO := CZTO - chHeight 63 | CZRO := CZLO - chWidth 64 | 65 | imageFilePath := "images\" 66 | 67 | imgSmile := {file:"smile.png", topOffset:0, leftOffset:1090, bottomOffset:0, rightOffset:0} 68 | imgQuality := {file:"quality.png", topOffset:0, leftOffset:1090, bottomOffset:0, rightOffset:0} 69 | imgFarm := {file:"farm.png", topOffset:0, leftOffset:1090, bottomOffset:0, rightOffset:0} 70 | imgProgression := {file:"progression.png", topOffset:0, leftOffset:1090, bottomOffset:0, rightOffset:0} 71 | imgAscend := {file:"ascend.png", topOffset:0, leftOffset:1090, bottomOffset:0, rightOffset:0} 72 | 73 | imgClickable := {file:"clickable.png", topOffset:CZTO, leftOffset:CZLO, bottomOffset:0, rightOffset:0} 74 | 75 | imgSkillBar := {file:"skill_bar.png", topOffset:0, leftOffset:575, bottomOffset:0, rightOffset:-496} 76 | imgSkillLocked := {file:"skill_locked.png", topOffset:0, leftOffset:575, bottomOffset:0, rightOffset:-496} 77 | 78 | imgCombatTab := {file:"combat_tab.png", topOffset:0, leftOffset:0, bottomOffset:CZBO, rightOffset:CZRO} 79 | 80 | imgHire := {file:"hire.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 81 | imgCoin := {file:"coin.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 82 | imgMaxLvl := {file:"max_lvl.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 83 | 84 | imgDimmedSkill := {file:"skill_dimmed.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 85 | imgSkill := {file:"skill.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 86 | 87 | imgChefBuff := {file:"way_of_the_chef.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 88 | imgKingsBuff := {file:"way_of_kings.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 89 | 90 | imgCid := {file:"cid.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 91 | imgDK := {file:"dk.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 92 | imgDKG := {file:"dk_g.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 93 | imgMax := {file:"max.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 94 | imgGog := {file:"gog.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 95 | imgSolomon := {file:"solomon.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 96 | 97 | imgGilded := {file:"gilded.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 98 | imgGildedButton := {file:"gilded_button.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 99 | imgBuyUpgrades := {file:"upgrades.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 100 | 101 | imgClanRaid := {file:"clan_raid.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 102 | imgClanFight := {file:"clan_fight.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 103 | imgClanFightAgain := {file:"clan_fight_again.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 104 | imgClanCollect := {file:"clan_collect.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:CZRO} 105 | 106 | imgYes := {file:"yes.png", topOffset:CZTO, leftOffset:0, bottomOffset:0, rightOffset:0} 107 | 108 | ; -- Coordinates -------------------------------------------------------------------------- 109 | 110 | ; Top LVL UP button when scrolled to the bottom 111 | xLvl := 80 112 | oLvl := 107 ; offset to next button 113 | 114 | ; Progression/Farm Mode 115 | xMode := 1121 116 | yMode := 281 117 | 118 | xAscend := 1121 119 | yAscend := 322 120 | 121 | ; Ascend Yes button 122 | xYes := 500 123 | yYes := 510 124 | 125 | oTab := 69 ; offset to next tab 126 | xCombatTab := 52 127 | xAncientTab := xCombatTab + oTab*3 128 | xRelicTab := xCombatTab + oTab*4 + 10 ; Halloween fix 129 | xClanTab := xCombatTab + oTab*5 130 | yTab := 130 131 | 132 | xRelic := 103 133 | yRelic := 380 134 | 135 | xUpgradeNo := 660 136 | yUpgradeNo := 580 137 | 138 | xSalvageJunk := 280 139 | ySalvageJunk := 470 140 | 141 | xDestroyYes := 500 142 | yDestroyYes := 430 143 | 144 | ; Scrollbar 145 | xScroll := 554 146 | yUp := 219 147 | yDown := 653 148 | top2BottomClicks := 45 149 | 150 | rangers := {0:"Power 5", -1:"Samurai", 1:"Dread Knight", 2:"Atlas", 3:"Terra", 4:"Phthalo", 5:"Banana", 6:"Lilin", 7:"Cadmia", 8:"Alabaster", 9:"Astraea", 10:"Chiron", 11:"Moloch", 12:"Bomber Max", 13:"Gog", 14:"Wepwawet", 15:"Betty", 16:"Midas"} 151 | 152 | ; Buy Available Upgrades button 153 | xBuy := 370 154 | yBuy := 582 155 | 156 | xFocus := 564 157 | yFocus := 69 158 | 159 | xMonster := 1010 160 | yMonster := 164 161 | 162 | ; Safety zones (script will pause when entering) 163 | safetyZones := {} 164 | safetyZones[1] := {zone:"tabs", x1:8, y1:104, x2:575, y2:153} 165 | safetyZones[2] := {zone:"settings", x1:1096, y1:31, x2:1143, y2:74} 166 | safetyZones[3] := {zone:"saleShop", x1:678, y1:600, x2:949, y2:670} 167 | safetyZones[4] := {zone:"gilded", x1:79, y1:554, x2:194, y2:612} 168 | 169 | ; The wrench 170 | xSettings := 1121 171 | ySettings := 52 172 | 173 | xSettingsClose := 961 174 | ySettingsClose := 52 175 | 176 | xSave := 286 177 | ySave := 112 178 | 179 | xSkill := 201 180 | oSkill := 36 ; offset to next skill 181 | 182 | xPrevZone := 679 183 | xMiddleZone := 858 184 | xPlusOneZone := 922 185 | xNextZone := 1044 186 | yZone := 70 187 | 188 | ; ----------------------------------------------------------------------------------------- 189 | 190 | ; Load system default settings 191 | #Include system\ch_bot_lib_default_settings.ahk 192 | 193 | IfNotExist, ch_bot_lib_settings.ahk 194 | { 195 | FileCopy, system\ch_bot_lib_default_settings.ahk, ch_bot_lib_settings.ahk 196 | } 197 | 198 | #Include *i ch_bot_lib_settings.ahk 199 | 200 | ; ----------------------------------------------------------------------------------------- 201 | ; -- Functions 202 | ; ----------------------------------------------------------------------------------------- 203 | 204 | clientCheck() { 205 | global 206 | local xPos, yPos 207 | calculateBrowserOffsets() 208 | 209 | if (locateImage(imgQuality, xPos, yPos)) { 210 | showTraceSplash("Switching to low quality") 211 | clickPos(xPos, yPos, 1, 1) 212 | } 213 | if (scriptName = "CH Sw1ft Bot") { 214 | showTraceSplash("xScreenR - xScreenL = " . xScreenR - xScreenL) 215 | showTraceSplash("yScreenB - yScreenT = " . yScreenB - yScreenT) 216 | } 217 | } 218 | 219 | calculateBrowserOffsets() { 220 | global 221 | local w, h 222 | winName := "Lvl.*Clicker Heroes.*" . browser 223 | IfWinExist, % winName 224 | { 225 | showDebugSplash("Calculating browser offsets (" . scriptName . ")") 226 | WinActivate 227 | WinGetPos, xWinPos, yWinPos, w, h 228 | WinGet, chWinId, ID, A 229 | 230 | local leftMargin := (w - chWidth) // 2 231 | leftMarginOffset := leftMargin - chMargin 232 | topMarginOffset := browserTopMargin - chTopMargin 233 | 234 | xScreenL := xWinPos + leftMargin 235 | yScreenT := yWinPos + browserTopMargin 236 | xScreenR := xScreenL + chWidth 237 | yScreenB := yScreenT + chHeight 238 | } else { 239 | showWarningSplash("Clicker Heroes started in " . browser . "?") 240 | } 241 | } 242 | 243 | switchToCombatTab() { 244 | global 245 | if (locateImage(imgCombatTab)) { 246 | clickAwayImage(imgCombatTab) 247 | } else { 248 | clickPos(xCombatTab, yTab) 249 | sleep % zzz * 4 250 | } 251 | } 252 | 253 | switchToAncientTab() { 254 | global 255 | clickPos(xAncientTab, yTab) 256 | sleep % zzz * 2 257 | } 258 | 259 | switchToRelicTab() { 260 | global 261 | clickPos(xRelicTab, yTab) 262 | sleep % zzz * 2 263 | } 264 | 265 | switchToClanTab() { 266 | global 267 | clickPos(xClanTab, yTab) 268 | sleep % zzz * 2 269 | } 270 | 271 | scrollToTop() { 272 | global 273 | clickPos(xScroll, yUp, top2BottomClicks) 274 | sleep % scrollDelay + top2BottomClicks * scrollClickDelay 275 | } 276 | 277 | scrollToBottom() { 278 | global 279 | clickPos(xScroll, yDown, top2BottomClicks) 280 | sleep % scrollDelay + top2BottomClicks * scrollClickDelay 281 | } 282 | 283 | scrollUp(clickCount:=1) { 284 | global 285 | clickPos(xScroll, yUp, clickCount) 286 | sleep % scrollDelay + clickCount * scrollClickDelay 287 | } 288 | 289 | scrollDown(clickCount:=1) { 290 | global 291 | clickPos(xScroll, yDown, clickCount) 292 | sleep % scrollDelay + clickCount * scrollClickDelay 293 | } 294 | 295 | maxClick(xCoord, yCoord, clickCount:=1, absolute:=0) { 296 | global 297 | ControlSend,, {shift down}{vk51 down}, ahk_id %chWinId% ; {q}, {vk51} or {sc010} 298 | clickPos(xCoord, yCoord, clickCount, absolute) 299 | ControlSend,, {vk51 up}{shift up}, ahk_id %chWinId% 300 | sleep % zzz 301 | } 302 | 303 | ctrlClick(xCoord, yCoord, clickCount:=1, sleepSome:=1, absolute:=0) { 304 | global 305 | ControlSend,, {ctrl down}, ahk_id %chWinId% 306 | clickPos(xCoord, yCoord, clickCount, absolute) 307 | ControlSend,, {ctrl up}, ahk_id %chWinId% 308 | if (sleepSome) { 309 | sleep % zzz 310 | } 311 | } 312 | 313 | clickPos(xCoord, yCoord, clickCount:=1, absolute:=0) { 314 | global 315 | local xAdj := absolute ? xCoord : getAdjustedX(xCoord) 316 | local yAdj := absolute ? yCoord : getAdjustedY(yCoord) 317 | ControlClick, x%xAdj% y%yAdj%, ahk_id %chWinId%,,, %clickCount%, NA 318 | } 319 | 320 | getAdjustedX(x) { 321 | global 322 | local leftMargin := chMargin + leftMarginOffset 323 | return round(aspectRatio*(x - chMargin) + leftMargin) 324 | } 325 | 326 | getAdjustedY(y) { 327 | global 328 | local topMargin := chTopMargin + topMarginOffset 329 | return round(aspectRatio*(y - chTopMargin) + topMargin) 330 | } 331 | 332 | playNotificationSound() { 333 | if (playNotificationSounds) { 334 | SoundPlay, %A_WinDir%\Media\Windows User Account Control.wav 335 | } 336 | } 337 | 338 | playWarningSound() { 339 | if (playWarningSounds) { 340 | SoundPlay, %A_WinDir%\Media\tada.wav 341 | } 342 | } 343 | 344 | showTraceSplash(text, seconds:=1) { 345 | showSplash(text, seconds, 0, "TRACE") 346 | } 347 | 348 | showDebugSplash(text, seconds:=1) { 349 | showSplash(text, seconds, 0, "DEBUG") 350 | } 351 | 352 | showUserSplash(text, seconds:=2) { 353 | showSplash(text, seconds, 1, "USER") 354 | } 355 | 356 | showWarningSplash(text, seconds:=4) { 357 | showSplash(text, seconds, 2, "WARN") 358 | } 359 | 360 | showSplash(text, seconds:=2, sound:=1, level="INFO") { 361 | global 362 | if (seconds > 0) { 363 | if (severityLevels[level] <= showSeverityLevel) { 364 | progress,% "w" wSplash " x" xSplash " y" ySplash " zh0 fs10", %text%,,% script 365 | } 366 | if (sound = 1) { 367 | playNotificationSound() 368 | } else if (sound = 2) { 369 | playWarningSound() 370 | } 371 | sleep % seconds * 1000 372 | progress, off 373 | } 374 | logger(text, level) 375 | } 376 | 377 | logArray(name, array) { 378 | local value := "" 379 | loop % array.Length() 380 | { 381 | value .= array[A_Index] 382 | if (A_Index < array.Length()) { 383 | value .= ", " 384 | } 385 | } 386 | logVariable(name, "[" . value . "]") 387 | } 388 | 389 | logVariable(name, value, isBool:=0, level="DEBUG") { 390 | if (isBool) { 391 | value := value ? "true" : "false" 392 | } 393 | logger(name . " = " . value, level) 394 | } 395 | 396 | ; 0:OFF, 1:WARN, 2:USER, 3:INFO, 4:DEBUG, 5:TRACE 397 | logger(msg, level, fileSuffix:="") { 398 | global 399 | local localTime := A_Now 400 | local currentDate 401 | local currentDateTime 402 | local fileName 403 | if (severityLevels[level] <= logSeverityLevel) { 404 | FormatTime, currentDate, localTime, yyyy-MM-dd 405 | FormatTime, currentDateTime, localTime, yyyy-MM-dd HH:mm:ss 406 | fileName := "logs\" . currentDate . fileSuffix . ".txt" 407 | FileAppend, % currentDateTime . "`t" . level . "`t" . msg . "`n", %fileName% 408 | } 409 | } 410 | 411 | formatSeconds(s) { 412 | time := 19990101 ; *Midnight* of an arbitrary date. 413 | time += %s%, seconds 414 | FormatTime, timeStr, %time%, HH:mm:ss 415 | return timeStr 416 | } 417 | 418 | toggleFlag(flagName, byref flag) { 419 | flag := !flag 420 | flagValue := flag ? "On" : "Off" 421 | showUserSplash("Toggled " . flagName . " " . flagValue) 422 | } 423 | 424 | scrollToZone(zone) { 425 | scrollZone(getZone(), zone) 426 | } 427 | 428 | scrollZone(fromZone, toZone) { 429 | global 430 | local zones := toZone - fromZone 431 | local xZone := zones > 0 ? xNextZone : xPrevZone 432 | 433 | if (zones != 0) { 434 | clickPos(xZone, yZone, abs(zones)) 435 | sleep % scrollDelay + 25 + abs(zones) * scrollClickDelay 436 | clickPos(xMiddleZone, yZone) 437 | sleep % zzz 438 | } 439 | } 440 | 441 | getZone() { 442 | global 443 | local title, zone 444 | WinGetTitle, title, ahk_id %chWinId% 445 | zone := SubStr(title, 5, InStr(title, "-") - 6) 446 | return zone 447 | } 448 | 449 | reFocus() { 450 | global 451 | clickPos(xFocus, yFocus) 452 | sleep 25 453 | } 454 | 455 | ; ----------------------------------------------------------------------------------------- 456 | ; Note that all image/pixel searches are done with absolute coordinates relative to the 457 | ; screen. The CH window is required to be visible and in default size for this to work. 458 | ; ----------------------------------------------------------------------------------------- 459 | 460 | clickAwayImage(image) { 461 | local xImg := 0, yImg := 0 462 | if (locateImage(image)) { 463 | while (locateImage(image, xImg, yImg)) { 464 | clickPos(xImg, yImg, 1, 1) 465 | sleep 250 466 | } 467 | sleep 1000 468 | return 1 469 | } 470 | return 0 471 | } 472 | 473 | upLocator(image, what, byref xPos, byref yPos, byref retries:=0, clickCount:=5, absolute:=0, startAt:=0, silent:=0) { 474 | return locator(image, what, xPos, yPos, retries, clickCount, absolute, startAt, silent, 1) 475 | } 476 | 477 | ; Try to locate the given image one screen at a time 478 | locator(image, what, byref xPos, byref yPos, byref retries:=0, clickCount:=5, absolute:=0, startAt:=0, silent:=0, directionUp:=0) { 479 | global 480 | 481 | local attempts := ceil(45 / clickCount) 482 | local attempt := 0 483 | local keepGoing := true 484 | 485 | while (!locateImage(image, xPos, yPos, absolute, startAt, directionUp)) { 486 | keepGoing := directionUp ? !locateImage(imgCid) : true 487 | if (++attempt <= attempts and keepGoing) { 488 | if (directionUp) { 489 | scrollUp(clickCount) 490 | startAt := 0 ; only offset once 491 | } else { 492 | scrollDown(clickCount) 493 | } 494 | } else if (retries-- != 0) { 495 | if (!silent) { 496 | showDebugSplash("Could not locate " . what . "! Trying again...") 497 | } 498 | if (directionUp) { 499 | scrollToBottom() 500 | } else { 501 | scrollToTop() 502 | } 503 | attempt := 0 504 | } else { 505 | return 0 506 | } 507 | } 508 | return 1 509 | } 510 | 511 | locateImage(image, byref xPos:="", byref yPos:="", absolute:=0, startAt:=0, directionUp:=0) { 512 | if (directionUp) { 513 | return locateImageUp(image, xPos, yPos, absolute, startAt) 514 | } else { 515 | return locateImageDown(image, xPos, yPos, absolute, startAt) 516 | } 517 | } 518 | 519 | ; Bottom up image search in chunks (size equal to the distance between two lvl up buttons) 520 | locateImageUp(image, byref xPos:="", byref yPos:="", absolute:=0, startAt:=0) { 521 | global 522 | 523 | local yT := yScreenT + image.topOffset 524 | local searchCount := ceil((yScreenB - yT) / oLvl) 525 | local offset := 0 526 | if (startAt > 0) { 527 | offset := startAt - yScreenB 528 | searchCount := ceil((startAt - yT) / oLvl) 529 | } 530 | local topOffset := offset + yScreenB - yScreenT - oLvl 531 | local bottomOffset := offset 532 | 533 | ; msgbox % "searchCount=" . searchCount . ", offset=" . offset . ", topOffset=" . topOffset . ", bottomOffset=" . bottomOffset 534 | 535 | loop % searchCount 536 | { 537 | if (locateImageDown(image, xPos, yPos, absolute, topOffset,, bottomOffset)) { 538 | return 1 539 | } else { 540 | topOffset -= oLvl 541 | if (A_Index > 1) { ; don't offset bottom until round two 542 | bottomOffset -= oLvl 543 | } 544 | } 545 | } 546 | return 0 547 | } 548 | 549 | ; Top down image search 550 | locateImageDown(image, byref xPos:="", byref yPos:="", absolute:=0, topOffset:=0, leftOffset:=0, bottomOffset:=0, rightOffset:=0) { 551 | global 552 | local imageFile := imageFilePath . image.file 553 | 554 | if (yScreenB = 0) { 555 | return 0 ; CH not started 556 | } 557 | 558 | local xL := xScreenL 559 | local yT := yScreenT 560 | local xR := xScreenR 561 | local yB := yScreenB 562 | 563 | xL += leftOffset ? leftOffset : image.leftOffset 564 | yT += topOffset ? topOffset : image.topOffset 565 | xR += rightOffset ? rightOffset : image.rightOffset 566 | yB += bottomOffset ? bottomOffset : image.bottomOffset 567 | 568 | ; msgbox % "file=" . image.file . ", topOffset=" . image.topOffset . ", leftOffset=" . image.leftOffset . ", bottomOffset=" . image.bottomOffset . ", rightOffset=" . image.rightOffset 569 | ; msgbox % "Searching from (" . xL . ", " . yT . ") to (" . xR . ", " . yB . ")" 570 | 571 | if (xL > xR or yT > yB) { 572 | msgbox,,% script,% "ImageSearch failed! xL (" . xL . ") > xR (" . xR . ") or yT (" . yT . ") > yB (" . yB . ")" 573 | exit 574 | } 575 | reFocus() 576 | ImageSearch xPos, yPos, xL, yT, xR, yB, *30 %imageFile% 577 | if (ErrorLevel = 2) { 578 | playWarningSound() 579 | msgbox,,% script,% "ImageSearch failed! Could not open: " . imageFile 580 | exit 581 | } else if (ErrorLevel = 0 and !absolute) { 582 | ; Absolute --> Relative 583 | xPos -= xWinPos 584 | yPos -= yWinPos 585 | } 586 | return !ErrorLevel 587 | } 588 | 589 | ; Search for a specific pixel color within the given region 590 | locatePixel(pixelColor, xL, yT, xR, yB, byref xPos:="", byref yPos:="") { 591 | global 592 | 593 | reFocus() 594 | PixelSearch, xPos, yPos, xL, yT, xR, yB, %pixelColor%,, Fast RGB 595 | if (ErrorLevel = 0) { 596 | ; Absolute --> Relative 597 | xPos -= xWinPos 598 | yPos -= yWinPos 599 | } 600 | return !ErrorLevel 601 | } 602 | 603 | matchPixelColor(color, x, y) { 604 | reFocus() 605 | PixelGetColor, pixelColor, x, y, RGB 606 | ; msgbox % "Is " . pixelColor . " at (" . x . ", " . y . ") equal to " . color . "?" 607 | return color = pixelColor 608 | } 609 | -------------------------------------------------------------------------------- /ch_sw1ft_bot.ahk: -------------------------------------------------------------------------------- 1 | ; ----------------------------------------------------------------------------------------- 2 | ; Clicker Heroes Sw1ft Bot 3 | ; by Sw1ftb 4 | ; ----------------------------------------------------------------------------------------- 5 | 6 | ; #Warn All 7 | #Persistent 8 | #NoEnv 9 | #InstallKeybdHook 10 | 11 | #Include %A_ScriptDir% 12 | #Include ch_bot_lib.ahk 13 | 14 | SetControlDelay, -1 15 | 16 | scriptName=CH Sw1ft Bot 17 | scriptVersion=4.3.0 18 | minLibVersion=4.0 19 | 20 | script := scriptName . " v" . scriptVersion 21 | 22 | clickerScript := "monster_clicker.ahk" 23 | clickerName := clickerScript . " - AutoHotkey" 24 | 25 | scheduleReload := false 26 | scheduleStop := false 27 | manualProgression := false 28 | 29 | elapsedTime := 0.0 30 | 31 | ; ----------------------------------------------------------------------------------------- 32 | 33 | #Include system\wm_messages.ahk 34 | 35 | ; Load system default settings 36 | #Include system\ch_bot_default_settings.ahk 37 | 38 | IfNotExist, ch_bot_settings.ahk 39 | { 40 | FileCopy, system\ch_bot_default_settings.ahk, ch_bot_settings.ahk 41 | } 42 | 43 | ; Load user settings 44 | #Include *i ch_bot_settings.ahk 45 | 46 | if (libVersion != minLibVersion) { 47 | showWarningSplash("The bot lib version must be " . minLibVersion . "!") 48 | ExitApp 49 | } 50 | 51 | SysGet, VirtualScreenWidth, 78 52 | SysGet, VirtualScreenHeight, 79 53 | 54 | logVariable("A_AhkVersion", A_AhkVersion) 55 | logVariable("A_OSVersion", A_OSVersion) 56 | logVariable("A_ScreenWidth", A_ScreenWidth) 57 | logVariable("A_ScreenHeight", A_ScreenHeight) 58 | if (VirtualScreenWidth > A_ScreenHeight) { 59 | logVariable("VirtualScreenWidth", VirtualScreenWidth) 60 | logVariable("VirtualScreenHeight", VirtualScreenHeight) 61 | } 62 | logVariable("A_ScreenDPI", A_ScreenDPI ) 63 | logVariable("script", script) 64 | 65 | clientCheck() 66 | 67 | Run, "%A_ScriptDir%\%clickerScript%",, UseErrorLevel 68 | if (ErrorLevel != 0) { 69 | playWarningSound() 70 | msgbox,,% script,% "Failed to auto-start " . clickerScript . " (system error code = " . A_LastError . ")!" 71 | } 72 | 73 | handleAutorun() 74 | 75 | ; ----------------------------------------------------------------------------------------- 76 | ; -- Hotkeys (+=Shift, !=Alt, ^=Ctrl, #=Win) 77 | ; ----------------------------------------------------------------------------------------- 78 | 79 | ; Show the cursor position with Alt+Middle Mouse Button 80 | !mbutton:: 81 | mousegetpos, xpos, ypos 82 | msgbox,,% script,% "Cursor position: x" xpos-leftMarginOffset " y" ypos-topMarginOffset 83 | return 84 | 85 | ; Top margin calculation when clicking in the center of the ancient tab eye 86 | ^mbutton:: 87 | mousegetpos, xpos, ypos 88 | msgbox,,% script,% "Set browserTopMargin to: " . ypos-102 89 | return 90 | 91 | ; -- Main Hotkeys ------------------------------------------------------------------------- 92 | 93 | ; Start a Vision Run loop with Ctrl+F1 94 | ^F1:: 95 | loopVisionRun() 96 | return 97 | 98 | ; Reload and restart Vision Run loop with Ctrl+F3 99 | ^F3:: 100 | global scheduleReload := true 101 | handleScheduledReload("loopVisionRun") 102 | return 103 | 104 | ; Pause/unpause the script 105 | ~Pause::Pause 106 | return 107 | 108 | ; Abort any active run or initiated ascension with Alt+Pause 109 | !Pause:: 110 | showUserSplash("Aborting...") 111 | exitThread := true 112 | return 113 | Hotkey, !Pause, , P10 114 | 115 | ; Schedule a stop after finishing the current run with Shift+Pause 116 | +Pause:: 117 | toggleFlag("scheduleStop", scheduleStop) 118 | return 119 | 120 | ; Reload the script (needed after configuration changes) 121 | !F5:: 122 | global scheduleReload := true 123 | handleScheduledReload() 124 | return 125 | Hotkey, !F5, , P10 126 | 127 | ; Schedule a script reload after finishing the current run, then restart it 128 | +^F5:: 129 | toggleFlag("scheduleReload", scheduleReload) 130 | return 131 | 132 | ; Re-initialize coordinates (needed after moving or re-sizing the client window) 133 | !F6:: 134 | showUserSplash("Re-initialize coordinates... ") 135 | clientCheck() 136 | clickerInitialize() 137 | return 138 | Hotkey, !F6, , P10 139 | 140 | ; -- Supplementary Hotkeys ---------------------------------------------------------------- 141 | 142 | ; Suspend/Unsuspend all other Hotkeys with Ctrl+Esc 143 | ~^Esc::Suspend, Toggle 144 | return 145 | 146 | ; Autosave the game 147 | ^F11:: 148 | save() 149 | return 150 | Hotkey, ^F11, , P5 151 | 152 | ; Raid once for free with Win+F6 153 | #F6:: 154 | raid() 155 | return 156 | Hotkey, #F6, , P5 157 | 158 | ; One paid raid 159 | #F7:: 160 | raid(1) 161 | return 162 | Hotkey, #F7, , P5 163 | 164 | ; Paid raids 165 | #F8:: 166 | raid(1, raidAttempts) 167 | return 168 | Hotkey, #F8, , P5 169 | 170 | ; Toggle boolean (true/false) flags with Shift+Ctrl+Fx 171 | 172 | +^F1:: 173 | toggleFlag("autoAscend", autoAscend) 174 | return 175 | 176 | +^F6:: 177 | toggleFlag("playNotificationSounds", playNotificationSounds) 178 | return 179 | Hotkey, +^F6, , P5 180 | 181 | +^F7:: 182 | toggleFlag("playWarningSounds", playWarningSounds) 183 | return 184 | 185 | +^F11:: 186 | toggleFlag("saveBeforeAscending", saveBeforeAscending) 187 | return 188 | 189 | ; -- Test Hotkeys ------------------------------------------------------------------------- 190 | 191 | ; Ctrl+Alt+F1 should scroll down to the bottom, then back up 192 | ^!F1:: 193 | scrollToBottom() 194 | scrollToTop() 195 | return 196 | 197 | ; Ctrl+Alt+F2 should switch between all used tabs 198 | ^!F2:: 199 | switchToAncientTab() 200 | switchToRelicTab() 201 | switchToClanTab() 202 | switchToCombatTab() 203 | return 204 | 205 | ; ----------------------------------------------------------------------------------------- 206 | ; -- Functions 207 | ; ----------------------------------------------------------------------------------------- 208 | 209 | getClickable(active:=1) { 210 | global 211 | local xPos, yPos 212 | if (active = 1) { 213 | clickPos(524, 487) 214 | clickPos(747, 431) 215 | clickPos(760, 380) 216 | clickPos(873, 512) 217 | clickPos(1005, 453) 218 | clickPos(1053, 443) 219 | } else { 220 | loop % clickableImageFiles.Length() 221 | { 222 | imgClickable.file := clickableImageFiles[A_Index] 223 | if (locateImage(imgClickable, xPos, yPos)) { 224 | clickPos(xPos, yPos, 1, 1) ; absolute pos 225 | break 226 | } 227 | } 228 | } 229 | } 230 | 231 | ; Level up and upgrade all heroes 232 | initRun(initMode:=0) { 233 | global 234 | local hasAscendButton := false 235 | local hasSkillBar := false 236 | local hasNoSkillLocked := false 237 | 238 | showDebugSplash("Init Run @ Lvl " . getCurrentZone()) 239 | 240 | switchToCombatTab() 241 | scrollToTop() 242 | reFocus() 243 | 244 | local foundDK := false 245 | local xButton, yButton, xDK, yDK, x 246 | local clickCount := initMode = 1 ? 1 : 2 247 | 248 | locateImage(imgCoin, xButton, yButton) ; get a x coordinate for the hire/lvl up buttons 249 | 250 | loop 10 ; pages 251 | { 252 | if (locateImage(imgDK, xDK, yDK) or locateImage(imgDKG, xDK, yDK)) { 253 | foundDK := true 254 | } 255 | loop 5 ; attempts per page 256 | { 257 | if (locateImage(imgDimmedSkill, x, yButton) 258 | or locateImage(imgHire, x, yButton)) { 259 | if (foundDK and yButton > yDK) { 260 | ; Don't level anything below Frostleaf 261 | continue 262 | } 263 | ctrlClick(xButton, yButton, clickCount, 1, 1) 264 | } else { 265 | break 266 | } 267 | } 268 | if (foundDK) { 269 | if (locateImage(imgAscend)) { 270 | hasAscendButton := true 271 | } 272 | break 273 | } 274 | scrollDown(5) 275 | } 276 | scrollToBottom() 277 | buyAvailableUpgrades() 278 | 279 | if (initMode = 0) { 280 | if (locateImage(imgSkillBar)) { 281 | hasSkillBar := true 282 | } 283 | if (!locateImage(imgSkillLocked)) { 284 | hasNoSkillLocked := true 285 | } 286 | logVariable("hasAscendButton", hasAscendButton, true, "TRACE") 287 | logVariable("hasSkillBar", hasSkillBar, true, "TRACE") 288 | logVariable("hasNoSkillLocked", hasNoSkillLocked, true, "TRACE") 289 | } 290 | 291 | return hasAscendButton and hasSkillBar and hasNoSkillLocked 292 | } 293 | 294 | getEndZone() { 295 | global 296 | return endLvlActive > endLvlIdle ? endLvlActive : endLvlIdle 297 | } 298 | 299 | getState() { 300 | global 301 | 302 | if (!WinExist(winName)) { 303 | return -2 ; no ch window 304 | } 305 | if (getCurrentZone() = 0) { 306 | return -1 ; vision, but not in browser 307 | } 308 | if (!locateImage(imgSmile)) { 309 | return 0 ; vision, but not finding anything 310 | } 311 | if (getCurrentZone() < getEndZone() and !readyToAscend) { 312 | return 1 ; ready for progression 313 | } else { 314 | return 2 ; ready to ascend 315 | } 316 | } 317 | 318 | loopVisionRun() { 319 | global 320 | readyToAscend := false 321 | 322 | local state := 0 323 | 324 | showUserSplash("Starting Vision Runs!") 325 | 326 | logVariable("browser", browser) 327 | logVariable("browserTopMargin", browserTopMargin) 328 | logVariable("gildedRanger", rangers[gildedRanger]) 329 | logVariable("endLvlIdle", endLvlIdle) 330 | logVariable("endLvlActive", endLvlActive) 331 | logVariable("maxIdleMonsterKillTime", maxIdleMonsterKillTime) 332 | logVariable("maxMonsterKillTime", maxMonsterKillTime) 333 | logVariable("chronos", chronos) 334 | logVariable("kumawakamaru", kumawakamaru) 335 | logVariable("vaagur", vaagur) 336 | if (endLvlActive > 0) { 337 | logArray("skillCombo", skillCombo) 338 | } 339 | logVariable("clickableHuntDelay", clickableHuntDelay) 340 | logVariable("saveBeforeAscending", saveBeforeAscending, true) 341 | logVariable("autoAscend", autoAscend, true) 342 | logVariable("noSleep", noSleep, true) 343 | logVariable("levelSolomon", levelSolomon, true) 344 | 345 | loop 346 | { 347 | state := getState() 348 | if (state < 1) { 349 | showWarningSplash("Start failed (state = " . state . ")! Trying again...") 350 | clientCheck() 351 | clickerInitialize() 352 | continue 353 | } 354 | if (getState() = 1) { 355 | visionRun() 356 | } 357 | if (getState() = 2) { 358 | if (saveBeforeAscending) { 359 | save() 360 | } 361 | ascend(autoAscend) 362 | readyToAscend := false 363 | if (levelSolomon) { 364 | solomonLeveler(solomonLevels) 365 | } 366 | handleScheduledStop() 367 | handleScheduledReload("loopVisionRun") 368 | } 369 | } 370 | } 371 | 372 | visionRun() { 373 | global 374 | exitThread := false 375 | isResuming := false 376 | 377 | local startRunTime := A_TickCount 378 | 379 | local isInitiated := false 380 | local isClickerRunning := false 381 | local isComboActive := false 382 | local triggerActive := false 383 | local hasBomberBuff := gildedRanger = 12 ? true : false 384 | local hasGogBuff := gildedRanger = 13 ? true : false 385 | local foundTheHero := false 386 | 387 | local xBtn := 0, yBtn := 0, isNew := 0, startAt := 0 388 | local xSkill := 0, ySkill := 0, skillSearch := false 389 | 390 | local locateGildedDelay := gildedRanger ? 60 : 4 391 | local locateBuyUpgradesDelay := 20 392 | local progressCheckDelay := 10 393 | 394 | local t := 0 395 | local elapsedRunTime := 0 396 | 397 | local comboDelay := skillCombo[1] 398 | comboIndex := 2 399 | 400 | manualProgression := false 401 | switchToCombatTab() 402 | setProgressionMode() 403 | if (!locateImage(imgProgression)) { 404 | showTraceSplash("Manual progression: On") 405 | manualProgression := true 406 | SetTimer, nextZoneTimer, 500 407 | } 408 | 409 | local previousZone := 0 410 | local previousIdleZone := 0 411 | 412 | local zoneMonsters := 10.0 + kumawakamaru 413 | local secPerMonster := 0 414 | local farmMonsterKillTime := 2.0 ; stop and farm before boss when exceeded 415 | 416 | farmTime := 60 417 | bossFightTimer := 30 + chronos + 1 418 | bossFailCounter := 0 419 | 420 | local startZone := getCurrentZone() 421 | local zone := startZone 422 | zoneTime := {} 423 | local initiatedZone := 0 424 | local earliestAscendZone := 140 425 | local estimatedAscendLevel := gildedRanger ? abs(gildedRanger) * 250 - 75 : earliestAscendZone 426 | local initZone := 146 427 | local earlyGameZone := 175 428 | 429 | local tr1 := -1 ; Samurai 430 | local tr2 := "" 431 | 432 | if (gildedCheck(tr1, tr2, earlyGameZone)) { 433 | showSplash("Recommended transitional hero(es): " . rangers[tr1] . " > " . rangers[tr2]) 434 | } 435 | 436 | local earlyGameMode := true 437 | gameMode := "INIT" 438 | 439 | showSplash("Starting Vision Run") 440 | 441 | showDebugSplash("Early game mode ends @ Lvl " . earlyGameZone) 442 | if (estimatedAscendLevel > earliestAscendZone) { 443 | showDebugSplash("Estimated ascension @ Lvl " . estimatedAscendLevel + 400 . " (idle), " . estimatedAscendLevel + 800 . " (active)") 444 | } 445 | 446 | startMonitoring() 447 | startTimer() 448 | reFocus() 449 | 450 | SetTimer, zoneTimer, 500 451 | 452 | loop 453 | { 454 | if (exitThread) { 455 | zoneTime := "" 456 | SetTimer, nextZoneTimer, off 457 | SetTimer, zoneTimer, off 458 | SetTimer, comboTimer, off 459 | clickerStop() 460 | stopTimer() 461 | stopMonitoring() 462 | showUserSplash("Vision Run aborted!") 463 | exit 464 | } 465 | 466 | ; Gief moar rubies plox! 467 | if (mod(t, clickableHuntDelay) = 0) { 468 | getClickable(isClickerRunning) 469 | } 470 | 471 | ; Active zone? 472 | if (isActiveZone(zone) or triggerActive) { 473 | if (!isClickerRunning) { 474 | ; Yup, start hammering! 475 | clickerStart() ; ~38 CPS 476 | isClickerRunning := true 477 | } 478 | if (isInitiated and isClickerRunning and !isComboActive) { 479 | ; Save combos till we have all skills 480 | Gosub, comboTimer 481 | SetTimer, comboTimer, % comboDelay * 1000 + 250 482 | isComboActive := true 483 | } 484 | } else if (isClickerRunning) { 485 | clickerStop() 486 | isClickerRunning := false 487 | } 488 | 489 | ; Early progression 490 | if (zone < earlyGameZone) { 491 | if (manualProgression) { 492 | if (zone > 100) { 493 | showTraceSplash("Manual progression: Off") 494 | manualProgression := false 495 | SetTimer, nextZoneTimer, off 496 | } 497 | } 498 | if (mod(t, locateBuyUpgradesDelay) = 0 or isResuming) { 499 | ; Scroll down when loosing track of the upgrades button 500 | if (!locateImage(imgBuyUpgrades)) { 501 | scrollToBottom() 502 | sleep % coinPickUpDelay * 1000 503 | buyAvailableUpgrades() 504 | } 505 | skillSearch := true 506 | isResuming := false 507 | } 508 | if (mod(t, lvlUpDelay) = 0) { 509 | ; Level heroes bottom up 510 | if (locateImageUp(imgCoin, xBtn, yBtn)) { 511 | ctrlClick(xBtn, yBtn, 2, 1, 1) 512 | } 513 | } 514 | if (zone > 30 and zone > initiatedZone and mod(zone-6, 30) = 0 and zone < initZone) { 515 | ; Lvl earlier heroes at zones 36, 66, 96 and 126 516 | initRun(1) ; x 100 517 | initiatedZone := zone 518 | } 519 | } else if (earlyGameMode) { 520 | showTraceSplash("Ending early game mode @ Lvl " . zone) 521 | earlyGameMode := false 522 | } 523 | 524 | if (!isInitiated and zone >= initZone) { 525 | ; If enough gold, run init 526 | isInitiated := initRun() 527 | isResuming := true 528 | } 529 | 530 | ; Normal progression 531 | if (!earlyGameMode and ((!foundTheHero and mod(t, locateGildedDelay) = 0) or isResuming)) { 532 | ; Traverse bottom up till we find the first gilded hero/ranger we can lvl up 533 | if (locateGilded(xBtn, yBtn, isNew, startAt, !gildedRanger, foundTheHero)) { 534 | maxClick(xBtn, yBtn, 2, 1) 535 | if (!gildedRanger) { 536 | ; "Power 5" mode, moving between gilded heroes 537 | startAt := yBtn + yWinPos - 56 538 | } else { 539 | if (isNew) { 540 | showDebugSplash("New gilded hero found @ Lvl " . zone) 541 | buyAvailableUpgrades() 542 | } 543 | skillSearch := true 544 | } 545 | isResuming := false 546 | } else { 547 | scrollToBottom() 548 | earlyGameZone := zone + 25 549 | earlyGameMode := true 550 | showTraceSplash("No gilded hero found yet! Early game mode extended to Lvl " . earlyGameZone) 551 | } 552 | } 553 | 554 | zone := getCurrentZone() 555 | 556 | ; [Hybrid] Trigger active? 557 | if (!triggerActive and isHybrid() and !isClickerRunning) { 558 | if (zone > 10 and zone > previousIdleZone) { 559 | previousIdleZone := zone 560 | ; Calculate average monster kill time for the previous 5 zones 561 | secPerMonster := timeBetweenZones(zone-5, zone) / 5.0 / zoneMonsters 562 | ; Still insta-killing? 563 | if (secPerMonster >= maxIdleMonsterKillTime) { 564 | ; No, trigger active 565 | showDebugSplash("Lvl " . zone-5 . " -> " . zone . " - Avg monster kill time: " . round(secPerMonster, 2)) 566 | triggerActive := true 567 | } 568 | } else if (gameMode = "INIT" and isInitiated and t > 5) { 569 | triggerActive := true 570 | } 571 | } 572 | 573 | ; Ascend or keep farming? 574 | if (zone > 10 and zone > previousZone and mod(zone-4, 5) = 0 and gameMode = "PROGRESSING") { 575 | ; Progressing @ zone before boss 576 | previousZone := zone 577 | ; Calculate average monster kill time for the previous zone 578 | secPerMonster := timeBetweenZones(zone-2, zone) / 2.0 / zoneMonsters 579 | ; Fast enough to kill next boss easily? 580 | if (secPerMonster >= farmMonsterKillTime) { 581 | showDebugSplash("Lvl " . zone-2 . " -> " . zone . " - Avg monster kill time: " . round(secPerMonster, 2)) 582 | ; No, time to ascend? 583 | if (secPerMonster >= maxMonsterKillTime and zone > estimatedAscendLevel) { 584 | ; Yeah, we are done here 585 | triggerAscension("End of run") 586 | break 587 | } 588 | if (gameMode = "PROGRESSING") { 589 | ; Farm a bit before next boss 590 | farmTime := ceil(secPerMonster * 25) 591 | startFarming() 592 | } 593 | } 594 | } 595 | 596 | ; Progressing? 597 | if (mod(t, progressCheckDelay) = 0) { 598 | if (!locateImage(imgProgression) and gameMode != "FARMING") { 599 | if (++bossFailCounter < 2) { 600 | setProgressionMode() 601 | } else { 602 | if (zone > estimatedAscendLevel) { 603 | triggerAscension("Stuck at high level boss") 604 | break 605 | } else { 606 | startFarming() 607 | } 608 | } 609 | } 610 | } 611 | 612 | ; Level up... 613 | if (!earlyGameMode and mod(t, lvlUpDelay) = 0 and !isResuming) { 614 | if (matchPixelColor(blueColor, xBtn+xWinPos, yBtn+yWinPos)) { 615 | if (!foundTheHero) { 616 | ; Get Bomber Max and Gog global gold and dps buffs when we can 617 | if (!hasBomberBuff and zone > 2930) { 618 | getBuff(imgMax, hasBomberBuff, skillSearch) 619 | } else if (!hasGogBuff and zone > 3210) { 620 | getBuff(imgGog, hasGogBuff, skillSearch) 621 | } 622 | } 623 | ; ... when we can afford to do so 624 | ctrlClick(xBtn, yBtn, 2, 1, 1) 625 | } else if (gildedRanger and !matchPixelColor(goldColor, xBtn-51+xWinPos, yBtn+yWinPos)) { 626 | if (!matchPixelColor(brightGoldColor, xBtn-51+xWinPos, yBtn+yWinPos)) { 627 | ; ... or not, lost sight of our gilded hero 628 | showTraceSplash("Trigger gilded hero locator") 629 | clickAwayImage(imgCombatTab) 630 | isResuming := true 631 | } 632 | } 633 | } 634 | 635 | if (skillSearch) { 636 | ; Aquire possible new skills 637 | while (locateImage(imgSkill, xSkill, ySkill)) { 638 | clickPos(xSkill, ySkill, 1, 1) 639 | sleep 500 640 | } 641 | if (!locateImage(imgDimmedSkill)) { 642 | skillSearch := false 643 | } 644 | } 645 | 646 | zone := getCurrentZone() 647 | t += 1 648 | sleep 1000 649 | 650 | } until zone > getEndZone() or readyToAscend 651 | 652 | if (earlyGameMode) { 653 | maxLevels() ; get some extra souls from levels 654 | } 655 | 656 | SetTimer, nextZoneTimer, off 657 | SetTimer, zoneTimer, off 658 | 659 | if (useZoneDataLogger) { 660 | logZoneData(zdlStart, zone, zdlInterval) 661 | } 662 | zoneTime := "" 663 | 664 | SetTimer, comboTimer, off 665 | clickerStop() 666 | stopTimer() 667 | stopMonitoring() 668 | 669 | elapsedRunTime := (A_TickCount - startRunTime) / 1000 670 | showSplash("Vision Run duration: " . formatSeconds(elapsedRunTime)) 671 | } 672 | 673 | gildedCheck(byref tr1, byref tr2, byref earlyGameZone) { 674 | global 675 | if (gildedRanger > 0) { 676 | if (gildedRanger > 3) { 677 | if (gildedRanger > 14) { 678 | ; Use Wepwawet as last transitional hero for gilded Betty or Midas 679 | tr2 := 14 680 | } else { 681 | tr2 := gildedRanger - 3 682 | } 683 | if (gildedRanger > 6) { 684 | tr1 := tr2 - 3 685 | earlyGameZone := tr1 * 250 - 75 686 | } 687 | } 688 | return 1 689 | } 690 | return 0 691 | } 692 | 693 | triggerAscension(msg, delay:=0) { 694 | global 695 | if (!readyToAscend) { 696 | if (delay > 0) { 697 | showDebugSplash("Trigger ascension in " . floor(delay) . " seconds (" . msg . ")") 698 | SetTimer, ascendTimer, % -delay * 1000 699 | } else { 700 | showDebugSplash("Ascension triggered! (" . msg . ")") 701 | readyToAscend := true 702 | } 703 | } 704 | } 705 | 706 | setGameMode(newGameMode) { 707 | global 708 | showTraceSplash(gameMode . " --> " . newGameMode . " @ Lvl " . getCurrentZone()) 709 | gameMode := newGameMode 710 | } 711 | 712 | isHybrid() { 713 | global 714 | return endLvlActive > endLvlIdle and endLvlIdle > 0 715 | } 716 | 717 | isActiveZone(zone) { 718 | global 719 | if (zone < 10) { 720 | return true 721 | } 722 | if (zone < endLvlActive) { 723 | if (endLvlIdle < endLvlActive and zone < endLvlIdle) { 724 | return false 725 | } 726 | return true 727 | } 728 | return false 729 | } 730 | 731 | getBuff(image, byref hasBuff, byref skillSearch) { 732 | global 733 | local who := image = imgMax ? "Bomber Max" : "Gog" 734 | scrollToBottom() 735 | if (upLocator(image, image.file, xImg, yImg)) { 736 | showDebugSplash("Get buff from " . who . " @ Lvl " . getCurrentZone()) 737 | ctrlClick(xImg-320, yImg+43, 2, 1, 1) ; hire 738 | skillSearch := true 739 | } 740 | hasBuff := true 741 | } 742 | 743 | ; Max levels early game for some extra souls 744 | maxLevels() { 745 | global 746 | 747 | showDebugSplash("Max levels for souls") 748 | 749 | scrollToTop() 750 | reFocus() 751 | 752 | local xButton, yButton 753 | loop 9 ; pages 754 | { 755 | ControlSend,, {vk51 down}, ahk_id %chWinId% ; {q}, {vk51} or {sc010} 756 | sleep 500 757 | if (locateImage(imgMaxLvl, xButton, yButton)) { 758 | loop 4 759 | { 760 | clickPos(xButton, yButton, 1, 1) 761 | sleep % zzz 762 | yButton += oLvl 763 | } 764 | } 765 | scrollDown(5) 766 | } 767 | ControlSend,, {vk51 up}, ahk_id %chWinId% 768 | } 769 | 770 | clickerStart(duration := 0) { 771 | sendClickerMsg(WM_CLICKER_START) 772 | if (duration > 0) { 773 | SetTimer, clickerStopTimer, % -duration * 1000 774 | } 775 | } 776 | 777 | clickerPause() { 778 | sendClickerMsg(WM_CLICKER_PAUSE) 779 | } 780 | 781 | clickerStop() { 782 | sendClickerMsg(WM_CLICKER_STOP) 783 | sleep 1000 784 | } 785 | 786 | clickerReload() { 787 | sendClickerMsg(WM_CLICKER_RELOAD) 788 | } 789 | 790 | clickerInitialize() { 791 | sendClickerMsg(WM_CLICKER_INITIALIZE) 792 | } 793 | 794 | clickerModeFast() { 795 | sendClickerMsg(WM_CLICKER_MODE_FAST) 796 | } 797 | 798 | clickerModeSlow() { 799 | sendClickerMsg(WM_CLICKER_MODE_SLOW) 800 | } 801 | 802 | getClickerStatus() { 803 | return sendClickerMsg(WM_CLICKER_STATUS, 1) 804 | } 805 | 806 | sendClickerMsg(msg, wait:=0) { 807 | global 808 | local reply := 0 809 | local tmm := A_TitleMatchMode 810 | local dhw := A_DetectHiddenWindows 811 | SetTitleMatchMode, 2 812 | DetectHiddenWindows, on 813 | if (!wait) { 814 | PostMessage, %msg%,,,,% clickerName 815 | } else { 816 | SendMessage, %msg%,,,,% clickerName 817 | if (ErrorLevel != "FAIL") { 818 | reply := ErrorLevel 819 | } else { 820 | showWarningSplash("SendMessage failed! " . clickerScript . " started?") 821 | } 822 | } 823 | DetectHiddenWindows,% dhw 824 | SetTitleMatchMode,% tmm 825 | return reply 826 | } 827 | 828 | openSaveDialog() { 829 | global 830 | 831 | clickPos(xSettings, ySettings) 832 | sleep % zzz * 3 833 | clickPos(xSave, ySave) 834 | sleep % zzz * 4 835 | } 836 | 837 | save() { 838 | global 839 | local fileName := "ch" . A_NowUTC . ".txt" 840 | local newFileName := "" 841 | 842 | showDebugSplash("Save to " . fileName) 843 | 844 | ; Close possible other dialog box 845 | ControlSend,, {esc}, ahk_class %dialogBoxClass% 846 | 847 | clickerPause() 848 | openSaveDialog() 849 | 850 | ; Change the file name... 851 | if (saveMode = 1) { 852 | ControlSetText, Edit1, %fileName%, ahk_class %dialogBoxClass% 853 | } else { 854 | ControlSend, Edit1, %fileName%, ahk_class %dialogBoxClass% 855 | } 856 | sleep % zzz * 4 857 | ; ... and double-check that it's correct 858 | ControlGetText, newFileName, Edit1, ahk_class %dialogBoxClass% 859 | if (newFileName = fileName) { 860 | ControlClick, %saveButtonClassNN%, ahk_class %dialogBoxClass%,,,, NA 861 | } else { 862 | ControlSend,, {esc}, ahk_class %dialogBoxClass% 863 | } 864 | 865 | sleep % zzz * 3 866 | clickPos(xSettingsClose, ySettingsClose) 867 | sleep % zzz 868 | } 869 | 870 | ascend(autoYes:=false) { 871 | global 872 | exitThread := false 873 | 874 | local x, y 875 | 876 | startMonitoring() 877 | 878 | if (autoYes) { 879 | if (autoAscendDelay > 0) { 880 | showWarningSplash(autoAscendDelay . " seconds till ASCENSION! (Abort with Alt+Pause)", autoAscendDelay) 881 | if (exitThread) { 882 | exitThread := false 883 | stopMonitoring() 884 | showUserSplash("Ascension aborted!") 885 | exit 886 | } 887 | } 888 | } else { 889 | playWarningSound() 890 | msgbox, 260,% script,Salvage Junk Pile & Ascend? ; default no 891 | ifmsgbox no 892 | { 893 | stopMonitoring() 894 | showUserSplash("Salvage aborted!") 895 | exit 896 | } 897 | } 898 | 899 | salvageJunkPile() ; must salvage junk relics before ascending 900 | setFarmMode() 901 | 902 | showDebugSplash("Ascend @ Lvl " . getCurrentZone()) 903 | 904 | clickPos(xAscend, yAscend) ; 0.23 ascend button 905 | sleep % zzz * 4 906 | clickPos(xYes, yYes) 907 | sleep % zzz * 2 908 | 909 | stopMonitoring() 910 | sleep 1000 ; wait a sec 911 | } 912 | 913 | salvageJunkPile() { 914 | global 915 | 916 | switchToRelicTab() 917 | 918 | if (autoAscend) { 919 | if (displayRelicsDuration > 0) { 920 | clickPos(xRelic, yRelic) ; focus (will show the upgrade screen in 0.23) 921 | } 922 | 923 | if (displayRelicsDuration > 0) { 924 | showWarningSplash("Salvaging junk in " . displayRelicsDuration . " seconds! (Abort with Alt+Pause)", displayRelicsDuration) 925 | if (exitThread) { 926 | exitThread := false 927 | showUserSplash("Salvage aborted!") 928 | exit 929 | } 930 | } 931 | 932 | if (displayRelicsDuration > 0) { 933 | clickPos(xUpgradeNo, yUpgradeNo) ; don't upgrade 934 | sleep % zzz 935 | clickPos(xRelic+100, yRelic) ; remove focus 936 | } 937 | } 938 | 939 | showDebugSplash("Salvage Junk Pile") 940 | 941 | clickPos(xSalvageJunk, ySalvageJunk) 942 | sleep % zzz * 4 943 | clickPos(xDestroyYes, yDestroyYes) 944 | sleep % zzz * 2 945 | } 946 | 947 | buyAvailableUpgrades() { 948 | global 949 | clickPos(xBuy, yBuy, 2) 950 | sleep % zzz * 3 951 | } 952 | 953 | raid(doSpend:=0, attempts:=1) { 954 | global 955 | exitThread := false 956 | 957 | local xBtn := 0, yBtn := 0, raidDuration := 34 * 1000 958 | local wasClickerRunning := getClickerStatus() 959 | 960 | local mode := doSpend ? "Paid" : "Free" 961 | showUserSplash(mode . " Raid x " . attempts) 962 | 963 | Thread, NoTimers ; block timers if mid run 964 | 965 | switchToClanTab() 966 | sleep 1000 967 | clickAwayImage(imgClanRaid) 968 | 969 | if (!wasClickerRunning) { 970 | clickerStart() 971 | sleep 2500 972 | } 973 | loop % attempts 974 | { 975 | if (exitThread) { 976 | exitThread := false 977 | showUserSplash("Raid aborted!") 978 | break 979 | } 980 | if (clickAwayImage(imgClanCollect)) { 981 | break 982 | } 983 | if (doSpend) { 984 | showSplash(mode . " Raid (" . A_Index . "/" . attempts . ")") 985 | if (locateImage(imgClanFightAgain, xBtn, yBtn)) { 986 | while (!locateImage(imgYes)) { 987 | clickPos(xBtn, yBtn, 1, 1) 988 | sleep 250 989 | } 990 | clickAwayImage(imgYes) 991 | clickAwayImage(imgClanFight) 992 | sleep % raidDuration 993 | } 994 | } else { 995 | if (clickAwayImage(imgClanFight)) { 996 | sleep % raidDuration 997 | } 998 | } 999 | getClickable() 1000 | } 1001 | if (!wasClickerRunning) { 1002 | clickerStop() 1003 | } 1004 | 1005 | clickAwayImage(imgCombatTab) 1006 | isResuming := true 1007 | } 1008 | 1009 | ; Toggle between farm and progression modes 1010 | toggleMode(toggle:=1) { 1011 | global 1012 | if (toggle) { 1013 | ; ControlSend,, {vk41}, ahk_id %chWinId% ; {a}, {vk41} or {sc01E} 1014 | clickPos(xMode, yMode) 1015 | sleep % zzz 1016 | } 1017 | } 1018 | 1019 | setFarmMode() { 1020 | global 1021 | if (!manualProgression and locateImage(imgProgression)) { 1022 | clickAwayImage(imgProgression) 1023 | showTraceSplash("Set Farm Mode") 1024 | } 1025 | } 1026 | 1027 | setProgressionMode() { 1028 | global 1029 | if (!manualProgression and locateImage(imgFarm)) { 1030 | clickAwayImage(imgFarm) 1031 | showTraceSplash("Set Progression Mode") 1032 | } 1033 | } 1034 | 1035 | activateSkills(skills) { 1036 | global 1037 | reFocus() 1038 | loop,parse,skills,- 1039 | { 1040 | ControlSend,,% A_LoopField, ahk_id %chWinId% 1041 | sleep 25 1042 | } 1043 | } 1044 | 1045 | startMonitoring() { 1046 | global 1047 | setTimer, checkMousePosition, 250 1048 | setTimer, checkWindowVisibility, 20000 1049 | if (noSleep) { 1050 | DllCall( "SetThreadExecutionState", UInt, 0x80000003) ; ES_CONTINUOUS + ES_DISPLAY_REQUIRED + ES_SYSTEM_REQUIRED 1051 | } 1052 | } 1053 | 1054 | stopMonitoring() { 1055 | global 1056 | setTimer, checkMousePosition, off 1057 | setTimer, checkWindowVisibility, off 1058 | if (noSleep) { 1059 | DllCall( "SetThreadExecutionState", UInt, 0x80000000) ; ES_CONTINUOUS 1060 | } 1061 | } 1062 | 1063 | handleScheduledReload(function := "") { 1064 | global 1065 | local params := function != "" ? "/autorun " . function : "" 1066 | if (scheduleReload) { 1067 | showUserSplash("Script Reload " . params, 3) 1068 | Run "%A_AhkPath%" /restart "%A_ScriptFullPath%" %params% 1069 | } 1070 | } 1071 | 1072 | handleScheduledStop() { 1073 | global 1074 | if (scheduleStop) { 1075 | showUserSplash("Scheduled stop. Exiting...") 1076 | scheduleStop := false 1077 | exit 1078 | } 1079 | } 1080 | 1081 | handleAutorun() { 1082 | global 1083 | option = %1% 1084 | function = %2% 1085 | if (option = "/autorun") { 1086 | loopVisionRun() 1087 | } 1088 | } 1089 | 1090 | hasClickable() { 1091 | global 1092 | return locateImage(imgClickable) 1093 | } 1094 | 1095 | ; Try to find the first gilded hero/ranger we can lvl up 1096 | locateGilded(byref xPos, byref yPos, byref isNew, startAt:=0, silent:=0, byref foundTheHero:=0) { 1097 | global 1098 | isNew := 0 1099 | local xAbs, yAbs 1100 | local retries := 1 1101 | 1102 | if (startAt = 0 and !locateImage(imgBuyUpgrades)) { 1103 | if (locateImage(imgCombatTab)) { 1104 | clickAwayImage(imgCombatTab) 1105 | } 1106 | scrollToBottom() 1107 | } 1108 | 1109 | if (gildedRanger = -1 and locateImage(imgBuyUpgrades)) { 1110 | scrollUp(30) ; Locate Samurai 1111 | foundTheHero := true 1112 | } else if (gildedRanger = 15 and locateImage(imgBuyUpgrades) and locateImage(imgChefBuff)) { 1113 | scrollUp(35) ; Locate Betty 1114 | foundTheHero := true 1115 | } else if (gildedRanger = 16 and locateImage(imgBuyUpgrades) and locateImage(imgKingsBuff)) { 1116 | scrollUp(22) ; Locate Midas 1117 | foundTheHero := true 1118 | } 1119 | 1120 | while (upLocator(imgGilded, "Gilded hero", xAbs, yAbs, retries, 5, 1, startAt, silent)) { 1121 | local xPixel := xAbs + 83 ; HI[R]E 1122 | local yPixel := yAbs + 38 1123 | if (matchPixelColor(dimmedYellowColor, xPixel, yPixel)) { 1124 | startAt := yAbs 1125 | continue 1126 | } else if (matchPixelColor(yellowColor, xPixel, yPixel)) { 1127 | isNew := 1 1128 | } 1129 | ; Transform to screen relative and offset coordinates to the lvl up button 1130 | xPos := xAbs - xWinPos + 57 1131 | yPos := yAbs - yWinPos + 56 1132 | return 1 1133 | } 1134 | return 0 1135 | } 1136 | 1137 | solomonLeveler(levels) { 1138 | global 1139 | local x, y 1140 | 1141 | showSplash("Level Solomon x " . levels) 1142 | 1143 | switchToAncientTab() 1144 | if (locator(imgSolomon, "Solomon", x, y)) { 1145 | ; Offset coordinates to the lvl up button 1146 | x -= 365 1147 | y += 28 1148 | clickPos(x, y, levels, 1) 1149 | sleep % zzz * 2 1150 | } 1151 | } 1152 | 1153 | checkSafetyZones() { 1154 | global 1155 | local window, x, y 1156 | local i, sz 1157 | local xL, yT, xR, yB 1158 | 1159 | MouseGetPos,,, window 1160 | if (window = WinExist(winName)) { 1161 | 1162 | WinActivate 1163 | MouseGetPos, x, y 1164 | 1165 | for i, sz in safetyZones 1166 | { 1167 | xL := getAdjustedX(sz.x1) 1168 | yT := getAdjustedY(sz.y1) 1169 | xR := getAdjustedX(sz.x2) 1170 | yB := getAdjustedY(sz.y2) 1171 | 1172 | if (x > xL && y > yT && x < xR && y < yB) { 1173 | if (sz.zone = "gilded" && !locateImage(imgGildedButton)) { 1174 | return 1175 | } 1176 | Thread, NoTimers ; block timers 1177 | playNotificationSound() 1178 | clickerModeSlow() 1179 | if (locateImage(imgSmile)) { 1180 | msgbox,,% script,Click safety pause engaged. Resume? 1181 | clickAwayImage(imgCombatTab) 1182 | isResuming := true 1183 | reFocus() 1184 | } else { 1185 | msgbox,,% script,Click safety pause engaged. Continue? 1186 | } 1187 | clickerModeFast() 1188 | } 1189 | } 1190 | } 1191 | } 1192 | 1193 | zoneMovedWithin(zone, sec) { 1194 | loop % sec * 10 { 1195 | sleep 100 1196 | zoneMoved := getCurrentZone() - zone 1197 | if (zoneMoved) { 1198 | return zoneMoved 1199 | } 1200 | } 1201 | return 0 1202 | } 1203 | 1204 | nextZone() { 1205 | global 1206 | if (gameMode != "FARMING") { 1207 | clickPos(xPlusOneZone, yZone) 1208 | sleep % zzz 1209 | } 1210 | } 1211 | 1212 | timeBetweenZones(z1, z2) { 1213 | global 1214 | local currentTime := getTime() 1215 | local z1time := zoneTime.HasKey(z1) ? zoneTime[z1] : currentTime 1216 | local z2time := zoneTime.HasKey(z2) ? zoneTime[z2] : currentTime 1217 | return abs(z1time - z2time) 1218 | } 1219 | 1220 | storeZoneTime() { 1221 | global 1222 | local cz := getCurrentZone() 1223 | if (cz > 0) { 1224 | local pz := cz - 1 1225 | local currentTime := getTime() 1226 | 1227 | if (!zoneTime.HasKey(pz)) { 1228 | zoneTime[pz] := currentTime 1229 | } 1230 | if (!zoneTime.HasKey(cz)) { 1231 | zoneTime[cz] := currentTime 1232 | ; Reached a new non-boss zone? 1233 | if (gameMode != "PROGRESSING" and mod(cz, 5) > 0 and pz > zoneTime.MinIndex()) { 1234 | ; Yup! 1235 | setGameMode("PROGRESSING") 1236 | } 1237 | bossFailCounter := 0 1238 | } 1239 | } 1240 | } 1241 | 1242 | logZoneData(zStart, zEnd, zInterval) { 1243 | global 1244 | local startZone := zStart < zoneTime.MinIndex() ? zoneTime.MinIndex() : zStart 1245 | local endZone := zEnd > zoneTime.MaxIndex() ? zoneTime.MaxIndex() : zEnd 1246 | local intervals := ceil((endZone - startZone) / zInterval) 1247 | 1248 | if (startZone >= endZone) { 1249 | return 0 1250 | } 1251 | 1252 | local zone := startZone 1253 | local prevZone := zone - zInterval 1254 | 1255 | local totalTime := 0 1256 | local intervalTime := 0 1257 | 1258 | local t := "`t" ; tab 1259 | local nl := "`n" ; new line 1260 | local zoneData := "Zones: " . startZone . " -> " . endZone . ", Interval: " . zInterval 1261 | zoneData .= nl . "Zone" . t . "Time" . t . "Diff (s)" 1262 | zoneData .= nl . zone . t . "00:00:00" . t . "0" 1263 | 1264 | loop % intervals { 1265 | zone += zInterval 1266 | if (zone > endZone) { 1267 | zone := endZone 1268 | } 1269 | prevZone += zInterval 1270 | 1271 | totalTime := timeBetweenZones(startZone, zone) 1272 | intervalTime := timeBetweenZones(prevZone, zone) 1273 | 1274 | zoneData .= nl . zone . t . formatSeconds(totalTime) . t . round(intervalTime, 1) 1275 | } 1276 | 1277 | logger(zoneData, "INFO", "_zone_data") 1278 | } 1279 | 1280 | startFarming() { 1281 | global 1282 | if (gameMode != "FARMING") { 1283 | setGameMode("FARMING") 1284 | setFarmMode() 1285 | scrollToZone(zoneTime.MaxIndex()) 1286 | local farmZone := getCurrentZone() 1287 | if (mod(farmZone, 5) = 0) { 1288 | scrollToZone(--farmZone) 1289 | } 1290 | ; Farm on highest recorded non-boss zone 1291 | showDebugSplash("Farm @ Lvl " . farmZone . " for " . farmTime . "s") 1292 | SetTimer, farmTimer, % -farmTime * 1000 1293 | } 1294 | } 1295 | 1296 | bossFight() { 1297 | global 1298 | if (gameMode != "FIGHTING") { 1299 | setGameMode("FIGHTING") 1300 | setProgressionMode() 1301 | SetTimer, bossTimer, % -bossFightTimer * 1000, 2 ; prio 2 1302 | } 1303 | } 1304 | 1305 | startTimer() { 1306 | global 1307 | SetTimer, timeTick, 250, 4 ; prio 4 1308 | } 1309 | 1310 | stopTimer() { 1311 | global 1312 | SetTimer, timeTick, off 1313 | } 1314 | 1315 | getTime() { 1316 | global 1317 | return elapsedTime 1318 | } 1319 | 1320 | getCurrentZone() { 1321 | global 1322 | local zone 1323 | ; Try get the current zone lvl 1324 | loop 2 { 1325 | zone := getZone() 1326 | if (zone > 0) { 1327 | return zone 1328 | } 1329 | sleep % zzz 1330 | } 1331 | showTraceSplash("Failed to get current zone lvl!") 1332 | return zoneTime.MaxIndex() 1333 | } 1334 | 1335 | ; ----------------------------------------------------------------------------------------- 1336 | ; -- Subroutines 1337 | ; ----------------------------------------------------------------------------------------- 1338 | 1339 | timeTick: 1340 | elapsedTime += 0.25 1341 | return 1342 | 1343 | ; Safety zone around the in-game tabs (that triggers an automatic script pause when breached) 1344 | checkMousePosition: 1345 | checkSafetyZones() 1346 | return 1347 | 1348 | checkWindowVisibility: 1349 | if (!locateImage(imgSmile)) { 1350 | WinActivate, ahk_id %chWinId% 1351 | } 1352 | return 1353 | 1354 | comboTimer: 1355 | activateSkills(skillCombo[comboIndex]) 1356 | comboIndex := comboIndex < skillCombo.MaxIndex() ? comboIndex+1 : 2 1357 | return 1358 | 1359 | clickerStopTimer: 1360 | clickerStop() 1361 | return 1362 | 1363 | farmTimer: 1364 | if (gameMode != "PROGRESSING") { 1365 | bossFight() 1366 | } 1367 | return 1368 | 1369 | bossTimer: 1370 | if (!locateImage(imgProgression)) { 1371 | ; Failed the boss, back to farming... 1372 | showDebugSplash("Failed boss!") 1373 | startFarming() 1374 | } 1375 | return 1376 | 1377 | ascendTimer: 1378 | readyToAscend := true 1379 | return 1380 | 1381 | zoneTimer: 1382 | storeZoneTime() 1383 | return 1384 | 1385 | nextZoneTimer: 1386 | nextZone() 1387 | return 1388 | -------------------------------------------------------------------------------- /common_setups.md: -------------------------------------------------------------------------------- 1 | # Common Setups 2 | 3 | Example settings for different styles of play. 4 | 5 | #### Idle 6 | 7 | endLvlIdle := 100000 8 | endLvlActive := 0 9 | 10 | #### Hybrid 11 | 12 | endLvlIdle := 1000 13 | endLvlActive := 100000 14 | 15 | #### Active 16 | 17 | endLvlIdle := 0 18 | endLvlActive := 100000 19 | 20 | ## Do not disturb 21 | 22 | autoAscendDelay := 0 23 | displayRelicsDuration := 0 24 | 25 | saveBeforeAscending := false 26 | 27 | global playNotificationSounds := false 28 | global playWarningSounds := false 29 | 30 | showSeverityLevel := 0 ; ch_bot_lib_settings.ahk 31 | 32 | ## Dual monitors 33 | 34 | #### Left monitor 35 | 36 | xSplash := A_ScreenWidth // 2 - wSplash // 2 - A_ScreenWidth 37 | 38 | #### Right monitor 39 | 40 | xSplash := A_ScreenWidth // 2 - wSplash // 2 + A_ScreenWidth 41 | -------------------------------------------------------------------------------- /images/ancient_eye_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/ancient_eye_click.png -------------------------------------------------------------------------------- /images/ascend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/ascend.png -------------------------------------------------------------------------------- /images/cid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/cid.png -------------------------------------------------------------------------------- /images/clan_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clan_collect.png -------------------------------------------------------------------------------- /images/clan_fight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clan_fight.png -------------------------------------------------------------------------------- /images/clan_fight_again.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clan_fight_again.png -------------------------------------------------------------------------------- /images/clan_raid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clan_raid.png -------------------------------------------------------------------------------- /images/clickable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable.png -------------------------------------------------------------------------------- /images/clickable_bag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_bag.png -------------------------------------------------------------------------------- /images/clickable_cake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_cake.png -------------------------------------------------------------------------------- /images/clickable_candy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_candy.png -------------------------------------------------------------------------------- /images/clickable_cane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_cane.png -------------------------------------------------------------------------------- /images/clickable_egg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_egg.png -------------------------------------------------------------------------------- /images/clickable_fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_fish.png -------------------------------------------------------------------------------- /images/clickable_heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/clickable_heart.png -------------------------------------------------------------------------------- /images/coin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/coin.png -------------------------------------------------------------------------------- /images/combat_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/combat_tab.png -------------------------------------------------------------------------------- /images/dk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/dk.png -------------------------------------------------------------------------------- /images/dk_g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/dk_g.png -------------------------------------------------------------------------------- /images/farm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/farm.png -------------------------------------------------------------------------------- /images/gilded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/gilded.png -------------------------------------------------------------------------------- /images/gilded_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/gilded_button.png -------------------------------------------------------------------------------- /images/gog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/gog.png -------------------------------------------------------------------------------- /images/guide/ancient_eye_click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/ancient_eye_click.png -------------------------------------------------------------------------------- /images/guide/ancient_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/ancient_settings.png -------------------------------------------------------------------------------- /images/guide/autohotkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/autohotkey.png -------------------------------------------------------------------------------- /images/guide/bot_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/bot_settings.png -------------------------------------------------------------------------------- /images/guide/browserTopMargin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/browserTopMargin.png -------------------------------------------------------------------------------- /images/guide/ch_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/ch_settings.png -------------------------------------------------------------------------------- /images/guide/display_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/display_settings.png -------------------------------------------------------------------------------- /images/guide/dl_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/dl_bot.png -------------------------------------------------------------------------------- /images/guide/error_msg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/error_msg.png -------------------------------------------------------------------------------- /images/guide/gilded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/gilded.png -------------------------------------------------------------------------------- /images/guide/gildedRanger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/gildedRanger.png -------------------------------------------------------------------------------- /images/guide/kumawakamaru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/kumawakamaru.png -------------------------------------------------------------------------------- /images/guide/lib_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/lib_settings.png -------------------------------------------------------------------------------- /images/guide/logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/logs.png -------------------------------------------------------------------------------- /images/guide/monitor_true_color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/monitor_true_color.png -------------------------------------------------------------------------------- /images/guide/playstyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/playstyle.png -------------------------------------------------------------------------------- /images/guide/siyalatas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/siyalatas.png -------------------------------------------------------------------------------- /images/guide/start_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/start_bot.png -------------------------------------------------------------------------------- /images/guide/taskbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/taskbar.png -------------------------------------------------------------------------------- /images/guide/unzip_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/guide/unzip_bot.png -------------------------------------------------------------------------------- /images/hire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/hire.png -------------------------------------------------------------------------------- /images/max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/max.png -------------------------------------------------------------------------------- /images/max_lvl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/max_lvl.png -------------------------------------------------------------------------------- /images/progression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/progression.png -------------------------------------------------------------------------------- /images/quality.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/quality.png -------------------------------------------------------------------------------- /images/skill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/skill.png -------------------------------------------------------------------------------- /images/skill_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/skill_bar.png -------------------------------------------------------------------------------- /images/skill_dimmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/skill_dimmed.png -------------------------------------------------------------------------------- /images/skill_locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/skill_locked.png -------------------------------------------------------------------------------- /images/smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/smile.png -------------------------------------------------------------------------------- /images/solomon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/solomon.png -------------------------------------------------------------------------------- /images/top_corner_alt_mmb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/top_corner_alt_mmb.png -------------------------------------------------------------------------------- /images/upgrades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/upgrades.png -------------------------------------------------------------------------------- /images/way_of_kings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/way_of_kings.png -------------------------------------------------------------------------------- /images/way_of_the_chef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/way_of_the_chef.png -------------------------------------------------------------------------------- /images/yes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftb/clicker-heroes-sw1ft-bot/75207590dfffefcc16fa04bc893e7127f9adf1ef/images/yes.png -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | -------------------------------------------------------------------------------- /monster_clicker.ahk: -------------------------------------------------------------------------------- 1 | ; ----------------------------------------------------------------------------------------------------- 2 | ; Clicker Heroes Monster Clicker 3 | ; by Sw1ftb 4 | 5 | ; Hotkeys: 6 | 7 | ; Shift+F1 to start 8 | ; Shift+F2 to pause 9 | ; Shift+F3 to stop 10 | ; Shift+F5 to reload the script (needed after configuration changes) 11 | ; Shift+F6 to re-initialize coordinates (needed after moving or re-sizing the client window) 12 | 13 | ; Pause to Pause/unpause the script 14 | ; Ctrl+Esc to Suspend/Unsuspend all other Hotkeys 15 | 16 | ; Built in click speed throttle when moving mouse cursor inside the Clicker Heroes window. 17 | ; ----------------------------------------------------------------------------------------------------- 18 | 19 | #Persistent 20 | #NoEnv 21 | #InstallKeybdHook 22 | #SingleInstance force 23 | 24 | #Include %A_ScriptDir% 25 | #Include ch_bot_lib.ahk 26 | 27 | SetControlDelay, -1 28 | SetBatchLines, -1 29 | 30 | scriptName=Monster Clicker 31 | scriptVersion=1.4 32 | minLibVersion=4.0 33 | 34 | script := scriptName . " v" . scriptVersion 35 | tag := "[Clicker] " 36 | 37 | short := 21 ; ms 38 | long := 2000 ; throttled delay 39 | 40 | clickDelay := short 41 | keepOnClicking := false 42 | 43 | ; ----------------------------------------------------------------------------------------- 44 | 45 | #Include system\wm_messages.ahk 46 | 47 | ; Load system default settings 48 | #Include system\monster_clicker_default_settings.ahk 49 | 50 | IfNotExist, monster_clicker_settings.ahk 51 | { 52 | FileCopy, system\monster_clicker_default_settings.ahk, monster_clicker_settings.ahk 53 | } 54 | 55 | #Include *i monster_clicker_settings.ahk 56 | 57 | if (libVersion < minLibVersion) { 58 | showWarningSplash(tag . "The bot lib version must be " . minLibVersion . " or higher!") 59 | ExitApp 60 | } 61 | 62 | logVariable("script", script) 63 | 64 | clientCheck() 65 | 66 | OnMessage(WM_CLICKER_START, "MsgMonitor") 67 | OnMessage(WM_CLICKER_PAUSE, "MsgMonitor") 68 | OnMessage(WM_CLICKER_STOP, "MsgMonitor") 69 | OnMessage(WM_CLICKER_STATUS, "MsgMonitor") 70 | OnMessage(WM_CLICKER_RELOAD, "MsgMonitor") 71 | OnMessage(WM_CLICKER_INITIALIZE, "MsgMonitor") 72 | OnMessage(WM_CLICKER_MODE_FAST, "MsgMonitor") 73 | OnMessage(WM_CLICKER_MODE_SLOW, "MsgMonitor") 74 | 75 | ; ----------------------------------------------------------------------------------------- 76 | ; -- Hotkeys (+=Shift) 77 | ; ----------------------------------------------------------------------------------------- 78 | 79 | +F1:: 80 | clickerStart() 81 | return 82 | 83 | +F2:: 84 | clickerPause() 85 | return 86 | 87 | +F3:: 88 | clickerStop() 89 | return 90 | 91 | +F5:: 92 | clickerReload() 93 | return 94 | 95 | +F6:: 96 | clickerInitialize() 97 | return 98 | 99 | ; Pause/unpause the script 100 | ~Pause::Pause 101 | return 102 | 103 | ; Suspend/Unsuspend all other Hotkeys with Ctrl+Esc 104 | ~^Esc::Suspend, Toggle 105 | return 106 | 107 | clickerStart() { 108 | global 109 | keepOnClicking := true 110 | 111 | local monsterClicks := 0 112 | local startTime := A_TickCount 113 | 114 | showSplash(tag . "Start") 115 | 116 | if (clickDuration > 0) { 117 | setTimer, stopClicking, % -clickDuration * 60 * 1000 ; run only once 118 | } 119 | setTimer, checkMouse, 250 120 | 121 | while(keepOnClicking) { 122 | clickPos(xMonster, yMonster) 123 | monsterClicks++ 124 | sleep % clickDelay 125 | } 126 | 127 | setTimer, checkMouse, off 128 | 129 | local elapsedTime := (A_TickCount - startTime) / 1000 130 | local clicksPerSecond := round(monsterClicks / elapsedTime, 2) 131 | showSplash(tag . "Duration: " . formatSeconds(elapsedTime) . ", CPS: " . clicksPerSecond) 132 | } 133 | 134 | clickerPause() { 135 | global 136 | critical 137 | if (keepOnClicking) { 138 | msgbox,,% script,Click safety pause engaged. Continue? 139 | } 140 | } 141 | 142 | clickerStop() { 143 | global 144 | keepOnClicking := false 145 | } 146 | 147 | clickerStatus() { 148 | global 149 | return keepOnClicking 150 | } 151 | 152 | clickerReload() { 153 | showUserSplash(tag . "Script Reload", 1) 154 | Reload 155 | } 156 | 157 | clickerInitialize() { 158 | clientCheck() 159 | } 160 | 161 | clickerModeFast() { 162 | global 163 | clickDelay := short 164 | } 165 | 166 | clickerModeSlow() { 167 | global 168 | clickDelay := long 169 | } 170 | 171 | MsgMonitor(wParam, lParam, msg) { 172 | if (msg = WM_CLICKER_START) { 173 | clickerStart() 174 | } else if (msg = WM_CLICKER_PAUSE) { 175 | clickerPause() 176 | } else if (msg = WM_CLICKER_STOP) { 177 | clickerStop() 178 | } else if (msg = WM_CLICKER_STATUS) { 179 | return clickerStatus() 180 | } else if (msg = WM_CLICKER_RELOAD) { 181 | clickerReload() 182 | } else if (msg = WM_CLICKER_INITIALIZE) { 183 | clickerInitialize() 184 | } else if (msg = WM_CLICKER_MODE_FAST) { 185 | setTimer, checkMouse, on 186 | clickerModeFast() 187 | } else if (msg = WM_CLICKER_MODE_SLOW) { 188 | setTimer, checkMouse, off 189 | clickerModeSlow() 190 | } 191 | } 192 | 193 | ; ----------------------------------------------------------------------------------------- 194 | ; -- Subroutines 195 | ; ----------------------------------------------------------------------------------------- 196 | 197 | checkMouse: 198 | MouseGetPos,,, window 199 | if (window = WinExist(winName)) { 200 | clickerModeSlow() 201 | } else { 202 | clickerModeFast() 203 | } 204 | return 205 | 206 | stopClicking: 207 | keepOnClicking := false 208 | return 209 | -------------------------------------------------------------------------------- /system/DO NOT EDIT THESE FILES.txt: -------------------------------------------------------------------------------- 1 | See "Starting the bot" in the README. -------------------------------------------------------------------------------- /system/ancients_optimizer_loader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |