Shop location sram offsets now fully static.

This commit is contained in:
CaitSith2 2021-01-22 07:08:50 -08:00
parent 50888eaa6b
commit a2eb666ae9
4 changed files with 27 additions and 29 deletions

View File

@ -2,7 +2,7 @@ from collections import namedtuple
import logging import logging
from BaseClasses import Region, RegionType, Location from BaseClasses import Region, RegionType, Location
from Shops import ShopType, Shop, TakeAny from Shops import ShopType, Shop, TakeAny, total_shop_slots
from Bosses import place_bosses from Bosses import place_bosses
from Dungeons import get_dungeon_item_pool from Dungeons import get_dungeon_item_pool
from EntranceShuffle import connect_entrance from EntranceShuffle import connect_entrance
@ -563,7 +563,7 @@ def set_up_take_anys(world, player):
entrance = world.get_region(reg, player).entrances[0] entrance = world.get_region(reg, player).entrances[0]
connect_entrance(world, entrance.name, old_man_take_any.name, player) connect_entrance(world, entrance.name, old_man_take_any.name, player)
entrance.target = 0x58 entrance.target = 0x58
old_man_take_any.shop = TakeAny(old_man_take_any, 0x0112, 0xE2, True, True) old_man_take_any.shop = TakeAny(old_man_take_any, 0x0112, 0xE2, True, True, total_shop_slots)
world.shops.append(old_man_take_any.shop) world.shops.append(old_man_take_any.shop)
swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player] swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player]
@ -585,7 +585,7 @@ def set_up_take_anys(world, player):
entrance = world.get_region(reg, player).entrances[0] entrance = world.get_region(reg, player).entrances[0]
connect_entrance(world, entrance.name, take_any.name, player) connect_entrance(world, entrance.name, take_any.name, player)
entrance.target = target entrance.target = target
take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True) take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True, total_shop_slots + num + 1)
world.shops.append(take_any.shop) world.shops.append(take_any.shop)
take_any.shop.add_inventory(0, 'Blue Potion', 0, 0) take_any.shop.add_inventory(0, 'Blue Potion', 0, 0)
take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0) take_any.shop.add_inventory(1, 'Boss Heart Container', 0, 0)

View File

@ -562,7 +562,7 @@ def copy_dynamic_regions_and_locations(world, ret):
if region.shop: if region.shop:
new_reg.shop = region.shop.__class__(new_reg, region.shop.room_id, region.shop.shopkeeper_config, new_reg.shop = region.shop.__class__(new_reg, region.shop.room_id, region.shop.shopkeeper_config,
region.shop.custom, region.shop.locked) region.shop.custom, region.shop.locked, region.shop.sram_offset)
ret.shops.append(new_reg.shop) ret.shops.append(new_reg.shop)
for location in world.dynamic_locations: for location in world.dynamic_locations:

9
Rom.py
View File

@ -1552,22 +1552,17 @@ def patch_race_rom(rom, world, player):
def write_custom_shops(rom, world, player): def write_custom_shops(rom, world, player):
shops = sorted([shop for shop in world.shops if shop.custom and shop.region.player == player], shops = sorted([shop for shop in world.shops if shop.custom and shop.region.player == player],
key=lambda shop: shop.region.name) key=lambda shop: shop.sram_offset)
shop_data = bytearray() shop_data = bytearray()
items_data = bytearray() items_data = bytearray()
sram_offset = 0
for shop_id, shop in enumerate(shops): for shop_id, shop in enumerate(shops):
if shop_id == len(shops) - 1: if shop_id == len(shops) - 1:
shop_id = 0xFF shop_id = 0xFF
bytes = shop.get_bytes() bytes = shop.get_bytes()
bytes[0] = shop_id bytes[0] = shop_id
bytes[-1] = sram_offset bytes[-1] = shop.sram_offset
if shop.type == ShopType.TakeAny:
sram_offset += 1
else:
sram_offset += 3
shop_data.extend(bytes) shop_data.extend(bytes)
# [id][item][price-low][price-high][max][repl_id][repl_price-low][repl_price-high][player] # [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:

