From 896aed5f39622e87cedf1ae61f0ec99f872e7d26 Mon Sep 17 00:00:00 2001 From: Tino Date: Tue, 7 May 2024 14:14:06 -0500 Subject: [PATCH] Update Roamer mode to use new navigation functions This removes calls to the deprecated same-map navigation function in favour of the new cross-map one. Doing that simplifies the code a little bit, and hopefully also fixes #316 (at least I wasn't able to reproduce the behaviour anymore.) As a semi-related fix, this resolves an issue where reapplying Repel would lead to the player continue running in the same direction until they hit an obstacle. --- modules/map_path.py | 7 +++- modules/modes/roamer_reset.py | 61 +++++++++++++---------------------- modules/modes/util/items.py | 7 +++- 3 files changed, 34 insertions(+), 41 deletions(-) diff --git a/modules/map_path.py b/modules/map_path.py index b1cd0210..75ad4bae 100644 --- a/modules/map_path.py +++ b/modules/map_path.py @@ -108,7 +108,12 @@ def tile_index(x: int, y: int): ) ) for map_object in map_data.objects: - tile = self._tiles[tile_index(*map_object.local_coordinates)] + try: + tile = self._tiles[tile_index(*map_object.local_coordinates)] + except IndexError: + # If loaded map object data is invalid, a map object's coordinates might be out of bounds. + # This `except` block catches that case and pretends like the object is not loaded at all. + continue if map_object.flag_id != 0: tile.dynamic_collision_flag = map_object.flag_id else: diff --git a/modules/modes/roamer_reset.py b/modules/modes/roamer_reset.py index 2d739c35..3fa5771c 100644 --- a/modules/modes/roamer_reset.py +++ b/modules/modes/roamer_reset.py @@ -21,8 +21,7 @@ apply_repel, ensure_facing_direction, fly_to, - follow_path, - deprecated_navigate_to_on_current_map, + navigate_to, replenish_repel, soft_reset, wait_for_player_avatar_to_be_standing_still, @@ -156,13 +155,14 @@ def run_emerald(self, has_good_ability: bool): yield from wait_for_player_avatar_to_be_standing_still() + # Leave bedroom if get_player().gender == "female": - yield from deprecated_navigate_to_on_current_map(1, 2) + yield from navigate_to(MapRSE.LITTLEROOT_TOWN_MAYS_HOUSE_2F, (1, 1)) else: - yield from deprecated_navigate_to_on_current_map(7, 2) - - yield from walk_one_tile("Up") + yield from navigate_to(MapRSE.LITTLEROOT_TOWN_BRENDANS_HOUSE_2F, (7, 1)) + # Dialogue with Dad, Mum, and the TV where they also ask about the colour of the Pokemon + # (which decides whether the roamer will be Latios or Latias.) yield from wait_until_task_is_active("Task_HandleMultichoiceInput", "B") if roamer_choice == "Latios": yield @@ -176,12 +176,11 @@ def run_emerald(self, has_good_ability: bool): yield from wait_for_player_avatar_to_be_standing_still() + # Leave player's house if get_player().gender == "female": - yield from deprecated_navigate_to_on_current_map(2, 8) + yield from navigate_to(MapRSE.LITTLEROOT_TOWN_MAYS_HOUSE_1F, (2, 8)) else: - yield from deprecated_navigate_to_on_current_map(8, 8) - - yield from walk_one_tile("Down") + yield from navigate_to(MapRSE.LITTLEROOT_TOWN_BRENDANS_HOUSE_1F, (8, 8)) # Cut scene where you get the National Dex if get_event_var("DEX_UPGRADE_JOHTO_STARTER_STATE") == 1: @@ -189,36 +188,27 @@ def run_emerald(self, has_good_ability: bool): "LittlerootTown_ProfessorBirchsLab_EventScript_UpgradeToNationalDex", "B" ) yield from wait_for_player_avatar_to_be_controllable() - yield from deprecated_navigate_to_on_current_map(6, 12) - yield from walk_one_tile("Down") + yield from navigate_to(MapRSE.LITTLEROOT_TOWN_PROFESSOR_BIRCHS_LAB, (6, 12)) # Fly to Slateport City, as the most efficient place to do this seems to be between # there and Route 110 yield from fly_to(FlyDestinationRSE.SlateportCity) - # Walk to Slateport's border with Route 110 - yield from deprecated_navigate_to_on_current_map(15, 0) - def inner_loop(): if _get_repel_steps_remaining() <= 0: yield from apply_repel() # Walk up to tall grass, spin, return - yield from walk_one_tile("Up") - yield from follow_path([(15, 97), (14, 97)]) + yield from navigate_to(MapRSE.ROUTE110, (14, 97)) directions = ["Down", "Right", "Up", "Left"] for index in range(42 if has_good_ability else 62): yield from ensure_facing_direction(directions[index % 4]) - yield from follow_path([(15, 97), (15, 99)]) - yield from walk_one_tile("Down") # Run to Battle Tent, enter, leave, go back to Route 110 # This is necessary because the game saves the last 3 locations the player # has been in and avoids them, so we need additional map transitions. - yield from follow_path([(17, 0), (17, 13), (10, 13)]) - yield from walk_one_tile("Up") + yield from navigate_to(MapRSE.SLATEPORT_CITY, (10, 12)) yield from walk_one_tile("Down") - yield from follow_path([(17, 13), (17, 0), (15, 0)]) while not self._should_reset and not self._ran_out_of_repels: for _ in inner_loop(): @@ -242,25 +232,23 @@ def run_frlg(self, has_good_ability: bool): yield from wait_for_player_avatar_to_be_standing_still() - yield from deprecated_navigate_to_on_current_map(14, 6) + # Walk up to Celio + yield from navigate_to(MapFRLG.ONE_ISLAND_POKEMON_CENTER_1F, (14, 6)) yield from ensure_facing_direction("Right") + # Talk to the Celio (giving him the Sapphire in the process) and wait for the dialogue to complete yield from wait_until_task_is_active("Task_DrawFieldMessageBox", "A") - while get_global_script_context().is_active: context.emulator.press_button("B") yield yield # Leave the building - while get_player_avatar().map_group_and_number != MapFRLG.ONE_ISLAND: - yield from follow_path([(14, 9), (9, 9)]) - yield from walk_one_tile("Down") + yield from navigate_to(MapFRLG.ONE_ISLAND_POKEMON_CENTER_1F, (9, 9)) # Walk to the ferry terminal and up to the sailor - yield from follow_path([(14, 12), (12, 12), (12, 18)]) - yield from walk_one_tile("Down") - yield from follow_path([(8, 5)]) + yield from navigate_to(MapFRLG.ONE_ISLAND, (12, 18)) + yield from navigate_to(MapFRLG.ONE_ISLAND_HARBOR, (8, 5)) # Talk to the sailor while get_game_state() == GameState.OVERWORLD: @@ -275,24 +263,19 @@ def run_frlg(self, has_good_ability: bool): # and Route 1 yield from fly_to(FlyDestinationFRLG.PalletTown) - # Go to the north of the map, just before Route 1 starts - yield from walk_one_tile("Right") - yield from deprecated_navigate_to_on_current_map(12, 0) - def inner_loop(): if _get_repel_steps_remaining() <= 0: yield from apply_repel() - yield from walk_one_tile("Up") + # Go to the first spot of tall grass on Route 1 and spin around for a while + yield from navigate_to(MapFRLG.ROUTE1, (12, 39)) directions = ["Left", "Down", "Right", "Up"] for index in range(18 if has_good_ability else 36): yield from ensure_facing_direction(directions[index % 4]) - yield from walk_one_tile("Down") - yield from follow_path([(12, 8), (15, 8)]) - yield from walk_one_tile("Up") + # Walk into rival's house to get an additional map transition. + yield from navigate_to(MapFRLG.PALLET_TOWN, (15, 7)) yield from walk_one_tile("Down") - yield from follow_path([(12, 8), (12, 0)]) while not self._should_reset and not self._ran_out_of_repels: for _ in inner_loop(): diff --git a/modules/modes/util/items.py b/modules/modes/util/items.py index 0f96bc86..77c4494d 100644 --- a/modules/modes/util/items.py +++ b/modules/modes/util/items.py @@ -147,7 +147,12 @@ def replenish_repel() -> None: if get_item_bag().number_of_repels == 0: raise RanOutOfRepels("Player ran out of repels") else: - context.controller_stack.insert(len(context.controller_stack) - 1, apply_repel()) + + def apply_repel_and_reset_inputs(): + yield from apply_repel() + context.emulator.reset_held_buttons() + + context.controller_stack.insert(len(context.controller_stack) - 1, apply_repel_and_reset_inputs()) @debug.track