Refactor some shop code
This commit is contained in:
parent
a39459e9fc
commit
6d38e87527
|
@ -1056,38 +1056,39 @@ class ShopType(Enum):
|
||||||
TakeAny = 1
|
TakeAny = 1
|
||||||
UpgradeShop = 2
|
UpgradeShop = 2
|
||||||
|
|
||||||
class Shop(object):
|
class Shop():
|
||||||
slots = 3
|
slots = 3 # slot count is not dynamic in asm, however inventory can have None as empty slots
|
||||||
|
blacklist = set() # items that don't work, todo: actually check against this
|
||||||
|
type = ShopType.Shop
|
||||||
|
|
||||||
def __init__(self, region, room_id, type, shopkeeper_config, custom, locked: bool):
|
def __init__(self, region: Region, room_id: int, shopkeeper_config: int, custom: bool, locked: bool):
|
||||||
self.region = region
|
self.region = region
|
||||||
self.room_id = room_id
|
self.room_id = room_id
|
||||||
self.type = type
|
self.inventory: List[Union[None, dict]] = [None] * self.slots
|
||||||
self.inventory: List[Union[None, dict]] = [None, None, None]
|
|
||||||
self.shopkeeper_config = shopkeeper_config
|
self.shopkeeper_config = shopkeeper_config
|
||||||
self.custom = custom
|
self.custom = custom
|
||||||
self.locked = locked
|
self.locked = locked
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def item_count(self):
|
def item_count(self) -> int:
|
||||||
return (3 if self.inventory[2] else
|
for x in range(self.slots - 1, -1, -1): # last x is 0
|
||||||
2 if self.inventory[1] else
|
if self.inventory[x]:
|
||||||
1 if self.inventory[0] else
|
return x + 1
|
||||||
0)
|
return 0
|
||||||
|
|
||||||
def get_bytes(self):
|
def get_bytes(self) -> List[int]:
|
||||||
# [id][roomID-low][roomID-high][doorID][zero][shop_config][shopkeeper_config][sram_index]
|
# [id][roomID-low][roomID-high][doorID][zero][shop_config][shopkeeper_config][sram_index]
|
||||||
entrances = self.region.entrances
|
entrances = self.region.entrances
|
||||||
config = self.item_count
|
config = self.item_count
|
||||||
if len(entrances) == 1 and entrances[0].name in door_addresses:
|
if len(entrances) == 1 and entrances[0].name in door_addresses:
|
||||||
door_id = door_addresses[entrances[0].name][0]+1
|
door_id = door_addresses[entrances[0].name][0] + 1
|
||||||
else:
|
else:
|
||||||
door_id = 0
|
door_id = 0
|
||||||
config |= 0x40 # ignore door id
|
config |= 0x40 # ignore door id
|
||||||
if self.type == ShopType.TakeAny:
|
if self.type == ShopType.TakeAny:
|
||||||
config |= 0x80
|
config |= 0x80
|
||||||
if self.type == ShopType.UpgradeShop:
|
elif self.type == ShopType.UpgradeShop:
|
||||||
config |= 0x10 # Alt. VRAM
|
config |= 0x10 # Alt. VRAM
|
||||||
return [0x00]+int16_as_bytes(self.room_id)+[door_id, 0x00, config, self.shopkeeper_config, 0x00]
|
return [0x00]+int16_as_bytes(self.room_id)+[door_id, 0x00, config, self.shopkeeper_config, 0x00]
|
||||||
|
|
||||||
def has_unlimited(self, item: str) -> bool:
|
def has_unlimited(self, item: str) -> bool:
|
||||||
|
@ -1111,7 +1112,7 @@ class Shop(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def clear_inventory(self):
|
def clear_inventory(self):
|
||||||
self.inventory = [None, None, None]
|
self.inventory = [None] * self.slots
|
||||||
|
|
||||||
def add_inventory(self, slot: int, item: str, price: int, max: int = 0,
|
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):
|
replacement: Optional[str] = None, replacement_price: int = 0, create_location: bool = False):
|
||||||
|
@ -1137,8 +1138,21 @@ class Shop(object):
|
||||||
'create_location': self.inventory[slot]["create_location"]
|
'create_location': self.inventory[slot]["create_location"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TakeAny(Shop):
|
||||||
|
type = ShopType.TakeAny
|
||||||
|
|
||||||
|
|
||||||
|
class UpgradeShop(Shop):
|
||||||
|
type = ShopType.UpgradeShop
|
||||||
|
# Potions break due to VRAM flags set in UpgradeShop.
|
||||||
|
# Didn't check for more things breaking as not much else can be shuffled here currently
|
||||||
|
blacklist = item_name_groups["Potions"]
|
||||||
|
|
||||||
|
|
||||||
class Spoiler(object):
|
class Spoiler(object):
|
||||||
world: World
|
world: World
|
||||||
|
|
||||||
def __init__(self, world):
|
def __init__(self, world):
|
||||||
self.world = world
|
self.world = world
|
||||||
self.hashes = {}
|
self.hashes = {}
|
||||||
|
|
30
ItemPool.py
30
ItemPool.py
|
@ -1,7 +1,7 @@
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import Region, RegionType, Shop, ShopType, Location
|
from BaseClasses import Region, RegionType, ShopType, Location, TakeAny
|
||||||
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
|
||||||
|
@ -350,27 +350,31 @@ def shuffle_shops(world, items, player: int):
|
||||||
|
|
||||||
if 'p' in option or 'i' in option:
|
if 'p' in option or 'i' in option:
|
||||||
shops = []
|
shops = []
|
||||||
|
upgrade_shops = []
|
||||||
total_inventory = []
|
total_inventory = []
|
||||||
for shop in world.shops:
|
for shop in world.shops:
|
||||||
if shop.type == ShopType.Shop and shop.region.player == player and shop.region.name != 'Potion Shop':
|
if shop.region.player == player:
|
||||||
shops.append(shop)
|
if shop.type == ShopType.UpgradeShop:
|
||||||
total_inventory.extend(shop.inventory)
|
upgrade_shops.append(shop)
|
||||||
|
elif shop.type == ShopType.Shop and shop.region.name != 'Potion Shop':
|
||||||
|
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:
|
||||||
# it is important that a base price of 0 always returns 0 as new price!
|
# it is important that a base price of 0 always returns 0 as new price!
|
||||||
return int(price * (0.5 + world.random.random() * 2))
|
return int(price * (0.5 + world.random.random() * 2))
|
||||||
|
|
||||||
for item in total_inventory:
|
def adjust_item(item):
|
||||||
if item:
|
if item:
|
||||||
item["price"] = price_adjust(item["price"])
|
item["price"] = price_adjust(item["price"])
|
||||||
item['replacement_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 total_inventory:
|
||||||
for item in shop.inventory:
|
adjust_item(item)
|
||||||
if item:
|
for shop in upgrade_shops:
|
||||||
item['price'] = price_adjust(item["price"])
|
for item in shop.inventory:
|
||||||
item['replacement_price'] = price_adjust(item["price"])
|
adjust_item(item)
|
||||||
|
|
||||||
if 'i' in option:
|
if 'i' in option:
|
||||||
world.random.shuffle(total_inventory)
|
world.random.shuffle(total_inventory)
|
||||||
|
@ -405,7 +409,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 = Shop(old_man_take_any, 0x0112, ShopType.TakeAny, 0xE2, True, True)
|
old_man_take_any.shop = TakeAny(old_man_take_any, 0x0112, 0xE2, True, True)
|
||||||
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]
|
||||||
|
@ -427,7 +431,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 = Shop(take_any, room_id, ShopType.TakeAny, 0xE3, True, True)
|
take_any.shop = TakeAny(take_any, room_id, 0xE3, True, True)
|
||||||
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)
|
||||||
|
|
3
Main.py
3
Main.py
|
@ -425,7 +425,8 @@ def copy_dynamic_regions_and_locations(world, ret):
|
||||||
# Note: ideally exits should be copied here, but the current use case (Take anys) do not require this
|
# Note: ideally exits should be copied here, but the current use case (Take anys) do not require this
|
||||||
|
|
||||||
if region.shop:
|
if region.shop:
|
||||||
new_reg.shop = Shop(new_reg, region.shop.room_id, region.shop.type, region.shop.shopkeeper_config, region.shop.custom, region.shop.locked)
|
new_reg.shop = region.shop.__class__(new_reg, region.shop.room_id, region.shop.shopkeeper_config,
|
||||||
|
region.shop.custom, region.shop.locked)
|
||||||
ret.shops.append(new_reg.shop)
|
ret.shops.append(new_reg.shop)
|
||||||
|
|
||||||
for location in world.dynamic_locations:
|
for location in world.dynamic_locations:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from BaseClasses import Region, Location, Entrance, RegionType, Shop, ShopType
|
from BaseClasses import Region, Location, Entrance, RegionType, Shop, TakeAny, UpgradeShop, ShopType
|
||||||
|
|
||||||
|
|
||||||
def create_regions(world, player):
|
def create_regions(world, player):
|
||||||
|
@ -365,12 +365,15 @@ def mark_light_world_regions(world, player: int):
|
||||||
|
|
||||||
|
|
||||||
def create_shops(world, player: int):
|
def create_shops(world, player: int):
|
||||||
|
cls_mapping = {ShopType.UpgradeShop: UpgradeShop,
|
||||||
|
ShopType.Shop: Shop,
|
||||||
|
ShopType.TakeAny: TakeAny}
|
||||||
for region_name, (room_id, type, shopkeeper, custom, locked, inventory) in shop_table.items():
|
for region_name, (room_id, type, shopkeeper, custom, locked, inventory) in shop_table.items():
|
||||||
if world.mode[player] == 'inverted' and region_name == 'Dark Lake Hylia Shop':
|
if world.mode[player] == 'inverted' and region_name == 'Dark Lake Hylia Shop':
|
||||||
locked = True
|
locked = True
|
||||||
inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)]
|
inventory = [('Blue Potion', 160), ('Blue Shield', 50), ('Bombs (10)', 50)]
|
||||||
region = world.get_region(region_name, player)
|
region = world.get_region(region_name, player)
|
||||||
shop = Shop(region, room_id, type, shopkeeper, custom, locked)
|
shop = cls_mapping[type](region, room_id, shopkeeper, custom, locked)
|
||||||
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):
|
||||||
|
|
Loading…
Reference in New Issue