Merge branch 'potion-shop' of github.com:pepperpow/MultiWorld-Utilities into multishop-all

This commit is contained in:
pepperpow 2020-12-02 20:35:59 -06:00
commit 7b5bd016b9
9 changed files with 51 additions and 10 deletions

View File

@ -132,6 +132,7 @@ class World(object):
set_player_attr('triforce_pieces_required', 20) set_player_attr('triforce_pieces_required', 20)
set_player_attr('shop_shuffle', 'off') set_player_attr('shop_shuffle', 'off')
set_player_attr('shop_shuffle_slots', 0) set_player_attr('shop_shuffle_slots', 0)
set_player_attr('potion_shop_shuffle', 'none')
set_player_attr('shuffle_prizes', "g") set_player_attr('shuffle_prizes', "g")
set_player_attr('sprite_pool', []) set_player_attr('sprite_pool', [])
set_player_attr('dark_room_logic', "lamp") set_player_attr('dark_room_logic', "lamp")
@ -1341,6 +1342,7 @@ class Spoiler(object):
'triforce_pieces_required': self.world.triforce_pieces_required, 'triforce_pieces_required': self.world.triforce_pieces_required,
'shop_shuffle': self.world.shop_shuffle, 'shop_shuffle': self.world.shop_shuffle,
'shop_shuffle_slots': self.world.shop_shuffle_slots, 'shop_shuffle_slots': self.world.shop_shuffle_slots,
'potion_shop_shuffle': self.world.potion_shop_shuffle,
'shuffle_prizes': self.world.shuffle_prizes, 'shuffle_prizes': self.world.shuffle_prizes,
'sprite_pool': self.world.sprite_pool, 'sprite_pool': self.world.sprite_pool,
'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss 'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss

View File

@ -335,6 +335,10 @@ def parse_arguments(argv, no_defaults=False):
help=''' help='''
Maximum amount of shop slots able to be filled by items from the item pool. Maximum amount of shop slots able to be filled by items from the item pool.
''') ''')
parser.add_argument('--potion_shop_shuffle', default=defval('none'), choices=['none', 'a'], help='''\
Determine if potion shop shuffle items should be affected by the rules of shop shuffle.
Value `none` will only allow prices to be shuffled, `a` will allow any items to be shuffled.
''')
parser.add_argument('--shuffle_prizes', default=defval('g'), choices=['', 'g', 'b', 'gb']) parser.add_argument('--shuffle_prizes', default=defval('g'), choices=['', 'g', 'b', 'gb'])
parser.add_argument('--sprite_pool', help='''\ parser.add_argument('--sprite_pool', help='''\
Specifies a colon separated list of sprites used for random/randomonevent. If not specified, the full sprite pool is used.''') Specifies a colon separated list of sprites used for random/randomonevent. If not specified, the full sprite pool is used.''')
@ -387,7 +391,7 @@ def parse_arguments(argv, no_defaults=False):
'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots', 'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', "skip_progression_balancing", "triforce_pieces_available", 'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots", "triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots", "potion_shop_shuffle",
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves', 'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic', 'restrict_dungeon_item_on_boss', 'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic', 'restrict_dungeon_item_on_boss',
'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes']: 'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes']:

View File

@ -368,13 +368,17 @@ def shuffle_shops(world, items, player: int):
shops = [] shops = []
upgrade_shops = [] upgrade_shops = []
total_inventory = [] total_inventory = []
potion_option = world.potion_shop_shuffle[player]
for shop in world.shops: for shop in world.shops:
if shop.region.player == player: if shop.region.player == player:
if shop.type == ShopType.UpgradeShop: if shop.type == ShopType.UpgradeShop:
upgrade_shops.append(shop) upgrade_shops.append(shop)
elif shop.type == ShopType.Shop and shop.region.name != 'Potion Shop': elif shop.type == ShopType.Shop:
shops.append(shop) if shop.region.name == 'Potion Shop' and potion_option in [None, '', 'none']:
total_inventory.extend(shop.inventory) upgrade_shops.append(shop) # just put it with the upgrade shops/caves so we don't shuffle the items, just prices
else:
shops.append(shop)
total_inventory.extend(shop.inventory)
if 'p' in option: if 'p' in option:
def price_adjust(price: int) -> int: def price_adjust(price: int) -> int:
@ -470,7 +474,7 @@ def create_dynamic_shop_locations(world, player):
world.clear_location_cache() world.clear_location_cache()
world.push_item(loc, ItemFactory(item['item'], player), False) world.push_item(loc, ItemFactory(item['item'], player), False)
loc.event = True loc.event = True
loc.locked = True loc.locked = True

View File

@ -84,6 +84,7 @@ def main(args, seed=None):
world.triforce_pieces_required = args.triforce_pieces_required.copy() world.triforce_pieces_required = args.triforce_pieces_required.copy()
world.shop_shuffle = args.shop_shuffle.copy() world.shop_shuffle = args.shop_shuffle.copy()
world.shop_shuffle_slots = args.shop_shuffle_slots.copy() world.shop_shuffle_slots = args.shop_shuffle_slots.copy()
world.potion_shop_shuffle = args.potion_shop_shuffle.copy()
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()} world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
world.shuffle_prizes = args.shuffle_prizes.copy() world.shuffle_prizes = args.shuffle_prizes.copy()
world.sprite_pool = args.sprite_pool.copy() world.sprite_pool = args.sprite_pool.copy()

