Implemented Bonk Drop Shuffle

This commit is contained in:
codemann8
2022-07-24 12:50:37 -05:00
parent a5729b51a2
commit 97455dc140
12 changed files with 389 additions and 55 deletions

View File

@@ -1080,6 +1080,9 @@ class CollectionState(object):
return True return True
return False return False
def can_collect_bonkdrops(self, player):
return self.has_Boots(player) or (self.has_sword(player) and self.has('Quake', player))
def can_farm_rupees(self, player): def can_farm_rupees(self, player):
tree_pulls = ['Lost Woods East Area', tree_pulls = ['Lost Woods East Area',
'Snitch Lady (East)', 'Snitch Lady (East)',
@@ -1192,7 +1195,7 @@ class CollectionState(object):
if can_reach_non_bunny(region): if can_reach_non_bunny(region):
return True return True
if self.has_Boots(player): if not self.world.shuffle_bonk_drops[player] and self.can_collect_bonkdrops(player):
for region in bonk_bombs: for region in bonk_bombs:
if can_reach_non_bunny(region): if can_reach_non_bunny(region):
return True return True
@@ -2696,6 +2699,7 @@ class LocationType(FastEnum):
Shop = 3 Shop = 3
Pot = 4 Pot = 4
Drop = 5 Drop = 5
Bonk = 6
class Item(object): class Item(object):
@@ -2911,6 +2915,7 @@ class Spoiler(object):
'ow_mixed': self.world.owMixed, 'ow_mixed': self.world.owMixed,
'ow_whirlpool': self.world.owWhirlpoolShuffle, 'ow_whirlpool': self.world.owWhirlpoolShuffle,
'ow_fluteshuffle': self.world.owFluteShuffle, 'ow_fluteshuffle': self.world.owFluteShuffle,
'bonk_drops': self.world.shuffle_bonk_drops,
'shuffle': self.world.shuffle, 'shuffle': self.world.shuffle,
'shuffleganon': self.world.shuffle_ganon, 'shuffleganon': self.world.shuffle_ganon,
'shufflelinks': self.world.shufflelinks, 'shufflelinks': self.world.shufflelinks,
@@ -3123,6 +3128,7 @@ class Spoiler(object):
outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player])) outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player]))
outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player])) outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player]))
outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player]) outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player])
outfile.write('Bonk Drops:'.ljust(line_width) + '%s\n' % yn(self.metadata['bonk_drops'][player]))
outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player]) outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player])
if self.metadata['shuffle'][player] != 'vanilla': if self.metadata['shuffle'][player] != 'vanilla':
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player])) outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player]))

21
Fill.py
View File

@@ -355,18 +355,23 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
# handle pot shuffle # handle pot shuffle
pots_used = False pots_used = False
pot_item_pool = collections.defaultdict(list) pot_item_pool = collections.defaultdict(list)
# guarantee one big magic in a bonk location
for player in range(1, world.players + 1):
if world.shuffle_bonk_drops[player]:
for item in world.itempool: for item in world.itempool:
if item.name in ['Chicken', 'Big Magic']: # can only fill these in that players world if item.name in ['Big Magic']:
pot_item_pool[item.player].append(item) pot_item_pool[player].append(item)
for player, pot_pool in pot_item_pool.items(): break
if pot_pool:
for pot_item in pot_pool: for player, magic_pool in pot_item_pool.items():
world.itempool.remove(pot_item) world.itempool.remove(magic_pool[0])
pot_locations = [location for location in fill_locations pot_locations = [location for location in fill_locations
if location.type == LocationType.Pot and location.player == player] if location.type == LocationType.Bonk and location.player == player]
pot_locations = filter_pot_locations(pot_locations, world) pot_locations = filter_pot_locations(pot_locations, world)
fast_fill_helper(world, pot_pool, pot_locations) fast_fill_helper(world, magic_pool, pot_locations)
pots_used = True pots_used = True
if pots_used: if pots_used:
fill_locations = world.get_unfilled_locations() fill_locations = world.get_unfilled_locations()
random.shuffle(fill_locations) random.shuffle(fill_locations)

View File