View File

@ -23,13 +23,14 @@ class Shop():
blacklist: Set[str] = set() # items that don't work, todo: actually check against this blacklist: Set[str] = set() # items that don't work, todo: actually check against this
type = ShopType.Shop type = ShopType.Shop
def __init__(self, region, room_id: int, shopkeeper_config: int, custom: bool, locked: bool): def __init__(self, region, room_id: int, shopkeeper_config: int, custom: bool, locked: bool, sram_offset: int):
self.region = region self.region = region
self.room_id = room_id self.room_id = room_id
self.inventory: List[Optional[dict]] = [None] * self.slots self.inventory: List[Optional[dict]] = [None] * self.slots
self.shopkeeper_config = shopkeeper_config self.shopkeeper_config = shopkeeper_config
self.custom = custom self.custom = custom
self.locked = locked self.locked = locked
self.sram_offset = sram_offset
@property @property
def item_count(self) -> int: def item_count(self) -> int:
@ -226,7 +227,7 @@ def create_shops(world, player: int):
new_basic_shop = world.random.sample(default_shop_table, k=3) new_basic_shop = world.random.sample(default_shop_table, k=3)
new_dark_shop = world.random.sample(default_shop_table, k=3) new_dark_shop = world.random.sample(default_shop_table, k=3)
for name, shop in player_shop_table.items(): for name, shop in player_shop_table.items():
typ, shop_id, keeper, custom, locked, items = shop typ, shop_id, keeper, custom, locked, items, sram_offset = shop
if not locked: if not locked:
new_items = world.random.sample(default_shop_table, k=3) new_items = world.random.sample(default_shop_table, k=3)
if 'f' not in option: if 'f' not in option:
@ -235,13 +236,13 @@ def create_shops(world, player: int):
elif items == _dark_world_shop_defaults: elif items == _dark_world_shop_defaults:
new_items = new_dark_shop new_items = new_dark_shop
keeper = world.random.choice([0xA0, 0xC1, 0xFF]) keeper = world.random.choice([0xA0, 0xC1, 0xFF])
player_shop_table[name] = ShopData(typ, shop_id, keeper, custom, locked, new_items) player_shop_table[name] = ShopData(typ, shop_id, keeper, custom, locked, new_items, sram_offset)
if world.mode[player] == "inverted": if world.mode[player] == "inverted":
player_shop_table["Dark Lake Hylia Shop"] = \ player_shop_table["Dark Lake Hylia Shop"] = \
player_shop_table["Dark Lake Hylia Shop"]._replace(locked=True, items=_inverted_hylia_shop_defaults) player_shop_table["Dark Lake Hylia Shop"]._replace(locked=True, items=_inverted_hylia_shop_defaults)
for region_name, (room_id, type, shopkeeper, custom, locked, inventory) in player_shop_table.items(): for region_name, (room_id, type, shopkeeper, custom, locked, inventory, sram_offset) in player_shop_table.items():
region = world.get_region(region_name, player) region = world.get_region(region_name, player)
shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked) shop: Shop = shop_class_mapping[type](region, room_id, shopkeeper, custom, locked, sram_offset)
region.shop = shop region.shop = shop
world.shops.append(shop) world.shops.append(shop)
for index, item in enumerate(inventory): for index, item in enumerate(inventory):
@ -270,28 +271,29 @@ class ShopData(NamedTuple):
custom: bool custom: bool
locked: bool locked: bool
items: List items: List
sram_offset: int
# (type, room_id, shopkeeper, custom, locked, [items]) # (type, room_id, shopkeeper, custom, locked, [items], sram_offset)
# item = (item, price, max=0, replacement=None, replacement_price=0) # item = (item, price, max=0, replacement=None, replacement_price=0)
_basic_shop_defaults = [('Red Potion', 150), ('Small Heart', 10), ('Bombs (10)', 50)] _basic_shop_defaults = [('Red Potion', 150), ('Small Heart', 10), ('Bombs (10)', 50)]
_dark_world_shop_defaults = [('Red Potion', 150), ('Blue Shield', 50), ('Bombs (10)', 50)] _dark_world_shop_defaults = [('Red Potion', 150), ('Blue Shield', 50), ('Bombs (10)', 50)]
_inverted_hylia_shop_defaults = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)] _inverted_hylia_shop_defaults = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)]
shop_table: Dict[str, ShopData] = { shop_table: Dict[str, ShopData] = {
'Cave Shop (Dark Death Mountain)': ShopData(0x0112, ShopType.Shop, 0xC1, True, False, _basic_shop_defaults), 'Cave Shop (Dark Death Mountain)': ShopData(0x0112, ShopType.Shop, 0xC1, True, False, _basic_shop_defaults, 0),
'Red Shield Shop': ShopData(0x0110, ShopType.Shop, 0xC1, True, False, 'Red Shield Shop': ShopData(0x0110, ShopType.Shop, 0xC1, True, False,
[('Red Shield', 500), ('Bee', 10), ('Arrows (10)', 30)]), [('Red Shield', 500), ('Bee', 10), ('Arrows (10)', 30)], 3),
'Dark Lake Hylia Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults), 'Dark Lake Hylia Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults, 6),
'Dark World Lumberjack Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults), 'Dark World Lumberjack Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults, 9),
'Village of Outcasts Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults), 'Village of Outcasts Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults, 12),
'Dark World Potion Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults), 'Dark World Potion Shop': ShopData(0x010F, ShopType.Shop, 0xC1, True, False, _dark_world_shop_defaults, 15),
'Light World Death Mountain Shop': ShopData(0x00FF, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults), 'Light World Death Mountain Shop': ShopData(0x00FF, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults, 18),
'Kakariko Shop': ShopData(0x011F, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults), 'Kakariko Shop': ShopData(0x011F, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults, 21),
'Cave Shop (Lake Hylia)': ShopData(0x0112, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults), 'Cave Shop (Lake Hylia)': ShopData(0x0112, ShopType.Shop, 0xA0, True, False, _basic_shop_defaults, 24),
'Potion Shop': ShopData(0x0109, ShopType.Shop, 0xA0, True, True, 'Potion Shop': ShopData(0x0109, ShopType.Shop, 0xA0, True, True,
[('Red Potion', 120), ('Green Potion', 60), ('Blue Potion', 160)]), [('Red Potion', 120), ('Green Potion', 60), ('Blue Potion', 160)], 27),
'Capacity Upgrade': ShopData(0x0115, ShopType.UpgradeShop, 0x04, True, True, 'Capacity Upgrade': ShopData(0x0115, ShopType.UpgradeShop, 0x04, True, True,
[('Bomb Upgrade (+5)', 100, 7), ('Arrow Upgrade (+5)', 100, 7)]) [('Bomb Upgrade (+5)', 100, 7), ('Arrow Upgrade (+5)', 100, 7)], 30)
} }
total_shop_slots = len(shop_table) * 3 total_shop_slots = len(shop_table) * 3
@ -299,7 +301,8 @@ total_dynamic_shop_slots = sum(3 for shopname, data in shop_table.items() if not
SHOP_ID_START = 0x400000 SHOP_ID_START = 0x400000
shop_table_by_location_id = {cnt: s for cnt, s in enumerate( shop_table_by_location_id = {cnt: s for cnt, s in enumerate(
(f"{name} Slot {num}" for name in sorted(shop_table) for num in range(1, 4)), start=SHOP_ID_START)} (f"{name} Slot {num}" for name in [key for key, value in sorted(shop_table.items(), key=lambda item: item[1].sram_offset)]
for num in range(1, 4)), start=SHOP_ID_START)}
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots)] = "Old Man Sword Cave" shop_table_by_location_id[(SHOP_ID_START + total_shop_slots)] = "Old Man Sword Cave"
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 1)] = "Take-Any #1" shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 1)] = "Take-Any #1"
shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 2)] = "Take-Any #2" shop_table_by_location_id[(SHOP_ID_START + total_shop_slots + 2)] = "Take-Any #2"