def set_value_with_ocr(value): """Store start EXP via OCR.""" try: if value == "TOTAL XP": Navigation.misc() Stats.total_xp = Inputs.ocr_notation(*coords.OCR_TOTAL_EXP) # print("OCR Captured TOTAL XP: {:,}".format(Stats.total_xp)) elif value == "XP": Navigation.exp() Stats.xp = Inputs.ocr_number(*coords.OCR_EXP) # print("OCR Captured Current XP: {:,}".format(Stats.xp)) elif value == "PP": Navigation.perks() Misc.waste_click() Stats.pp = Inputs.ocr_number(*coords.OCR_PP) # print("OCR Captured Current PP: {:,}".format(Stats.pp)) Stats.OCR_failed = False Stats.OCR_failures = 0 except ValueError: Stats.OCR_failures += 1 if Stats.OCR_failures <= 3: print("OCR couldn't detect {}, retrying.".format(value)) if Stats.OCR_failures >= 2: print("Clearing Navigation.current_menu") Navigation.current_menu = "" Stats.set_value_with_ocr(value) else: print("Something went wrong with the OCR") Stats.OCR_failures = 0 Stats.OCR_failed = True
def challenges() -> None: if Navigation.current_menu == 'challenges': return Navigation.rebirth() Inputs.click(*coords.CHALLENGE_BUTTON) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu == 'challenges'
def run_challenge(challenge: int, cont: bool = False) -> None: """Run the selected challenge. Keyword arguments challenge -- The index of the challenge, starting at 1 for Basic challenge, ending at 11 for No TM challenge cont -- Whether the challenge is already running. """ global ChList Navigation.challenges() if cont: pass else: x = coords.CHALLENGE.x y = coords.CHALLENGE.y + challenge * coords.CHALLENGEOFFSET Inputs.click(x, y) time.sleep(userset.LONG_SLEEP) Navigation.confirm() chall = ChList[challenge - 1] print(f"Starting {chall.name} Challenge script.") for x in chall.extra: if callable(x): print(x()) else: print(x) chall.script()
def info(): """Click info 'n stuff.""" if Navigation.current_menu == 'info': return Inputs.click(*coords.INFO) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'info'
def rebirth(): """Click rebirth menu.""" if Navigation.current_menu == 'rebirth': return Inputs.click(*coords.REBIRTH) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'rebirth'
def exp(): """Navigate to EXP Menu.""" if Navigation.current_menu == 'exp': return Inputs.click(*coords.XP_MENU) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'exp'
def sellout(): """Navigate to sellout shop.""" if Navigation.current_menu == 'sellout': return Inputs.click(*coords.SELLOUT) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = "sellout"
def first_rebirth(duration): """Procedure for first rebirth.""" ss_assigned = False adventure_pushed = False FightBoss.nuke() Adventure.adventure(highest=True) while Inputs.check_pixel_color(*coords.COLOR_TM_LOCKED): if not ss_assigned: time.sleep(1) Augmentation.augments({"SS": 1}, Misc.get_idle_cap(1)) ss_assigned = True Wandoos.wandoos(True) if Wandoos.check_wandoos_bb_status(): Augmentation.augments({"SS": 1}, Misc.get_idle_cap(1)) FightBoss.nuke() time.sleep(2) FightBoss.fight() if ss_assigned: Misc.reclaim_aug() Augmentation.augments({"EB": 1}, Misc.get_idle_cap(1)) while Inputs.check_pixel_color(*coords.COLOR_BM_LOCKED): Wandoos.wandoos(True) if Wandoos.check_wandoos_bb_status(): Augmentation.augments({"EB": 1}, Misc.get_idle_cap(1)) FightBoss.nuke() FightBoss.fight() BloodMagic.toggle_auto_spells(drop=False, gold=False) BloodMagic.blood_magic(8) rb_time = Rebirth.get_rebirth_time() while int(rb_time.timestamp.tm_min) < duration: Wandoos.wandoos(True) FightBoss.nuke() FightBoss.fight() time.sleep(2) try: current_boss = int(FightBoss.get_current_boss()) if current_boss > 28 and current_boss < 49: if not Timemachine.buster_assigned: Misc.reclaim_aug() Timemachine.buster_assigned = True Augmentation.augments({"EB": 1}, Misc.get_idle_cap(1)) elif current_boss >= 49: if not Timemachine.final_aug: Misc.reclaim_aug() Timemachine.final_aug = True time.sleep(1) Augmentation.augments({ "EB": 0.66, "CS": 0.34 }, Misc.get_idle_cap(1)) if current_boss > 58 and not adventure_pushed: Adventure.adventure(highest=True) adventure_pushed = True except ValueError: print("couldn't get current boss") rb_time = Rebirth.get_rebirth_time()
def exp_adventure(): """Navigate to the adventure menu within the EXP menu.""" if Navigation.current_menu == "exp_adventure": return Navigation.exp() Inputs.click(*coords.ADVENTURE_MENU) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = "exp_adventure"
def sellout_boost_2(): """Navigate to Boost 2 menu within the sellout shop.""" if Navigation.current_menu == 'boost_2': return Navigation.sellout() Inputs.click(*coords.SELLOUT_BOOST_2) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = "boost_2"
def menu(target): """Navigate through main menu.""" target = target.lower() if Navigation.current_menu == target: return Inputs.click(*Navigation.menus[target]) time.sleep(userset.LONG_SLEEP) Navigation.current_menu = target
def spells(): """Navigate to the spells menu within the magic menu.""" if Navigation.current_menu == 'spells': return Navigation.menu('bloodmagic') Inputs.click(*coords.BM_SPELL) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'spells'
def perks(): """Navigate to Perks screen.""" if Navigation.current_menu == 'perks': return Navigation.menu('adventure') Inputs.click(*coords.ITOPOD_PERKS) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'perks'
def exp_magic(): """Navigate to the magic menu within the EXP menu.""" if Navigation.current_menu == 'exp_magic': return Navigation.exp() Inputs.click(*coords.MAGIC_MENU) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'exp_magic'
def ngu_magic(): """Navigate to NGU magic.""" if Navigation.current_menu == 'ngu_magic': return Navigation.menu('ngu') Inputs.click(*coords.NGU_MAGIC) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'ngu_magic'
def exp_rich(): """Navigate to the misc menu within the EXP menu.""" if Navigation.current_menu == "exp_rich": return Navigation.exp() Inputs.click(*coords.RICH_MENU) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = "exp_rich"
def exp_hack(): """Navigate to the hacks menu within the EXP menu.""" if Navigation.current_menu == "exp_hack": return Navigation.exp() Inputs.click(*coords.EXP_HACK_MENU) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = "exp_hack"
def misc(): """Navigate to Misc stats.""" if Navigation.current_menu == 'misc': return Navigation.info() Inputs.click(*coords.MISC) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'misc'
def stat_breakdown(): """Navigate to stat breakdown.""" if Navigation.current_menu == 'stat_breakdown': return Navigation.misc() Inputs.click(*coords.STAT_BREAKDOWN) time.sleep(userset.SHORT_SLEEP) Navigation.current_menu = 'stat_breakdown'
def update_gamestate(): """Update relevant state information.""" global advanced_training_locked, bm_locked, tm_locked if advanced_training_locked: advanced_training_locked = Inputs.check_pixel_color( *coords.COLOR_ADV_TRAINING_LOCKED) if bm_locked: bm_locked = Inputs.check_pixel_color(*coords.COLOR_BM_LOCKED) if tm_locked: tm_locked = Inputs.check_pixel_color(*coords.COLOR_TM_LOCKED)
def get24boss(): try: x = coords.CHALLENGE.x y = coords.CHALLENGE.y + 3 * coords.CHALLENGEOFFSET Navigation.challenges() Inputs.click(x, y, button="right") time.sleep(userset.LONG_SLEEP) target = Inputs.ocr(*coords.OCR_CHALLENGE_24HC_TARGET) target = Inputs.get_numbers(target)[0] return f"Target boss: {target}" except ValueError: Discord.send_message("Couldn't detect the target level of 24HC", Discord.ERROR) return "Couldn't detect the target level of 24HC"
def speedrun(duration): """Start a speedrun. Keyword arguments duration -- duration in minutes to run f -- feature object """ diggers = [2, 3, 11, 12] FightBoss.nuke() time.sleep(2) FightBoss.fight() Adventure.adventure(highest=True) time.sleep(2) rb_time = Rebirth.get_rebirth_time() while int(rb_time.timestamp.tm_min) < duration: GoldDiggers.gold_diggers(diggers) Wandoos.wandoos(True) Augmentation.augments({"SM": 1}, coords.INPUT_MAX) if not Inputs.check_pixel_color(*coords.COLOR_TM_LOCKED): BloodMagic.blood_magic(6) FightBoss.nuke() rb_time = Rebirth.get_rebirth_time() MoneyPit.pit() MoneyPit.spin() return
def update_gamestate(): """Update relevant state information.""" rb_time = Rebirth.get_rebirth_time() Basic.minutes_elapsed = int(rb_time.timestamp.tm_min) try: Basic.current_boss = int(FightBoss.get_current_boss()) except ValueError: Basic.current_boss = 1 print("couldn't get current boss") if Basic.advanced_training_locked: Basic.advanced_training_locked = Inputs.check_pixel_color( *coords.COLOR_ADV_TRAINING_LOCKED) if Basic.bm_locked: Basic.bm_locked = Inputs.check_pixel_color(*coords.COLOR_BM_LOCKED) if Basic.tm_locked: Basic.tm_locked = Inputs.check_pixel_color(*coords.COLOR_TM_LOCKED)
def init(printCoords: bool = False) -> None: """Initialize Window class variables. Helper.init() should go at the very top of any script, straight after imports. """ rect = Window.init() w = rect[2] - rect[0] h = rect[3] - rect[1] cds = Inputs.pixel_search(coords.TOP_LEFT_COLOR, 0, 0, w, h) if cds is None: raise RuntimeError("Game window not found. Maybe it's minimized?") Window.setPos(*cds) # Sometimes the very first click is ignored, this makes sure the first click is unimportant. Inputs.click(*coords.WASTE_CLICK) if printCoords: print(f"Top left found at: {Window.x}, {Window.y}")
def init(target: int) -> None: """Counts available inventory pages.""" Glop.start = time.time() Glop.target = target Navigation.menu("inventory") for btn in coords.INVENTORY_PAGE: res = Inputs.check_pixel_color(*btn, coords.COLOR_INVENTORY_BG) if not res: Glop.inv_pages_unlocked += 1 Glop.update_inventory()
def normal_rebirth(duration): """Procedure for first rebirth.""" diggers = [2, 3, 11, 12] # Wandoos, stat, blood, exp FightBoss.nuke() time.sleep(2) FightBoss.fight() Adventure.adventure(highest=True) Wandoos.set_wandoos(1) # wandoos Meh, use 0 for 98 BloodMagic.toggle_auto_spells(drop=False) GoldDiggers.gold_diggers(diggers) while Inputs.check_pixel_color(*coords.COLOR_TM_LOCKED): Wandoos.wandoos(True) FightBoss.nuke() time.sleep(2) FightBoss.fight() TimeMachine.time_machine(Misc.get_idle_cap(1) * 0.1, magic=True) Adventure.adventure(itopod=True, itopodauto=True) while Inputs.check_pixel_color(*coords.COLOR_BM_LOCKED): Wandoos.wandoos(True) FightBoss.nuke() time.sleep(2) FightBoss.fight() GoldDiggers.gold_diggers(diggers) BloodMagic.blood_magic(8) rb_time = Rebirth.get_rebirth_time() while int(rb_time.timestamp.tm_min) < duration: Wandoos.wandoos(True) FightBoss.nuke() FightBoss.fight() time.sleep(2) GoldDiggers.gold_diggers(diggers) rb_time = Rebirth.get_rebirth_time() # return if challenge is completed and rebirth time is above 3 minutes if int(rb_time.timestamp.tm_min ) >= 3 and not Rebirth.check_challenge(): return Rebirth.do_rebirth()
def init(printCoords: bool = False) -> None: """Initialize Window class variables. Helper.init() should go at the very top of any script, straight after imports. """ rects = Window.init() for window_id, rect in rects.items(): if printCoords: print(f"Scanning window id: {window_id}") w = rect[2] - rect[0] h = rect[3] - rect[1] Window.id = window_id cds = Inputs.pixel_search(coords.TOP_LEFT_COLOR, 0, 0, w, h) if cds: Window.setPos(*cds) break if cds is None: raise RuntimeError( "Game window not found. Maybe it's minimized or the game is not fully visible?" ) # Sometimes the very first click is ignored, this makes sure the first click is unimportant. Inputs.click(*coords.WASTE_CLICK) if printCoords: print(f"Top left found at: {Window.x}, {Window.y}")
def update_inventory() -> None: """Scan all inventory pages for glop related items.""" Navigation.menu("inventory") for item in coords.GLOP_FILENAMES: Glop.reagents[item] = [] for page in range(Glop.inv_pages_unlocked): Inputs.click(*coords.INVENTORY_PAGE[page]) time.sleep(userset.LONG_SLEEP) bmp = Inputs.get_bitmap() for item in coords.GLOP_FILENAMES: path = Inputs.get_file_path("images", item) # Using the whole window instead of cropping out just the inventory yields higher accuracy rect = (Window.x, Window.y, Window.x + 960, Window.y + 600) res = Inputs.find_all(*rect, path, threshold=0.9, bmp=bmp) reagents = list( map(lambda x: Reagent(x[0], x[1], item, page), res)) if reagents: Glop.reagents[item].extend(reagents) print("\nScan found these glop reagents\n") for item in coords.GLOP_FILENAMES: print(f"{item}: {len(Glop.reagents[item])}")
def add_emr(self, wish, emr): """Add EMR to wish.""" alloc_coords = [ coords.WISH_E_ADD, coords.WISH_M_ADD, coords.WISH_R_ADD ] Navigation.menu("wishes") page = ((wish.id - 1) // 21) Inputs.click(*coords.WISH_PAGE[page]) x = coords.WISH_SELECTION.x + ( (wish.id - 1) % 21 % 7) * coords.WISH_SELECTION_OFFSET.x y = coords.WISH_SELECTION.y + ( (wish.id - 1) % 21 // 7) * coords.WISH_SELECTION_OFFSET.y # have to add to add some offset here, otherwise the clicks don't register for some reason. Inputs.click(x + 20, y + 20) for i, e in enumerate(emr): Navigation.input_box() Inputs.send_string(e) Inputs.click(*alloc_coords[i])
def fix_text(self, text): """Fix OCR output to something useable.""" try: fields = [] values = [] res = [] method = 0 for line in text.splitlines(): match = re.search(r"[a-zA-Z\s]+:\s*[xX]\s*\d+\%?", line) if match is not None: method = 1 break if method == 1: for line in text.splitlines(): if line == "": continue else: match = re.match(r"(^[a-zA-Z\s]+:?)", line) if match is not None: fields.append(match.group(1)) values.append(Inputs.remove_letters(line)) else: for line in text.splitlines(): if line == "" or line[0].lower() == "x": continue if line[0].isdigit(): values.append(re.sub(r'[^0-9E+\.]', '', line)) else: fields.append(line) assert len(fields) == len(values) for index, field in enumerate(fields): res.append((field, values[index])) return res except AssertionError: print("OCR couldn't determine breakdown values") return []