Added Multiworld Support for Bonk Drops

This commit is contained in:
codemann8
2022-07-24 16:21:21 -05:00
parent a97ee6c57a
commit 9ef8f54e5b
4 changed files with 61 additions and 48 deletions

View File

@@ -507,7 +507,7 @@ def create_dynamic_shop_locations(world, player):
def create_dynamic_bonkdrop_locations(world, player): def create_dynamic_bonkdrop_locations(world, player):
from Regions import bonk_prize_table from Regions import bonk_prize_table
for bonk_location, (_, _, _, region_name, hint_text) in bonk_prize_table.items(): for bonk_location, (_, _, _, _, region_name, hint_text) in bonk_prize_table.items():
region = world.get_region(region_name, player) region = world.get_region(region_name, player)
loc = Location(player, bonk_location, 0, region, hint_text) loc = Location(player, bonk_location, 0, region, hint_text)
loc.type = LocationType.Bonk loc.type = LocationType.Bonk

View File

@@ -929,14 +929,22 @@ async def track_locations(ctx : Context, roomid, roomdata):
ow_unchecked = {} ow_unchecked = {}
for location, screenid in location_table_ow.items(): for location, screenid in location_table_ow.items():
if location not in ctx.locations_checked: if location not in ctx.locations_checked:
ow_unchecked[location] = screenid ow_unchecked[location] = (screenid, 0x40)
ow_begin = min(ow_begin, screenid)
ow_end = max(ow_end, screenid + 1)
from Regions import bonk_prize_table
from OWEdges import OWTileRegions
for location, (_, flag, _, _, region_name, _) in bonk_prize_table.items():
if location not in ctx.locations_checked:
screenid = OWTileRegions[region_name]
ow_unchecked[location] = (screenid, flag)
ow_begin = min(ow_begin, screenid) ow_begin = min(ow_begin, screenid)
ow_end = max(ow_end, screenid + 1) ow_end = max(ow_end, screenid + 1)
if ow_begin < ow_end: if ow_begin < ow_end:
ow_data = await snes_read(ctx, SAVEDATA_START + 0x280 + ow_begin, ow_end - ow_begin) ow_data = await snes_read(ctx, SAVEDATA_START + 0x280 + ow_begin, ow_end - ow_begin)
if ow_data is not None: if ow_data is not None:
for location, screenid in ow_unchecked.items(): for location, (screenid, flag) in ow_unchecked.items():
if ow_data[screenid - ow_begin] & 0x40 != 0: if ow_data[screenid - ow_begin] & flag != 0:
new_check(location) new_check(location)
if not all([location in ctx.locations_checked for location in location_table_npc.keys()]): if not all([location in ctx.locations_checked for location in location_table_npc.keys()]):

View File

