Fixes to barter pricing min/max, future key logic, spoiler log

This commit is contained in:
pepperpow 2021-09-12 16:09:13 -05:00 committed by Fabian Dill
parent 4d68000692
commit 8cc045f370
3 changed files with 48 additions and 17 deletions

View File

@ -1056,7 +1056,7 @@ class Spoiler():
listed_locations.update(other_locations) listed_locations.update(other_locations)
self.shops = [] self.shops = []
from worlds.alttp.Shops import ShopType, price_type_display_name from worlds.alttp.Shops import ShopType, price_type_display_name, price_rate_display
for shop in self.world.shops: for shop in self.world.shops:
if not shop.custom: if not shop.custom:
continue continue
@ -1067,7 +1067,8 @@ class Spoiler():
for index, item in enumerate(shop.inventory): for index, item in enumerate(shop.inventory):
if item is None: if item is None:
continue continue
shopdata['item_{}'.format(index)] = f"{item['item']}{item['price']} {price_type_display_name[item['price_type']]}" my_price = item['price'] // price_rate_display.get(item['price_type'], 1)
shopdata['item_{}'.format(index)] = f"{item['item']}{my_price} {price_type_display_name[item['price_type']]}"
if item['player'] > 0: if item['player'] > 0:
shopdata['item_{}'.format(index)] = shopdata['item_{}'.format(index)].replace('', '(Player {}) — '.format(item['player'])) shopdata['item_{}'.format(index)] = shopdata['item_{}'.format(index)].replace('', '(Player {}) — '.format(item['player']))

View File

@ -22,7 +22,7 @@ from typing import Optional
from BaseClasses import CollectionState, Region from BaseClasses import CollectionState, Region
from worlds.alttp.SubClasses import ALttPLocation from worlds.alttp.SubClasses import ALttPLocation
from worlds.alttp.Shops import ShopType from worlds.alttp.Shops import ShopType, ShopPriceType
from worlds.alttp.Dungeons import dungeon_music_addresses from worlds.alttp.Dungeons import dungeon_music_addresses
from worlds.alttp.Regions import location_table, old_location_address_to_new_location_address from worlds.alttp.Regions import location_table, old_location_address_to_new_location_address
from worlds.alttp.Text import MultiByteTextMapper, text_addresses, Credits, TextTable from worlds.alttp.Text import MultiByteTextMapper, text_addresses, Credits, TextTable
@ -1711,7 +1711,13 @@ def write_custom_shops(rom, world, player):
for index, item in enumerate(shop.inventory): for index, item in enumerate(shop.inventory):
if item is None: if item is None:
break break
price_data = int16_as_bytes(0x8000 | 0x100 * (item["price_type"] - 1) | item['price']) if item['price_type'] != ShopPriceType.Rupees:
# Set special price flag 0x8000
# Then set the type of price we're setting 0x7F00 (this starts from Hearts, not Rupees, subtract 1)
# Then append the price/index into the second byte 0x00FF
price_data = int16_as_bytes(0x8000 | 0x100 * (item["price_type"] - 1) | item['price'])
else:
price_data = int16_as_bytes(item['price'])
slot = 0 if shop.type == ShopType.TakeAny else index slot = 0 if shop.type == ShopType.TakeAny else index
if not item['item'] in item_table: # item not native to ALTTP if not item['item'] in item_table: # item not native to ALTTP
item_code = get_nonnative_item_sprite(item['item']) item_code = get_nonnative_item_sprite(item['item'])

View File

