From 17f884d0479e0e06fc6bfbd81e5e3e78a208c14e Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 7 Jun 2020 15:22:24 +0200 Subject: [PATCH 1/6] make triforce pieces required an option --- BaseClasses.py | 26 ++++++++++++++++++-------- EntranceRandomizer.py | 13 +++++++++---- ItemList.py | 7 ++----- Main.py | 1 + Mystery.py | 4 ++++ Rom.py | 1 - 6 files changed, 34 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 3e99cbac6c..e1cbd986c6 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -114,6 +114,7 @@ class World(object): set_player_attr('glitch_boots', True) set_player_attr('progression_balancing', True) set_player_attr('local_items', set()) + set_player_attr('triforce_pieces_required', 20) def get_name_string_for_object(self, obj) -> str: return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})' @@ -1193,7 +1194,8 @@ class Spoiler(object): 'shufflepots': self.world.shufflepots, 'players': self.world.players, 'teams': self.world.teams, - 'progression_balancing' : self.world.progression_balancing + 'progression_balancing': self.world.progression_balancing, + 'triforce_pieces_required': self.world.triforce_pieces_required, } def to_json(self): @@ -1227,25 +1229,33 @@ class Spoiler(object): outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_names(player))) for team in range(self.world.teams): outfile.write('%s%s\n' % ( - f"Hash - {self.world.player_names[player][team]} (Team {team + 1}): " if self.world.teams > 1 else 'Hash: ', - self.hashes[player, team])) + f"Hash - {self.world.player_names[player][team]} (Team {team + 1}): " if self.world.teams > 1 else 'Hash: ', + self.hashes[player, team])) outfile.write('Logic: %s\n' % self.metadata['logic'][player]) if self.world.players > 1: - outfile.write('Progression Balanced: %s\n' % ('Yes' if self.metadata['progression_balancing'][player] else 'No')) + outfile.write('Progression Balanced: %s\n' % ( + 'Yes' if self.metadata['progression_balancing'][player] else 'No')) outfile.write('Mode: %s\n' % self.metadata['mode'][player]) - outfile.write('Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No')) + outfile.write( + 'Retro: %s\n' % ('Yes' if self.metadata['retro'][player] else 'No')) outfile.write('Swords: %s\n' % self.metadata['weapons'][player]) outfile.write('Goal: %s\n' % self.metadata['goal'][player]) + if "triforce" in self.metadata["goal"][player]: # triforce hunt + outfile.write( + "Pieces required for Triforce: %s\n" % self.metadata["triforce_pieces_required"][player]) outfile.write('Difficulty: %s\n' % self.metadata['item_pool'][player]) outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player]) outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player]) outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player]) outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player]) outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player]) - outfile.write('Pyramid hole pre-opened: %s\n' % ('Yes' if self.metadata['open_pyramid'][player] else 'No')) + outfile.write('Pyramid hole pre-opened: %s\n' % ( + 'Yes' if self.metadata['open_pyramid'][player] else 'No')) outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player]) - outfile.write('Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No')) - outfile.write('Compass shuffle: %s\n' % ('Yes' if self.metadata['compassshuffle'][player] else 'No')) + outfile.write( + 'Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No')) + outfile.write('Compass shuffle: %s\n' % ( + 'Yes' if self.metadata['compassshuffle'][player] else 'No')) outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No')) outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No')) outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player]) diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index ee4cadf7be..1877b795ec 100755 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -81,15 +81,20 @@ def parse_arguments(argv, no_defaults=False): Local Triforce Hunt: Places 30 Triforce Pieces in your world, collect 20 of them to beat the game. ''') - parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], + parser.add_argument('--triforce_pieces_required', default=defval(20), + type=lambda value: min(max(int(value), 1), 30), + help='''Set Triforce Pieces required to win a Triforce Hunt''') + parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', + choices=['normal', 'hard', 'expert'], help='''\ Select game difficulty. Affects available itempool. (default: %(default)s) Normal: Normal difficulty. Hard: A harder setting with less equipment and reduced health. Expert: A harder yet setting with minimum equipment and health. ''') - parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], - help='''\ + parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?', + choices=['normal', 'hard', 'expert'], + help='''\ Select limits on item functionality to increase difficulty. (default: %(default)s) Normal: Normal functionality. Hard: Reduced functionality. @@ -329,7 +334,7 @@ def parse_arguments(argv, no_defaults=False): 'local_items', 'retro', 'accessibility', 'hints', 'beemizer', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', - 'heartbeep', "skip_progression_balancing", + 'heartbeep', "skip_progression_balancing", "triforce_pieces_required", 'remote_items', 'progressive', 'extendedmsu', 'dungeon_counters', 'glitch_boots']: value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) if player == 1: diff --git a/ItemList.py b/ItemList.py index d72229a314..5590bdab10 100644 --- a/ItemList.py +++ b/ItemList.py @@ -33,7 +33,7 @@ Difficulty = namedtuple('Difficulty', ['baseitems', 'bottles', 'bottle_count', 'same_bottle', 'progressiveshield', 'basicshield', 'progressivearmor', 'basicarmor', 'swordless', 'progressivesword', 'basicsword', 'basicbow', 'timedohko', 'timedother', - 'triforcehunt', 'triforce_pieces_required', 'retro', + 'triforcehunt', 'retro', 'extras', 'progressive_sword_limit', 'progressive_shield_limit', 'progressive_armor_limit', 'progressive_bottle_limit', 'progressive_bow_limit', 'heart_piece_limit', 'boss_heart_container_limit']) @@ -57,7 +57,6 @@ difficulties = { timedohko = ['Green Clock'] * 25, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, triforcehunt = ['Triforce Piece'] * 30, - triforce_pieces_required = 20, retro = ['Small Key (Universal)'] * 17 + ['Rupees (20)'] * 10, extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], progressive_sword_limit = 4, @@ -84,7 +83,6 @@ difficulties = { timedohko = ['Green Clock'] * 25, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, triforcehunt = ['Triforce Piece'] * 30, - triforce_pieces_required = 20, retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15, extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], progressive_sword_limit = 3, @@ -111,7 +109,6 @@ difficulties = { timedohko = ['Green Clock'] * 20 + ['Red Clock'] * 5, timedother = ['Green Clock'] * 20 + ['Blue Clock'] * 10 + ['Red Clock'] * 10, triforcehunt = ['Triforce Piece'] * 30, - triforce_pieces_required = 20, retro = ['Small Key (Universal)'] * 12 + ['Rupees (5)'] * 15, extras = [normalfirst15extra, normalsecond15extra, normalthird10extra, normalfourth5extra, normalfinal25extra], progressive_sword_limit = 2, @@ -507,7 +504,7 @@ def get_pool_core(world, player: int): if goal in {'triforcehunt', 'localtriforcehunt'}: pool.extend(diff.triforcehunt) extraitems -= len(diff.triforcehunt) - treasure_hunt_count = diff.triforce_pieces_required + treasure_hunt_count = world.triforce_pieces_required[player] treasure_hunt_icon = 'Triforce Piece' for extra in diff.extras: diff --git a/Main.py b/Main.py index cd878fabb3..b8b543a63b 100644 --- a/Main.py +++ b/Main.py @@ -59,6 +59,7 @@ def main(args, seed=None): world.dungeon_counters = args.dungeon_counters.copy() world.extendedmsu = args.extendedmsu.copy() world.glitch_boots = args.glitch_boots.copy() + world.triforce_pieces_required = args.triforce_pieces_required.copy() world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()} world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} diff --git a/Mystery.py b/Mystery.py index b5495ff2a9..21a3562a7f 100644 --- a/Mystery.py +++ b/Mystery.py @@ -294,6 +294,10 @@ def roll_settings(weights): ret.crystals_ganon = get_choice('ganon_open', weights) + ret.triforce_pieces_required = get_choice('triforce_pieces_required', + weights) if "triforce_pieces_required" in weights else 20 + ret.triforce_pieces_required = min(max(1, int(ret.triforce_pieces_required)), 30) + ret.mode = get_choice('world_state', weights) if ret.mode == 'retro': ret.mode = 'open' diff --git a/Rom.py b/Rom.py index 73e1230115..c515870a6d 100644 --- a/Rom.py +++ b/Rom.py @@ -637,7 +637,6 @@ def patch_rom(world, rom, player, team, enemized): rom.write_byte(0x18003A, 0x01 if world.dark_world_light_cone else 0x00) GREEN_TWENTY_RUPEES = 0x47 - TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code GREEN_CLOCK = ItemFactory('Green Clock', player).code rom.write_byte(0x18004F, 0x01) # Byrna Invulnerability: on From 264ee44fde32c4fd55d4522260597b6b3bf16ddd Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 7 Jun 2020 15:24:36 +0200 Subject: [PATCH 2/6] decument triforce pieces required in easy.yaml --- easy.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/easy.yaml b/easy.yaml index bab35eb32d..10bf1fc302 100644 --- a/easy.yaml +++ b/easy.yaml @@ -75,6 +75,14 @@ goals: pedestal: 0 # Pull the Triforce from the Master Sword pedestal triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle local_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle +triforce_pieces_required: # set to how many out of 30 triforce pieces you need to win the game in a triforce hunt. 20 is the default. Max is 30, Min is 1. + 15: 0 + 20: 1 + 21: 0 + 22: 0 + 23: 0 + 24: 0 + 25: 0 tower_open: # Crystals required to open GT '0': 8 '1': 7 From ae289ec305e48cc13160eb87e8e90f3beecab5dd Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 7 Jun 2020 15:33:26 +0200 Subject: [PATCH 3/6] decument triforce pieces required in easy.yaml --- easy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/easy.yaml b/easy.yaml index 10bf1fc302..7823e286b0 100644 --- a/easy.yaml +++ b/easy.yaml @@ -76,6 +76,7 @@ goals: triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout the worlds, then turn them in to Murahadala in front of Hyrule Castle local_triforce_hunt: 0 # Collect 20 of 30 Triforce pieces spread throughout your world, then turn them in to Murahadala in front of Hyrule Castle triforce_pieces_required: # set to how many out of 30 triforce pieces you need to win the game in a triforce hunt. 20 is the default. Max is 30, Min is 1. + # format "pieces: chance" 15: 0 20: 1 21: 0 From f9a29d3140e990cbf4bab740601a7251b8f8ef16 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 7 Jun 2020 23:14:07 +0200 Subject: [PATCH 4/6] fix disable web ui --- MultiClient.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/MultiClient.py b/MultiClient.py index 612e740357..04e1452e02 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -50,7 +50,7 @@ class Context(): self.ui_node = WebUI.WebUiClient() self.custom_address = None - self.webui_socket_port = port + self.webui_socket_port: typing.Optional[int] = port self.exit_event = asyncio.Event() self.watcher_event = asyncio.Event() @@ -1007,7 +1007,10 @@ class ClientCommandProcessor(CommandProcessor): self.ctx.ui_node.log_info(f"Setting slow mode to {self.ctx.slow_mode}") def _cmd_web(self): - webbrowser.open(f'http://localhost:5050?port={self.ctx.webui_socket_port}') + if self.ctx.webui_socket_port: + webbrowser.open(f'http://localhost:5050?port={self.ctx.webui_socket_port}') + else: + self.output("Web UI was never started.") def default(self, raw: str): asyncio.create_task(self.ctx.send_msgs([['Say', raw]])) @@ -1263,7 +1266,7 @@ async def main(): parser.add_argument('--disable_web_ui', default=False, action='store_true', help="Turn off emitting a webserver for the webbrowser based user interface.") args = parser.parse_args() logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO)) - + port = None if not args.disable_web_ui: # Find an available port on the host system to use for hosting the websocket server while True: From 10dca0461d269294a5ca6d4176ae54d2002ad7a9 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Mon, 8 Jun 2020 05:28:35 +0200 Subject: [PATCH 5/6] update VC++ --- inno_setup.iss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inno_setup.iss b/inno_setup.iss index 7a10cb79ae..f1a8c593b1 100644 --- a/inno_setup.iss +++ b/inno_setup.iss @@ -73,9 +73,9 @@ begin if (RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64', 'Version', strVersion)) then begin - // Is the installed version at least 14.24 ? + // Is the installed version at least the packaged one ? Log('VC Redist x64 Version : found ' + strVersion); - Result := (CompareStr(strVersion, 'v14.24.28127.4') < 0); + Result := (CompareStr(strVersion, 'v14.26.28720') < 0); end else begin From ccf418a61420fcdc91c3d8004385245fdf3137a4 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Mon, 8 Jun 2020 06:58:38 +0200 Subject: [PATCH 6/6] fix treasure hunt (aka triforce hunt) condition --- ItemList.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ItemList.py b/ItemList.py index 5590bdab10..c575c190af 100644 --- a/ItemList.py +++ b/ItemList.py @@ -143,7 +143,7 @@ def generate_itempool(world, player): loc = Location(player, "Murahdahla", parent=region) loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', - player) > \ + player) >= \ state.world.treasure_hunt_count[player] region.locations.append(loc) world.dynamic_locations.append(loc)