async def click_sit_button(): log_process("Standing up" if CFG.sitting_status else "Sitting down") await check_active() need_zoom_adjust = False if CFG.zoom_level < CFG.zoom_ui_min: ACFG.zoom("o", CFG.zoom_out_ui) need_zoom_adjust = True try: ratio_x, ratio_y = CFG.sit_button_position x = round(CFG.screen_res["width"] * ratio_x) y = round(CFG.screen_res["height"] * ratio_y) ACFG.moveMouseAbsolute(x=x, y=y) ACFG.left_click() await async_sleep(0.25) ACFG.resetMouse() CFG.sitting_status = not CFG.sitting_status except Exception: log("Could not find sit button on screen?") await async_sleep(5) log("") if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) log_process("")
async def click_backpack_button(): log_process(f"{'Closing' if CFG.backpack_open else 'Opening'} backpack") await check_active() need_zoom_adjust = False if CFG.zoom_level < CFG.zoom_ui_min: ACFG.zoom("o", CFG.zoom_out_ui) need_zoom_adjust = True try: ratio_x, ratio_y = CFG.backpack_button_position x = round(CFG.screen_res["width"] * ratio_x) y = round(CFG.screen_res["height"] * ratio_y) ACFG.moveMouseAbsolute(x=x, y=y) ACFG.left_click() await async_sleep(0.25) ACFG.resetMouse() CFG.backpack_open = not CFG.backpack_open except Exception: log("Could not find backpack button on screen?") await async_sleep(5) log("") if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) log_process("")
def main_to_shrimp_tree(): log_process("AutoNav") log("Main -> Shrimp Tree") # If main spawn is facing North, # Turn to face West ACFG.look("left", 0.75, raw=True) ACFG.move("a", 1.3, raw=True) # 0.3576 ACFG.move("w", 0.75, raw=True) # Right in front of first step ACFG.leap(0.54, 0.475) # Right before first tree ACFG.leap(0.4, 0.4) # Move towards edge of tree ACFG.move("a", 0.1, raw=True) # Turn towards shrimp tree ACFG.look("left", 1.135, raw=True) # Leap to Shrimp Tree ACFG.leap(0.6, 0.4) # Face South, character looking North ACFG.look("right", 0.385, raw=True) ACFG.move("a", 0.07, raw=True) ACFG.move("s", 0.07, raw=True) ACFG.move("d", 0.07, raw=True) log_process("") log("")
async def handle_join_new_server(crash=False): CFG.crashed = True # Just in case process_name = "Automatic Relocation System" action = "Detected more optimal server. Relocating." if crash: process_name = "Automatic Crash Recovery" action = "Detected Roblox Crash. Recovering." log_process(process_name) log(action) kill_process(force=True) server_id = await force_get_best_server() await async_sleep(1) log_process(f"{process_name} - Joining Server") success = await join_target_server(server_id) if not success: return False output_log("change_server_status_text", "") log_process(f"{process_name} - Handling Spawn") if not await server_spawn(): return False log_process("") log("Complete. Please use '!dev Error' if we're not in-game.") await async_sleep(5) CFG.crashed = False log_process("") log("")
async def force_respawn_character(): await check_active() await async_sleep(0.5) log_process("Force-Respawning") await send_chat("[Respawning!]") await change_characters(respawn=True) log_process("")
def treehouse_to_main(): log_process("AutoNav") log("Treehouse -> Main") ACFG.move("w", 3.3, raw=True) ACFG.move("d", 0.2, raw=True) ACFG.look("left", 1.10, raw=True) log_process("") log("")
def comedy_to_main(): log_process("AutoNav") log("Comedy Machine -> Main") ACFG.move("w", 3.75, raw=True) ACFG.move("a", 0.5) ACFG.look("right", 0.3875, raw=True) log_process("") log("")
async def chat_mouse_click(): log_process("Left Clicking") mouse_x, mouse_y = get_mouse_position()[0], get_mouse_position()[1] print("Got mouse position") had_to_move, area, _, __ = await test_chat_mouse_pos(mouse_x, mouse_y) if had_to_move: log(f"Mouse is in unsafe spot (near {area}), relocating...") await move_mouse_chat_cmd(mouse_x, mouse_y) sleep(2) ACFG.left_click()
def initalize_serial_interface(self, do_log=False): if do_log: log_process("Precision Chip Interface") log("Reserving precision chip interface port") self.interface.close() while not self.interface_ready: sleep(1) self.interface_try_open(do_log=do_log) log("") log_process("")
async def click_item(item_number: int): log_process(f"Clicking item #{item_number}") await check_active() item_x = int( CFG.screen_res["width"] * CFG.backpack_item_positions[item_number]["x"] ) item_y = int( CFG.screen_res["height"] * CFG.backpack_item_positions[item_number]["y"] ) ACFG.moveMouseAbsolute(x=item_x, y=item_y) ACFG.left_click() CFG.backpack_open = False
async def toggle_collisions() -> bool: log_process( f"{'Enabling' if CFG.collisions_disabled else 'Disabling'} Grief Collisions" ) log("Opening Settings") await check_active(force_fullscreen=False) await async_sleep(1) need_zoom_adjust = False if CFG.zoom_level < CFG.zoom_ui_min_cv: ACFG.zoom("o", CFG.zoom_out_ui_cv) need_zoom_adjust = True if not await click_settings_button(check_open_state=True): notify_admin("Failed to open settings") log("") log_process("") if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) return False log(f"Finding {CFG.settings_menu_grief_label} option") await async_sleep(1) if not await ocr_for_settings(): notify_admin("Failed to click settings option") log("") log_process("") if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) return False CFG.collisions_disabled = not (CFG.collisions_disabled) collisions_msg = ("" if CFG.collisions_disabled else "[WARN] Griefing/Collisions enabled!") output_log("collisions", collisions_msg) log("Closing Settings") await async_sleep(0.25) if not await click_settings_button(check_open_state=False): notify_admin("Failed to close settings") log("") log_process("") if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) return False log("") log_process("") ACFG.resetMouse() if need_zoom_adjust: ACFG.zoom("i", CFG.zoom_out_ui_cv) return True
def main_to_ratcade(): log_process("AutoNav") log("Main -> Ratcade") ACFG.move("a", 1.5, raw=True) ACFG.move("w", 5, raw=True) ACFG.move("d", 0.5, raw=True) ACFG.move("w", 0.9, raw=True) ACFG.move("d", 2, raw=True) ACFG.move("w", 0.075, raw=True) ACFG.move("a", 0.075, raw=True) ACFG.move("s", 0.075, raw=True) ACFG.look("right", 0.75, raw=True) log_process("") log("")
async def auto_nav(location: str, do_checks: bool = True, slow_spawn_detect: bool = True): log_process("AutoNav") if do_checks: await check_active(force_fullscreen=False) await async_sleep(0.5) await send_chat( f"[AutoNavigating to {CFG.nav_locations[location]['name']}!]") if not CFG.collisions_disabled: log("Disabling collisions") await toggle_collisions() await async_sleep(0.5) await async_sleep(1) log("Respawning") await respawn_character(notify_chat=False) await async_sleep(7) log("Zooming out to full scale") ACFG.zoom(zoom_direction_key="o", amount=105) spawn = spawn_detection_main(CFG.resources_path, slow=slow_spawn_detect) if spawn == "ERROR": log("Failed to detect spawn!\n Notifying Dev...") notify_admin("Failed to find spawn in `auto_nav`") sleep(5) return if spawn == "comedy_machine": comedy_to_main() elif spawn == "tree_house": treehouse_to_main() await async_sleep(1) if location == "shrimp": main_to_shrimp_tree() elif location == "ratcade": main_to_ratcade() elif location == "train": main_to_train() elif location == "classic": main_to_classic() elif location == "treehouse": main_to_treehouse() log("Zooming in to normal scale") default_zoom_in_amount = CFG.zoom_max - CFG.zoom_default zoom_in_amount = CFG.nav_post_zoom_in.get(location, default_zoom_in_amount) ACFG.zoom(zoom_direction_key="i", amount=zoom_in_amount) log(f"Complete! This is experimental, so please re-run \n'!nav {location}' if it didn't work." ) await async_sleep(3)
def main_to_treehouse(): log_process("AutoNav") log("Main -> Funky Treehouse") ACFG.move("a", 1.5, raw=True) ACFG.move("w", 3, raw=True) ACFG.move("a", 1, raw=True) ACFG.move("w", 1.5, raw=True) ACFG.move("a", 1.1, raw=True) ACFG.move("s", 1, raw=True) ACFG.leap(forward_time=1, jump_time=1, direction_key="s") ACFG.move("s", 0.5, raw=True) ACFG.move("d", 0.5, raw=True) ACFG.move("w", 0.3, raw=True) ACFG.move("d", 0.2, raw=True) ACFG.leap(forward_time=0.305, jump_time=0.3, direction_key="w") ACFG.move("d", 0.2, raw=True) ACFG.leap(forward_time=0.6, jump_time=0.3, direction_key="s", jump_delay=0.15) ACFG.move("w", 0.125, raw=True) ACFG.leap(forward_time=0.2, jump_time=0.3, direction_key="d", jump_delay=0.1) ACFG.move("d", 0.125, raw=True) ACFG.leap(forward_time=0.2, jump_time=0.3, direction_key="d") ACFG.move("s", 0.5, raw=True) ACFG.leap(forward_time=0.2, jump_time=0.2, direction_key="s") ACFG.move("a", 0.1, raw=True) ACFG.move("s", 0.15, raw=True) ACFG.move("a", 0.8, raw=True) ACFG.move("w", 0.125, raw=True) ACFG.leap(forward_time=0.3, jump_time=0.15, direction_key="d") ACFG.move("d", 1.7, raw=True) ACFG.move("w", 0.5, raw=True) ACFG.move("a", 0.5, raw=True) ACFG.move("s", 0.41, raw=True) ACFG.move("d", 0.55, raw=True) ACFG.leap(forward_time=0.4, jump_time=0.75, direction_key="a") ACFG.leap(forward_time=0.2, jump_time=0.3, direction_key="d", jump_delay=0.1) ACFG.move("s", 0.075, raw=True) ACFG.move("a", 0.05, raw=True)
async def respawn_character(notify_chat: bool = True): await check_active() log_process("Respawning") if notify_chat: await send_chat("[Respawning!]") await async_sleep(0.75) ACFG.jump() await async_sleep(0.75) ACFG.keyPress("KEY_ESC") await async_sleep(0.5) ACFG.keyPress("r") await async_sleep(0.5) ACFG.keyPress("KEY_RETURN") await async_sleep(0.5) log_process("")
async def mute_toggle(set_mute: Union[bool, None] = None): log_process("In-game Mute") desired_mute_state = not CFG.audio_muted if set_mute is not None: # If specified, force to state desired_mute_state = set_mute desired_volume = 0 if desired_mute_state else 100 log_msg = "Muting" if desired_mute_state else "Un-muting" log(log_msg) sc_exe_path = str(CFG.resources_path / CFG.sound_control_executable_name) os.system( # nosec f'{sc_exe_path} /SetVolume "{CFG.game_executable_name}" {desired_volume}' ) # Kill the process no matter what, race condition for this is two songs playing (bad) kill_process(executable=CFG.vlc_executable_name, force=True) if desired_mute_state: # Start playing music copyfile( CFG.resources_path / OBS.muted_icon_name, OBS.output_folder / OBS.muted_icon_name, ) vlc_exe_path = str(CFG.vlc_path / CFG.vlc_executable_name) music_folder = str(CFG.resources_path / "soundtracks" / "overworld") Popen( f'"{vlc_exe_path}" --playlist-autostart --loop --playlist-tree {music_folder}' ) output_log("muted_status", "In-game audio muted!\nRun !mute to unmute") sleep(5) # Give it time to load VLC else: # Stop playing music try: if os.path.exists(OBS.output_folder / OBS.muted_icon_name): os.remove(OBS.output_folder / OBS.muted_icon_name) except OSError: log("Error, could not remove icon!\nNotifying admin...") async_sleep(2) notify_admin("Mute icon could not be removed") log(log_msg) output_log("muted_status", "") CFG.audio_muted = desired_mute_state await check_active() log_process("") log("")
async def routine_reboot(): action_queue_item = ActionQueueItem( "chat", {"msgs": ["[System restart in 2 minutes]"]} ) await CFG.add_action_queue(action_queue_item) await async_sleep(60) action_queue_item = ActionQueueItem( "chat", {"msgs": ["[System restart in 1 minute]"]} ) await CFG.add_action_queue(action_queue_item) await async_sleep(60) log_process("System Shutdown") log("Initiating shutdown sequence") action_queue_item = ActionQueueItem("chat", {"msgs": ["[System restarting]"]}) await CFG.add_action_queue(action_queue_item) await async_sleep(10) system("shutdown /f /r /t 0") # nosec
def main_to_train(): log_process("AutoNav") log("Main -> Train Station") ACFG.move("a", 0.25, raw=True) ACFG.move("s", 4.5, raw=True) ACFG.move("d", 1.525, raw=True) ACFG.move("s", 2.9, raw=True) ACFG.move("d", 1, raw=True) ACFG.move("s", 2, raw=True) ACFG.move("d", 0.6, raw=True) ACFG.look("left", 1.5, raw=True) ACFG.leap(0.75, 0.75) ACFG.move("w", 0.75, raw=True) ACFG.leap(1, 1) ACFG.look("left", 0.75, raw=True) ACFG.move("s", 0.05, raw=True) ACFG.move("a", 0.075, raw=True) ACFG.move("s", 0.1, raw=True) log_process("") log("")
def main_to_classic(): log_process("AutoNav") log("Main -> BecomeFumo Classic Portal") ACFG.move("a", 0.25, raw=True) ACFG.move("s", 4.5, raw=True) ACFG.move("d", 1.75, raw=True) ACFG.move("s", 2.6, raw=True) ACFG.move("a", 1, raw=True) ACFG.move("s", 2.55, raw=True) ACFG.move("d", 1, raw=True) ACFG.move("s", 2.5, raw=True) ACFG.leap(forward_time=0.3, jump_time=0.25, direction_key="s") ACFG.move("d", 0.5, raw=True) ACFG.move("s", 0.3, raw=True) ACFG.leap(forward_time=0.3, jump_time=0.3, direction_key="s") ACFG.move("d", 0.2, raw=True) ACFG.move("s", 0.275, raw=True) ACFG.leap(forward_time=0.625, jump_time=0.5, direction_key="s") ACFG.leap(forward_time=1, jump_time=0.2, direction_key="d", jump_delay=0.35) ACFG.move("s", 0.225, raw=True) ACFG.leap(forward_time=0.8, jump_time=0.4, direction_key="d", jump_delay=0.3) ACFG.use() sleep(5) ACFG.move("w", 1.8, raw=True) ACFG.move("d", 0.125, raw=True) ACFG.move("w", 2.275, raw=True) ACFG.look("right", 0.375, raw=True) ACFG.move("s", 0.075, raw=True) ACFG.move("d", 0.06, raw=True) log_process("") log("")
async def check_for_better_server(): last_check_time = time() output_log("last_check_for_better_server", last_check_time) previous_status_text = read_output_log("change_server_status_text") output_log("change_server_status_text", "") log_process("Checking for better server") current_server_id = await get_current_server_id() if current_server_id == "ERROR": for i in range(CFG.max_attempts_better_server): log_process( f"Attempt {i+1}/{CFG.max_attempts_better_server} failed! Retrying better server check..." ) await async_sleep(5) current_server_id = await get_current_server_id() if current_server_id != "ERROR": break if current_server_id == "ERROR": log_process( f"Failed to connect to Roblox API {CFG.max_attempts_better_server} times! Skipping..." ) await async_sleep(5) log_process("") return True if current_server_id == "N/A": for id in list(CFG.game_ids_other.keys()): current_server_id == await get_current_server_id(id) if current_server_id != "N/A": break if current_server_id == "N/A": log_process("Could not find FumoCam in any servers") await CFG.add_action_queue(ActionQueueItem("handle_crash")) return False else: log_process("") log("") return True ( should_change_servers, change_server_status_text, ) = await check_if_should_change_servers(current_server_id) log(change_server_status_text) output_log("change_server_status_text", change_server_status_text) if not should_change_servers: log("PASS! Current server has sufficient players") log("") log_process("") return True elif previous_status_text != change_server_status_text: if "Could not find FumoCam" in change_server_status_text: for attempt in range(CFG.max_attempts_better_server): log(f"Rechecking (attempt {attempt+1}/{CFG.max_attempts_better_server}" ) current_server_id = await get_current_server_id() while current_server_id == "": log_process("Retrying get current server check") await async_sleep(5) current_server_id = await get_current_server_id() ( should_change_servers, change_server_status_text, ) = await check_if_should_change_servers(current_server_id) if "Could not find FumoCam" not in change_server_status_text: break if should_change_servers: notify_admin(change_server_status_text) await CFG.add_action_queue( ActionQueueItem("handle_join_new_server")) else: await CFG.add_action_queue( ActionQueueItem("handle_join_new_server")) log("") log_process("")