@@ -3,11 +3,12 @@ import logging
import math import math
import RaceRandom as random import RaceRandom as random
from BaseClasses import Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem from BaseClasses import LocationType, Region, RegionType, Shop, ShopType, Location, CollectionState, PotItem
from EntranceShuffle import connect_entrance from EntranceShuffle import connect_entrance
from Regions import shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location from Regions import shop_to_location_table, retro_shops, shop_table_by_location, valid_pot_location
from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool from Fill import FillError, fill_restrictive, fast_fill, get_dungeon_item_pool
from PotShuffle import vanilla_pots from PotShuffle import vanilla_pots
from Tables import bonk_prize_lookup
from Items import ItemFactory from Items import ItemFactory
from source.item.FillUtil import trash_items, pot_items from source.item.FillUtil import trash_items, pot_items
@@ -411,6 +412,10 @@ def generate_itempool(world, player):
if world.pottery[player] not in ['none', 'keys']: if world.pottery[player] not in ['none', 'keys']:
add_pot_contents(world, player) add_pot_contents(world, player)
if world.shuffle_bonk_drops[player]:
create_dynamic_bonkdrop_locations(world, player)
add_bonkdrop_contents(world, player)
take_any_locations = [ take_any_locations = [
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut', 'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
@@ -500,6 +505,21 @@ def create_dynamic_shop_locations(world, player):
loc.locked = True loc.locked = True
def create_dynamic_bonkdrop_locations(world, player):
from Regions import bonk_prize_table
for bonk_location, (_, _, _, region_name, hint_text) in bonk_prize_table.items():
region = world.get_region(region_name, player)
loc = Location(player, bonk_location, 0, region, hint_text)
loc.type = LocationType.Bonk
loc.parent_region = region
loc.address = 0x2abb00 + (bonk_prize_table[loc.name][0] * 6) + 3
region.locations.append(loc)
world.dynamic_locations.append(loc)
world.clear_location_cache()
def fill_prizes(world, attempts=15): def fill_prizes(world, attempts=15):
all_state = world.get_all_state(keys=True) all_state = world.get_all_state(keys=True)
for player in range(1, world.players + 1): for player in range(1, world.players + 1):
@@ -779,6 +799,17 @@ def add_pot_contents(world, player):
world.itempool.append(ItemFactory(item, player)) world.itempool.append(ItemFactory(item, player))
def add_bonkdrop_contents(world, player):
from Items import item_table
for item_name, (_, count, alt_item) in bonk_prize_lookup.items():
if item_name not in item_table:
item_name = alt_item
while (count > 0):
item = ItemFactory(item_name, player)
world.itempool.append(item)
count -= 1
def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic, flute_activated): def get_pool_core(progressive, shuffle, difficulty, treasure_hunt_total, timer, goal, mode, swords, retro, bombbag, door_shuffle, logic, flute_activated):
pool = [] pool = []
placed_items = {} placed_items = {}

View File

@@ -81,10 +81,10 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), 'Arrow Upgrade (+10)': (False, False, None, 0x54, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'), 'Arrow Upgrade (+5)': (False, False, None, 0x53, 100, 'Increase arrow\nstorage, low\nlow price', 'and the quiver', 'quiver-enlarging kid', 'arrow boost for sale', 'witch and more skewers', 'upgrade boy sews more again', 'arrow capacity'),
'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'), 'Single Bomb': (False, False, None, 0x27, 5, 'I make things\ngo BOOM! But\njust once.', 'and the explosion', 'the bomb-holding kid', 'firecracker for sale', 'blend fungus into bomb', '\'splosion boy explodes again', 'a bomb'),
'Arrows (5)': (False, False, None, 0x5A, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'), 'Arrows (5)': (False, False, None, 0xB5, 15, 'This will give\nyou five shots\nwith your bow!', 'and the arrow pack', 'stick-collecting kid', 'sewing kit for sale', 'fungus for arrows', 'archer boy sews again', 'five arrows'),
'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'), 'Small Magic': (False, False, None, 0x45, 5, 'A bit of magic', 'and the bit of magic', 'bit-o-magic kid', 'magic bit for sale', 'fungus for magic', 'magic boy conjures again', 'a bit of magic'),
'Big Magic': (False, False, None, 0x5A, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'), 'Big Magic': (False, False, None, 0xB4, 40, 'A lot of magic', 'and lots of magic', 'lot-o-magic kid', 'magic refill for sale', 'fungus for magic', 'magic boy conjures again', 'a magic refill'),
'Chicken': (False, False, None, 0x5A, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'), 'Chicken': (False, False, None, 0xB3, 999, 'Cucco of Legend', 'and the legendary cucco', 'chicken kid', 'fried chicken for sale', 'fungus for chicken', 'cucco boy clucks again', 'a cucco'),
'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'), 'Bombs (3)': (False, False, None, 0x28, 15, 'I make things\ngo triple\nBOOM!!!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'three bombs'),
'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'), 'Bombs (10)': (False, False, None, 0x31, 50, 'I make things\ngo BOOM! Ten\ntimes!', 'and the explosions', 'the bomb-holding kid', 'firecrackers for sale', 'blend fungus into bombs', '\'splosion boy explodes again', 'ten bombs'),
'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'), 'Bomb Upgrade (+10)': (False, False, None, 0x52, 100, 'Increase bomb\nstorage, low\nlow price', 'and the bomb bag', 'boom-enlarging kid', 'bomb boost for sale', 'the shroom goes boom', 'upgrade boy explodes more again', 'bomb capacity'),
@@ -177,6 +177,8 @@ item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narche
'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'), 'Blue Potion': (False, False, None, 0x30, 160, 'Delicious blue goop!', 'and the blue goo', 'the liquid kid', 'potion for sale', 'free samples', 'bottle boy has blue goo again', 'a blue potion'),
'Bee': (False, False, None, 0x0E, 10, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'), 'Bee': (False, False, None, 0x0E, 10, 'I will sting your foes a few times', 'and the sting buddy', 'the beekeeper kid', 'insect for sale', 'shroom pollenation', 'bottle boy has mad bee again', 'a bee'),
'Small Heart': (False, False, None, 0x42, 10, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'), 'Small Heart': (False, False, None, 0x42, 10, 'Just a little\npiece of love!', 'and the heart', 'the life-giving kid', 'little love for sale', 'fungus for life', 'life boy feels some love again', 'a heart'),
'Apples': (False, False, None, 0xB1, 30, 'Just a few pieces of fruit!', 'and the juicy fruit', 'the fruity kid', 'the fruit stand', 'expired fruit', 'bottle boy has fruit again', 'an apple hoard'),
'Fairy': (False, False, None, 0xB2, 50, 'Just a pixie!', 'and the pixie', 'the pixie kid', 'pixie for sale', 'pixie fungus', 'bottle boy has pixie again', 'a pixie'),
'Beat Agahnim 1': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Beat Agahnim 1': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Beat Agahnim 2': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Beat Agahnim 2': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),
'Get Frog': (True, False, 'Event', 999, None, None, None, None, None, None, None, None), 'Get Frog': (True, False, 'Event', 999, None, None, None, None, None, None, None, None),

View File

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

65
Rom.py
View File

@@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '210e4631353e3d094f01bf91562844a5' RANDOMIZERBASEHASH = 'f76555dcc8cbd0f185fb37eafa3779c3'
class JsonRom(object): class JsonRom(object):
@@ -630,6 +630,14 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(sprite_pointer+1, 0) rom.write_byte(sprite_pointer+1, 0)
rom.write_byte(sprite_pointer+2, code) rom.write_byte(sprite_pointer+2, code)
continue continue
elif location.type == LocationType.Bonk:
address = snes_to_pc(location.address)
rom.write_byte(address, handle_native_dungeon(location, itemid))
if location.item.player != player:
rom.write_byte(address+1, location.item.player)
else:
rom.write_byte(address+1, 0)
continue
if location.address is None or (type(location.address) is int and location.address >= 0x400000): if location.address is None or (type(location.address) is int and location.address >= 0x400000):
continue continue
@@ -771,17 +779,41 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# set world flag # set world flag
world_flag = 0x00 if b >= 0x40 and b < 0x80 else 0x40 world_flag = 0x00 if b >= 0x40 and b < 0x80 else 0x40
rom.write_byte(0x153A00 + b, world_flag) rom.write_byte(0x1539B0 + b, world_flag)
if b & 0xBF in megatiles: if b & 0xBF in megatiles:
rom.write_byte(0x153A00 + b + 1, world_flag) rom.write_byte(0x1539B0 + b + 1, world_flag)
rom.write_byte(0x153A00 + b + 8, world_flag) rom.write_byte(0x1539B0 + b + 8, world_flag)
rom.write_byte(0x153A00 + b + 9, world_flag) rom.write_byte(0x1539B0 + b + 9, world_flag)
for edge in world.owedges: for edge in world.owedges:
if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player: if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player:
write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc) write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc)
if not edge.specialExit: if not edge.specialExit:
rom.write_byte(0x1539e0 + (edge.specialID - 0x80) * 2 if edge.specialEntrance else edge.getAddress() + 0x0e, edge.getTarget()) rom.write_byte(0x1539A0 + (edge.specialID - 0x80) * 2 if edge.specialEntrance else edge.getAddress() + 0x0e, edge.getTarget())
# patch bonk prizes
if world.shuffle_bonk_drops:
bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3,
0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD]
bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD,
0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51,
0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7,
0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A]
# # legacy bonk prize shuffle, shuffles bonk prizes amongst themselves
# random.shuffle(bonk_prizes)
# for prize, address in zip(bonk_prizes, bonk_addresses):
# rom.write_byte(address, prize)
owFlags |= 0x200
# setting spriteID to D8, a placeholder sprite we use to inform ROM to spawn a dynamic item
#for address in bonk_addresses:
for address in [b for b in bonk_addresses if b != 0x4D0AE]: # temp fix for screen 1A murahdahla sprite replacement
rom.write_byte(address, 0xD8)
# temporary fix for screen 1A
rom.write_byte(snes_to_pc(0x09AE32), 0xD8)
rom.write_byte(snes_to_pc(0x09AE35), 0xD8)
write_int16(rom, 0x150002, owMode) write_int16(rom, 0x150002, owMode)
write_int16(rom, 0x150004, owFlags) write_int16(rom, 0x150004, owFlags)
@@ -875,6 +907,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and not l.forced_item) valid_locations = [l for l in my_locations if ((l.type == LocationType.Pot and not l.forced_item)
or (l.type == LocationType.Drop and not l.forced_item) or (l.type == LocationType.Drop and not l.forced_item)
or (l.type == LocationType.Normal and not l.forced_item) or (l.type == LocationType.Normal and not l.forced_item)
or (l.type == LocationType.Bonk and not l.forced_item)
or (l.type == LocationType.Shop and world.shopsanity[player]))] or (l.type == LocationType.Shop and world.shopsanity[player]))]
valid_loc_by_dungeon = valid_dungeon_locations(valid_locations) valid_loc_by_dungeon = valid_dungeon_locations(valid_locations)
@@ -1251,18 +1284,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# fill enemy prize packs # fill enemy prize packs
rom.write_bytes(0x37A78, pack_prizes) rom.write_bytes(0x37A78, pack_prizes)
# set bonk prizes
bonk_prizes = [0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xAC, 0xE3, 0xE3, 0xDA, 0xE3, 0xDA, 0xD8, 0xAC, 0xAC, 0xE3, 0xD8, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xDC, 0xDB, 0xE3, 0xDA, 0x79, 0x79, 0xE3, 0xE3,
0xDA, 0x79, 0xAC, 0xAC, 0x79, 0xE3, 0x79, 0xAC, 0xAC, 0xE0, 0xDC, 0xE3, 0x79, 0xDE, 0xE3, 0xAC, 0xDB, 0x79, 0xE3, 0xD8, 0xAC, 0x79, 0xE3, 0xDB, 0xDB, 0xE3, 0xE3, 0x79, 0xD8, 0xDD]
bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028, 0x4D03C, 0x4D059, 0x4D07A, 0x4D09E, 0x4D0A8, 0x4D0AB, 0x4D0AE, 0x4D0BE, 0x4D0DD,
0x4D16A, 0x4D1E5, 0x4D1EE, 0x4D20B, 0x4CBBF, 0x4CBBF, 0x4CC17, 0x4CC1A, 0x4CC4A, 0x4CC4D, 0x4CC53, 0x4CC69, 0x4CC6F, 0x4CC7C, 0x4CCEF, 0x4CD51,
0x4CDC0, 0x4CDC3, 0x4CDC6, 0x4CE37, 0x4D2DE, 0x4D32F, 0x4D355, 0x4D367, 0x4D384, 0x4D387, 0x4D397, 0x4D39E, 0x4D3AB, 0x4D3AE, 0x4D3D1, 0x4D3D7,
0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3, 0x4D504, 0x4D507, 0x4D55E, 0x4D56A]
if world.shuffle_bonk_prizes:
random.shuffle(bonk_prizes)
for prize, address in zip(bonk_prizes, bonk_addresses):
rom.write_byte(address, prize)
# Fill in item substitutions table # Fill in item substitutions table
rom.write_bytes(0x184000, [ rom.write_bytes(0x184000, [
# original_item, limit, replacement_item, filler # original_item, limit, replacement_item, filler
@@ -1644,6 +1665,12 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
# temporarally we are just nopping out this check we will conver this to a rom fix soon. # temporarally we are just nopping out this check we will conver this to a rom fix soon.
rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F]) rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F])
# sprite patches
rom.write_byte(snes_to_pc(0x0db7d1), 0x03) # patch apple sprites to not permadeatch like enemies
if world.shuffle_bonk_drops[player]:
# warning, this temporary patch might cause fairies to respawn differently?, limiting this to bonk drop mode only
rom.write_byte(snes_to_pc(0x0db808), 0x03) # patch fairies sprites to not permadeatch like enemies
# allow smith into multi-entrance caves in appropriate shuffles # allow smith into multi-entrance caves in appropriate shuffles
if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'): if world.shuffle[player] in ['restricted', 'full', 'lite', 'lean', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
rom.write_byte(0x18004C, 0x01) rom.write_byte(0x18004C, 0x01)
@@ -2754,7 +2781,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
# apply inverted map changes # apply inverted map changes
for b in range(0x00, len(inverted_buffer)): for b in range(0x00, len(inverted_buffer)):
rom.write_byte(0x153B00 + b, inverted_buffer[b]) rom.write_byte(0x153A70 + b, inverted_buffer[b])
def patch_shuffled_dark_sanc(world, rom, player): def patch_shuffled_dark_sanc(world, rom, player):
dark_sanc = world.get_region('Dark Sanctuary Hint', player) dark_sanc = world.get_region('Dark Sanctuary Hint', player)

