LttP: make shuffle names consistent
This commit is contained in:
parent
1c42564d90
commit
cc70a6fa26
|
@ -569,7 +569,7 @@ class CollectionState(object):
|
|||
def has_key(self, item, player, count: int = 1):
|
||||
if self.world.logic[player] == 'nologic':
|
||||
return True
|
||||
if self.world.smallkeyshuffle[player] == "universal":
|
||||
if self.world.smallkey_shuffle[player] == "universal":
|
||||
return self.can_buy_unlimited('Small Key (Universal)', player)
|
||||
return self.prog_items[item, player] >= count
|
||||
|
||||
|
|
12
Options.py
12
Options.py
|
@ -243,14 +243,14 @@ if __name__ == "__main__":
|
|||
|
||||
from worlds.alttp.Options import Logic
|
||||
import argparse
|
||||
mapshuffle = Toggle
|
||||
compassshuffle = Toggle
|
||||
map_shuffle = Toggle
|
||||
compass_shuffle = Toggle
|
||||
keyshuffle = Toggle
|
||||
bigkeyshuffle = Toggle
|
||||
bigkey_shuffle = Toggle
|
||||
hints = Toggle
|
||||
test = argparse.Namespace()
|
||||
test.logic = Logic.from_text("no_logic")
|
||||
test.mapshuffle = mapshuffle.from_text("ON")
|
||||
test.map_shuffle = map_shuffle.from_text("ON")
|
||||
test.hints = hints.from_text('OFF')
|
||||
try:
|
||||
test.logic = Logic.from_text("overworld_glitches_typo")
|
||||
|
@ -260,7 +260,7 @@ if __name__ == "__main__":
|
|||
test.logic_owg = Logic.from_text("owg")
|
||||
except KeyError as e:
|
||||
print(e)
|
||||
if test.mapshuffle:
|
||||
print("Mapshuffle is on")
|
||||
if test.map_shuffle:
|
||||
print("map_shuffle is on")
|
||||
print(f"Hints are {bool(test.hints)}")
|
||||
print(test)
|
||||
|
|
|
@ -279,22 +279,31 @@ A Link to the Past:
|
|||
on: 0 # prevents unshuffled compasses, maps and keys to be boss drops, they can still drop keysanity and other players' items
|
||||
off: 50
|
||||
### End of Logic Section ###
|
||||
map_shuffle: # Shuffle dungeon maps into the world and other dungeons, including other players' worlds
|
||||
on: 0
|
||||
off: 50
|
||||
compass_shuffle: # Shuffle compasses into the world and other dungeons, including other players' worlds
|
||||
on: 0
|
||||
off: 50
|
||||
smallkey_shuffle: # Shuffle small keys into the world and other dungeons, including other players' worlds
|
||||
on: 0
|
||||
universal: 0 # allows small keys to be used in any dungeon and adds shops to buy more
|
||||
off: 50
|
||||
bigkey_shuffle: # Shuffle big keys into the world and other dungeons, including other players' worlds
|
||||
on: 0
|
||||
off: 50
|
||||
local_keys: # Keep small keys and big keys local to your world
|
||||
on: 0
|
||||
off: 50
|
||||
bigkey_shuffle: # Big Key Placement
|
||||
original_dungeon: 50
|
||||
own_dungeons: 0
|
||||
own_world: 0
|
||||
any_world: 0
|
||||
different_world: 0
|
||||
smallkey_shuffle: # Small Key Placement
|
||||
original_dungeon: 50
|
||||
own_dungeons: 0
|
||||
own_world: 0
|
||||
any_world: 0
|
||||
different_world: 0
|
||||
universal: 0
|
||||
compass_shuffle: # Compass Placement
|
||||
original_dungeon: 50
|
||||
own_dungeons: 0
|
||||
own_world: 0
|
||||
any_world: 0
|
||||
different_world: 0
|
||||
map_shuffle: # Map Placement
|
||||
original_dungeon: 50
|
||||
own_dungeons: 0
|
||||
own_world: 0
|
||||
any_world: 0
|
||||
different_world: 0
|
||||
dungeon_items: # Alternative to the 4 shuffles and local_keys above this, does nothing until the respective 4 shuffles and local_keys above are deleted
|
||||
mc: 0 # Shuffle maps and compasses
|
||||
none: 50 # Shuffle none of the 4
|
||||
|
|
|
@ -8,7 +8,7 @@ from worlds.alttp.Regions import lookup_boss_drops
|
|||
def create_dungeons(world, player):
|
||||
def make_dungeon(name, default_boss, dungeon_regions, big_key, small_keys, dungeon_items):
|
||||
dungeon = Dungeon(name, dungeon_regions, big_key,
|
||||
[] if world.smallkeyshuffle[player] == "universal" else small_keys,
|
||||
[] if world.smallkey_shuffle[player] == "universal" else small_keys,
|
||||
dungeon_items, player)
|
||||
for item in dungeon.all_items:
|
||||
item.dungeon = dungeon
|
||||
|
|
|
@ -274,7 +274,7 @@ def generate_itempool(world):
|
|||
itempool.extend(['Rupees (300)'] * 34)
|
||||
itempool.extend(['Bombs (10)'] * 5)
|
||||
itempool.extend(['Arrows (10)'] * 7)
|
||||
if world.smallkeyshuffle[player] == 'universal':
|
||||
if world.smallkey_shuffle[player] == 'universal':
|
||||
itempool.extend(itemdiff.universal_keys)
|
||||
itempool.append('Small Key (Universal)')
|
||||
|
||||
|
@ -633,7 +633,7 @@ def get_pool_core(world, player: int):
|
|||
if retro:
|
||||
replace = {'Single Arrow', 'Arrows (10)', 'Arrow Upgrade (+5)', 'Arrow Upgrade (+10)'}
|
||||
pool = ['Rupees (5)' if item in replace else item for item in pool]
|
||||
if world.smallkeyshuffle[player] == "universal":
|
||||
if world.smallkey_shuffle[player] == "universal":
|
||||
pool.extend(diff.universal_keys)
|
||||
item_to_place = 'Small Key (Universal)' if goal != 'icerodhunt' else 'Nothing'
|
||||
if mode == 'standard':
|
||||
|
@ -770,7 +770,7 @@ def make_custom_item_pool(world, player):
|
|||
itemtotal = itemtotal + 1
|
||||
|
||||
if mode == 'standard':
|
||||
if world.smallkeyshuffle[player] == "universal":
|
||||
if world.smallkey_shuffle[player] == "universal":
|
||||
key_location = world.random.choice(
|
||||
['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest',
|
||||
'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
||||
|
@ -793,7 +793,7 @@ def make_custom_item_pool(world, player):
|
|||
pool.extend(['Magic Mirror'] * customitemarray[22])
|
||||
pool.extend(['Moon Pearl'] * customitemarray[28])
|
||||
|
||||
if world.smallkeyshuffle == "universal":
|
||||
if world.smallkey_shuffle == "universal":
|
||||
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in Retro Mode
|
||||
if itemtotal < total_items_to_place:
|
||||
pool.extend(['Nothing'] * (total_items_to_place - itemtotal))
|
||||
|
|
|
@ -43,26 +43,26 @@ class DungeonItem(Choice):
|
|||
return self.value in {0, 1}
|
||||
|
||||
|
||||
class BigKeyShuffle(DungeonItem):
|
||||
class bigkey_shuffle(DungeonItem):
|
||||
"""Big Key Placement"""
|
||||
item_name_group = "Big Keys"
|
||||
displayname = "Big Key Shuffle"
|
||||
|
||||
|
||||
class SmallKeyShuffle(DungeonItem):
|
||||
class smallkey_shuffle(DungeonItem):
|
||||
"""Small Key Placement"""
|
||||
option_universal = 5
|
||||
item_name_group = "Small Keys"
|
||||
displayname = "Small Key Shuffle"
|
||||
|
||||
|
||||
class CompassShuffle(DungeonItem):
|
||||
class compass_shuffle(DungeonItem):
|
||||
"""Compass Placement"""
|
||||
item_name_group = "Compasses"
|
||||
displayname = "Compass Shuffle"
|
||||
|
||||
|
||||
class MapShuffle(DungeonItem):
|
||||
class map_shuffle(DungeonItem):
|
||||
"""Map Placement"""
|
||||
item_name_group = "Maps"
|
||||
displayname = "Map Shuffle"
|
||||
|
@ -221,10 +221,10 @@ class TriforceHud(Choice):
|
|||
alttp_options: typing.Dict[str, type(Option)] = {
|
||||
"crystals_needed_for_gt": CrystalsTower,
|
||||
"crystals_needed_for_ganon": CrystalsGanon,
|
||||
"bigkeyshuffle": BigKeyShuffle,
|
||||
"smallkeyshuffle": SmallKeyShuffle,
|
||||
"compassshuffle": CompassShuffle,
|
||||
"mapshuffle": MapShuffle,
|
||||
"bigkey_shuffle": bigkey_shuffle,
|
||||
"smallkey_shuffle": smallkey_shuffle,
|
||||
"compass_shuffle": compass_shuffle,
|
||||
"map_shuffle": map_shuffle,
|
||||
"progressive": Progressive,
|
||||
"shop_item_slots": ShopItemSlots,
|
||||
"ow_palettes": OWPalette,
|
||||
|
|
|
@ -802,14 +802,14 @@ def patch_rom(world, rom, player, enemized):
|
|||
|
||||
# patch music
|
||||
music_addresses = dungeon_music_addresses[location.name]
|
||||
if world.mapshuffle[player]:
|
||||
if world.map_shuffle[player]:
|
||||
music = local_random.choice([0x11, 0x16])
|
||||
else:
|
||||
music = 0x11 if 'Pendant' in location.item.name else 0x16
|
||||
for music_address in music_addresses:
|
||||
rom.write_byte(music_address, music)
|
||||
|
||||
if world.mapshuffle[player]:
|
||||
if world.map_shuffle[player]:
|
||||
rom.write_byte(0x155C9, local_random.choice([0x11, 0x16])) # Randomize GT music too with map shuffle
|
||||
|
||||
# patch entrance/exits/holes
|
||||
|
@ -1491,18 +1491,18 @@ def patch_rom(world, rom, player, enemized):
|
|||
# block HC upstairs doors in rain state in standard mode
|
||||
rom.write_byte(0x18008A, 0x01 if world.mode[player] == "standard" and world.shuffle[player] != 'vanilla' else 0x00)
|
||||
|
||||
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.smallkeyshuffle[player] else 0x00)
|
||||
| (0x02 if world.compassshuffle[player] else 0x00)
|
||||
| (0x04 if world.mapshuffle[player] else 0x00)
|
||||
| (0x08 if world.bigkeyshuffle[player] else 0x00))) # free roaming item text boxes
|
||||
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
|
||||
rom.write_byte(0x18016A, 0x10 | ((0x01 if world.smallkey_shuffle[player] else 0x00)
|
||||
| (0x02 if world.compass_shuffle[player] else 0x00)
|
||||
| (0x04 if world.map_shuffle[player] else 0x00)
|
||||
| (0x08 if world.bigkey_shuffle[player] else 0x00))) # free roaming item text boxes
|
||||
rom.write_byte(0x18003B, 0x01 if world.map_shuffle[player] else 0x00) # maps showing crystals on overworld
|
||||
|
||||
# compasses showing dungeon count
|
||||
if world.clock_mode[player] or not world.dungeon_counters[player]:
|
||||
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location
|
||||
elif world.dungeon_counters[player] is True:
|
||||
rom.write_byte(0x18003C, 0x02) # always on
|
||||
elif world.compassshuffle[player] or world.dungeon_counters[player] == 'pickup':
|
||||
elif world.compass_shuffle[player] or world.dungeon_counters[player] == 'pickup':
|
||||
rom.write_byte(0x18003C, 0x01) # show on pickup
|
||||
else:
|
||||
rom.write_byte(0x18003C, 0x00)
|
||||
|
@ -1515,10 +1515,10 @@ def patch_rom(world, rom, player, enemized):
|
|||
# b - Big Key
|
||||
# a - Small Key
|
||||
#
|
||||
rom.write_byte(0x180045, ((0x01 if world.smallkeyshuffle[player] is True else 0x00)
|
||||
| (0x02 if world.bigkeyshuffle[player] else 0x00)
|
||||
| (0x04 if world.mapshuffle[player] else 0x00)
|
||||
| (0x08 if world.compassshuffle[player] else 0x00))) # free roaming items in menu
|
||||
rom.write_byte(0x180045, ((0x01 if world.smallkey_shuffle[player] is True else 0x00)
|
||||
| (0x02 if world.bigkey_shuffle[player] else 0x00)
|
||||
| (0x04 if world.map_shuffle[player] else 0x00)
|
||||
| (0x08 if world.compass_shuffle[player] else 0x00))) # free roaming items in menu
|
||||
|
||||
# Map reveals
|
||||
reveal_bytes = {
|
||||
|
@ -1544,11 +1544,11 @@ def patch_rom(world, rom, player, enemized):
|
|||
return 0x0000
|
||||
|
||||
rom.write_int16(0x18017A,
|
||||
get_reveal_bytes('Green Pendant') if world.mapshuffle[player] else 0x0000) # Sahasrahla reveal
|
||||
rom.write_int16(0x18017C, get_reveal_bytes('Crystal 5') | get_reveal_bytes('Crystal 6') if world.mapshuffle[
|
||||
get_reveal_bytes('Green Pendant') if world.map_shuffle[player] else 0x0000) # Sahasrahla reveal
|
||||
rom.write_int16(0x18017C, get_reveal_bytes('Crystal 5') | get_reveal_bytes('Crystal 6') if world.map_shuffle[
|
||||
player] else 0x0000) # Bomb Shop Reveal
|
||||
|
||||
rom.write_byte(0x180172, 0x01 if world.smallkeyshuffle[player] == "universal" else 0x00) # universal keys
|
||||
rom.write_byte(0x180172, 0x01 if world.smallkey_shuffle[player] == "universal" else 0x00) # universal keys
|
||||
rom.write_byte(0x18637E, 0x01 if world.retro[player] else 0x00) # Skip quiver in item shops once bought
|
||||
rom.write_byte(0x180175, 0x01 if world.retro[player] else 0x00) # rupee bow
|
||||
rom.write_byte(0x180176, 0x0A if world.retro[player] else 0x00) # wood arrow cost
|
||||
|
@ -2247,9 +2247,9 @@ def write_strings(rom, world, player):
|
|||
|
||||
# Lastly we write hints to show where certain interesting items are. It is done the way it is to re-use the silver code and also to give one hint per each type of item regardless of how many exist. This supports many settings well.
|
||||
items_to_hint = RelevantItems.copy()
|
||||
if world.smallkeyshuffle[player]:
|
||||
if world.smallkey_shuffle[player]:
|
||||
items_to_hint.extend(SmallKeys)
|
||||
if world.bigkeyshuffle[player]:
|
||||
if world.bigkey_shuffle[player]:
|
||||
items_to_hint.extend(BigKeys)
|
||||
local_random.shuffle(items_to_hint)
|
||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'dungeonscrossed'] else 8
|
||||
|
|
|
@ -212,7 +212,7 @@ def global_rules(world, player):
|
|||
|
||||
set_rule(world.get_entrance('Sewers Door', player),
|
||||
lambda state: state.has_key('Small Key (Hyrule Castle)', player) or (
|
||||
world.smallkeyshuffle[player] == "universal" and world.mode[
|
||||
world.smallkey_shuffle[player] == "universal" and world.mode[
|
||||
player] == 'standard')) # standard universal small keys cannot access the shop
|
||||
set_rule(world.get_entrance('Sewers Back Door', player),
|
||||
lambda state: state.has_key('Small Key (Hyrule Castle)', player))
|
||||
|
@ -243,7 +243,7 @@ def global_rules(world, player):
|
|||
set_rule(world.get_location('Desert Palace - Boss', player), lambda state: state.has_key('Small Key (Desert Palace)', player) and state.has('Big Key (Desert Palace)', player) and state.has_fire_source(player) and state.world.get_location('Desert Palace - Boss', player).parent_region.dungeon.boss.can_defeat(state))
|
||||
|
||||
# logic patch to prevent placing a crystal in Desert that's required to reach the required keys
|
||||
if not (world.smallkeyshuffle[player] and world.bigkeyshuffle[player]):
|
||||
if not (world.smallkey_shuffle[player] and world.bigkey_shuffle[player]):
|
||||
add_rule(world.get_location('Desert Palace - Prize', player), lambda state: state.world.get_region('Desert Palace Main (Outer)', player).can_reach(state))
|
||||
|
||||
set_rule(world.get_entrance('Tower of Hera Small Key Door', player), lambda state: state.has_key('Small Key (Tower of Hera)', player) or item_name(state, 'Tower of Hera - Big Key Chest', player) == ('Small Key (Tower of Hera)', player))
|
||||
|
@ -260,7 +260,7 @@ def global_rules(world, player):
|
|||
if world.accessibility[player] != 'locations':
|
||||
set_always_allow(world.get_location('Swamp Palace - Big Chest', player), lambda state, item: item.name == 'Big Key (Swamp Palace)' and item.player == player)
|
||||
set_rule(world.get_entrance('Swamp Palace (North)', player), lambda state: state.has('Hookshot', player))
|
||||
if not world.smallkeyshuffle[player] and world.logic[player] != 'nologic':
|
||||
if not world.smallkey_shuffle[player] and world.logic[player] != 'nologic':
|
||||
forbid_item(world.get_location('Swamp Palace - Entrance', player), 'Big Key (Swamp Palace)', player)
|
||||
|
||||
set_rule(world.get_entrance('Thieves Town Big Key Door', player), lambda state: state.has('Big Key (Thieves Town)', player))
|
||||
|
@ -915,14 +915,14 @@ def set_trock_key_rules(world, player):
|
|||
return 4
|
||||
|
||||
# If TR is only accessible from the middle, the big key must be further restricted to prevent softlock potential
|
||||
if not can_reach_front and not world.smallkeyshuffle[player]:
|
||||
if not can_reach_front and not world.smallkey_shuffle[player]:
|
||||
# Must not go in the Big Key Chest - only 1 other chest available and 2+ keys required for all other chests
|
||||
forbid_item(world.get_location('Turtle Rock - Big Key Chest', player), 'Big Key (Turtle Rock)', player)
|
||||
if not can_reach_big_chest:
|
||||
# Must not go in the Chain Chomps chest - only 2 other chests available and 3+ keys required for all other chests
|
||||
forbid_item(world.get_location('Turtle Rock - Chain Chomps', player), 'Big Key (Turtle Rock)', player)
|
||||
if world.accessibility[player] == 'locations' and world.goal[player] != 'icerodhunt':
|
||||
if world.bigkeyshuffle[player] and can_reach_big_chest:
|
||||
if world.bigkey_shuffle[player] and can_reach_big_chest:
|
||||
# Must not go in the dungeon - all 3 available chests (Chomps, Big Chest, Crystaroller) must be keys to access laser bridge, and the big key is required first
|
||||
for location in ['Turtle Rock - Chain Chomps', 'Turtle Rock - Compass Chest',
|
||||
'Turtle Rock - Roller Room - Left', 'Turtle Rock - Roller Room - Right']:
|
||||
|
|
|
@ -271,7 +271,7 @@ def create_shops(world, player: int):
|
|||
# make sure that blue potion is available in inverted, special case locked = None; lock when done.
|
||||
player_shop_table["Dark Lake Hylia Shop"] = \
|
||||
player_shop_table["Dark Lake Hylia Shop"]._replace(items=_inverted_hylia_shop_defaults, locked=None)
|
||||
chance_100 = int(world.retro[player])*0.25+int(world.smallkeyshuffle[player] == "universal") * 0.5
|
||||
chance_100 = int(world.retro[player])*0.25+int(world.smallkey_shuffle[player] == "universal") * 0.5
|
||||
for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram_offset) in player_shop_table.items():
|
||||
region = world.get_region(region_name, player)
|
||||
shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked, sram_offset)
|
||||
|
@ -371,13 +371,13 @@ def set_up_shops(world, player: int):
|
|||
rss = world.get_region('Red Shield Shop', player).shop
|
||||
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
|
||||
['Blue Shield', 50], ['Small Heart', 10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them.
|
||||
if world.smallkeyshuffle[player] == "universal":
|
||||
if world.smallkey_shuffle[player] == "universal":
|
||||
replacement_items.append(['Small Key (Universal)', 100])
|
||||
replacement_item = world.random.choice(replacement_items)
|
||||
rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
|
||||
rss.locked = True
|
||||
|
||||
if world.smallkeyshuffle[player] == "universal" or world.retro[player]:
|
||||
if world.smallkey_shuffle[player] == "universal" or world.retro[player]:
|
||||
for shop in world.random.sample([s for s in world.shops if
|
||||
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
|
||||
5):
|
||||
|
@ -385,7 +385,7 @@ def set_up_shops(world, player: int):
|
|||
slots = [0, 1, 2]
|
||||
world.random.shuffle(slots)
|
||||
slots = iter(slots)
|
||||
if world.smallkeyshuffle[player] == "universal":
|
||||
if world.smallkey_shuffle[player] == "universal":
|
||||
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
|
||||
if world.retro[player]:
|
||||
shop.push_inventory(next(slots), 'Single Arrow', 80)
|
||||
|
|
|
@ -65,7 +65,7 @@ class ALTTPWorld(World):
|
|||
world.er_seeds[player] = seed
|
||||
elif world.shuffle[player] == "vanilla":
|
||||
world.er_seeds[player] = "vanilla"
|
||||
for dungeon_item in ["smallkeyshuffle", "bigkeyshuffle", "compassshuffle", "mapshuffle"]:
|
||||
for dungeon_item in ["smallkey_shuffle", "bigkey_shuffle", "compass_shuffle", "map_shuffle"]:
|
||||
option = getattr(world, dungeon_item)[player]
|
||||
if option == "own_world":
|
||||
world.local_items[player] |= self.item_name_groups[option.item_name_group]
|
||||
|
@ -324,8 +324,8 @@ class ALTTPWorld(World):
|
|||
trash_counts = {}
|
||||
standard_keyshuffle_players = set()
|
||||
for player in world.get_game_players("A Link to the Past"):
|
||||
if world.mode[player] == 'standard' and world.smallkeyshuffle[player] \
|
||||
and world.smallkeyshuffle[player] != "universal":
|
||||
if world.mode[player] == 'standard' and world.smallkey_shuffle[player] \
|
||||
and world.smallkey_shuffle[player] != "universal":
|
||||
standard_keyshuffle_players.add(player)
|
||||
if not world.ganonstower_vanilla[player] or \
|
||||
world.logic[player] in {'owglitches', 'hybridglitches', "nologic"}:
|
||||
|
|
Loading…
Reference in New Issue