From 49accbd2b1712028bd1309d42c1d3542fa84dbd5 Mon Sep 17 00:00:00 2001 From: aerinon Date: Wed, 9 Feb 2022 14:19:10 -0700 Subject: [PATCH] Many bugfixes * Fixed inverted generation issues with pottery option * Moved SRAM according to SRAM standard * Removed equitable algorithm * Upped TFH goal limit to 254 * Cuccos should no longer cause trap door rooms to not open * Added double click fix for install.py * Fix for pottery item palettes near bonkable torches * Fix for multiworld progression balancing would place Nothing or Arrow items --- Fill.py | 8 ++++++-- InvertedRegions.py | 1 + ItemList.py | 3 ++- Main.py | 5 +++-- MultiClient.py | 4 ++-- RELEASENOTES.md | 15 ++++++++++----- Regions.py | 8 ++++++-- Rom.py | 5 ++++- data/base2current.bps | Bin 82914 -> 82915 bytes resources/app/cli/args.json | 1 - resources/app/cli/lang/en.json | 2 -- resources/app/gui/lang/en.json | 1 - resources/app/gui/randomize/item/widgets.json | 1 - resources/ci/common/install.py | 4 +++- source/item/District.py | 2 +- 15 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Fill.py b/Fill.py index 4fe72e89..4538bce5 100644 --- a/Fill.py +++ b/Fill.py @@ -446,15 +446,19 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None unfilled = [location.name for location in fill_locations] if unplaced or unfilled: logging.warning('Unplaced items: %s - Unfilled Locations: %s', unplaced, unfilled) + ensure_good_pots(world) + +def ensure_good_pots(world, write_skips=False): for loc in world.get_locations(): # convert Arrows 5 and Nothing when necessary if (loc.item.name in {'Arrows (5)', 'Nothing'} and (loc.type != LocationType.Pot or loc.item.player != loc.player)): loc.item = ItemFactory(invalid_location_replacement[loc.item.name], loc.item.player) # don't write out all pots to spoiler - if loc.type == LocationType.Pot and loc.item.name in valid_pot_items: - loc.skip = True + if write_skips: + if loc.type == LocationType.Pot and loc.item.name in valid_pot_items: + loc.skip = True invalid_location_replacement = {'Arrows (5)': 'Arrows (10)', 'Nothing': 'Rupees (5)'} diff --git a/InvertedRegions.py b/InvertedRegions.py index b5625d1f..1b3560cf 100644 --- a/InvertedRegions.py +++ b/InvertedRegions.py @@ -117,6 +117,7 @@ def create_inverted_regions(world, player): 'Spectacle Rock Cave Peak', 'Spectacle Rock Cave (Bottom)', 'Broken Bridge (West)', 'Death Mountain Mirror Spot']), create_cave_region(player, 'Death Mountain Return Cave (left)', 'a connector', None, ['Death Mountain Return Cave Exit (West)', 'Death Mountain Return Cave E']), create_cave_region(player, 'Death Mountain Return Cave (right)', 'a connector', None, ['Death Mountain Return Cave Exit (East)', 'Death Mountain Return Cave W']), + create_lw_region(player, 'Death Mountain Return Ledge', None, ['Death Mountain Return Ledge Drop', 'Death Mountain Return Cave (West)', 'Bumper Cave Ledge Mirror Spot']), create_cave_region(player, 'Spectacle Rock Cave (Top)', 'a connector', ['Spectacle Rock Cave'], ['Spectacle Rock Cave Drop', 'Spectacle Rock Cave Exit (Top)']), create_cave_region(player, 'Spectacle Rock Cave (Bottom)', 'a connector', None, ['Spectacle Rock Cave Exit']), create_cave_region(player, 'Spectacle Rock Cave (Peak)', 'a connector', None, ['Spectacle Rock Cave Peak Drop', 'Spectacle Rock Cave Exit (Peak)']), diff --git a/ItemList.py b/ItemList.py index 1c620ddf..05844ff7 100644 --- a/ItemList.py +++ b/ItemList.py @@ -964,7 +964,8 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s pool.append(thisbottle) if customitemarray["triforcepieces"] > 0 or customitemarray["triforcepiecesgoal"] > 0: - treasure_hunt_count = max(min(customitemarray["triforcepiecesgoal"], 99), 1) #To display, count must be between 1 and 99. + # To display, count must be between 1 and 254 - larger values are not yet supported + treasure_hunt_count = max(min(customitemarray["triforcepiecesgoal"], 254), 1) treasure_hunt_icon = 'Triforce Piece' # Ensure game is always possible to complete here, force sufficient pieces if the player is unwilling. if (customitemarray["triforcepieces"] < treasure_hunt_count) and (goal == 'triforcehunt') and (customitemarray["triforce"] == 0): diff --git a/Main.py b/Main.py index 4e6cfe20..9bb9dc67 100644 --- a/Main.py +++ b/Main.py @@ -23,7 +23,7 @@ from DoorShuffle import link_doors, connect_portal, link_doors_prep from RoomData import create_rooms from Rules import set_rules from Dungeons import create_dungeons -from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive +from Fill import distribute_items_restrictive, promote_dungeon_items, fill_dungeons_restrictive, ensure_good_pots from Fill import sell_potions, sell_keys, balance_multiworld_progression, balance_money_progression, lock_shop_locations from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops from Utils import output_path, parse_player_names @@ -31,7 +31,7 @@ from Utils import output_path, parse_player_names from source.item.FillUtil import create_item_pool_config, massage_item_pool, district_item_pool_config -__version__ = '1.0.1.2-v' +__version__ = '1.0.1.3-v' from source.classes.BabelFish import BabelFish @@ -253,6 +253,7 @@ def main(args, seed=None, fish=None): customize_shops(world, player) if args.algorithm in ['balanced', 'equitable']: balance_money_progression(world) + ensure_good_pots(world, True) outfilebase = f'DR_{args.outputname if args.outputname else world.seed}' diff --git a/MultiClient.py b/MultiClient.py index 4504fed7..bc496f5b 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -90,8 +90,8 @@ INGAME_MODES = {0x07, 0x09, 0x0b} SAVEDATA_START = WRAM_START + 0xF000 SAVEDATA_SIZE = 0x500 -POT_ITEMS_SRAM_START = WRAM_START + 0x016600 -SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016850 +POT_ITEMS_SRAM_START = WRAM_START + 0x016018 +SPRITE_ITEMS_SRAM_START = WRAM_START + 0x016268 ITEM_SRAM_SIZE = 0x250 RECV_PROGRESS_ADDR = SAVEDATA_START + 0x4D0 # 2 bytes diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fad39b71..ce764cf5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -45,10 +45,6 @@ The "Item Sorting" option or ```--algorithm``` has been updated with new placeme This one stays the same as before and is recommended for the most random distribution of items. -### Equitable - -This one is currently under development and may not fill correctly. It is a new method that should allow item and key logic to interact. (Vanilla key placement in PoD is theoretically possible, but isn't yet.) - ### Vanilla Fill This fill attempts to place all items in their vanilla locations when possible. Obviously shuffling entrances or the dungeon interiors will often prevent items from being placed in their vanilla location. If the vanilla fill is not possible, then other locations are tried in sequence preferring "major" locations (see below), then heart piece locations, then the rest except for GT locations which are preferred last. Note the PoD small key that is normally found in the dark maze in vanilla is move to Harmless Hellway due to the placement algorithm limitation. @@ -95,7 +91,7 @@ In multiworld, the districts chosen apply to all players. ### CLI values: -```balanced, equitable, vanilla_fill, major_only, dungeon_only, district``` +```balanced, vanilla_fill, major_only, dungeon_only, district``` ## New Hints @@ -148,6 +144,15 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Volatile +* 1.0.1.3 + * Fixed inverted generation issues with pottery option + * Moved SRAM according to SRAM standard + * Removed equitable algorithm + * Upped TFH goal limit to 254 + * Cuccos should no longer cause trap door rooms to not open + * Added double click fix for install.py + * Fix for pottery item palettes near bonkable torches + * Fix for multiworld progression balancing would place Nothing or Arrow items * 1.0.1.2 * Fixed logic for pots in TR Hub and TR Dark Ride * Fix for districting + shopsanity diff --git a/Regions.py b/Regions.py index c7e5a209..1b5401c7 100644 --- a/Regions.py +++ b/Regions.py @@ -1057,7 +1057,11 @@ def create_pot_location(pot, pot_index, super_tile, world, player): if (pot.item not in [PotItem.Key, PotItem.Hole] and (pot.item != PotItem.Switch or world.potshuffle[player])): address = pot_address(pot_index, super_tile) - parent = world.get_region(pot.room, player) + region = pot.room + if world.mode[player] == 'inverted': + if region == 'Links House': + region = 'Inverted Links House' + parent = world.get_region(region, player) descriptor = 'Large Block' if pot.flags & PotFlags.Block else f'Pot #{pot_index+1}' hint_text = ('under a block' if pot.flags & PotFlags.Block else 'in a pot') modifier = parent.hint_text not in {'a storyteller', 'fairies deep in a cave', 'a spiky hint', @@ -1073,7 +1077,7 @@ def create_pot_location(pot, pot_index, super_tile, world, player): def pot_address(pot_index, super_tile): - return 0x7f6600 + super_tile * 2 + (pot_index << 24) + return 0x7f6018 + super_tile * 2 + (pot_index << 24) # (type, room_id, shopkeeper, custom, locked, [items]) diff --git a/Rom.py b/Rom.py index e2a2ecb4..2e7c33d6 100644 --- a/Rom.py +++ b/Rom.py @@ -35,7 +35,7 @@ from source.item.FillUtil import valid_pot_items JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '83bdcdbe989281b7eb36a10150314997' +RANDOMIZERBASEHASH = 'a25e589ca9359e73b0ed94cab8db107d' class JsonRom(object): @@ -884,6 +884,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(0x142A51, multiClientFlags) rom.write_byte(0x142A55, ((0x1 if world.pottery[player] != 'none' else 0) # StandingItemCounterMask | (0x2 if world.dropshuffle[player] else 0))) + if world.pottery[player] not in ['none', 'keys']: + # Cuccos should not prevent kill rooms from opening + rom.write_byte(snes_to_pc(0x0DB457), 0x40) write_int16(rom, 0x187010, credits_total) # dynamic credits if credits_total != 216: diff --git a/data/base2current.bps b/data/base2current.bps index dd96fe33b92cca25de2ddb7fd402c9b36bc0ead3..5e4a494197020922c39617ca79965edee8d0451c 100644 GIT binary patch delta 152 zcmV;J0B8T=hXvz@1+YZ{1S_!APlHJTmq`Hu#SLg;e2TIV12mn%>beDq!0X+c|x4{Gf89xa0d3o8d G@gHGsj6Rb9 delta 151 zcmV;I0BHZ?hXvw?1+YZ{1hTSCO@m1Rmq`Hu#SKtseJ8v+3~52*lV zf8sED`mF;5YnM5Cw_gGQ;sHU$u7DD=gt5XPsdcW4ORI$ly?_UrI7qdY7b=&9WCyEO z%8}-h=8~(I6m5@|PCKQE2mnx;U%8hDO3;Z208*Q1mxKfXJpn7X!UO>sKL{EvJ)s() F6q%6fI&lC1 diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 3444b667..23d1d8df 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -116,7 +116,6 @@ "algorithm": { "choices": [ "balanced", - "equitable", "vanilla_fill", "major_only", "dungeon_only", diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json index dfd76380..ca8eddd3 100644 --- a/resources/app/cli/lang/en.json +++ b/resources/app/cli/lang/en.json @@ -154,8 +154,6 @@ "balanced: vt26 derivative that aims to strike a balance between", " the overworld heavy vt25 and the dungeon heavy vt26", " algorithm.", - "equitable: does not place dungeon items first allowing new potential", - " but mixed with the normal advancement pool", "restricted placements: these consider all major items to be special and attempts", "to place items from fixed to semi-random locations. For purposes of these shuffles, all", "Y items, A items, swords (unless vanilla swords), mails, shields, heart containers and", diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 158aaaf0..ecd6c991 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -289,7 +289,6 @@ "randomizer.item.sortingalgo": "Item Sorting", "randomizer.item.sortingalgo.balanced": "Balanced", - "randomizer.item.sortingalgo.equitable": "Equitable", "randomizer.item.sortingalgo.vanilla_fill": "Vanilla Fill", "randomizer.item.sortingalgo.major_only": "Major Location Restriction", "randomizer.item.sortingalgo.dungeon_only": "Dungeon Restriction", diff --git a/resources/app/gui/randomize/item/widgets.json b/resources/app/gui/randomize/item/widgets.json index 7b76d8fe..2177335b 100644 --- a/resources/app/gui/randomize/item/widgets.json +++ b/resources/app/gui/randomize/item/widgets.json @@ -117,7 +117,6 @@ "default": "balanced", "options": [ "balanced", - "equitable", "vanilla_fill", "major_only", "dungeon_only", diff --git a/resources/ci/common/install.py b/resources/ci/common/install.py index 5874d0dd..6830905e 100644 --- a/resources/ci/common/install.py +++ b/resources/ci/common/install.py @@ -6,7 +6,9 @@ import subprocess # do stuff at the shell level env = common.prepare_env() -pip_requirements = os.path.join(".","resources","app","meta","manifests","pip_requirements.txt") +pip_requirements = os.path.join("..","resources","app","meta","manifests","pip_requirements.txt") +if not os.path.isfile(pip_requirements): + pip_requirements = os.path.join("..","..","..","resources","app","meta","manifests","pip_requirements.txt") def run_install(PY_VERSION,USER): # get executables diff --git a/source/item/District.py b/source/item/District.py index b1dc8c01..b6f1ca9d 100644 --- a/source/item/District.py +++ b/source/item/District.py @@ -100,7 +100,7 @@ def create_district_helper(world, player): central_lw_entrances.append('Inverted Big Bomb Shop') central_lw_entrances.remove('Links House') south_dw_entrances.append('Inverted Links House') - voo_north_entrances.remove('Dark Sanctuary') + voo_north_entrances.remove('Dark Sanctuary Hint') voo_north_entrances.append('Inverted Dark Sanctuary') voo_north_entrances.remove('Bumper Cave (Top)') nw_lw_entrances.append('Bumper Cave (Top)')