Merge branch 'shop-fill' into multishop-all
This commit is contained in:
commit
767c84a581
|
@ -342,27 +342,6 @@ class World(object):
|
|||
if collect:
|
||||
self.state.collect(item, location.event, location)
|
||||
|
||||
# TODO: Prevents fast_filling certain items. Move this to a proper filter.
|
||||
if location.parent_region.shop is not None and location.name != 'Potion Shop': # includes potion shop slots but not potion shop powder
|
||||
slot_num = int(location.name[-1]) - 1
|
||||
my_item = location.parent_region.shop.inventory[slot_num]
|
||||
if (my_item is not None and my_item['item'] == item.name) or 'Rupee' in item.name or ('Bee' in item.name and 'Trap' not in item.name):
|
||||
# this will filter items that match the item in the shop or Rupees, or single bees
|
||||
# really not a way for the player to know a renewable item from a player pool item
|
||||
# bombs can be sitting on top of arrows or a potion refill, but dunno if that's a big deal
|
||||
logging.debug('skipping item shop {}'.format(item.name))
|
||||
else:
|
||||
if my_item is None:
|
||||
location.parent_region.shop.add_inventory(slot_num, 'None', 0)
|
||||
my_item = location.parent_region.shop.inventory[slot_num]
|
||||
else:
|
||||
my_item['replacement'] = my_item['item']
|
||||
my_item['replacement_price'] = my_item['price']
|
||||
my_item['item'] = item.name
|
||||
my_item['price'] = self.random.randrange(1, 61) * 5 # can probably replace this with a price chart
|
||||
my_item['max'] = 1
|
||||
my_item['player'] = item.player if item.player != location.player else 0
|
||||
|
||||
logging.debug('Placed %s at %s', item, location)
|
||||
else:
|
||||
raise RuntimeError('Cannot assign item %s to location %s.' % (item, location))
|
||||
|
|
|
@ -470,7 +470,11 @@ def create_dynamic_shop_locations(world, player):
|
|||
if item is None:
|
||||
continue
|
||||
if item['create_location']:
|
||||
<<<<<<< HEAD
|
||||
loc = Location(player, "{} Slot Item {}".format(shop.region.name, i+1), parent=shop.region)
|
||||
=======
|
||||
loc = Location(player, "{} Shop Slot {}".format(shop.region.name, i+1), parent=shop.region)
|
||||
>>>>>>> ffe5b4b1a1d806c09a1be91a283dd3a6cdbcaafa
|
||||
shop.region.locations.append(loc)
|
||||
world.dynamic_locations.append(loc)
|
||||
|
||||
|
|
1
Main.py
1
Main.py
|
@ -306,6 +306,7 @@ def main(args, seed=None):
|
|||
main_entrance = get_entrance_to_region(region)
|
||||
for location in region.locations:
|
||||
if type(location.address) == int: # skips events and crystals
|
||||
if location.address >= 0x400000: continue
|
||||
if lookup_vanilla_location_to_entrance[location.address] != main_entrance.name:
|
||||
er_hint_data[region.player][location.address] = main_entrance.name
|
||||
|
||||
|
|
|
@ -157,6 +157,11 @@ SCOUT_LOCATION_ADDR = SAVEDATA_START + 0x4D7 # 1 byte
|
|||
SCOUTREPLY_LOCATION_ADDR = SAVEDATA_START + 0x4D8 # 1 byte
|
||||
SCOUTREPLY_ITEM_ADDR = SAVEDATA_START + 0x4D9 # 1 byte
|
||||
SCOUTREPLY_PLAYER_ADDR = SAVEDATA_START + 0x4DA # 1 byte
|
||||
SHOP_ADDR = SAVEDATA_START + 0x302 # 2 bytes
|
||||
|
||||
|
||||
location_shop_order = [ name for name, info in Regions.shop_table.items() ] # probably don't leave this here. This relies on python 3.6+ dictionary keys having defined order
|
||||
location_shop_ids = set([info[0] for name, info in Regions.shop_table.items()])
|
||||
|
||||
location_table_uw = {"Blind's Hideout - Top": (0x11d, 0x10),
|
||||
"Blind's Hideout - Left": (0x11d, 0x20),
|
||||
|
@ -1117,6 +1122,18 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||
ctx.ui_node.log_info("New check: %s (%d/216)" % (location, len(ctx.unsafe_locations_checked)))
|
||||
ctx.ui_node.send_location_check(ctx, location)
|
||||
|
||||
try:
|
||||
if roomid in location_shop_ids:
|
||||
misc_data = await snes_read(ctx, SHOP_ADDR, len(location_shop_order)*3)
|
||||
for cnt, b in enumerate(misc_data):
|
||||
my_check = Regions.shop_table_by_location_id[0x400000 + cnt]
|
||||
if int(b) > 0 and my_check not in ctx.unsafe_locations_checked:
|
||||
new_check(my_check)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
ctx.ui_node.log_info(f"Exception: {e}")
|
||||
|
||||
|
||||
for location, (loc_roomid, loc_mask) in location_table_uw.items():
|
||||
try:
|
||||
if location not in ctx.unsafe_locations_checked and loc_roomid == roomid and (roomdata << 4) & loc_mask != 0:
|
||||
|
@ -1175,7 +1192,13 @@ async def track_locations(ctx : Context, roomid, roomdata):
|
|||
for location in ctx.unsafe_locations_checked:
|
||||
if (location in ctx.items_missing and location not in ctx.locations_checked) or ctx.send_unsafe:
|
||||
ctx.locations_checked.add(location)
|
||||
new_locations.append(Regions.lookup_name_to_id[location])
|
||||
try:
|
||||
my_id = Regions.lookup_name_to_id.get(location, Regions.shop_table_by_location.get(location, -1))
|
||||
new_locations.append(my_id)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
ctx.ui_node.log_info(f"Exception: {e}")
|
||||
|
||||
|
||||
await ctx.send_msgs([['LocationChecks', new_locations]])
|
||||
|
||||
|
|
|
@ -950,7 +950,7 @@ def get_missing_checks(ctx: Context, client: Client) -> list:
|
|||
#for location_id in [k[0] for k, v in ctx.locations if k[1] == client.slot]:
|
||||
# if location_id not in ctx.location_checks[client.team, client.slot]:
|
||||
# locations.append(Regions.lookup_id_to_name.get(location_id, f'Unknown Location ID: {location_id}'))
|
||||
for location_id, location_name in Regions.lookup_id_to_name.items(): # cheat console is -1, keep in mind
|
||||
for location_id, location_name in {**Regions.lookup_id_to_name, **Regions.shop_table_by_location_id}.items(): # cheat console is -1, keep in mind
|
||||
if location_id != -1 and location_id not in ctx.location_checks[client.team, client.slot] and (location_id, client.slot) in ctx.locations:
|
||||
locations.append(location_name)
|
||||
return locations
|
||||
|
|
|
@ -418,7 +418,8 @@ def create_shops(world, player: int):
|
|||
if my_shop_slots.pop():
|
||||
additional_item = world.random.choice(['Rupees (20)', 'Rupees (50)', 'Rupees (100)'])
|
||||
world.itempool.append(ItemFactory(additional_item, player))
|
||||
loc = Location(player, "{} Slot Item {}".format(shop.region.name, index+1), parent=shop.region)
|
||||
slot_name = "{} Shop Slot {}".format(shop.region.name, index+1)
|
||||
loc = Location(player, slot_name, address=shop_table_by_location[slot_name], parent=shop.region)
|
||||
shop.region.locations.append(loc)
|
||||
world.dynamic_locations.append(loc)
|
||||
|
||||
|
@ -443,6 +444,9 @@ shop_table = {
|
|||
'Capacity Upgrade': (0x0115, ShopType.UpgradeShop, 0x04, True, True, [('Bomb Upgrade (+5)', 100, 7), ('Arrow Upgrade (+5)', 100, 7)])
|
||||
}
|
||||
|
||||
shop_table_by_location_id = {0x400000 + cnt: s for cnt, s in enumerate( [item for sublist in [ ["{} Shop Slot {}".format(name, num + 1) for num in range(3)] for name in shop_table ] for item in sublist])}
|
||||
shop_table_by_location = {y:x for x,y in shop_table_by_location_id.items()}
|
||||
|
||||
shop_generation_types = {
|
||||
'default': _basic_shop_defaults + [('Bombs (3)', 20), ('Green Potion', 90), ('Blue Potion', 190), ('Bee', 10), ('Single Arrow', 5)] + [('Red Shield', 500), ('Blue Shield', 50)],
|
||||
'potion': [('Red Potion', 150), ('Green Potion', 90), ('Blue Potion', 190)],
|
||||
|
@ -748,8 +752,10 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
|
|||
|
||||
lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
|
||||
lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}, -1: "cheat console"}
|
||||
lookup_id_to_name.update(shop_table_by_location_id)
|
||||
lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int}
|
||||
lookup_name_to_id = {**lookup_name_to_id, **{name: data[1] for name, data in key_drop_data.items()}, "cheat console": -1}
|
||||
lookup_name_to_id.update(shop_table_by_location)
|
||||
|
||||
lookup_vanilla_location_to_entrance = {1572883: 'Kings Grave Inner Rocks', 191256: 'Kings Grave Inner Rocks',
|
||||
1573194: 'Kings Grave Inner Rocks', 1573189: 'Kings Grave Inner Rocks',
|
||||
|
|
22
Rom.py
22
Rom.py
|
@ -642,6 +642,28 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
if location.address is None:
|
||||
continue
|
||||
|
||||
if 'Shop Slot' in location.name and location.parent_region.shop is not None:
|
||||
slot_num = int(location.name[-1]) - 1
|
||||
my_item = location.parent_region.shop.inventory[slot_num]
|
||||
item = location.item
|
||||
if (my_item is not None and my_item['item'] == item.name) or 'Rupee' in item.name or (item.name in ['Bee']):
|
||||
# this will filter items that match the item in the shop or Rupees, or single bees
|
||||
# really not a way for the player to know a renewable item from a player pool item
|
||||
# bombs can be sitting on top of arrows or a potion refill, but dunno if that's a big deal
|
||||
logging.debug('skipping item shop {}'.format(item.name))
|
||||
else:
|
||||
if my_item is None:
|
||||
location.parent_region.shop.add_inventory(slot_num, 'None', 0)
|
||||
my_item = location.parent_region.shop.inventory[slot_num]
|
||||
else:
|
||||
my_item['replacement'] = my_item['item']
|
||||
my_item['replacement_price'] = my_item['price']
|
||||
my_item['item'] = item.name
|
||||
my_item['price'] = world.random.randrange(1, 61) * 5 # can probably replace this with a price chart
|
||||
my_item['max'] = 1
|
||||
my_item['player'] = item.player if item.player != location.player else 0
|
||||
continue
|
||||
|
||||
if not location.crystal:
|
||||
if location.item is not None:
|
||||
# Keys in their native dungeon should use the orignal item code for keys
|
||||
|
|
|
@ -13,13 +13,13 @@ general_options:
|
|||
# Null means nothing, for the server this means to default the value
|
||||
# These overwrite command line arguments!
|
||||
server_options:
|
||||
host: null
|
||||
host: 0.0.0.0
|
||||
port: 38281
|
||||
password: null
|
||||
multidata: null
|
||||
savefile: null
|
||||
disable_save: false
|
||||
loglevel: "info"
|
||||
loglevel: "debug"
|
||||
# Allows for clients to log on and manage the server. If this is null, no remote administration is possible.
|
||||
server_password: null
|
||||
# Automatically forward the port that is used, then close that port after 24 hours
|
||||
|
@ -28,9 +28,9 @@ server_options:
|
|||
disable_item_cheat: false
|
||||
# Client hint system
|
||||
# Points given to a player for each acquired item in their world
|
||||
location_check_points: 1
|
||||
location_check_points: 50
|
||||
# Point cost to receive a hint via !hint for players
|
||||
hint_cost: 1000 # Set to 0 if you want free hints
|
||||
hint_cost: 0 # Set to 0 if you want free hints
|
||||
# Forfeit modes
|
||||
# "disabled" -> clients can't forfeit,
|
||||
# "enabled" -> clients can always forfeit
|
||||
|
|
Loading…
Reference in New Issue