diff --git a/PokemonClient.py b/PokemonClient.py index 2328243d..33e902a3 100644 --- a/PokemonClient.py +++ b/PokemonClient.py @@ -170,12 +170,12 @@ async def gb_sync_task(ctx: GBContext): data_decoded = json.loads(data.decode()) #print(data_decoded) - if ctx.seed_name and ctx.seed_name != bytes(data_decoded['seedName']).decode(): + if ctx.seed_name and ctx.seed_name != ''.join([chr(i) for i in data_decoded['seedName'] if i != 0]): msg = "The server is running a different multiworld than your client is. (invalid seed_name)" logger.info(msg, extra={'compact_gui': True}) ctx.gui_error('Error', msg) error_status = CONNECTION_RESET_STATUS - ctx.seed_name = bytes(data_decoded['seedName']).decode() + ctx.seed_name = ''.join([chr(i) for i in data_decoded['seedName'] if i != 0]) if not ctx.auth: ctx.auth = ''.join([chr(i) for i in data_decoded['playerName'] if i != 0]) if ctx.auth == '': @@ -260,7 +260,7 @@ async def patch_and_run_game(game_version, patch_file, ctx): patch = stream.read() patched_rom_data = bsdiff4.patch(base_patched_rom_data, patch) - written_hash = patched_rom_data[0xFFCC:0xFFDC] + written_hash = patched_rom_data[0xFFCB:0xFFDB] if written_hash == basemd5.digest(): with open(comp_path, "wb") as patched_rom_file: patched_rom_file.write(patched_rom_data) diff --git a/data/lua/PKMN_RB/pkmn_rb.lua b/data/lua/PKMN_RB/pkmn_rb.lua index 7518a5f1..30ccbbd3 100644 --- a/data/lua/PKMN_RB/pkmn_rb.lua +++ b/data/lua/PKMN_RB/pkmn_rb.lua @@ -161,7 +161,7 @@ function receive() -- Determine Message to send back memDomain.rom() newPlayerName = uRange(0xFFF0, 0x10) - newSeedName = uRange(0xFFDC, 20) + newSeedName = uRange(0xFFDB, 21) if (playerName ~= nil and not arrayEqual(playerName, newPlayerName)) or (seedName ~= nil and not arrayEqual(seedName, newSeedName)) then print("ROM changed, quitting") curstate = STATE_UNINITIALIZED diff --git a/worlds/pokemon_rb/__init__.py b/worlds/pokemon_rb/__init__.py index 2f65f301..c6980fc0 100644 --- a/worlds/pokemon_rb/__init__.py +++ b/worlds/pokemon_rb/__init__.py @@ -80,6 +80,9 @@ class PokemonRedBlueWorld(World): self.trainer_name = encode_name(self.multiworld.trainer_name[self.player].value, "Player") self.rival_name = encode_name(self.multiworld.rival_name[self.player].value, "Rival") + if len(self.multiworld.player_name[self.player].encode()) > 16: + raise Exception(f"Player name too long for {self.multiworld.get_player_name(self.player)}. Player name cannot exceed 16 bytes for Pokémon Red and Blue.") + if self.multiworld.badges_needed_for_hm_moves[self.player].value >= 2: badges_to_add = ["Marsh Badge", "Volcano Badge", "Earth Badge"] if self.multiworld.badges_needed_for_hm_moves[self.player].value == 3: @@ -96,6 +99,7 @@ class PokemonRedBlueWorld(World): process_pokemon_data(self) def create_items(self) -> None: + start_inventory = self.multiworld.start_inventory[self.player].value.copy() locations = [location for location in location_data if location.type == "Item"] item_pool = [] for location in locations: @@ -105,7 +109,12 @@ class PokemonRedBlueWorld(World): continue if location.name == "Celadon City - Mansion Lady" and not self.multiworld.tea[self.player].value: continue - item = self.create_item(location.original_item) + if location.original_item in self.multiworld.start_inventory[self.player].value and \ + location.original_item in item_groups["Unique"]: + start_inventory[location.original_item] -= 1 + item = self.create_filler() + else: + item = self.create_item(location.original_item) if location.event: self.multiworld.get_location(location.name, self.player).place_locked_item(item) elif ("Badge" not in item.name or self.multiworld.badgesanity[self.player].value) and \ @@ -115,8 +124,7 @@ class PokemonRedBlueWorld(World): self.multiworld.itempool += item_pool - - def pre_fill(self): + def generate_basic(self) -> None: process_wild_pokemon(self) process_static_pokemon(self) @@ -169,7 +177,7 @@ class PokemonRedBlueWorld(World): unplaced_items = [] if loc.name in self.multiworld.priority_locations[self.player].value: add_item_rule(loc, lambda i: i.advancement) - for item in self.multiworld.itempool: + for item in reversed(self.multiworld.itempool): if item.player == self.player and loc.item_rule(item): self.multiworld.itempool.remove(item) state = sweep_from_pool(self.multiworld.state, self.multiworld.itempool + unplaced_items) @@ -197,11 +205,14 @@ class PokemonRedBlueWorld(World): def create_regions(self): if self.multiworld.free_fly_location[self.player].value: - fly_map_code = self.multiworld.random.randint(5, 9) + if self.multiworld.old_man[self.player].value == 0: + fly_map_code = self.multiworld.random.randint(1, 9) + else: + fly_map_code = self.multiworld.random.randint(5, 9) + if fly_map_code == 5: + fly_map_code = 4 if fly_map_code == 9: fly_map_code = 10 - if fly_map_code == 5: - fly_map_code = 4 else: fly_map_code = 0 self.fly_map = ["Pallet Town", "Viridian City", "Pewter City", "Cerulean City", "Lavender Town", @@ -236,7 +247,29 @@ class PokemonRedBlueWorld(World): def get_filler_item_name(self) -> str: return self.multiworld.random.choice([item for item in item_table if item_table[item].classification in - [ItemClassification.filler, ItemClassification.trap]]) + [ItemClassification.filler, ItemClassification.trap] and item not in + item_groups["Vending Machine Drinks"]]) + + def fill_slot_data(self) -> dict: + # for trackers + return { + "second_fossil_check_condition": self.multiworld.second_fossil_check_condition[self.player].value, + "require_item_finder": self.multiworld.require_item_finder[self.player].value, + "randomize_hidden_items": self.multiworld.randomize_hidden_items[self.player].value, + "badges_needed_for_hm_moves": self.multiworld.badges_needed_for_hm_moves[self.player].value, + "oaks_aide_rt_2": self.multiworld.oaks_aide_rt_2[self.player].value, + "oaks_aide_rt_11": self.multiworld.oaks_aide_rt_11[self.player].value, + "oaks_aide_rt_15": self.multiworld.oaks_aide_rt_15[self.player].value, + "extra_key_items": self.multiworld.extra_key_items[self.player].value, + "extra_strength_boulders": self.multiworld.extra_strength_boulders[self.player].value, + "tea": self.multiworld.tea[self.player].value, + "old_man": self.multiworld.old_man[self.player].value, + "elite_four_condition": self.multiworld.elite_four_condition[self.player].value, + "victory_road_condition": self.multiworld.victory_road_condition[self.player].value, + "viridian_gym_condition": self.multiworld.viridian_gym_condition[self.player].value, + "free_fly_map": self.fly_map_code, + "extra_badges": self.extra_badges + } class PokemonRBItem(Item): diff --git a/worlds/pokemon_rb/basepatch_blue.bsdiff4 b/worlds/pokemon_rb/basepatch_blue.bsdiff4 index c688ebed..1dd71016 100644 Binary files a/worlds/pokemon_rb/basepatch_blue.bsdiff4 and b/worlds/pokemon_rb/basepatch_blue.bsdiff4 differ diff --git a/worlds/pokemon_rb/basepatch_red.bsdiff4 b/worlds/pokemon_rb/basepatch_red.bsdiff4 index a9005d37..488ae272 100644 Binary files a/worlds/pokemon_rb/basepatch_red.bsdiff4 and b/worlds/pokemon_rb/basepatch_red.bsdiff4 differ diff --git a/worlds/pokemon_rb/docs/setup_en.md b/worlds/pokemon_rb/docs/setup_en.md index 58ed3b0d..7ec79b61 100644 --- a/worlds/pokemon_rb/docs/setup_en.md +++ b/worlds/pokemon_rb/docs/setup_en.md @@ -14,6 +14,11 @@ As we are using Bizhawk, this guide is only applicable to Windows and Linux syst (select `Pokemon Client` during installation). - Pokémon Red and/or Blue ROM files. The Archipelago community cannot provide these. +## Optional Software + +- [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/j-imbo/pkmnrb_jim/releases/latest), for use with [PopTracker](https://github.com/black-sliver/PopTracker/releases) + + ## Configuring Bizhawk Once Bizhawk has been installed, open Bizhawk and change the following settings: @@ -82,3 +87,14 @@ To connect the client to the multiserver simply put `
:` on the te server uses password, type in the bottom textfield `/connect
: [password]`) Now you are ready to start your adventure in Kanto. + +## Auto-Tracking + +Pokémon Red and Blue has a fully functional map tracker that supports auto-tracking. + +1. Download [Pokémon Red and Blue Archipelago Map Tracker](https://github.com/j-imbo/pkmnrb_jim/releases/latest) and [PopTracker](https://github.com/black-sliver/PopTracker/releases). +2. Open PopTracker, and load the Pokémon Red and Blue pack. +3. Click on the "AP" symbol at the top. +4. Enter the AP address, slot name and password. + +The rest should take care of itself! Items and checks will be marked automatically, and it even knows your settings - It will hide checks & adjust logic accordingly. diff --git a/worlds/pokemon_rb/items.py b/worlds/pokemon_rb/items.py index 53722c02..82ac6345 100644 --- a/worlds/pokemon_rb/items.py +++ b/worlds/pokemon_rb/items.py @@ -66,9 +66,9 @@ item_table = { "Max Repel": ItemData(57, ItemClassification.filler, ["Consumables"]), "Dire Hit": ItemData(58, ItemClassification.filler, ["Consumables", "Battle Items"]), #"Coin": ItemData(59, ItemClassification.filler), - "Fresh Water": ItemData(60, ItemClassification.filler, ["Consumables"]), - "Soda Pop": ItemData(61, ItemClassification.filler, ["Consumables"]), - "Lemonade": ItemData(62, ItemClassification.filler, ["Consumables"]), + "Fresh Water": ItemData(60, ItemClassification.filler, ["Consumables", "Vending Machine Drinks"]), + "Soda Pop": ItemData(61, ItemClassification.filler, ["Consumables", "Vending Machine Drinks"]), + "Lemonade": ItemData(62, ItemClassification.filler, ["Consumables", "Vending Machine Drinks"]), "S.S. Ticket": ItemData(63, ItemClassification.progression, ["Unique", "Key Items"]), "Gold Teeth": ItemData(64, ItemClassification.progression, ["Unique", "Key Items"]), "X Attack": ItemData(65, ItemClassification.filler, ["Consumables", "Battle Items"]), diff --git a/worlds/pokemon_rb/locations.py b/worlds/pokemon_rb/locations.py index a619336f..e6f54dc8 100644 --- a/worlds/pokemon_rb/locations.py +++ b/worlds/pokemon_rb/locations.py @@ -321,21 +321,21 @@ location_data = [ LocationData("Viridian Forest", "Hidden Item Entrance Tree", "Antidote", rom_addresses['Hidden_Item_Viridian_Forest_2'], Hidden(1)), LocationData("Mt Moon B2F", "Hidden Item Dead End Before Fossils", "Moon Stone", rom_addresses['Hidden_Item_MtMoonB2F_1'], Hidden(2)), LocationData("Route 25", "Hidden Item Fence Outside Bill's House", "Ether", rom_addresses['Hidden_Item_Route_25_1'], Hidden(3)), - LocationData("Route 9", "Hidden Item Rock By Grass", "Ether", rom_addresses['Hidden_Item_Route_9'], Hidden(4)), + LocationData("Route 9", "Hidden Item Bush By Grass", "Ether", rom_addresses['Hidden_Item_Route_9'], Hidden(4)), LocationData("S.S. Anne 1F", "Hidden Item Kitchen Trash", "Great Ball", rom_addresses['Hidden_Item_SS_Anne_Kitchen'], Hidden(5)), LocationData("S.S. Anne B1F", "Hidden Item Under Pillow", "Hyper Potion", rom_addresses['Hidden_Item_SS_Anne_B1F'], Hidden(6)), - LocationData("Route 10 North", "Hidden Item Behind Rock Tunnel Entrance Tree", "Super Potion", rom_addresses['Hidden_Item_Route_10_1'], Hidden(7)), - LocationData("Route 10 South", "Hidden Item Rock", "Max Ether", rom_addresses['Hidden_Item_Route_10_2'], Hidden(8)), + LocationData("Route 10 North", "Hidden Item Behind Rock Tunnel Entrance Cuttable Tree", "Super Potion", rom_addresses['Hidden_Item_Route_10_1'], Hidden(7)), + LocationData("Route 10 South", "Hidden Item Bush", "Max Ether", rom_addresses['Hidden_Item_Route_10_2'], Hidden(8)), LocationData("Rocket Hideout B1F", "Hidden Item Pot Plant", "PP Up", rom_addresses['Hidden_Item_Rocket_Hideout_B1F'], Hidden(9)), LocationData("Rocket Hideout B3F", "Hidden Item Near East Item", "Nugget", rom_addresses['Hidden_Item_Rocket_Hideout_B3F'], Hidden(10)), LocationData("Rocket Hideout B4F", "Hidden Item Behind Giovanni", "Super Potion", rom_addresses['Hidden_Item_Rocket_Hideout_B4F'], Hidden(11)), LocationData("Pokemon Tower 5F", "Hidden Item Near West Staircase", "Elixir", rom_addresses['Hidden_Item_Pokemon_Tower_5F'], Hidden(12)), - LocationData("Route 13", "Hidden Item Dead End Boulder", "PP Up", rom_addresses['Hidden_Item_Route_13_1'], Hidden(13)), + LocationData("Route 13", "Hidden Item Dead End Bush", "PP Up", rom_addresses['Hidden_Item_Route_13_1'], Hidden(13)), LocationData("Route 13", "Hidden Item Dead End By Water Corner", "Calcium", rom_addresses['Hidden_Item_Route_13_2'], Hidden(14)), LocationData("Pokemon Mansion B1F", "Hidden Item Secret Key Room Corner", "Rare Candy", rom_addresses['Hidden_Item_Pokemon_Mansion_B1F'], Hidden(15)), LocationData("Safari Zone West", "Hidden Item Secret House Statue", "Revive", rom_addresses['Hidden_Item_Safari_Zone_West'], Hidden(17)), LocationData("Silph Co 5F", "Hidden Item Pot Plant", "Elixir", rom_addresses['Hidden_Item_Silph_Co_5F'], Hidden(18)), - LocationData("Silph Co 9F", "Hidden Item Nurse Bed", "Max Potion", rom_addresses['Hidden_Item_Silph_Co_9F'], Hidden(19)), + LocationData("Silph Co 9F", "Hidden Item Nurse Bed (Card Key)", "Max Potion", rom_addresses['Hidden_Item_Silph_Co_9F'], Hidden(19)), LocationData("Copycat's House", "Hidden Item Desk", "Nugget", rom_addresses['Hidden_Item_Copycats_House'], Hidden(20)), LocationData("Cerulean Cave 1F", "Hidden Item Center Rocks", "Rare Candy", rom_addresses['Hidden_Item_Cerulean_Cave_1F'], Hidden(21)), LocationData("Cerulean Cave B1F", "Hidden Item Northeast Rocks", "Ultra Ball", rom_addresses['Hidden_Item_Cerulean_Cave_B1F'], Hidden(22)), @@ -345,15 +345,15 @@ location_data = [ LocationData("Seafoam Islands B4F", "Hidden Item Corner Island", "Ultra Ball", rom_addresses['Hidden_Item_Seafoam_Islands_B4F'], Hidden(26)), LocationData("Pokemon Mansion 1F", "Hidden Item Block Near Entrance Carpet", "Moon Stone", rom_addresses['Hidden_Item_Pokemon_Mansion_1F'], Hidden(27)), LocationData("Pokemon Mansion 3F", "Hidden Item Behind Burglar", "Max Revive", rom_addresses['Hidden_Item_Pokemon_Mansion_3F'], Hidden(28)), - LocationData("Route 23 North", "Hidden Item Rocks Before Final Guard", "Full Restore", rom_addresses['Hidden_Item_Route_23_1'], Hidden(29)), - LocationData("Route 23 North", "Hidden Item East Tree After Water", "Ultra Ball", rom_addresses['Hidden_Item_Route_23_2'], Hidden(30)), - LocationData("Route 23 South", "Hidden Item On Island", "Max Ether", rom_addresses['Hidden_Item_Route_23_3'], Hidden(31)), + LocationData("Route 23", "Hidden Item Rocks Before Final Guard", "Full Restore", rom_addresses['Hidden_Item_Route_23_1'], Hidden(29)), + LocationData("Route 23", "Hidden Item East Bush After Water", "Ultra Ball", rom_addresses['Hidden_Item_Route_23_2'], Hidden(30)), + LocationData("Route 23", "Hidden Item On Island", "Max Ether", rom_addresses['Hidden_Item_Route_23_3'], Hidden(31)), LocationData("Victory Road 2F", "Hidden Item Rock Before Moltres", "Ultra Ball", rom_addresses['Hidden_Item_Victory_Road_2F_1'], Hidden(32)), LocationData("Victory Road 2F", "Hidden Item Rock In Final Room", "Full Restore", rom_addresses['Hidden_Item_Victory_Road_2F_2'], Hidden(33)), - #LocationData("Vermilion City", "Hidden Item The Truck", "Max Elixir", rom_addresses['Hidden_Item_Unused_6F'], Hidden(34)), + LocationData("Viridian City", "Hidden Item Cuttable Tree", "Potion", rom_addresses['Hidden_Item_Viridian_City'], Hidden(35)), - LocationData("Route 11", "Hidden Item Isolated Tree Near Gate", "Potion", rom_addresses['Hidden_Item_Route_11'], Hidden(36)), - LocationData("Route 12 West", "Hidden Item Tree Near Gate", "Hyper Potion", rom_addresses['Hidden_Item_Route_12'], Hidden(37)), + LocationData("Route 11", "Hidden Item Isolated Bush Near Gate", "Potion", rom_addresses['Hidden_Item_Route_11'], Hidden(36)), + LocationData("Route 12 West", "Hidden Item Bush Near Gate", "Hyper Potion", rom_addresses['Hidden_Item_Route_12'], Hidden(37)), LocationData("Route 17", "Hidden Item In Grass", "Rare Candy", rom_addresses['Hidden_Item_Route_17_1'], Hidden(38)), LocationData("Route 17", "Hidden Item Near Northernmost Sign", "Full Restore", rom_addresses['Hidden_Item_Route_17_2'], Hidden(39)), LocationData("Route 17", "Hidden Item East Center", "PP Up", rom_addresses['Hidden_Item_Route_17_3'], Hidden(40)), @@ -421,13 +421,13 @@ location_data = [ None, event=True, type="Wild Encounter"), LocationData("Route 19", "Super Rod Pokemon - 4", "Goldeen", rom_addresses["Wild_Super_Rod_H"] + 7, None, event=True, type="Wild Encounter"), - LocationData("Route 23 South", "Super Rod Pokemon - 1", "Slowbro", rom_addresses["Wild_Super_Rod_I"] + 1, + LocationData("Route 23", "Super Rod Pokemon - 1", "Slowbro", rom_addresses["Wild_Super_Rod_I"] + 1, None, event=True, type="Wild Encounter"), - LocationData("Route 23 South", "Super Rod Pokemon - 2", "Seaking", rom_addresses["Wild_Super_Rod_I"] + 3, + LocationData("Route 23", "Super Rod Pokemon - 2", "Seaking", rom_addresses["Wild_Super_Rod_I"] + 3, None, event=True, type="Wild Encounter"), - LocationData("Route 23 South", "Super Rod Pokemon - 3", "Kingler", rom_addresses["Wild_Super_Rod_I"] + 5, + LocationData("Route 23", "Super Rod Pokemon - 3", "Kingler", rom_addresses["Wild_Super_Rod_I"] + 5, None, event=True, type="Wild Encounter"), - LocationData("Route 23 South", "Super Rod Pokemon - 4", "Seadra", rom_addresses["Wild_Super_Rod_I"] + 7, + LocationData("Route 23", "Super Rod Pokemon - 4", "Seadra", rom_addresses["Wild_Super_Rod_I"] + 7, None, event=True, type="Wild Encounter"), LocationData("Fuchsia City", "Super Rod Pokemon - 1", "Seaking", rom_addresses["Wild_Super_Rod_J"] + 1, None, event=True, type="Wild Encounter"), @@ -1480,25 +1480,25 @@ location_data = [ None, event=True, type="Wild Encounter"), LocationData("Power Plant", "Wild Pokemon - 10", ["Electabuzz", "Raichu"], rom_addresses["Wild_PowerPlant"] + 19, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 1", ["Ekans", "Sandshrew"], rom_addresses["Wild_Route23"] + 1, + LocationData("Route 23", "Wild Pokemon - 1", ["Ekans", "Sandshrew"], rom_addresses["Wild_Route23"] + 1, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 2", "Ditto", rom_addresses["Wild_Route23"] + 3, None, event=True, + LocationData("Route 23", "Wild Pokemon - 2", "Ditto", rom_addresses["Wild_Route23"] + 3, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 3", "Spearow", rom_addresses["Wild_Route23"] + 5, None, + LocationData("Route 23", "Wild Pokemon - 3", "Spearow", rom_addresses["Wild_Route23"] + 5, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 4", "Fearow", rom_addresses["Wild_Route23"] + 7, None, + LocationData("Route 23", "Wild Pokemon - 4", "Fearow", rom_addresses["Wild_Route23"] + 7, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 5", "Ditto", rom_addresses["Wild_Route23"] + 9, None, event=True, + LocationData("Route 23", "Wild Pokemon - 5", "Ditto", rom_addresses["Wild_Route23"] + 9, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 6", "Fearow", rom_addresses["Wild_Route23"] + 11, None, + LocationData("Route 23", "Wild Pokemon - 6", "Fearow", rom_addresses["Wild_Route23"] + 11, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 7", ["Arbok", "Sandslash"], rom_addresses["Wild_Route23"] + 13, + LocationData("Route 23", "Wild Pokemon - 7", ["Arbok", "Sandslash"], rom_addresses["Wild_Route23"] + 13, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 8", "Ditto", rom_addresses["Wild_Route23"] + 15, None, + LocationData("Route 23", "Wild Pokemon - 8", "Ditto", rom_addresses["Wild_Route23"] + 15, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 9", "Fearow", rom_addresses["Wild_Route23"] + 17, None, + LocationData("Route 23", "Wild Pokemon - 9", "Fearow", rom_addresses["Wild_Route23"] + 17, None, event=True, type="Wild Encounter"), - LocationData("Route 23 North", "Wild Pokemon - 10", "Fearow", rom_addresses["Wild_Route23"] + 19, None, + LocationData("Route 23", "Wild Pokemon - 10", "Fearow", rom_addresses["Wild_Route23"] + 19, None, event=True, type="Wild Encounter"), LocationData("Victory Road 2F", "Wild Pokemon - 1", "Machop", rom_addresses["Wild_VictoryRoad2F"] + 1, None, event=True, type="Wild Encounter"), diff --git a/worlds/pokemon_rb/options.py b/worlds/pokemon_rb/options.py index e7e972f3..6ab2b254 100644 --- a/worlds/pokemon_rb/options.py +++ b/worlds/pokemon_rb/options.py @@ -83,9 +83,9 @@ class BadgeSanity(Toggle): class BadgesNeededForHMMoves(Choice): - """Off will remove the requirement for badges to use HM moves. Extra will give the Marsh, Volcano, and Earth - Badges a random HM move to enable. Extra Plus will additionally pick two random badges to enable a second HM move. - A man in Cerulean City will reveal the moves enabled by each Badge.""" + """Off will remove the requirement for badges to use HM moves. Extra will give the Marsh, Volcano, and Earth Badges + a random HM move to enable. Extra Plus will additionally pick two random badges to enable a second HM move. + You will only need one of the required badges to use the HM move.""" display_name = "Badges Needed For HM Moves" default = 1 option_on = 1 diff --git a/worlds/pokemon_rb/regions.py b/worlds/pokemon_rb/regions.py index 1b537904..5141f06c 100644 --- a/worlds/pokemon_rb/regions.py +++ b/worlds/pokemon_rb/regions.py @@ -41,8 +41,7 @@ def create_regions(world: MultiWorld, player: int): create_region(world, player, "Route 2 East", locations_per_region), create_region(world, player, "Diglett's Cave", locations_per_region), create_region(world, player, "Route 22", locations_per_region), - create_region(world, player, "Route 23 South", locations_per_region), - create_region(world, player, "Route 23 North", locations_per_region), + create_region(world, player, "Route 23", locations_per_region), create_region(world, player, "Viridian Forest", locations_per_region), create_region(world, player, "Pewter City", locations_per_region), create_region(world, player, "Pewter Gym", locations_per_region), @@ -154,9 +153,9 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Pallet Town", "Route 1") connect(world, player, "Route 1", "Viridian City") connect(world, player, "Viridian City", "Route 22") - connect(world, player, "Route 22", "Route 23 South", - lambda state: state.pokemon_rb_has_badges(state.multiworld.victory_road_condition[player].value, player)) - connect(world, player, "Route 23 South", "Route 23 North", lambda state: state.pokemon_rb_can_surf(player)) + connect(world, player, "Route 22", "Route 23", + lambda state: state.pokemon_rb_has_badges(state.multiworld.victory_road_condition[player].value, player) and + state.pokemon_rb_can_surf(player)) connect(world, player, "Viridian City North", "Viridian Gym", lambda state: state.pokemon_rb_has_badges(state.multiworld.viridian_gym_condition[player].value, player), one_way=True) connect(world, player, "Route 2", "Route 2 East", lambda state: state.pokemon_rb_can_cut(player)) @@ -270,7 +269,7 @@ def create_regions(world: MultiWorld, player: int): connect(world, player, "Pokemon Mansion 1F", "Pokemon Mansion 2F", one_way=True) connect(world, player, "Pokemon Mansion 2F", "Pokemon Mansion 3F", one_way=True) connect(world, player, "Pokemon Mansion 1F", "Pokemon Mansion B1F", one_way=True) - connect(world, player, "Route 23 North", "Victory Road 1F", lambda state: state.pokemon_rb_can_strength(player), one_way=True) + connect(world, player, "Route 23", "Victory Road 1F", lambda state: state.pokemon_rb_can_strength(player), one_way=True) connect(world, player, "Victory Road 1F", "Victory Road 2F", one_way=True) connect(world, player, "Victory Road 2F", "Victory Road 3F", one_way=True) connect(world, player, "Victory Road 2F", "Indigo Plateau", lambda state: state.pokemon_rb_has_badges(state.multiworld.elite_four_condition[player], player), one_way=True) diff --git a/worlds/pokemon_rb/rom.py b/worlds/pokemon_rb/rom.py index 9e3c567f..12e22a0f 100644 --- a/worlds/pokemon_rb/rom.py +++ b/worlds/pokemon_rb/rom.py @@ -409,6 +409,8 @@ def generate_output(self, output_directory: str): data[rom_addresses["Starting_Money_High"]] = int(money[:2], 16) data[rom_addresses["Starting_Money_Middle"]] = int(money[2:4], 16) data[rom_addresses["Starting_Money_Low"]] = int(money[4:], 16) + data[rom_addresses["Text_Badges_Needed_Viridian_Gym"]] = encode_text( + str(self.multiworld.viridian_gym_condition[self.player].value))[0] data[rom_addresses["Text_Badges_Needed"]] = encode_text( str(max(self.multiworld.victory_road_condition[self.player].value, self.multiworld.elite_four_condition[self.player].value)))[0] @@ -545,7 +547,7 @@ def generate_output(self, output_directory: str): mons.sort(key=lambda mon: 0 if mon == self.multiworld.get_location("Pallet Town - Starter 2", self.player).item.name else 1 if mon == self.multiworld.get_location("Pallet Town - Starter 1", self.player).item.name else 2 if mon == self.multiworld.get_location("Pallet Town - Starter 3", self.player).item.name else 3) - write_bytes(data, encode_text(self.multiworld.seed_name, 20, True), rom_addresses['Title_Seed']) + write_bytes(data, encode_text(self.multiworld.seed_name[-20:], 20, True), rom_addresses['Title_Seed']) slot_name = self.multiworld.player_name[self.player] slot_name.replace("@", " ") @@ -556,8 +558,8 @@ def generate_output(self, output_directory: str): write_bytes(data, self.trainer_name, rom_addresses['Player_Name']) write_bytes(data, self.rival_name, rom_addresses['Rival_Name']) - write_bytes(data, basemd5.digest(), 0xFFCC) - write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDC) + write_bytes(data, basemd5.digest(), 0xFFCB) + write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDB) write_bytes(data, self.multiworld.player_name[self.player].encode(), 0xFFF0) diff --git a/worlds/pokemon_rb/rom_addresses.py b/worlds/pokemon_rb/rom_addresses.py index c04a75bc..206365a2 100644 --- a/worlds/pokemon_rb/rom_addresses.py +++ b/worlds/pokemon_rb/rom_addresses.py @@ -327,9 +327,9 @@ rom_addresses = { "Learnset_Bellsprout": 0x3b9dc, "Learnset_Weepinbell": 0x3b9f0, "Learnset_Victreebel": 0x3ba00, - "Type_Chart": 0x3e4b6, - "Type_Chart_Divider": 0x3e5ac, - "Ghost_Battle3": 0x3efd9, + "Type_Chart": 0x3e4b0, + "Type_Chart_Divider": 0x3e5a6, + "Ghost_Battle3": 0x3efd3, "Missable_Pokemon_Mansion_1F_Item_1": 0x443d6, "Missable_Pokemon_Mansion_1F_Item_2": 0x443dd, "Map_Rock_TunnelF": 0x44676, @@ -585,4 +585,5 @@ rom_addresses = { "Badge_Text_Marsh_Badge": 0x9918c, "Badge_Text_Volcano_Badge": 0x991d6, "Badge_Text_Earth_Badge": 0x991f3, + "Text_Badges_Needed_Viridian_Gym": 0xa49f2, } diff --git a/worlds/pokemon_rb/rules.py b/worlds/pokemon_rb/rules.py index 2f0e573d..2f885fd6 100644 --- a/worlds/pokemon_rb/rules.py +++ b/worlds/pokemon_rb/rules.py @@ -73,12 +73,12 @@ def set_rules(world, player): "Anywhere - Good Rod Pokemon - 1": lambda state: state.has("Good Rod", player), "Anywhere - Good Rod Pokemon - 2": lambda state: state.has("Good Rod", player), "Anywhere - Old Rod Pokemon": lambda state: state.has("Old Rod", player), - "Celadon Prize Corner - Pokemon Prize - 1": lambda state: state.has("Coin Case", player), - "Celadon Prize Corner - Pokemon Prize - 2": lambda state: state.has("Coin Case", player), - "Celadon Prize Corner - Pokemon Prize - 3": lambda state: state.has("Coin Case", player), - "Celadon Prize Corner - Pokemon Prize - 4": lambda state: state.has("Coin Case", player), - "Celadon Prize Corner - Pokemon Prize - 5": lambda state: state.has("Coin Case", player), - "Celadon Prize Corner - Pokemon Prize - 6": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 1": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 2": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 3": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 4": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 5": lambda state: state.has("Coin Case", player), + "Celadon Prize Corner - Pokemon Prize - 6": lambda state: state.has("Coin Case", player), "Cinnabar Island - Old Amber Pokemon": lambda state: state.has("Old Amber", player), "Cinnabar Island - Helix Fossil Pokemon": lambda state: state.has("Helix Fossil", player), "Cinnabar Island - Dome Fossil Pokemon": lambda state: state.has("Dome Fossil", player), @@ -96,10 +96,10 @@ def set_rules(world, player): player), "Route 25 - Hidden Item Fence Outside Bill's House": lambda state: state.pokemon_rb_can_get_hidden_items( player), - "Route 9 - Hidden Item Rock By Grass": lambda state: state.pokemon_rb_can_get_hidden_items(player), + "Route 9 - Hidden Item Bush By Grass": lambda state: state.pokemon_rb_can_get_hidden_items(player), "S.S. Anne 1F - Hidden Item Kitchen Trash": lambda state: state.pokemon_rb_can_get_hidden_items(player), "S.S. Anne B1F - Hidden Item Under Pillow": lambda state: state.pokemon_rb_can_get_hidden_items(player), - "Route 10 - Hidden Item Behind Rock Tunnel Entrance Tree": lambda + "Route 10 - Hidden Item Behind Rock Tunnel Entrance Cuttable Tree": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 10 - Hidden Item Rock": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Rocket Hideout B1F - Hidden Item Pot Plant": lambda state: state.pokemon_rb_can_get_hidden_items(player), @@ -107,14 +107,15 @@ def set_rules(world, player): "Rocket Hideout B4F - Hidden Item Behind Giovanni": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Pokemon Tower 5F - Hidden Item Near West Staircase": lambda state: state.pokemon_rb_can_get_hidden_items( player), - "Route 13 - Hidden Item Dead End Boulder": lambda state: state.pokemon_rb_can_get_hidden_items(player), + "Route 13 - Hidden Item Dead End Bush": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 13 - Hidden Item Dead End By Water Corner": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Pokemon Mansion B1F - Hidden Item Secret Key Room Corner": lambda state: state.pokemon_rb_can_get_hidden_items( player), "Safari Zone West - Hidden Item Secret House Statue": lambda state: state.pokemon_rb_can_get_hidden_items( player), "Silph Co 5F - Hidden Item Pot Plant": lambda state: state.pokemon_rb_can_get_hidden_items(player), - "Silph Co 9F - Hidden Item Nurse Bed": lambda state: state.pokemon_rb_can_get_hidden_items(player), + "Silph Co 9F - Hidden Item Nurse Bed (Card Key)": lambda state: state.pokemon_rb_can_get_hidden_items( + player) and state.has("Card Key", player), "Copycat's House - Hidden Item Desk": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Cerulean Cave 1F - Hidden Item Center Rocks": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Cerulean Cave B1F - Hidden Item Northeast Rocks": lambda state: state.pokemon_rb_can_get_hidden_items(player), @@ -127,15 +128,15 @@ def set_rules(world, player): "Pokemon Mansion 3F - Hidden Item Behind Burglar": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 23 - Hidden Item Rocks Before Final Guard": lambda state: state.pokemon_rb_can_get_hidden_items( player), - "Route 23 - Hidden Item East Tree After Water": lambda state: state.pokemon_rb_can_get_hidden_items( + "Route 23 - Hidden Item East Bush After Water": lambda state: state.pokemon_rb_can_get_hidden_items( player), "Route 23 - Hidden Item On Island": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Victory Road 2F - Hidden Item Rock Before Moltres": lambda state: state.pokemon_rb_can_get_hidden_items( player), "Victory Road 2F - Hidden Item Rock In Final Room": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Viridian City - Hidden Item Cuttable Tree": lambda state: state.pokemon_rb_can_get_hidden_items(player), - "Route 11 - Hidden Item Isolated Tree Near Gate": lambda state: state.pokemon_rb_can_get_hidden_items(player), - "Route 12 - Hidden Item Tree Near Gate": lambda state: state.pokemon_rb_can_get_hidden_items(player), + "Route 11 - Hidden Item Isolated Bush Near Gate": lambda state: state.pokemon_rb_can_get_hidden_items(player), + "Route 12 - Hidden Item Bush Near Gate": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 17 - Hidden Item In Grass": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 17 - Hidden Item Near Northernmost Sign": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Route 17 - Hidden Item East Center": lambda state: state.pokemon_rb_can_get_hidden_items(player), @@ -153,7 +154,7 @@ def set_rules(world, player): "Mt Moon B2F - Hidden Item Lone Rock": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Seafoam Islands B3F - Hidden Item Rock": lambda state: state.pokemon_rb_can_get_hidden_items(player), "Vermilion City - Hidden Item In Water Near Fan Club": lambda state: state.pokemon_rb_can_get_hidden_items( - player), + player) and state.pokemon_rb_can_surf(player), "Cerulean City - Hidden Item Gym Badge Guy's Backyard": lambda state: state.pokemon_rb_can_get_hidden_items( player), "Route 4 - Hidden Item Plateau East Of Mt Moon": lambda state: state.pokemon_rb_can_get_hidden_items(player),