View File

@@ -823,6 +823,15 @@ def default_rules(world, player):
set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player))
set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Bombos Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player))
# Bonk Item Access
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
from Regions import bonk_prize_table
for location_name, (_, aga_required, _, _, _) in bonk_prize_table.items():
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)))
add_bunny_rule(loc, player)
# Entrance Access # Entrance Access
set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_beaten_aga(player)) set_rule(world.get_entrance('Lumberjack Tree Tree', player), lambda state: state.has_Boots(player) and state.has_beaten_aga(player))
set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player)) set_rule(world.get_entrance('Bonk Rock Cave', player), lambda state: state.has_Boots(player))
@@ -1731,6 +1740,11 @@ def standard_rules(world, player):
add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_entrance('Bonk Fairy (Light)', player), lambda state: state.has('Zelda Delivered', 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
add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player))
# don't allow bombs to get past here before zelda is rescued # don't allow bombs to get past here before zelda is rescued
set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player))

View File

@@ -125,17 +125,23 @@ divisor_lookup = {
# 0xf8: 0xbac, 0xf9: 0xbba, 0xfa: 0xbc1, 0xfb: 0xbcc, 0xfc: 0xbd7, 0xfd: 0xbd7, 0xfe: 0xbba, 0xff: 0xbe3 # 0xf8: 0xbac, 0xf9: 0xbba, 0xfa: 0xbc1, 0xfb: 0xbcc, 0xfc: 0xbd7, 0xfd: 0xbd7, 0xfe: 0xbba, 0xff: 0xbe3
# } # }
prize_lookup = { # item name: (spriteID, pool count, replacement item)
0xd8: 'Small Magic Refill', bonk_prize_lookup = {
0xd9: 'Rupee (1)', 'Chicken': (0x0b, 0, None),
0xda: 'Rupees (5)', 'Bee Trap': (0x79, 6, None),
0xdb: 'Rupees (20)', 'Apples': (0xac, 8, None),
0xdc: 'Bomb (1)', 'Small Heart': (0xd8, 2, None),
0xdd: 'Bombs (4)', 'Rupee (1)': (0xd9, 0, None),
0xde: 'Bombs (8)', 'Rupees (5)': (0xda, 3, None), # TODO: add in murahdahla tree rupee
0xdf: 'Heart', 'Rupees (20)': (0xdb, 3, None),
0xe0: 'Fairy', 'Single Bomb': (0xdc, 2, None),
0xe1: 'Arrows (5)', 'Bombs (3)': (None, 0, 'Bombs (4)'),
0xe2: 'Arrows (10)', 'Bombs (4)': (0xdd, 0, 'Bombs (3)'),
0xe3: 'Full Magic Refill' 'Bombs (8)': (0xde, 1, 'Bombs (10)'),
'Bombs (10)': (None, 0, 'Bombs (8)'),
'Small Magic': (0xdf, 0, None),
'Big Magic': (0xe0, 1, None),
'Arrows (5)': (0xe1, 0, None),
'Arrows (10)': (0xe2, 0, None),
'Fairy': (0xe3, 15, None)
} }

View File

@@ -143,6 +143,9 @@ jsl.l OWWorldCheck16 : nop
org $02b16e ; AND #$3F : ORA 7EF3CA org $02b16e ; AND #$3F : ORA 7EF3CA
and #$7f : eor #$40 : nop #2 and #$7f : eor #$40 : nop #2
org $06AD4C
jsl.l OWBonkDrops : nop #4
;Code ;Code
org $aa8800 org $aa8800
OWTransitionDirection: OWTransitionDirection:
@@ -368,6 +371,136 @@ LoadMapDarkOrMixed:
dw $0400+$0210 ; bottom right dw $0400+$0210 ; bottom right
} }
; Y = sprite slot index of bonk sprite
OWBonkDrops:
{
CMP.b #$D8 : BEQ +
RTL
+ LDA.l OWFlags+1 : AND.b #$02 : BNE +
JSL.l Sprite_TransmuteToBomb : RTL
+
; loop thru rando bonk table to find match
PHB : PHK : PLB
LDA.b $8A
LDX.b #(40*6) ; 40 bonk items, 6 bytes each
- CMP.w OWBonkPrizeData,X : BNE +
INX
LDA.w $0D10,Y : LSR A : LSR A : LSR A : LSR A
EOR.w $0D00,Y : CMP.w OWBonkPrizeData,X : BNE ++ ; X = row + 1
BRA .found_match
++ DEX : LDA.b $8A
+ CPX.b #$00 : BNE +
PLB : RTL
+ DEX : DEX : DEX : DEX : DEX : DEX : BRA -
.found_match
INX : LDA.w OWBonkPrizeData,X : PHX : PHA ; S = FlagBitmask, X (row + 2)
LDX.b $8A : LDA.l OverworldEventDataWRAM,X : AND 1,S : PHA : BNE + ; S = Collected, FlagBitmask, X (row + 2)
LDA.b #$1B : STA $12F ; JSL Sound_SetSfx3PanLong ; seems that when you bonk, there is a pending bonk sfx, so we clear that out and replace with reveal secret sfx
+
LDA 3,S : TAX : INX : LDA.w OWBonkPrizeData,X
PHA : INX : LDA.w OWBonkPrizeData,X : BEQ +
; multiworld item
DEX : PLA ; X = row + 3
JMP .spawn_item
+ DEX : PLA ; X = row + 3
.determine_type ; A = item id ; S = Collected, FlagBitmask, X (row + 2)
CMP.b #$B0 : BNE +
LDA.b #$79 : JMP .sprite_transform ; transform to bees
+ CMP.b #$42 : BNE +
JSL.l Sprite_TransmuteToBomb ; transform a heart to bomb, vanilla behavior
JMP .mark_collected
+ CMP.b #$34 : BNE +
LDA.b #$D9 : CLC : JMP .sprite_transform ; transform to single rupee
+ CMP.b #$35 : BNE +
LDA.b #$DA : CLC : BRA .sprite_transform ; transform to blue rupee
+ CMP.b #$36 : BNE +
LDA.b #$DB : CLC : BRA .sprite_transform ; transform to red rupee
+ CMP.b #$27 : BNE +
LDA.b #$DC : CLC : BRA .sprite_transform ; transform to 1 bomb
+ CMP.b #$28 : BNE +
LDA.b #$DD : CLC : BRA .sprite_transform ; transform to 4 bombs
+ CMP.b #$31 : BNE +
LDA.b #$DE : CLC : BRA .sprite_transform ; transform to 8 bombs
+ CMP.b #$45 : BNE +
LDA.b #$DF : CLC : BRA .sprite_transform ; transform to small magic
+ CMP.b #$B4 : BNE +
LDA.b #$E0 : CLC : BRA .sprite_transform ; transform to big magic
+ CMP.b #$B5 : BNE +
LDA.b #$E1 : CLC : BRA .sprite_transform ; transform to 5 arrows
+ CMP.b #$44 : BNE +
LDA.b #$E2 : CLC : BRA .sprite_transform ; transform to 10 arrows
+ CMP.b #$B1 : BNE +
LDA.b #$AC : BRA .sprite_transform ; transform to apples
+ CMP.b #$B2 : BNE +
LDA.b #$E3 : BRA .sprite_transform ; transform to fairy
+ CMP.b #$B3 : BNE .spawn_item
INX : INX : LDA.w OWBonkPrizeData,X ; X = row + 5
CLC : ADC.b #$08 : PHA
LDA.w $0D00,Y : SEC : SBC.b 1,S : STA.w $0D00,Y
LDA.w $0D20,Y : SBC.b #$00 : STA.w $0D20,Y : PLX
LDA.b #$0B : SEC ; BRA .sprite_transform ; transform to chicken
.sprite_transform
STA.w $0E20,Y
TYX : JSL.l Sprite_LoadProperties
BEQ +
; these are sprite properties that make it fall out of the tree to the east
LDA #$30 : STA $0F80,Y ; amount of force (related to speed)
LDA #$10 : STA $0D50,Y ; eastward rate of speed
LDA #$FF : STA $0B58,Y ; expiration timer
+
.mark_collected ; S = Collected, FlagBitmask, X (row + 2)
PLA : BNE + ; S = FlagBitmask, X (row + 2)
LDX.b $8A : LDA.l OverworldEventDataWRAM,X : ORA 1,S : STA.l OverworldEventDataWRAM,X
REP #$20
LDA.l TotalItemCounter : INC : STA.l TotalItemCounter
SEP #$20
+ JMP .return
; spawn itemget item
.spawn_item ; A = item id ; Y = tree sprite slot ; S = Collected, FlagBitmask, X (row + 2)
PLX : BEQ + : LDA.b #$00 : STA.w $0DD0,Y : JMP .return ; S = FlagBitmask, X (row + 2)
+ LDA 2,S : TAX : INX : INX
LDA.w OWBonkPrizeData,X : STA.l !MULTIWORLD_SPRITEITEM_PLAYER_ID
DEX
LDA.b #$01 : STA !REDRAW
LDA.b #$EB
STA.l $7FFE00
JSL Sprite_SpawnDynamically+15 ; +15 to skip finding a new slot, use existing sprite
; affects the rate the item moves in the Y/X direction
LDA.b #$00 : STA.w $0D40,Y
LDA.b #$0A : STA.w $0D50,Y
LDA.b #$20 : STA.w $0F80,Y ; amount of force (gives height to the arch)
LDA.b #$FF : STA.w $0B58,Y ; stun timer
LDA.b #$30 : STA.w $0F10,Y ; aux delay timer 4 ?? dunno what that means
LDA.b #$00 : STA.w $0F20,Y ; layer the sprite is on
; sets OW event bitmask flag, uses free RAM
PLA : STA.w $0ED0,Y ; S = X (row + 2)
; determines the initial spawn point of item
PLX : INX : INX : INX
LDA.w $0D00,Y : SEC : SBC.w OWBonkPrizeData,X : STA.w $0D00,Y
LDA.w $0D20,Y : SBC #$00 : STA.w $0D20,Y
LDA.b #$01 : STA !REDRAW : STA !FORCE_HEART_SPAWN
PLB : RTL
.return
PLA : PLA : PLB : RTL
}
org $aa9000 org $aa9000
OWDetectEdgeTransition: OWDetectEdgeTransition:
{ {
@@ -1130,11 +1263,11 @@ dw $0f20, $0f40, $0020, $0f30, $757e, $0000, $0000, $0049
dw $0f70, $0fb8, $0048, $0f94, $757e, $0000, $0000, $004a dw $0f70, $0fb8, $0048, $0f94, $757e, $0000, $0000, $004a
dw $0058, $00c0, $0068, $008c, $8080, $0000, $0000, $0017 ;Hobo (unused) dw $0058, $00c0, $0068, $008c, $8080, $0000, $0000, $0017 ;Hobo (unused)
org $aab9e0 ;PC 1539e0 org $aab9a0 ;PC 1539a0
OWSpecialDestIndex: OWSpecialDestIndex:
dw $0080, $0081, $0082 dw $0080, $0081, $0082
org $aaba00 ;PC 153a00 org $aab9b0 ;PC 1539b0
OWTileWorldAssoc: OWTileWorldAssoc:
db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0
@@ -1154,7 +1287,7 @@ db $40, $40, $40, $40, $40, $40, $40, $40
db $40, $40, $40, $40, $40, $40, $40, $40 db $40, $40, $40, $40, $40, $40, $40, $40
db $00, $00 db $00, $00
org $aabb00 ;PC 153b00 org $aaba70 ;PC 153a70
OWTileMapAlt: OWTileMapAlt:
db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0
@@ -1175,3 +1308,63 @@ db 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0, 0, 0, 0, 0, 0, 0 db 0, 0, 0, 0, 0, 0, 0, 0
db 0, 0 db 0, 0
org $aabb00 ;PC 153b00
OWBonkPrizeData:
; OWID YX Flag Item MW Offset
db $00, $59, $10, $b0, $00, $20
db $05, $04, $10, $b2, $00, $00
db $0a, $4e, $10, $b0, $00, $20
db $0a, $a9, $08, $b1, $00, $20
db $10, $c7, $10, $b1, $00, $20
db $10, $f7, $08, $b4, $00, $20
db $11, $08, $10, $27, $00, $00
db $12, $a4, $10, $b2, $00, $20
db $13, $c7, $10, $31, $00, $20
db $13, $98, $08, $b1, $00, $20
db $15, $a4, $10, $b1, $00, $20
db $15, $fb, $08, $b2, $00, $20
db $18, $a8, $10, $b2, $00, $20
db $18, $36, $08, $35, $00, $20
db $1a, $8a, $10, $42, $00, $20
db $1a, $1d, $08, $b2, $00, $20
;db $1a, $77, $04, $35, $00, $20 ; pre aga ONLY ; hijacked murahdahla bonk tree
db $1b, $46, $10, $b1, $00, $10
db $1d, $6b, $10, $b1, $00, $20
db $1e, $72, $10, $b2, $00, $20
db $2a, $8f, $10, $36, $00, $20
db $2a, $45, $08, $36, $00, $20
db $2b, $d6, $10, $b2, $00, $20
db $2e, $9c, $10, $b2, $00, $20
db $2e, $b4, $08, $b0, $00, $20
db $32, $29, $10, $42, $00, $20
db $32, $9a, $08, $b2, $00, $20
db $42, $66, $10, $b2, $00, $20
db $51, $08, $10, $b2, $00, $00
db $51, $09, $08, $b2, $00, $00
db $54, $b5, $10, $27, $00, $00
db $54, $ef, $08, $b2, $00, $08
db $54, $b9, $04, $36, $00, $00
db $55, $aa, $10, $b0, $00, $20
db $55, $fb, $08, $35, $00, $20
db $56, $e4, $10, $b0, $00, $20
db $5b, $a7, $10, $b2, $00, $20
db $5e, $00, $10, $b2, $00, $20
db $6e, $8c, $10, $35, $00, $10
db $6e, $90, $08, $b0, $00, $10
db $6e, $a4, $04, $b1, $00, $10
db $74, $4e, $10, $b1, $00, $1c
; temporary fix - murahdahla replaces one of the bonk tree prizes
; so we copy the sprite table here and update the pointer
; longterm solution should be to spawn in murahdahla separately
org $09AE2A
Overworld_Sprites_Screen1A_2:
db $08, $0F, $41 ; yx:{ 0x080, 0x0F0 }
db $0E, $0C, $41 ; yx:{ 0x0E0, 0x0C0 }
db $11, $0D, $E3 ; yx:{ 0x110, 0x0D0 }
db $18, $0A, $D8 ; yx:{ 0x180, 0x0A0 }
db $18, $0F, $45 ; yx:{ 0x180, 0x0F0 }
db $FF ; END
org $09CA55
dw Overworld_Sprites_Screen1A_2&$FFFF

Binary file not shown.

View File

@@ -22,6 +22,9 @@
vanilla: 0 vanilla: 0
balanced: 1 balanced: 1
random: 1 random: 1
bonk_drops:
on: 1
off: 1
door_shuffle: door_shuffle:
vanilla: 0 vanilla: 0
basic: 2 basic: 2

View File

@@ -792,8 +792,8 @@ trash_items = {
'Bee Trap': 0, 'Bee Trap': 0,
'Rupee (1)': 1, 'Rupees (5)': 1, 'Small Heart': 1, 'Bee': 1, 'Arrows (5)': 1, 'Chicken': 1, 'Single Bomb': 1, 'Rupee (1)': 1, 'Rupees (5)': 1, 'Small Heart': 1, 'Bee': 1, 'Arrows (5)': 1, 'Chicken': 1, 'Single Bomb': 1,
'Rupees (20)': 2, 'Small Magic': 2, 'Rupees (20)': 2, 'Small Magic': 2,
'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, 'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, 'Apples': 3,
'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4, 'Fairy': 4, 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4,
'Rupees (300)': 5, 'Rupees (300)': 5,
'Piece of Heart': 17 'Piece of Heart': 17
} }