@@ -1266,52 +1266,55 @@ def pot_address(pot_index, super_tile):
return 0x7f6018 + super_tile * 2 + (pot_index << 24) return 0x7f6018 + super_tile * 2 + (pot_index << 24)
# bonk location: record id, aga required, default item, region, hint text # bonk location: record id, OW flag bitmask, aga required, default item, region, hint text
bonk_prize_table = { bonk_prize_table = {
'Lost Woods Hideout Tree': (0x00, False, '', 'Lost Woods East Area', 'in a tree'), 'Lost Woods Hideout Tree': (0x00, 0x10, False, '', 'Lost Woods East Area', 'in a tree'),
'Death Mountain Bonk Rocks': (0x01, False, '', 'East Death Mountain (Top East)', 'encased in stone'), 'Death Mountain Bonk Rocks': (0x01, 0x10, False, '', 'East Death Mountain (Top East)', 'encased in stone'),
'Mountain Entry Pull Tree': (0x02, False, '', 'Mountain Entry Area', 'in a tree'), 'Mountain Entry Pull Tree': (0x02, 0x10, False, '', 'Mountain Entry Area', 'in a tree'),
'Mountain Entry Southeast Tree': (0x03, False, '', 'Mountain Entry Area', 'in a tree'), 'Mountain Entry Southeast Tree': (0x03, 0x08, False, '', 'Mountain Entry Area', 'in a tree'),
'Lost Woods Pass West Tree': (0x04, False, '', 'Lost Woods Pass West Area', 'in a tree'), 'Lost Woods Pass West Tree': (0x04, 0x10, False, '', 'Lost Woods Pass West Area', 'in a tree'),
'Kakariko Portal Tree': (0x05, False, '', 'Lost Woods Pass East Top Area', 'in a tree'), 'Kakariko Portal Tree': (0x05, 0x08, False, '', 'Lost Woods Pass East Top Area', 'in a tree'),
'Fortune Bonk Rocks': (0x06, False, '', 'Kakariko Fortune Area', 'in a tree'), 'Fortune Bonk Rocks': (0x06, 0x10, False, '', 'Kakariko Fortune Area', 'in a tree'),
'Kakariko Pond Tree': (0x07, True, '', 'Kakariko Pond Area', 'in a tree'), 'Kakariko Pond Tree': (0x07, 0x10, True, '', 'Kakariko Pond Area', 'in a tree'),
'Bonk Rocks Tree': (0x08, True, '', 'Bonk Rock Ledge', 'in a tree'), 'Bonk Rocks Tree': (0x08, 0x10, True, '', 'Bonk Rock Ledge', 'in a tree'),
'Sanctuary Tree': (0x09, False, '', 'Sanctuary Area', 'in a tree'), 'Sanctuary Tree': (0x09, 0x08, False, '', 'Sanctuary Area', 'in a tree'),
'River Bend West Tree': (0x0a, True, '', 'River Bend Area', 'in a tree'), 'River Bend West Tree': (0x0a, 0x10, True, '', 'River Bend Area', 'in a tree'),
'River Bend East Tree': (0x0b, False, '', 'River Bend East Bank', 'in a tree'), 'River Bend East Tree': (0x0b, 0x08, False, '', 'River Bend East Bank', 'in a tree'),
'Blinds Hideout Tree': (0x0c, False, '', 'Kakariko Area', 'in a tree'), 'Blinds Hideout Tree': (0x0c, 0x10, False, '', 'Kakariko Area', 'in a tree'),
'Kakariko Welcome Tree': (0x0d, False, '', 'Kakariko Area', 'in a tree'), 'Kakariko Welcome Tree': (0x0d, 0x08, False, '', 'Kakariko Area', 'in a tree'),
'Forgotten Forest Southwest Tree': (0x0e, False, '', 'Forgotten Forest Area', 'in a tree'), 'Forgotten Forest Southwest Tree': (0x0e, 0x10, False, '', 'Forgotten Forest Area', 'in a tree'),
'Forgotten Forest Central Tree': (0x0f, False, '', 'Forgotten Forest Area', 'in a tree'), 'Forgotten Forest Central Tree': (0x0f, 0x08, False, '', 'Forgotten Forest Area', 'in a tree'),
#'Forgotten Forest Southeast Tree': (0x??, False, '', 'Forgotten Forest Area', 'in a tree'), #'Forgotten Forest Southeast Tree': (0x??, 0x04, False, '', 'Forgotten Forest Area', 'in a tree'),
'Hyrule Castle Tree': (0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'), 'Hyrule Castle Tree': (0x10, 0x10, False, '', 'Hyrule Castle Courtyard', 'in a tree'),
'Wooden Bridge Tree': (0x11, False, '', 'Wooden Bridge Area', 'in a tree'), 'Wooden Bridge Tree': (0x11, 0x10, False, '', 'Wooden Bridge Area', 'in a tree'),
'Eastern Palace Tree': (0x12, True, '', 'Eastern Palace Area', 'in a tree'), 'Eastern Palace Tree': (0x12, 0x10, True, '', 'Eastern Palace Area', 'in a tree'),
'Flute Boy South Tree': (0x13, True, '', 'Flute Boy Area', 'in a tree'), 'Flute Boy South Tree': (0x13, 0x10, True, '', 'Flute Boy Area', 'in a tree'),
'Flute Boy East Tree': (0x14, True, '', 'Flute Boy Area', 'in a tree'), 'Flute Boy East Tree': (0x14, 0x08, True, '', 'Flute Boy Area', 'in a tree'),
'Central Bonk Rocks Tree': (0x15, False, '', 'Central Bonk Rocks Area', 'in a tree'), 'Central Bonk Rocks Tree': (0x15, 0x10, False, '', 'Central Bonk Rocks Area', 'in a tree'),
'Tree Line Tree 2': (0x16, True, '', 'Tree Line Area', 'in a tree'), 'Tree Line Tree 2': (0x16, 0x10, True, '', 'Tree Line Area', 'in a tree'),
'Tree Line Tree 4': (0x17, True, '', 'Tree Line Area', 'in a tree'), 'Tree Line Tree 4': (0x17, 0x08, True, '', 'Tree Line Area', 'in a tree'),
'Flute Boy Approach South Tree': (0x18, False, '', 'Flute Boy Approach Area', 'in a tree'), 'Flute Boy Approach South Tree': (0x18, 0x10, False, '', 'Flute Boy Approach Area', 'in a tree'),
'Flute Boy Approach North Tree': (0x19, False, '', 'Flute Boy Approach Area', 'in a tree'), 'Flute Boy Approach North Tree': (0x19, 0x08, False, '', 'Flute Boy Approach Area', 'in a tree'),
'Dark Lumberjack Tree': (0x1a, False, '', 'Dark Lumberjack Area', 'in a tree'), 'Dark Lumberjack Tree': (0x1a, 0x10, False, '', 'Dark Lumberjack Area', 'in a tree'),
'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, False, '', 'Dark Fortune Area', 'encased in stone'), 'Dark Fortune Bonk Rocks (Drop 1)': (0x1b, 0x10, False, '', 'Dark Fortune Area', 'encased in stone'),
'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, False, '', 'Dark Fortune Area', 'encased in stone'), 'Dark Fortune Bonk Rocks (Drop 2)': (0x1c, 0x08, False, '', 'Dark Fortune Area', 'encased in stone'),
'Dark Graveyard West Bonk Rocks': (0x1d, False, '', 'Dark Graveyard Area', 'encased in stone'), 'Dark Graveyard West Bonk Rocks': (0x1d, 0x10, False, '', 'Dark Graveyard Area', 'encased in stone'),
'Dark Graveyard North Bonk Rocks': (0x1e, False, '', 'Dark Graveyard North', 'encased in stone'), 'Dark Graveyard North Bonk Rocks': (0x1e, 0x08, False, '', 'Dark Graveyard North', 'encased in stone'),
'Dark Graveyard Tomb Bonk Rocks': (0x1f, False, '', 'Dark Graveyard North', 'encased in stone'), 'Dark Graveyard Tomb Bonk Rocks': (0x1f, 0x04, False, '', 'Dark Graveyard North', 'encased in stone'),
'Qirn Jump West Tree': (0x20, False, '', 'Qirn Jump Area', 'in a tree'), 'Qirn Jump West Tree': (0x20, 0x10, False, '', 'Qirn Jump Area', 'in a tree'),
'Qirn Jump East Tree': (0x21, False, '', 'Qirn Jump East Bank', 'in a tree'), 'Qirn Jump East Tree': (0x21, 0x08, False, '', 'Qirn Jump East Bank', 'in a tree'),
'Dark Witch Tree': (0x22, False, '', 'Dark Witch Area', 'in a tree'), 'Dark Witch Tree': (0x22, 0x10, False, '', 'Dark Witch Area', 'in a tree'),
'Pyramid Tree': (0x23, False, '', 'Pyramid Area', 'in a tree'), 'Pyramid Tree': (0x23, 0x10, False, '', 'Pyramid Area', 'in a tree'),
'Palace of Darkness Tree': (0x24, False, '', 'Palace of Darkness Area', 'in a tree'), 'Palace of Darkness Tree': (0x24, 0x10, False, '', 'Palace of Darkness Area', 'in a tree'),
'Dark Tree Line Tree 2': (0x25, False, '', 'Dark Tree Line Area', 'in a tree'), 'Dark Tree Line Tree 2': (0x25, 0x10, False, '', 'Dark Tree Line Area', 'in a tree'),
'Dark Tree Line Tree 3': (0x26, False, '', 'Dark Tree Line Area', 'in a tree'), 'Dark Tree Line Tree 3': (0x26, 0x08, False, '', 'Dark Tree Line Area', 'in a tree'),
'Dark Tree Line Tree 4': (0x27, False, '', 'Dark Tree Line Area', 'in a tree'), 'Dark Tree Line Tree 4': (0x27, 0x04, False, '', 'Dark Tree Line Area', 'in a tree'),
'Hype Cave Statue': (0x28, False, '', 'Hype Cave Area', 'encased in stone') 'Hype Cave Statue': (0x28, 0x10, False, '', 'Hype Cave Area', 'encased in stone')
} }
bonk_table_by_location_id = {0x153B00+(data[0]*6)+3: name for name, data in bonk_prize_table.items()}
bonk_table_by_location = {y: x for x, y in bonk_table_by_location_id.items()}
# (room_id, type, shopkeeper, custom, locked, [items]) # (room_id, type, shopkeeper, custom, locked, [items])
# item = (item, price, max=0, replacement=None, replacement_price=0) # item = (item, price, max=0, replacement=None, replacement_price=0)
@@ -1662,5 +1665,7 @@ 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 = {data[0]: name for name, data in location_table.items() if type(data[0]) == int}
lookup_id_to_name.update(shop_table_by_location_id) lookup_id_to_name.update(shop_table_by_location_id)
lookup_id_to_name.update(bonk_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 = {name: data[0] for name, data in location_table.items() if type(data[0]) == int}
lookup_name_to_id.update(shop_table_by_location) lookup_name_to_id.update(shop_table_by_location)
lookup_name_to_id.update(bonk_table_by_location)

View File

@@ -827,7 +827,7 @@ def default_rules(world, player):
if world.shuffle_bonk_drops[player]: if world.shuffle_bonk_drops[player]:
if world.get_region('Big Bomb Shop', player).entrances: # just some location that is placed late in the ER algorithm, prevent standard rules from applying when trying to search reachability in the overworld if world.get_region('Big Bomb Shop', player).entrances: # just some location that is placed late in the ER algorithm, prevent standard rules from applying when trying to search reachability in the overworld
from Regions import bonk_prize_table from Regions import bonk_prize_table
for location_name, (_, aga_required, _, _, _) in bonk_prize_table.items(): for location_name, (_, _, aga_required, _, _, _) in bonk_prize_table.items():
loc = world.get_location(location_name, player) loc = world.get_location(location_name, player)
set_rule(loc, lambda state: (state.can_collect_bonkdrops(player)) and (not aga_required or state.has_beaten_aga(player))) set_rule(loc, lambda state: (state.can_collect_bonkdrops(player)) and (not aga_required or state.has_beaten_aga(player)))
add_bunny_rule(loc, player) add_bunny_rule(loc, player)