From 97455dc1406727c825c6454282a8b6ef2d5ec7de Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 24 Jul 2022 12:50:37 -0500 Subject: [PATCH] Implemented Bonk Drop Shuffle --- BaseClasses.py | 8 +- Fill.py | 29 +++--- ItemList.py | 33 ++++++- Items.py | 8 +- Regions.py | 49 +++++++++- Rom.py | 65 +++++++++---- Rules.py | 14 +++ Tables.py | 32 ++++--- asm/owrando.asm | 199 +++++++++++++++++++++++++++++++++++++++- data/base2current.bps | Bin 99252 -> 103920 bytes mystery_example.yml | 3 + source/item/FillUtil.py | 4 +- 12 files changed, 389 insertions(+), 55 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 01825043..4a484834 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -1080,6 +1080,9 @@ class CollectionState(object): return True 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): tree_pulls = ['Lost Woods East Area', 'Snitch Lady (East)', @@ -1192,7 +1195,7 @@ class CollectionState(object): if can_reach_non_bunny(region): 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: if can_reach_non_bunny(region): return True @@ -2696,6 +2699,7 @@ class LocationType(FastEnum): Shop = 3 Pot = 4 Drop = 5 + Bonk = 6 class Item(object): @@ -2911,6 +2915,7 @@ class Spoiler(object): 'ow_mixed': self.world.owMixed, 'ow_whirlpool': self.world.owWhirlpoolShuffle, 'ow_fluteshuffle': self.world.owFluteShuffle, + 'bonk_drops': self.world.shuffle_bonk_drops, 'shuffle': self.world.shuffle, 'shuffleganon': self.world.shuffle_ganon, '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('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('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]) if self.metadata['shuffle'][player] != 'vanilla': outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player])) diff --git a/Fill.py b/Fill.py index 9bf7f98f..fe9cbcf9 100644 --- a/Fill.py +++ b/Fill.py @@ -355,18 +355,23 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None # handle pot shuffle pots_used = False pot_item_pool = collections.defaultdict(list) - for item in world.itempool: - if item.name in ['Chicken', 'Big Magic']: # can only fill these in that players world - pot_item_pool[item.player].append(item) - for player, pot_pool in pot_item_pool.items(): - if pot_pool: - for pot_item in pot_pool: - world.itempool.remove(pot_item) - pot_locations = [location for location in fill_locations - if location.type == LocationType.Pot and location.player == player] - pot_locations = filter_pot_locations(pot_locations, world) - fast_fill_helper(world, pot_pool, pot_locations) - pots_used = True + + # 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: + if item.name in ['Big Magic']: + pot_item_pool[player].append(item) + break + + for player, magic_pool in pot_item_pool.items(): + world.itempool.remove(magic_pool[0]) + pot_locations = [location for location in fill_locations + if location.type == LocationType.Bonk and location.player == player] + pot_locations = filter_pot_locations(pot_locations, world) + fast_fill_helper(world, magic_pool, pot_locations) + pots_used = True + if pots_used: fill_locations = world.get_unfilled_locations() random.shuffle(fill_locations) diff --git a/ItemList.py b/ItemList.py index 18472fb0..7350ff9a 100644 --- a/ItemList.py +++ b/ItemList.py @@ -3,11 +3,12 @@ import logging import math 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 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 PotShuffle import vanilla_pots +from Tables import bonk_prize_lookup from Items import ItemFactory 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']: 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 = [ '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 +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): all_state = world.get_all_state(keys=True) for player in range(1, world.players + 1): @@ -779,6 +799,17 @@ def add_pot_contents(world, 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): pool = [] placed_items = {} diff --git a/Items.py b/Items.py index ea81c136..10d93159 100644 --- a/Items.py +++ b/Items.py @@ -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 (+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'), - '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'), - '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'), - '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'), + '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, 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 (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'), @@ -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'), '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'), + '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 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), diff --git a/Regions.py b/Regions.py index 18c14c9a..af3c13ef 100644 --- a/Regions.py +++ b/Regions.py @@ -1266,7 +1266,54 @@ def pot_address(pot_index, super_tile): 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) _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)] diff --git a/Rom.py b/Rom.py index b614e730..7c43ea9f 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '210e4631353e3d094f01bf91562844a5' +RANDOMIZERBASEHASH = 'f76555dcc8cbd0f185fb37eafa3779c3' 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+2, code) 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): continue @@ -771,18 +779,42 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): # set world flag 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: - rom.write_byte(0x153A00 + b + 1, world_flag) - rom.write_byte(0x153A00 + b + 8, world_flag) - rom.write_byte(0x153A00 + b + 9, world_flag) + rom.write_byte(0x1539B0 + b + 1, world_flag) + rom.write_byte(0x1539B0 + b + 8, world_flag) + rom.write_byte(0x1539B0 + b + 9, world_flag) for edge in world.owedges: if edge.dest is not None and isinstance(edge.dest, OWEdge) and edge.player == player: write_int16(rom, edge.getAddress() + 0x0a, edge.vramLoc) 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, 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) or (l.type == LocationType.Drop 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]))] 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 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 rom.write_bytes(0x184000, [ # 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. 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 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) @@ -2754,7 +2781,7 @@ def set_inverted_mode(world, player, rom, inverted_buffer): # apply inverted map changes 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): dark_sanc = world.get_region('Dark Sanctuary Hint', player) diff --git a/Rules.py b/Rules.py index 45aa6ba6..9619c897 100644 --- a/Rules.py +++ b/Rules.py @@ -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('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 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)) @@ -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('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 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)) diff --git a/Tables.py b/Tables.py index 64464b9f..a30f24f0 100644 --- a/Tables.py +++ b/Tables.py @@ -125,17 +125,23 @@ divisor_lookup = { # 0xf8: 0xbac, 0xf9: 0xbba, 0xfa: 0xbc1, 0xfb: 0xbcc, 0xfc: 0xbd7, 0xfd: 0xbd7, 0xfe: 0xbba, 0xff: 0xbe3 # } -prize_lookup = { - 0xd8: 'Small Magic Refill', - 0xd9: 'Rupee (1)', - 0xda: 'Rupees (5)', - 0xdb: 'Rupees (20)', - 0xdc: 'Bomb (1)', - 0xdd: 'Bombs (4)', - 0xde: 'Bombs (8)', - 0xdf: 'Heart', - 0xe0: 'Fairy', - 0xe1: 'Arrows (5)', - 0xe2: 'Arrows (10)', - 0xe3: 'Full Magic Refill' +# item name: (spriteID, pool count, replacement item) +bonk_prize_lookup = { + 'Chicken': (0x0b, 0, None), + 'Bee Trap': (0x79, 6, None), + 'Apples': (0xac, 8, None), + 'Small Heart': (0xd8, 2, None), + 'Rupee (1)': (0xd9, 0, None), + 'Rupees (5)': (0xda, 3, None), # TODO: add in murahdahla tree rupee + 'Rupees (20)': (0xdb, 3, None), + 'Single Bomb': (0xdc, 2, None), + 'Bombs (3)': (None, 0, 'Bombs (4)'), + 'Bombs (4)': (0xdd, 0, 'Bombs (3)'), + '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) } diff --git a/asm/owrando.asm b/asm/owrando.asm index 2d0c1ebd..7793ce2d 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -143,6 +143,9 @@ jsl.l OWWorldCheck16 : nop org $02b16e ; AND #$3F : ORA 7EF3CA and #$7f : eor #$40 : nop #2 +org $06AD4C +jsl.l OWBonkDrops : nop #4 + ;Code org $aa8800 OWTransitionDirection: @@ -368,6 +371,136 @@ LoadMapDarkOrMixed: 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 OWDetectEdgeTransition: { @@ -1130,11 +1263,11 @@ dw $0f20, $0f40, $0020, $0f30, $757e, $0000, $0000, $0049 dw $0f70, $0fb8, $0048, $0f94, $757e, $0000, $0000, $004a dw $0058, $00c0, $0068, $008c, $8080, $0000, $0000, $0017 ;Hobo (unused) -org $aab9e0 ;PC 1539e0 +org $aab9a0 ;PC 1539a0 OWSpecialDestIndex: dw $0080, $0081, $0082 -org $aaba00 ;PC 153a00 +org $aab9b0 ;PC 1539b0 OWTileWorldAssoc: 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 $00, $00 -org $aabb00 ;PC 153b00 +org $aaba70 ;PC 153a70 OWTileMapAlt: 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 + +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 \ No newline at end of file diff --git a/data/base2current.bps b/data/base2current.bps index 52e4e07c704403b489d94ed7510bf4ac972dc0f3..9e8c66e6f28d20e47f2a3afbf45daccad2b38606 100644 GIT binary patch delta 21133 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 OYk%|+{O{Nri~k270uTrQ diff --git a/mystery_example.yml b/mystery_example.yml index 41a46ca6..ab7ffe63 100644 --- a/mystery_example.yml +++ b/mystery_example.yml @@ -22,6 +22,9 @@ vanilla: 0 balanced: 1 random: 1 + bonk_drops: + on: 1 + off: 1 door_shuffle: vanilla: 0 basic: 2 diff --git a/source/item/FillUtil.py b/source/item/FillUtil.py index 9acdb45b..bf48c755 100644 --- a/source/item/FillUtil.py +++ b/source/item/FillUtil.py @@ -792,8 +792,8 @@ trash_items = { 'Bee Trap': 0, '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, - 'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, - 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4, + 'Bombs (3)': 3, 'Arrows (10)': 3, 'Bombs (10)': 3, 'Apples': 3, + 'Fairy': 4, 'Big Magic': 4, 'Red Potion': 4, 'Blue Shield': 4, 'Rupees (50)': 4, 'Rupees (100)': 4, 'Rupees (300)': 5, 'Piece of Heart': 17 }