Add Mirror Scroll as an option instead of baking it into door shuffle.

This commit is contained in:
Telethar
2024-12-28 17:44:42 -08:00
committed by aerinon
parent f5a8b563d9
commit d558e14065
13 changed files with 32 additions and 4 deletions

1
.gitignore vendored
View File

@@ -28,6 +28,7 @@ weights/
/Players/
/QUsb2Snes/
/output/
/enemizer/
base2current.json

View File

@@ -143,6 +143,7 @@ class World(object):
set_player_attr('potshuffle', False)
set_player_attr('pot_contents', None)
set_player_attr('pseudoboots', False)
set_player_attr('mirrorscroll', False)
set_player_attr('collection_rate', False)
set_player_attr('colorizepots', True)
set_player_attr('pot_pool', {})
@@ -2588,6 +2589,7 @@ class Spoiler(object):
'potshuffle': self.world.potshuffle,
'shopsanity': self.world.shopsanity,
'pseudoboots': self.world.pseudoboots,
'mirrorscroll': self.world.mirrorscroll,
'triforcegoal': self.world.treasure_hunt_count,
'triforcepool': self.world.treasure_hunt_total,
'race': self.world.settings.world_rep['meta']['race'],
@@ -2766,6 +2768,7 @@ class Spoiler(object):
outfile.write(f"Bow Mode: {self.metadata['bow_mode'][player]}\n")
outfile.write(f"Bombbag: {yn(self.metadata['bombbag'][player])}\n")
outfile.write(f"Pseudoboots: {yn(self.metadata['pseudoboots'][player])}\n")
outfile.write(f"Mirror Scroll: {yn(self.metadata['mirrorscroll'][player])}\n")
outfile.write('\n')
# Item Pool Settings
@@ -3120,7 +3123,7 @@ take_any_mode = {'none': 0, 'random': 1, 'fixed': 2}
bow_mode = {'progressive': 0, 'silvers': 1, 'retro': 2, 'retro_silvers': 3}
# additions
# byte 12: POOT TKKK (pseudoboots, overworld_map, trap_door_mode, key_logic_algo)
# byte 12: POOT TKKK (mirrorscroll, pseudoboots, overworld_map, trap_door_mode, key_logic_algo)
overworld_map_mode = {'default': 0, 'compass': 1, 'map': 2}
trap_door_mode = {'vanilla': 0, 'optional': 1, 'boss': 2, 'oneway': 3}
key_logic_algo = {'dangerous': 0, 'partial': 1, 'strict': 2}
@@ -3176,7 +3179,7 @@ class Settings(object):
(flute_mode[w.flute_mode[p]] << 7 | bow_mode[w.bow_mode[p]] << 4
| take_any_mode[w.take_any[p]] << 2 | keyshuffle_mode[w.keyshuffle[p]]),
((0x80 if w.pseudoboots[p] else 0) | overworld_map_mode[w.overworld_map[p]] << 5
((0xF0 if w.mirrorscroll[p] else 0) | (0x80 if w.pseudoboots[p] else 0) | overworld_map_mode[w.overworld_map[p]] << 5
| trap_door_mode[w.trap_door_mode[p]] << 3 | key_logic_algo[w.key_logic_algorithm[p]]),
(skullwoods_mode[w.skullwoods[p]] << 6 | linked_drops_mode[w.linked_drops[p]] << 4),
@@ -3249,6 +3252,7 @@ class Settings(object):
args.take_any[p] = r(take_any_mode)[(settings[11] & 0xC) >> 2]
args.keyshuffle[p] = r(keyshuffle_mode)[settings[11] & 0x3]
if len(settings) > 12:
args.mirrorscroll[p] = True if settings[12] & 0xF0 else False
args.pseudoboots[p] = True if settings[12] & 0x80 else False
args.overworld_map[p] = r(overworld_map_mode)[(settings[12] & 0x60) >> 5]
args.trap_door_mode[p] = r(trap_door_mode)[(settings[12] & 0x18) >> 3]

3
CLI.py
View File

@@ -136,7 +136,7 @@ def parse_cli(argv, no_defaults=False):
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
'skullwoods', 'linked_drops',
'pseudoboots', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'pseudoboots', 'mirrorscroll', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
@@ -197,6 +197,7 @@ def parse_settings():
"overworld_map": "default",
'take_any': 'none',
"pseudoboots": False,
"mirrorscroll": False,
"shuffleenemies": "none",
"shufflebosses": "none",

View File

@@ -138,6 +138,7 @@ def main(args, seed=None, fish=None):
world.skullwoods = args.skullwoods.copy()
world.linked_drops = args.linked_drops.copy()
world.pseudoboots = args.pseudoboots.copy()
world.mirrorscroll = args.mirrorscroll.copy()
world.overworld_map = args.overworld_map.copy()
world.take_any = args.take_any.copy()
world.restrict_boss_items = args.restrict_boss_items.copy()

View File

@@ -300,6 +300,12 @@ Dashing is allowed without the boots item however doors and certain rocks remain
CLI `--pseudoboots`
#### Mirror Scroll
Mirror is usable inside dungeons. Locations that require the mirror are still unattainable.
CLI `--mirrorscroll`
#### Flute Mode
Normal mode for flute means you need to activate it at the village statue after finding it like usual. Activated flute mode mean you can use it immediately upon finding it. The flute SFX plays to let you know this is the case.

6
Rom.py
View File

@@ -545,7 +545,11 @@ def patch_rom(world, rom, player, team, is_mystery=False):
patch_shuffled_dark_sanc(world, rom, player)
# setup dr option flags based on experimental, etc.
dr_flags = DROptions.Eternal_Mini_Bosses if world.doorShuffle[player] == 'vanilla' else DROptions.Town_Portal
dr_flags = DROptions.NoOptions
if world.mirrorscroll[player]:
dr_flags = DROptions.Town_Portal
if world.doorShuffle[player] == 'vanilla':
dr_flags |= DROptions.Eternal_Mini_Bosses
if world.doorShuffle[player] not in ['vanilla', 'basic']:
dr_flags |= DROptions.Map_Info
if ((world.collection_rate[player] or world.goal[player] == 'completionist')

View File

@@ -465,6 +465,10 @@
"action": "store_true",
"type": "bool"
},
"mirrorscroll": {
"action": "store_true",
"type": "bool"
},
"calc_playthrough": {
"action": "store_false",
"type": "bool"

View File

@@ -348,6 +348,7 @@
"Fixed: Take any caves will replace certain location. See documentation for full list"
],
"pseudoboots": [ " Players starts with pseudo boots that allow dashing but no item checks (default: %(default)s"],
"mirrorscroll": [ " Players starts with mirror scroll that allows mirror in dungeons but not overworld (default: %(default)s"],
"bombbag": ["Start with 0 bomb capacity. Two capacity upgrades (+10) are added to the pool (default: %(default)s)" ],
"any_enemy_logic": [
"How to handle potential traversal between dungeon in Crossed door shuffle",

View File

@@ -241,6 +241,7 @@
"randomizer.item.race": "Generate \"Race\" ROM",
"randomizer.item.retro": "Retro mode",
"randomizer.item.pseudoboots": "Pseudoboots",
"randomizer.item.mirrorscroll": "Mirror Scroll",
"randomizer.item.worldstate": "World State",
"randomizer.item.worldstate.standard": "Standard",

View File

@@ -2,6 +2,7 @@
"checkboxes": {
"hints": { "type": "checkbox" },
"pseudoboots": { "type": "checkbox" },
"mirrorscroll": { "type": "checkbox" },
"race": { "type": "checkbox" }
},
"leftItemFrame": {

View File

@@ -150,6 +150,7 @@ class CustomSettings(object):
args.restrict_boss_items[p] = get_setting(settings['restrict_boss_items'], args.restrict_boss_items[p])
args.overworld_map[p] = get_setting(settings['overworld_map'], args.overworld_map[p])
args.pseudoboots[p] = get_setting(settings['pseudoboots'], args.pseudoboots[p])
args.mirrorscroll[p] = get_setting(settings['mirrorscroll'], args.mirrorscroll[p])
args.triforce_goal[p] = get_setting(settings['triforce_goal'], args.triforce_goal[p])
args.triforce_pool[p] = get_setting(settings['triforce_pool'], args.triforce_pool[p])
args.triforce_goal_min[p] = get_setting(settings['triforce_goal_min'], args.triforce_goal_min[p])
@@ -287,6 +288,7 @@ class CustomSettings(object):
settings_dict[p]['linked_drops'] = world.linked_drops[p]
settings_dict[p]['overworld_map'] = world.overworld_map[p]
settings_dict[p]['pseudoboots'] = world.pseudoboots[p]
settings_dict[p]['mirrorscroll'] = world.mirrorscroll[p]
settings_dict[p]['triforce_goal'] = world.treasure_hunt_count[p]
settings_dict[p]['triforce_pool'] = world.treasure_hunt_total[p]
settings_dict[p]['beemizer'] = world.beemizer[p]

View File

@@ -57,6 +57,7 @@ SETTINGSTOPROCESS = {
"item": {
"hints": "hints",
"pseudoboots": "pseudoboots",
"mirrorscroll": "mirrorscroll",
"race": "race",
"worldstate": "mode",

View File

@@ -134,6 +134,7 @@ def roll_settings(weights):
ret.skullwoods = get_choice('skullwoods')
ret.linked_drops = get_choice('linked_drops')
ret.pseudoboots = get_choice_bool('pseudoboots')
ret.mirrorscroll = get_choice_bool('mirrorscroll')
ret.shopsanity = get_choice_bool('shopsanity')
keydropshuffle = get_choice_bool('keydropshuffle')
ret.dropshuffle = get_choice('dropshuffle') if 'dropshuffle' in weights else 'none'