@ -458,7 +458,7 @@ def shuffle_shops(world, items, player: int):
for item in new_items: for item in new_items:
world.push_precollected(ItemFactory(item, player)) world.push_precollected(ItemFactory(item, player))
if 'p' in option or 'i' in option: if any(setting in option for setting in 'ipP'):
shops = [] shops = []
upgrade_shops = [] upgrade_shops = []
total_inventory = [] total_inventory = []
@ -490,9 +490,12 @@ def shuffle_shops(world, items, player: int):
if 'P' in option: if 'P' in option:
for item in total_inventory: for item in total_inventory:
price_to_funny_price(item, world, player) price_to_funny_price(item, world, player)
# Don't apply to upgrade shops
# Upgrade shop is only one place, and will generally be too easy to
# replenish hearts and bombs
for shop in upgrade_shops: for shop in upgrade_shops:
for item in shop.inventory: for item in shop.inventory:
price_to_funny_price(item, world, player) pass
if 'i' in option: if 'i' in option:
world.random.shuffle(total_inventory) world.random.shuffle(total_inventory)
@ -519,14 +522,14 @@ price_blacklist = {
price_chart = { price_chart = {
ShopPriceType.Rupees: lambda p: p, ShopPriceType.Rupees: lambda p: p,
ShopPriceType.Hearts: lambda p: min(1, p // 5) * 4, ShopPriceType.Hearts: lambda p: min(5, p // 5) * 8, # Each heart is 0x8 in memory, Max of 5 hearts (20 total??)
ShopPriceType.Magic: lambda p: min(8, p // 5) * 4, ShopPriceType.Magic: lambda p: min(15, p // 5) * 8, # Each pip is 0x8 in memory, Max of 15 pips (16 total...)
ShopPriceType.Bombs: lambda p: min(10, p // 5), ShopPriceType.Bombs: lambda p: max(1, min(10, p // 5)), # 10 Bombs max
ShopPriceType.Arrows: lambda p: min(30, p // 5), ShopPriceType.Arrows: lambda p: max(1, min(30, p // 5)), # 30 Arrows Max
ShopPriceType.HeartContainer: lambda p: 0x8, ShopPriceType.HeartContainer: lambda p: 0x8,
ShopPriceType.BombUpgrade: lambda p: 0x1, ShopPriceType.BombUpgrade: lambda p: 0x1,
ShopPriceType.ArrowUpgrade: lambda p: 0x1, ShopPriceType.ArrowUpgrade: lambda p: 0x1,
ShopPriceType.Keys: lambda p: min(3, (p // 100) + 1), ShopPriceType.Keys: lambda p: min(3, (p // 100) + 1), # Max of 3 keys for a price
ShopPriceType.Potion: lambda p: (p // 5) % 5, ShopPriceType.Potion: lambda p: (p // 5) % 5,
} }
@ -535,6 +538,13 @@ price_type_display_name = {
ShopPriceType.Hearts: "Hearts", ShopPriceType.Hearts: "Hearts",
ShopPriceType.Bombs: "Bombs", ShopPriceType.Bombs: "Bombs",
ShopPriceType.Arrows: "Arrows", ShopPriceType.Arrows: "Arrows",
ShopPriceType.Keys: "Keys",
}
# price division
price_rate_display = {
ShopPriceType.Hearts: 8,
ShopPriceType.Magic: 8,
} }
# prices with no? logic requirements # prices with no? logic requirements
@ -543,20 +553,34 @@ simple_price_types = [
ShopPriceType.Hearts, ShopPriceType.Hearts,
ShopPriceType.Bombs, ShopPriceType.Bombs,
ShopPriceType.Arrows, ShopPriceType.Arrows,
ShopPriceType.Keys
] ]
def price_to_funny_price(item: dict, world, player: int): def price_to_funny_price(item: dict, world, player: int):
"""
Converts a raw Rupee price into a special price type
"""
if item: if item:
my_price_types = simple_price_types.copy() my_price_types = simple_price_types.copy()
world.random.shuffle(my_price_types) world.random.shuffle(my_price_types)
for p in my_price_types: for p_type in my_price_types:
if p in [ShopPriceType.Rupees, ShopPriceType.BombUpgrade, ShopPriceType.ArrowUpgrade] or ( # Ignore rupee prices, logic-based prices or Keys (if we're not on universal keys)
p in [ShopPriceType.Keys] and world.smallkey_shuffle[player] == smallkey_shuffle.option_universal): if p_type in [ShopPriceType.Rupees, ShopPriceType.BombUpgrade, ShopPriceType.ArrowUpgrade]:
return return
if any(x in item['item'] for x in price_blacklist[p]): # If we're using keys...
# Check if we're in universal, check if our replacement isn't a Small Key
# Check if price isn't super small... (this will ideally be handled in a future table)
if p_type in [ShopPriceType.Keys]:
if world.smallkey_shuffle[player] != smallkey_shuffle.option_universal:
continue
elif item['replacement'] and 'Small Key' in item['replacement']:
continue
if item['price'] < 50:
continue
if any(x in item['item'] for x in price_blacklist[p_type]):
continue continue
else: else:
item['price'] = price_chart[p](item['price']) item['price'] = min(price_chart[p_type](item['price']) , 255)
item['price_type'] = p item['price_type'] = p_type
break break