shopsanity
This commit is contained in:
parent
26ab3dd69a
commit
9cabd41d3b
|
@ -5,7 +5,7 @@ from enum import Enum, unique
|
|||
import logging
|
||||
import json
|
||||
from collections import OrderedDict, Counter, deque
|
||||
from typing import Union, Optional
|
||||
from typing import Union, Optional, List
|
||||
import secrets
|
||||
import random
|
||||
|
||||
|
@ -521,6 +521,10 @@ class CollectionState(object):
|
|||
return any(shop.region.player == player and shop.has_unlimited(item) and shop.region.can_reach(self) for
|
||||
shop in self.world.shops)
|
||||
|
||||
def can_buy(self, item: str, player: int) -> bool:
|
||||
return any(shop.region.player == player and shop.has(item) and shop.region.can_reach(self) for
|
||||
shop in self.world.shops)
|
||||
|
||||
def item_count(self, item, player: int) -> int:
|
||||
return self.prog_items[item, player]
|
||||
|
||||
|
@ -598,7 +602,7 @@ class CollectionState(object):
|
|||
def can_shoot_arrows(self, player: int) -> bool:
|
||||
if self.world.retro[player]:
|
||||
# TODO: Progressive and Non-Progressive silvers work differently (progressive is not usable until the shop arrow is bought)
|
||||
return (self.has('Bow', player) or self.has('Silver Bow', player)) and self.can_buy_unlimited('Single Arrow', player)
|
||||
return (self.has('Bow', player) or self.has('Silver Bow', player)) and self.can_buy('Single Arrow', player)
|
||||
return self.has('Bow', player) or self.has('Silver Bow', player)
|
||||
|
||||
def can_get_good_bee(self, player: int) -> bool:
|
||||
|
@ -1054,11 +1058,12 @@ class ShopType(Enum):
|
|||
|
||||
class Shop(object):
|
||||
slots = 3
|
||||
def __init__(self, region, room_id, type, shopkeeper_config, custom, locked):
|
||||
|
||||
def __init__(self, region, room_id, type, shopkeeper_config, custom, locked: bool):
|
||||
self.region = region
|
||||
self.room_id = room_id
|
||||
self.type = type
|
||||
self.inventory = [None, None, None]
|
||||
self.inventory: List[Union[None, dict]] = [None, None, None]
|
||||
self.shopkeeper_config = shopkeeper_config
|
||||
self.custom = custom
|
||||
self.locked = locked
|
||||
|
@ -1085,20 +1090,31 @@ class Shop(object):
|
|||
config |= 0x10 # Alt. VRAM
|
||||
return [0x00]+int16_as_bytes(self.room_id)+[door_id, 0x00, config, self.shopkeeper_config, 0x00]
|
||||
|
||||
def has_unlimited(self, item):
|
||||
def has_unlimited(self, item: str) -> bool:
|
||||
for inv in self.inventory:
|
||||
if inv is None:
|
||||
continue
|
||||
if inv['item'] == item:
|
||||
return True
|
||||
if inv['max'] != 0 and inv['replacement'] is not None and inv['replacement'] == item:
|
||||
return True
|
||||
elif inv['item'] is not None and inv['item'] == item:
|
||||
return False
|
||||
|
||||
def has(self, item: str) -> bool:
|
||||
for inv in self.inventory:
|
||||
if inv is None:
|
||||
continue
|
||||
if inv['item'] == item:
|
||||
return True
|
||||
if inv['max'] != 0 and inv['replacement'] == item:
|
||||
return True
|
||||
return False
|
||||
|
||||
def clear_inventory(self):
|
||||
self.inventory = [None, None, None]
|
||||
|
||||
def add_inventory(self, slot, item, price, max=0, replacement=None, replacement_price=0, create_location=False):
|
||||
def add_inventory(self, slot: int, item: str, price: int, max: int = 0,
|
||||
replacement: Optional[str] = None, replacement_price: int = 0, create_location: bool = False):
|
||||
self.inventory[slot] = {
|
||||
'item': item,
|
||||
'price': price,
|
||||
|
@ -1108,6 +1124,18 @@ class Shop(object):
|
|||
'create_location': create_location
|
||||
}
|
||||
|
||||
def push_inventory(self, slot: int, item: str, price: int, max: int = 1):
|
||||
if not self.inventory[slot]:
|
||||
raise ValueError("Inventory can't be pushed back if it doesn't exist")
|
||||
|
||||
self.inventory[slot] = {
|
||||
'item': item,
|
||||
'price': price,
|
||||
'max': max,
|
||||
'replacement': self.inventory[slot]["item"],
|
||||
'replacement_price': self.inventory[slot]["price"],
|
||||
'create_location': self.inventory[slot]["create_location"]
|
||||
}
|
||||
|
||||
class Spoiler(object):
|
||||
world: World
|
||||
|
@ -1243,6 +1271,7 @@ class Spoiler(object):
|
|||
'progression_balancing': self.world.progression_balancing,
|
||||
'triforce_pieces_available': self.world.triforce_pieces_available,
|
||||
'triforce_pieces_required': self.world.triforce_pieces_required,
|
||||
'shop_shuffle': self.world.shop_shuffle
|
||||
}
|
||||
|
||||
def to_json(self):
|
||||
|
@ -1290,15 +1319,15 @@ class Spoiler(object):
|
|||
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 available for Triforce: %s\n" % self.metadata['triforce_pieces_available'][player])
|
||||
outfile.write(
|
||||
"Pieces required for Triforce: %s\n" % self.metadata["triforce_pieces_required"][player])
|
||||
outfile.write("Pieces available for Triforce: %s\n" %
|
||||
self.metadata['triforce_pieces_available'][player])
|
||||
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])
|
||||
|
@ -1308,14 +1337,20 @@ class Spoiler(object):
|
|||
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' % (bool_to_text(self.metadata['keyshuffle'][player])))
|
||||
outfile.write('Big Key shuffle: %s\n' % (
|
||||
'Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
||||
outfile.write('Shop inventory shuffle: %s\n' %
|
||||
bool_to_text("i" in self.metadata["shop_shuffle"][player]))
|
||||
outfile.write('Shop price shuffle: %s\n' %
|
||||
bool_to_text("p" in self.metadata["shop_shuffle"][player]))
|
||||
outfile.write('Shop upgrade shuffle: %s\n' %
|
||||
bool_to_text("u" in self.metadata["shop_shuffle"][player]))
|
||||
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
||||
outfile.write(
|
||||
'Enemy shuffle: %s\n' % bool_to_text(self.metadata['enemy_shuffle'][player]))
|
||||
|
@ -1331,7 +1366,11 @@ class Spoiler(object):
|
|||
'Pot shuffle %s\n' % ('Yes' if self.metadata['shufflepots'][player] else 'No'))
|
||||
if self.entrances:
|
||||
outfile.write('\n\nEntrances:\n\n')
|
||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', entry['entrance'], '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', entry['exit']) for entry in self.entrances.values()]))
|
||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: '
|
||||
if self.world.players > 1 else '', entry['entrance'],
|
||||
'<=>' if entry['direction'] == 'both' else
|
||||
'<=' if entry['direction'] == 'exit' else '=>',
|
||||
entry['exit']) for entry in self.entrances.values()]))
|
||||
outfile.write('\n\nMedallions:\n')
|
||||
for dungeon, medallion in self.medallions.items():
|
||||
outfile.write(f'\n{dungeon}: {medallion}')
|
||||
|
|
|
@ -312,7 +312,12 @@ def parse_arguments(argv, no_defaults=False):
|
|||
parser.add_argument('--enemy_damage', default=defval('default'), choices=['default', 'shuffled', 'chaos'])
|
||||
parser.add_argument('--shufflepots', default=defval(False), action='store_true')
|
||||
parser.add_argument('--beemizer', default=defval(0), type=lambda value: min(max(int(value), 0), 4))
|
||||
parser.add_argument('--shop_shuffle', default='off', choices=['off', 'inventory', 'price', 'inventory_price'])
|
||||
parser.add_argument('--shop_shuffle', default='', help='''\
|
||||
combine letters for options:
|
||||
i: shuffle the inventories of the shops around
|
||||
p: randomize the prices of the items in shop inventories
|
||||
u: shuffle capacity upgrades into the item pool
|
||||
''')
|
||||
parser.add_argument('--remote_items', default=defval(False), action='store_true')
|
||||
parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255))
|
||||
parser.add_argument('--names', default=defval(''))
|
||||
|
|
|
@ -1061,7 +1061,8 @@ def link_entrances(world, player):
|
|||
# place remaining doors
|
||||
connect_doors(world, single_doors, door_targets, player)
|
||||
else:
|
||||
raise NotImplementedError(f'{world.shuffle[player]} Shuffling not supported yet. Player {player}')
|
||||
raise NotImplementedError(
|
||||
f'{world.shuffle[player]} Shuffling not supported yet. Player {world.get_player_names(player)}')
|
||||
|
||||
# check for swamp palace fix
|
||||
if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)':
|
||||
|
|
30
Gui.py
30
Gui.py
|
@ -75,14 +75,14 @@ def guiMain(args=None):
|
|||
compassshuffleCheckbutton = Checkbutton(mcsbshuffleFrame, text="Compasses", variable=compassshuffleVar)
|
||||
|
||||
bigkeyshuffleVar = IntVar()
|
||||
bigkeyshuffleCheckbutton = Checkbutton(mcsbshuffleFrame, text="BigKeys", variable=bigkeyshuffleVar)
|
||||
bigkeyshuffleCheckbutton = Checkbutton(mcsbshuffleFrame, text="Big Keys", variable=bigkeyshuffleVar)
|
||||
|
||||
keyshuffleFrame = Frame(checkBoxFrame)
|
||||
keyshuffleVar = StringVar()
|
||||
keyshuffleVar.set('off')
|
||||
modeOptionMenu = OptionMenu(keyshuffleFrame, keyshuffleVar, 'off', 'universal', 'on')
|
||||
modeOptionMenu.pack(side=LEFT)
|
||||
modeLabel = Label(keyshuffleFrame, text='Key Shuffle')
|
||||
modeLabel = Label(keyshuffleFrame, text='Small Key Shuffle')
|
||||
modeLabel.pack(side=LEFT)
|
||||
|
||||
retroVar = IntVar()
|
||||
|
@ -447,6 +447,20 @@ def guiMain(args=None):
|
|||
killable_thievesShuffleButton = Checkbutton(enemizerFrame, text="Killable Thieves", variable=killableThievesVar)
|
||||
killable_thievesShuffleButton.grid(row=2, column=3, sticky=W)
|
||||
|
||||
shopframe = LabelFrame(randomizerWindow, text="Shops", padx=5, pady=2)
|
||||
|
||||
shopPriceShuffleVar = IntVar()
|
||||
shopPriceShuffleButton = Checkbutton(shopframe, text="Random Prices", variable=shopPriceShuffleVar)
|
||||
shopPriceShuffleButton.grid(row=0, column=0, sticky=W)
|
||||
|
||||
shopShuffleVar = IntVar()
|
||||
shopShuffleButton = Checkbutton(shopframe, text="Shuffle Inventories", variable=shopShuffleVar)
|
||||
shopShuffleButton.grid(row=0, column=1, sticky=W)
|
||||
|
||||
shopUpgradeShuffleVar = IntVar()
|
||||
shopUpgradeShuffleButton = Checkbutton(shopframe, text="Lootable Upgrades", variable=shopUpgradeShuffleVar)
|
||||
shopUpgradeShuffleButton.grid(row=0, column=2, sticky=W)
|
||||
|
||||
multiworldframe = LabelFrame(randomizerWindow, text="Multiworld", padx=5, pady=2)
|
||||
|
||||
worldLabel = Label(multiworldframe, text='Worlds')
|
||||
|
@ -521,6 +535,13 @@ def guiMain(args=None):
|
|||
guiargs.custom = bool(customVar.get())
|
||||
guiargs.triforce_pieces_required = min(90, int(triforcecountVar.get()))
|
||||
guiargs.triforce_pieces_available = min(90, int(triforcepieceVar.get()))
|
||||
guiargs.shop_shuffle = ""
|
||||
if shopShuffleVar.get():
|
||||
guiargs.shop_shuffle += "i"
|
||||
if shopPriceShuffleVar.get():
|
||||
guiargs.shop_shuffle += "p"
|
||||
if shopUpgradeShuffleVar.get():
|
||||
guiargs.shop_shuffle += "u"
|
||||
guiargs.customitemarray = [int(bowVar.get()), int(silverarrowVar.get()), int(boomerangVar.get()),
|
||||
int(magicboomerangVar.get()), int(hookshotVar.get()), int(mushroomVar.get()),
|
||||
int(magicpowderVar.get()), int(firerodVar.get()),
|
||||
|
@ -567,9 +588,9 @@ def guiMain(args=None):
|
|||
main(seed=guiargs.seed, args=guiargs)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
messagebox.showerror(title="Error while creating multiworld", message=str(e))
|
||||
else:
|
||||
messagebox.showinfo(title="Success", message="Rom patched successfully")
|
||||
messagebox.showinfo(title="Success", message="Multiworld created successfully")
|
||||
|
||||
generateButton = Button(farBottomFrame, text='Generate Patched Rom', command=generateRom)
|
||||
|
||||
|
@ -590,6 +611,7 @@ def guiMain(args=None):
|
|||
topFrame.pack(side=TOP)
|
||||
multiworldframe.pack(side=BOTTOM, expand=True, fill=X)
|
||||
enemizerFrame.pack(side=BOTTOM, fill=BOTH)
|
||||
shopframe.pack(side=BOTTOM, expand=True, fill=X)
|
||||
|
||||
# Adjuster Controls
|
||||
|
||||
|
|
101
ItemPool.py
101
ItemPool.py
|
@ -311,8 +311,6 @@ def generate_itempool(world, player: int):
|
|||
progressionitems += [ItemFactory("Triforce Piece", player)] * (triforce_pieces - 30)
|
||||
nonprogressionitems = nonprogressionitems[(triforce_pieces - 30):]
|
||||
|
||||
world.itempool += progressionitems + nonprogressionitems
|
||||
|
||||
# shuffle medallions
|
||||
mm_medallion = ['Ether', 'Quake', 'Bombos'][world.random.randint(0, 2)]
|
||||
tr_medallion = ['Ether', 'Quake', 'Bombos'][world.random.randint(0, 2)]
|
||||
|
@ -323,43 +321,64 @@ def generate_itempool(world, player: int):
|
|||
|
||||
if world.retro[player]:
|
||||
set_up_take_anys(world, player)
|
||||
if world.shop_shuffle[player] != 'off':
|
||||
shuffle_shops(world, player)
|
||||
if world.shop_shuffle[player]:
|
||||
shuffle_shops(world, nonprogressionitems, player)
|
||||
create_dynamic_shop_locations(world, player)
|
||||
|
||||
world.itempool += progressionitems + nonprogressionitems
|
||||
|
||||
def shuffle_shops(world, player: int):
|
||||
|
||||
def shuffle_shops(world, items, player: int):
|
||||
option = world.shop_shuffle[player]
|
||||
shops = []
|
||||
total_inventory = []
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.Shop and shop.region.player == player:
|
||||
shops.append(shop)
|
||||
total_inventory.extend(shop.inventory)
|
||||
|
||||
if 'price' in option:
|
||||
def price_adjust(price: int) -> int:
|
||||
# it is important that a base price of 0 always returns 0 as new price!
|
||||
return int(price * (0.5 + world.random.random() * 2))
|
||||
|
||||
for item in total_inventory:
|
||||
if item:
|
||||
item["price"] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
if 'u' in option:
|
||||
if world.retro[player]:
|
||||
new_items = ["Bomb Upgrade (+5)"] * 7
|
||||
else:
|
||||
new_items = ["Bomb Upgrade (+5)", "Arrow Upgrade (+5)"] * 7
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.UpgradeShop and shop.region.player == player:
|
||||
for item in shop.inventory:
|
||||
if item:
|
||||
item['price'] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
if shop.type == ShopType.UpgradeShop and shop.region.player == player and \
|
||||
shop.region.name == "Capacity Upgrade":
|
||||
shop.clear_inventory()
|
||||
|
||||
if 'inventory' in option:
|
||||
world.random.shuffle(total_inventory)
|
||||
i = 0
|
||||
for shop in shops:
|
||||
slots = shop.slots
|
||||
shop.inventory = total_inventory[i:i + slots]
|
||||
i += slots
|
||||
for i, item in enumerate(items):
|
||||
if item.name.startswith(("Bombs", "Arrows", "Rupees")):
|
||||
items[i] = ItemFactory(new_items.pop(), player)
|
||||
if not new_items:
|
||||
break
|
||||
else:
|
||||
logging.warning(f"Not all upgrades put into Player{player}' item pool. Still missing: {new_items}")
|
||||
|
||||
if 'p' in option or 'i' in option:
|
||||
shops = []
|
||||
total_inventory = []
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.Shop and shop.region.player == player:
|
||||
shops.append(shop)
|
||||
total_inventory.extend(shop.inventory)
|
||||
|
||||
if 'p' in option:
|
||||
def price_adjust(price: int) -> int:
|
||||
# it is important that a base price of 0 always returns 0 as new price!
|
||||
return int(price * (0.5 + world.random.random() * 2))
|
||||
|
||||
for item in total_inventory:
|
||||
if item:
|
||||
item["price"] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.UpgradeShop and shop.region.player == player:
|
||||
for item in shop.inventory:
|
||||
if item:
|
||||
item['price'] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
|
||||
if 'i' in option:
|
||||
world.random.shuffle(total_inventory)
|
||||
i = 0
|
||||
for shop in shops:
|
||||
slots = shop.slots
|
||||
shop.inventory = total_inventory[i:i + slots]
|
||||
i += slots
|
||||
|
||||
|
||||
take_any_locations = [
|
||||
|
@ -466,21 +485,21 @@ def set_up_shops(world, player: int):
|
|||
|
||||
if world.retro[player]:
|
||||
rss = world.get_region('Red Shield Shop', player).shop
|
||||
if not rss.locked:
|
||||
rss.add_inventory(2, 'Single Arrow', 80)
|
||||
rss.add_inventory(2, 'Single Arrow', 80)
|
||||
rss.locked = True
|
||||
|
||||
if world.keyshuffle[player] == "universal":
|
||||
if world.keyshuffle[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):
|
||||
shop.locked = True
|
||||
slots = [0, 1, 2]
|
||||
world.random.shuffle(slots)
|
||||
slots = iter(slots)
|
||||
if world.retro[player]:
|
||||
shop.add_inventory(0, 'Single Arrow', 80)
|
||||
else:
|
||||
shop.add_inventory(0, "Red Potion", 150)
|
||||
shop.add_inventory(1, 'Small Key (Universal)', 100)
|
||||
shop.add_inventory(2, 'Bombs (10)', 50)
|
||||
shop.push_inventory(next(slots), 'Single Arrow', 80)
|
||||
if world.keyshuffle[player] == "universal":
|
||||
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
|
||||
|
||||
|
||||
def get_pool_core(world, player: int):
|
||||
|
|
|
@ -312,7 +312,7 @@ def roll_settings(weights):
|
|||
|
||||
ret.shop_shuffle = get_choice('shop_shuffle', weights, False)
|
||||
if not ret.shop_shuffle:
|
||||
ret.shop_shuffle = 'off'
|
||||
ret.shop_shuffle = ''
|
||||
|
||||
ret.mode = get_choice('world_state', weights, None) # legacy support
|
||||
if ret.mode == 'retro':
|
||||
|
|
25
Rom.py
25
Rom.py
|
@ -1157,20 +1157,27 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
assert equip[:0x340] == [0] * 0x340
|
||||
rom.write_bytes(0x183000, equip[0x340:])
|
||||
rom.write_bytes(0x271A6, equip[0x340:0x340+60])
|
||||
rom.write_bytes(0x271A6, equip[0x340:0x340 + 60])
|
||||
|
||||
rom.write_byte(0x18004A, 0x00 if world.mode[player] != 'inverted' else 0x01) # Inverted mode
|
||||
rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier
|
||||
rom.write_byte(0x2AF79, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both)
|
||||
rom.write_byte(0x3A943, 0xD0 if world.mode[player] != 'inverted' else 0xF0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both)
|
||||
rom.write_byte(0x3A96D, 0xF0 if world.mode[player] != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
|
||||
rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
|
||||
|
||||
rom.write_bytes(0x180080, [50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
|
||||
rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier
|
||||
rom.write_byte(0x2AF79, 0xD0 if world.mode[
|
||||
player] != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both)
|
||||
rom.write_byte(0x3A943, 0xD0 if world.mode[
|
||||
player] != 'inverted' else 0xF0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both)
|
||||
rom.write_byte(0x3A96D, 0xF0 if world.mode[
|
||||
player] != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
|
||||
rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
|
||||
if 'u' in world.shop_shuffle[player]:
|
||||
rom.write_bytes(0x180080,
|
||||
[5, 10, 5, 10]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
|
||||
else:
|
||||
rom.write_bytes(0x180080,
|
||||
[50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
|
||||
|
||||
rom.write_byte(0x18004D, ((0x01 if 'arrows' in world.escape_assist[player] else 0x00) |
|
||||
(0x02 if 'bombs' in world.escape_assist[player] else 0x00) |
|
||||
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
|
||||
(0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist
|
||||
|
||||
if world.goal[player] in ['pedestal', 'triforcehunt', 'localtriforcehunt']:
|
||||
rom.write_byte(0x18003E, 0x01) # make ganon invincible
|
||||
|
|
|
@ -190,10 +190,13 @@ beemizer: # Remove items from the global item pool and replace them with single
|
|||
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
||||
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
||||
shop_shuffle:
|
||||
off: 1
|
||||
inventory: 0 # shuffle the inventories of the shops around
|
||||
price: 0 # randomize the prices of the items in shop inventories
|
||||
inventory_price: 0 # shuffle inventories and randomize prices
|
||||
none: 1
|
||||
i: 0 # shuffle the inventories of the shops around
|
||||
p: 0 # randomize the prices of the items in shop inventories
|
||||
u: 0 # shuffle capacity upgrades into the item pool (and allow them to traverse the multiworld)
|
||||
ip: 0 # shuffle inventories and randomize prices
|
||||
uip: 0 # shuffle inventories, randomize prices and shuffle capacity upgrades into the item pool
|
||||
# you can add more combos
|
||||
timer:
|
||||
none: 1
|
||||
timed: 0
|
||||
|
@ -245,7 +248,6 @@ linked_options:
|
|||
full: 1
|
||||
random: 1
|
||||
singularity: 1
|
||||
duality: 1
|
||||
enemy_damage:
|
||||
shuffled: 1
|
||||
random: 1
|
||||
|
|
Loading…
Reference in New Issue