diff --git a/BaseClasses.py b/BaseClasses.py index 8a3da107..4fa982db 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -147,7 +147,7 @@ class World(object): set_player_attr('crystals_needed_for_gt', 7) set_player_attr('crystals_ganon_orig', {}) set_player_attr('crystals_gt_orig', {}) - set_player_attr('open_pyramid', False) + set_player_attr('open_pyramid', 'auto') set_player_attr('treasure_hunt_icon', 'Triforce Piece') set_player_attr('treasure_hunt_count', 0) set_player_attr('treasure_hunt_total', 0) @@ -317,6 +317,19 @@ class World(object): def is_bombshop_start(self, player): return self.is_tile_swapped(0x2c, player) and (self.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull'] or not self.shufflelinks[player]) + def is_pyramid_open(self, player): + if self.open_pyramid[player] == 'yes': + return True + elif self.open_pyramid[player] == 'no': + return False + else: + if self.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull']: + return False + elif self.goal[player] in ['crystals', 'trinity']: + return True + else: + return False + def check_for_door(self, doorname, player): if isinstance(doorname, Door): return doorname @@ -3045,7 +3058,7 @@ class Spoiler(object): if self.metadata['shuffle'][player] != 'vanilla' or self.metadata['ow_mixed'][player]: outfile.write('Overworld Map:'.ljust(line_width) + '%s\n' % self.metadata['overworld_map'][player]) if self.metadata['goal'][player] != 'trinity': - outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % yn(self.metadata['open_pyramid'][player])) + outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % self.metadata['open_pyramid'][player]) outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player]) if self.metadata['door_shuffle'][player] != 'vanilla': outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player]) @@ -3338,7 +3351,7 @@ class Settings(object): | (counter_mode[w.dungeon_counters[p]] << 1) | (1 if w.experimental[p] else 0), ((8 if w.crystals_ganon_orig[p] == "random" else int(w.crystals_ganon_orig[p])) << 3) - | (0x4 if w.open_pyramid[p] else 0) | access_mode[w.accessibility[p]], + | (0x4 if w.is_pyramid_open(p) else 0) | access_mode[w.accessibility[p]], (0x80 if w.bigkeyshuffle[p] else 0) | (0x40 if w.keyshuffle[p] else 0) | (0x20 if w.mapshuffle[p] else 0) | (0x10 if w.compassshuffle[p] else 0) diff --git a/CLI.py b/CLI.py index 264e1f06..e8ba78de 100644 --- a/CLI.py +++ b/CLI.py @@ -144,7 +144,7 @@ def parse_settings(): "restrict_boss_items": "none", # Shuffle Ganon defaults to TRUE - "openpyramid": False, + "openpyramid": "auto", "shuffleganon": True, "ow_shuffle": "vanilla", "ow_crossed": "none", diff --git a/Mystery.py b/Mystery.py index f378ccea..faf5d16a 100644 --- a/Mystery.py +++ b/Mystery.py @@ -184,7 +184,6 @@ def roll_settings(weights): if ret.dungeon_counters == 'default': ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle == 'on' else 'off' - ret.shufflelinks = get_choice('shufflelinks') == 'on' ret.pseudoboots = get_choice('pseudoboots') == 'on' ret.shopsanity = get_choice('shopsanity') == 'on' ret.keydropshuffle = get_choice('keydropshuffle') == 'on' @@ -200,12 +199,13 @@ def roll_settings(weights): 'triforce-hunt': 'triforcehunt', 'trinity': 'trinity' }[goal] - ret.openpyramid = goal in ['fast_ganon', 'trinity'] if ret.shuffle in ['vanilla', 'dungeonsfull', 'dungeonssimple'] else False + + ret.openpyramid = get_choice('open_pyramid') if 'open_pyramid' in weights else 'auto' ret.shuffleganon = get_choice('shuffleganon') == 'on' + ret.shufflelinks = get_choice('shufflelinks') == 'on' ret.crystals_gt = get_choice('tower_open') - ret.crystals_ganon = get_choice('ganon_open') goal_min = get_choice_default('triforce_goal_min', default=20) diff --git a/Rom.py b/Rom.py index d2bd5930..3eba1055 100644 --- a/Rom.py +++ b/Rom.py @@ -1287,7 +1287,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest - rom.write_byte(0x18008B, 0x01 if world.open_pyramid[player] or world.goal[player] == 'trinity' else 0x00) # pre-open Pyramid Hole + rom.write_byte(0x18008B, 0x01 if world.is_pyramid_open(player) else 0x00) # pre-open Pyramid Hole rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0 rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped rom.write_byte(0xF5D73, 0xF0) # bees are catchable diff --git a/Rules.py b/Rules.py index 3810a1cb..f934f2ca 100644 --- a/Rules.py +++ b/Rules.py @@ -1046,7 +1046,7 @@ def ow_rules(world, player): set_rule(world.get_entrance('Top of Pyramid', player), lambda state: state.has('Beat Agahnim 1', player)) set_rule(world.get_entrance('Top of Pyramid (Inner)', player), lambda state: state.has('Beat Agahnim 1', player)) else: - set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.open_pyramid[player] or world.goal[player] == 'trinity' or state.has('Beat Agahnim 2', player)) + set_rule(world.get_entrance('Inverted Pyramid Hole', player), lambda state: world.is_pyramid_open(player) or state.has('Beat Agahnim 2', player)) set_rule(world.get_entrance('Pyramid Hole', player), lambda state: False) set_rule(world.get_entrance('Pyramid Entrance', player), lambda state: False) diff --git a/mystery_example.yml b/mystery_example.yml index a3663361..d7fe4580 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -53,6 +53,10 @@ lean: 2 crossed: 3 insanity: 1 + open_pyramid: + auto: 1 + yes: 0 + no: 0 shufflelinks: on: 1 off: 1 diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index b62fe115..7c0aa769 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -218,8 +218,11 @@ ] }, "openpyramid": { - "action": "store_true", - "type": "bool" + "choices": [ + "auto", + "yes", + "no" + ] }, "rom": {}, "loglevel": { diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 229d044e..b66c4def 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -138,6 +138,9 @@ "randomizer.entrance.openpyramid": "Pre-open Pyramid Hole", + "randomizer.entrance.openpyramid.auto": "Auto", + "randomizer.entrance.openpyramid.yes": "Yes", + "randomizer.entrance.openpyramid.no": "No", "randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool", "randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool", "randomizer.entrance.overworld_map": "Overworld Map", diff --git a/resources/app/gui/randomize/entrando/widgets.json b/resources/app/gui/randomize/entrando/widgets.json index d4cf3afe..9c3102f6 100644 --- a/resources/app/gui/randomize/entrando/widgets.json +++ b/resources/app/gui/randomize/entrando/widgets.json @@ -1,6 +1,16 @@ { "widgets": { - "openpyramid": { "type": "checkbox" }, + "openpyramid": { + "type": "selectbox", + "options": [ + "auto", + "yes", + "no" + ], + "config": { + "width": 10 + } + }, "shuffleganon": { "type": "checkbox" }, "shufflelinks": { "type": "checkbox" }, "overworld_map": { diff --git a/source/gui/randomize/entrando.py b/source/gui/randomize/entrando.py index 0759218c..476e6ff2 100644 --- a/source/gui/randomize/entrando.py +++ b/source/gui/randomize/entrando.py @@ -27,7 +27,7 @@ def entrando_page(parent): for key in dictWidgets: self.widgets[key] = dictWidgets[key] packAttrs = {"anchor":E} - if self.widgets[key].type == "checkbox": + if self.widgets[key].type == "checkbox" or key == "openpyramid": packAttrs["anchor"] = W self.widgets[key].pack(packAttrs)