View File

@ -368,6 +368,10 @@ def roll_settings(weights):
if not ret.shop_shuffle: if not ret.shop_shuffle:
ret.shop_shuffle = '' ret.shop_shuffle = ''
ret.potion_shop_shuffle = get_choice('potion_shop_shuffle', weights, '')
if not ret.potion_shop_shuffle:
ret.potion_shop_shuffle = ''
ret.mode = get_choice('world_state', weights, None) # legacy support ret.mode = get_choice('world_state', weights, None) # legacy support
if ret.mode == 'retro': if ret.mode == 'retro':
ret.mode = 'open' ret.mode = 'open'

9
Rom.py
View File

@ -122,6 +122,9 @@ class LocalRom(object):
if not os.path.exists(local_path('data', 'basepatch.bmbp')): if not os.path.exists(local_path('data', 'basepatch.bmbp')):
Patch.create_patch_file(local_path('basepatch.sfc')) Patch.create_patch_file(local_path('basepatch.sfc'))
return return
if not os.path.isfile(local_path('data', 'basepatch.bmbp')):
raise RuntimeError('Base patch unverified. Unable to continue.')
if os.path.isfile(local_path('data', 'basepatch.bmbp')): if os.path.isfile(local_path('data', 'basepatch.bmbp')):
_, target, buffer = Patch.create_rom_bytes(local_path('data', 'basepatch.bmbp')) _, target, buffer = Patch.create_rom_bytes(local_path('data', 'basepatch.bmbp'))
@ -130,6 +133,7 @@ class LocalRom(object):
with open(local_path('basepatch.sfc'), 'wb') as stream: with open(local_path('basepatch.sfc'), 'wb') as stream:
stream.write(buffer) stream.write(buffer)
return return
raise RuntimeError('Base patch unverified. Unable to continue.')
raise RuntimeError('Could not find Base Patch. Unable to continue.') raise RuntimeError('Could not find Base Patch. Unable to continue.')
@ -1509,12 +1513,11 @@ def write_custom_shops(rom, world, player):
else: else:
sram_offset += shop.item_count sram_offset += shop.item_count
shop_data.extend(bytes) shop_data.extend(bytes)
# [id][item][price-low][price-high][max][repl_id][repl_price-low][repl_price-high] # [id][item][price-low][price-high][max][repl_id][repl_price-low][repl_price-high][player]
for item in shop.inventory: for item in shop.inventory:
if item is None: if item is None:
break break
item_data = [shop_id, ItemFactory(item['item'], player).code] + int16_as_bytes(item['price']) + [ item_data = [shop_id, ItemFactory(item['item'], player).code] + int16_as_bytes(item['price']) + [ item['max'],\
item['max'],
ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF] + int16_as_bytes( ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF] + int16_as_bytes(
item['replacement_price']) + [item['player']] item['replacement_price']) + [item['player']]
items_data.extend(item_data) items_data.extend(item_data)

View File

@ -85,7 +85,7 @@ def set_rules(world, player):
add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or') add_rule(world.get_entrance('Ganons Tower', player), lambda state: state.world.get_entrance('Ganons Tower Ascent', player).can_reach(state), 'or')
set_bunny_rules(world, player, world.mode[player] == 'inverted') set_bunny_rules(world, player, world.mode[player] == 'inverted')
def mirrorless_path_to_castle_courtyard(world, player): def mirrorless_path_to_castle_courtyard(world, player):
# If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch. # If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch.

View File

@ -1095,7 +1095,7 @@
"i": { "i": {
"keyString": "shop_shuffle.i", "keyString": "shop_shuffle.i",
"friendlyName": "Inventory Shuffle", "friendlyName": "Inventory Shuffle",
"description": "Randomizes the inventories of shops.", "description": "Shuffles the inventories of shops between each other.",
"defaultValue": 0 "defaultValue": 0
}, },
"p": { "p": {
@ -1162,6 +1162,26 @@
} }
} }
}, },
"potion_shop_shuffle": {
"keyString": "potion_shop_shuffle",
"friendlyName": "Potion Shop Shuffle Rules",
"description": "Influence on potion shop by shop shuffle options",
"inputType": "range",
"subOptions": {
"none": {
"keyString": "potion_shop_shuffle.none",
"friendlyName": "Vanilla Shops",
"description": "Shop contents are left unchanged, only prices.",
"defaultValue": 50
},
"a": {
"keyString": "potion_shop_shuffle.a",
"friendlyName": "Any Items can be shuffled in and out of the shop",
"description": "",
"defaultValue": 0
}
}
},
"shuffle_prizes": { "shuffle_prizes": {
"keyString": "shuffle_prizes", "keyString": "shuffle_prizes",
"friendlyName": "Prize Shuffle", "friendlyName": "Prize Shuffle",

View File

@ -217,6 +217,9 @@ shop_shuffle_slots: # Maximum amount of allowed shop slots to place item pool it
5: 0 5: 0
15: 0 15: 0
999: 0 999: 0
potion_shop_shuffle: # influence of potion shop by shop shuffle
none: 50 # only shuffle price
a: 0 # generate/shuffle in any items
shop_shuffle: shop_shuffle:
none: 50 none: 50
i: 0 # Shuffle default inventories of the shops around i: 0 # Shuffle default inventories of the shops around