import typing from BaseClasses import Item def oot_data_to_ap_id(data, event): if event or data[2] is None or data[0] == 'Shop': return None offset = 66000 if data[0] in ['Item', 'BossKey', 'Compass', 'Map', 'SmallKey', 'Token', 'GanonBossKey', 'FortressSmallKey', 'Song']: return offset + data[2] else: raise Exception(f'Unexpected OOT item type found: {data[0]}') def ap_id_to_oot_data(ap_id): offset = 66000 val = ap_id - offset try: return list(filter(lambda d: d[1][0] == 'Item' and d[1][2] == val, item_table.items()))[0] except IndexError: raise Exception(f'Could not find desired item ID: {ap_id}') class OOTItem(Item): game: str = "Ocarina of Time" def __init__(self, name, player, data, event, force_not_advancement): (type, advancement, index, special) = data # "advancement" is True, False or None; some items are not advancement based on settings adv = bool(advancement) and not force_not_advancement super(OOTItem, self).__init__(name, adv, oot_data_to_ap_id(data, event), player) self.type = type self.index = index self.special = special or {} self.looks_like_item = None self.price = special.get('price', None) if special else None self.internal = False if force_not_advancement: self.never_exclude = True # The playthrough calculation calls a function that uses "sweep_for_events(key_only=True)" # This checks if the item it's looking for is a small key, using the small key property. # Because of overlapping item fields, this means that OoT small keys are technically counted, unless we do this. # This causes them to be double-collected during playthrough and generation. @property def smallkey(self) -> bool: return False @property def bigkey(self) -> bool: return False @property def dungeonitem(self) -> bool: return self.type in ['SmallKey', 'FortressSmallKey', 'BossKey', 'GanonBossKey', 'Map', 'Compass'] # Progressive: True -> Advancement # False -> Priority # None -> Normal # Item: (type, Progressive, GetItemID, special), item_table = { 'Bombs (5)': ('Item', None, 0x01, None), 'Deku Nuts (5)': ('Item', None, 0x02, None), 'Bombchus (10)': ('Item', True, 0x03, None), 'Boomerang': ('Item', True, 0x06, None), 'Deku Stick (1)': ('Item', None, 0x07, None), 'Lens of Truth': ('Item', True, 0x0A, None), 'Megaton Hammer': ('Item', True, 0x0D, None), 'Cojiro': ('Item', True, 0x0E, None), 'Bottle': ('Item', True, 0x0F, {'bottle': float('Inf')}), 'Bottle with Milk': ('Item', True, 0x14, {'bottle': float('Inf')}), 'Rutos Letter': ('Item', True, 0x15, None), 'Deliver Letter': ('Item', True, None, {'bottle': float('Inf')}), 'Sell Big Poe': ('Item', True, None, {'bottle': float('Inf')}), 'Magic Bean': ('Item', True, 0x16, None), 'Skull Mask': ('Item', True, 0x17, None), 'Spooky Mask': ('Item', None, 0x18, None), 'Keaton Mask': ('Item', None, 0x1A, None), 'Bunny Hood': ('Item', None, 0x1B, None), 'Mask of Truth': ('Item', True, 0x1C, None), 'Pocket Egg': ('Item', True, 0x1D, None), 'Pocket Cucco': ('Item', True, 0x1E, None), 'Odd Mushroom': ('Item', True, 0x1F, None), 'Odd Potion': ('Item', True, 0x20, None), 'Poachers Saw': ('Item', True, 0x21, None), 'Broken Sword': ('Item', True, 0x22, None), 'Prescription': ('Item', True, 0x23, None), 'Eyeball Frog': ('Item', True, 0x24, None), 'Eyedrops': ('Item', True, 0x25, None), 'Claim Check': ('Item', True, 0x26, None), 'Kokiri Sword': ('Item', True, 0x27, None), 'Giants Knife': ('Item', True, 0x28, None), 'Deku Shield': ('Item', None, 0x29, None), 'Hylian Shield': ('Item', None, 0x2A, None), 'Mirror Shield': ('Item', True, 0x2B, None), 'Goron Tunic': ('Item', True, 0x2C, None), 'Zora Tunic': ('Item', True, 0x2D, None), 'Iron Boots': ('Item', True, 0x2E, None), 'Hover Boots': ('Item', True, 0x2F, None), 'Stone of Agony': ('Item', True, 0x39, None), 'Gerudo Membership Card': ('Item', True, 0x3A, None), 'Heart Container': ('Item', None, 0x3D, None), 'Piece of Heart': ('Item', None, 0x3E, None), 'Boss Key': ('BossKey', True, 0x3F, None), 'Compass': ('Compass', None, 0x40, None), 'Map': ('Map', None, 0x41, None), 'Small Key': ('SmallKey', True, 0x42, {'progressive': float('Inf')}), 'Weird Egg': ('Item', True, 0x47, None), 'Recovery Heart': ('Item', None, 0x48, None), 'Arrows (5)': ('Item', None, 0x49, None), 'Arrows (10)': ('Item', None, 0x4A, None), 'Arrows (30)': ('Item', None, 0x4B, None), 'Rupee (1)': ('Item', None, 0x4C, None), 'Rupees (5)': ('Item', None, 0x4D, None), 'Rupees (20)': ('Item', None, 0x4E, None), 'Heart Container (Boss)': ('Item', None, 0x4F, None), 'Milk': ('Item', None, 0x50, None), 'Goron Mask': ('Item', None, 0x51, None), 'Zora Mask': ('Item', None, 0x52, None), 'Gerudo Mask': ('Item', None, 0x53, None), 'Rupees (50)': ('Item', None, 0x55, None), 'Rupees (200)': ('Item', None, 0x56, None), 'Biggoron Sword': ('Item', True, 0x57, None), 'Fire Arrows': ('Item', True, 0x58, None), 'Ice Arrows': ('Item', True, 0x59, None), 'Light Arrows': ('Item', True, 0x5A, None), 'Gold Skulltula Token': ('Token', True, 0x5B, {'progressive': float('Inf')}), 'Dins Fire': ('Item', True, 0x5C, None), 'Nayrus Love': ('Item', True, 0x5E, None), 'Farores Wind': ('Item', True, 0x5D, None), 'Deku Nuts (10)': ('Item', None, 0x64, None), 'Bombs (10)': ('Item', None, 0x66, None), 'Bombs (20)': ('Item', None, 0x67, None), 'Deku Seeds (30)': ('Item', None, 0x69, None), 'Bombchus (5)': ('Item', True, 0x6A, None), 'Bombchus (20)': ('Item', True, 0x6B, None), 'Rupee (Treasure Chest Game)': ('Item', None, 0x72, None), 'Piece of Heart (Treasure Chest Game)': ('Item', None, 0x76, None), 'Ice Trap': ('Item', None, 0x7C, None), 'Progressive Hookshot': ('Item', True, 0x80, {'progressive': 2}), 'Progressive Strength Upgrade': ('Item', True, 0x81, {'progressive': 3}), 'Bomb Bag': ('Item', True, 0x82, None), 'Bow': ('Item', True, 0x83, None), 'Slingshot': ('Item', True, 0x84, None), 'Progressive Wallet': ('Item', True, 0x85, {'progressive': 3}), 'Progressive Scale': ('Item', True, 0x86, {'progressive': 2}), 'Deku Nut Capacity': ('Item', None, 0x87, None), 'Deku Stick Capacity': ('Item', None, 0x88, None), 'Bombchus': ('Item', True, 0x89, None), 'Magic Meter': ('Item', True, 0x8A, None), 'Ocarina': ('Item', True, 0x8B, None), 'Bottle with Red Potion': ('Item', True, 0x8C, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Green Potion': ('Item', True, 0x8D, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Blue Potion': ('Item', True, 0x8E, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Fairy': ('Item', True, 0x8F, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Fish': ('Item', True, 0x90, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Blue Fire': ('Item', True, 0x91, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Bugs': ('Item', True, 0x92, {'bottle': True, 'shop_object': 0x0F}), 'Bottle with Big Poe': ('Item', True, 0x93, {'shop_object': 0x0F}), 'Bottle with Poe': ('Item', True, 0x94, {'bottle': True, 'shop_object': 0x0F}), 'Boss Key (Forest Temple)': ('BossKey', True, 0x95, None), 'Boss Key (Fire Temple)': ('BossKey', True, 0x96, None), 'Boss Key (Water Temple)': ('BossKey', True, 0x97, None), 'Boss Key (Spirit Temple)': ('BossKey', True, 0x98, None), 'Boss Key (Shadow Temple)': ('BossKey', True, 0x99, None), 'Boss Key (Ganons Castle)': ('GanonBossKey',True,0x9A,None), 'Compass (Deku Tree)': ('Compass', None, 0x9B, None), 'Compass (Dodongos Cavern)': ('Compass', None, 0x9C, None), 'Compass (Jabu Jabus Belly)': ('Compass', None, 0x9D, None), 'Compass (Forest Temple)': ('Compass', None, 0x9E, None), 'Compass (Fire Temple)': ('Compass', None, 0x9F, None), 'Compass (Water Temple)': ('Compass', None, 0xA0, None), 'Compass (Spirit Temple)': ('Compass', None, 0xA1, None), 'Compass (Shadow Temple)': ('Compass', None, 0xA2, None), 'Compass (Bottom of the Well)': ('Compass', None, 0xA3, None), 'Compass (Ice Cavern)': ('Compass', None, 0xA4, None), 'Map (Deku Tree)': ('Map', None, 0xA5, None), 'Map (Dodongos Cavern)': ('Map', None, 0xA6, None), 'Map (Jabu Jabus Belly)': ('Map', None, 0xA7, None), 'Map (Forest Temple)': ('Map', None, 0xA8, None), 'Map (Fire Temple)': ('Map', None, 0xA9, None), 'Map (Water Temple)': ('Map', None, 0xAA, None), 'Map (Spirit Temple)': ('Map', None, 0xAB, None), 'Map (Shadow Temple)': ('Map', None, 0xAC, None), 'Map (Bottom of the Well)': ('Map', None, 0xAD, None), 'Map (Ice Cavern)': ('Map', None, 0xAE, None), 'Small Key (Forest Temple)': ('SmallKey', True, 0xAF, {'progressive': float('Inf')}), 'Small Key (Fire Temple)': ('SmallKey', True, 0xB0, {'progressive': float('Inf')}), 'Small Key (Water Temple)': ('SmallKey', True, 0xB1, {'progressive': float('Inf')}), 'Small Key (Spirit Temple)': ('SmallKey', True, 0xB2, {'progressive': float('Inf')}), 'Small Key (Shadow Temple)': ('SmallKey', True, 0xB3, {'progressive': float('Inf')}), 'Small Key (Bottom of the Well)': ('SmallKey', True, 0xB4, {'progressive': float('Inf')}), 'Small Key (Gerudo Training Grounds)': ('SmallKey',True, 0xB5, {'progressive': float('Inf')}), 'Small Key (Gerudo Fortress)': ('FortressSmallKey',True, 0xB6, {'progressive': float('Inf')}), 'Small Key (Ganons Castle)': ('SmallKey', True, 0xB7, {'progressive': float('Inf')}), 'Double Defense': ('Item', True, 0xB8, None), 'Magic Bean Pack': ('Item', True, 0xC9, None), 'Triforce Piece': ('Item', True, 0xCA, {'progressive': float('Inf')}), 'Zeldas Letter': ('Item', True, 0x0B, None), 'Time Travel': ('Event', True, None, None), 'Scarecrow Song': ('Event', True, None, None), 'Triforce': ('Event', True, None, None), # Event items otherwise generated by generic event logic # can be defined here to enforce their appearance in playthroughs. 'Water Temple Clear': ('Event', True, None, None), 'Forest Trial Clear': ('Event', True, None, None), 'Fire Trial Clear': ('Event', True, None, None), 'Water Trial Clear': ('Event', True, None, None), 'Shadow Trial Clear': ('Event', True, None, None), 'Spirit Trial Clear': ('Event', True, None, None), 'Light Trial Clear': ('Event', True, None, None), 'Deku Stick Drop': ('Drop', True, None, None), 'Deku Nut Drop': ('Drop', True, None, None), 'Blue Fire': ('Drop', True, None, None), 'Fairy': ('Drop', True, None, None), 'Fish': ('Drop', True, None, None), 'Bugs': ('Drop', True, None, None), 'Big Poe': ('Drop', True, None, None), 'Bombchu Drop': ('Drop', True, None, None), # Consumable refills defined mostly to placate 'starting with' options 'Arrows': ('Refill', None, None, None), 'Bombs': ('Refill', None, None, None), 'Deku Seeds': ('Refill', None, None, None), 'Deku Sticks': ('Refill', None, None, None), 'Deku Nuts': ('Refill', None, None, None), 'Rupees': ('Refill', None, None, None), 'Minuet of Forest': ('Song', True, 0xBB, { 'text_id': 0x73, 'song_id': 0x02, 'item_id': 0x5A, }), 'Bolero of Fire': ('Song', True, 0xBC, { 'text_id': 0x74, 'song_id': 0x03, 'item_id': 0x5B, }), 'Serenade of Water': ('Song', True, 0xBD, { 'text_id': 0x75, 'song_id': 0x04, 'item_id': 0x5C, }), 'Requiem of Spirit': ('Song', True, 0xBE, { 'text_id': 0x76, 'song_id': 0x05, 'item_id': 0x5D, }), 'Nocturne of Shadow': ('Song', True, 0xBF, { 'text_id': 0x77, 'song_id': 0x06, 'item_id': 0x5E, }), 'Prelude of Light': ('Song', True, 0xC0, { 'text_id': 0x78, 'song_id': 0x07, 'item_id': 0x5F, }), 'Zeldas Lullaby': ('Song', True, 0xC1, { 'text_id': 0xD4, 'song_id': 0x0A, 'item_id': 0x60, }), 'Eponas Song': ('Song', True, 0xC2, { 'text_id': 0xD2, 'song_id': 0x09, 'item_id': 0x61, }), 'Sarias Song': ('Song', True, 0xC3, { 'text_id': 0xD1, 'song_id': 0x08, 'item_id': 0x62, }), 'Suns Song': ('Song', True, 0xC4, { 'text_id': 0xD3, 'song_id': 0x0B, 'item_id': 0x63, }), 'Song of Time': ('Song', True, 0xC5, { 'text_id': 0xD5, 'song_id': 0x0C, 'item_id': 0x64, }), 'Song of Storms': ('Song', True, 0xC6, { 'text_id': 0xD6, 'song_id': 0x0D, 'item_id': 0x65, }), 'Buy Deku Nut (5)': ('Shop', True, 0x00, {'object': 0x00BB, 'price': 15}), 'Buy Arrows (30)': ('Shop', False, 0x01, {'object': 0x00D8, 'price': 60}), 'Buy Arrows (50)': ('Shop', False, 0x02, {'object': 0x00D8, 'price': 90}), 'Buy Bombs (5) [25]': ('Shop', False, 0x03, {'object': 0x00CE, 'price': 25}), 'Buy Deku Nut (10)': ('Shop', True, 0x04, {'object': 0x00BB, 'price': 30}), 'Buy Deku Stick (1)': ('Shop', True, 0x05, {'object': 0x00C7, 'price': 10}), 'Buy Bombs (10)': ('Shop', False, 0x06, {'object': 0x00CE, 'price': 50}), 'Buy Fish': ('Shop', True, 0x07, {'object': 0x00F4, 'price': 200}), 'Buy Red Potion [30]': ('Shop', False, 0x08, {'object': 0x00EB, 'price': 30}), 'Buy Green Potion': ('Shop', False, 0x09, {'object': 0x00EB, 'price': 30}), 'Buy Blue Potion': ('Shop', False, 0x0A, {'object': 0x00EB, 'price': 100}), 'Buy Hylian Shield': ('Shop', True, 0x0C, {'object': 0x00DC, 'price': 80}), 'Buy Deku Shield': ('Shop', True, 0x0D, {'object': 0x00CB, 'price': 40}), 'Buy Goron Tunic': ('Shop', True, 0x0E, {'object': 0x00F2, 'price': 200}), 'Buy Zora Tunic': ('Shop', True, 0x0F, {'object': 0x00F2, 'price': 300}), 'Buy Heart': ('Shop', False, 0x10, {'object': 0x00B7, 'price': 10}), 'Buy Bombchu (10)': ('Shop', True, 0x15, {'object': 0x00D9, 'price': 99}), 'Buy Bombchu (20)': ('Shop', True, 0x16, {'object': 0x00D9, 'price': 180}), 'Buy Bombchu (5)': ('Shop', True, 0x18, {'object': 0x00D9, 'price': 60}), 'Buy Deku Seeds (30)': ('Shop', False, 0x1D, {'object': 0x0119, 'price': 30}), 'Sold Out': ('Shop', False, 0x26, {'object': 0x0148}), 'Buy Blue Fire': ('Shop', True, 0x27, {'object': 0x0173, 'price': 300}), 'Buy Bottle Bug': ('Shop', True, 0x28, {'object': 0x0174, 'price': 50}), 'Buy Poe': ('Shop', False, 0x2A, {'object': 0x0176, 'price': 30}), 'Buy Fairy\'s Spirit': ('Shop', True, 0x2B, {'object': 0x0177, 'price': 50}), 'Buy Arrows (10)': ('Shop', False, 0x2C, {'object': 0x00D8, 'price': 20}), 'Buy Bombs (20)': ('Shop', False, 0x2D, {'object': 0x00CE, 'price': 80}), 'Buy Bombs (30)': ('Shop', False, 0x2E, {'object': 0x00CE, 'price': 120}), 'Buy Bombs (5) [35]': ('Shop', False, 0x2F, {'object': 0x00CE, 'price': 35}), 'Buy Red Potion [40]': ('Shop', False, 0x30, {'object': 0x00EB, 'price': 40}), 'Buy Red Potion [50]': ('Shop', False, 0x31, {'object': 0x00EB, 'price': 50}), 'Kokiri Emerald': ('DungeonReward', True, None, { 'stone': True, 'addr2_data': 0x80, 'bit_mask': 0x00040000, 'item_id': 0x6C, 'actor_type': 0x13, 'object_id': 0x00AD, }), 'Goron Ruby': ('DungeonReward', True, None, { 'stone': True, 'addr2_data': 0x81, 'bit_mask': 0x00080000, 'item_id': 0x6D, 'actor_type': 0x14, 'object_id': 0x00AD, }), 'Zora Sapphire': ('DungeonReward', True, None, { 'stone': True, 'addr2_data': 0x82, 'bit_mask': 0x00100000, 'item_id': 0x6E, 'actor_type': 0x15, 'object_id': 0x00AD, }), 'Forest Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x3E, 'bit_mask': 0x00000001, 'item_id': 0x66, 'actor_type': 0x0B, 'object_id': 0x00BA, }), 'Fire Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x3C, 'bit_mask': 0x00000002, 'item_id': 0x67, 'actor_type': 0x09, 'object_id': 0x00BA, }), 'Water Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x3D, 'bit_mask': 0x00000004, 'item_id': 0x68, 'actor_type': 0x0A, 'object_id': 0x00BA, }), 'Spirit Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x3F, 'bit_mask': 0x00000008, 'item_id': 0x69, 'actor_type': 0x0C, 'object_id': 0x00BA, }), 'Shadow Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x41, 'bit_mask': 0x00000010, 'item_id': 0x6A, 'actor_type': 0x0D, 'object_id': 0x00BA, }), 'Light Medallion': ('DungeonReward', True, None, { 'medallion': True, 'addr2_data': 0x40, 'bit_mask': 0x00000020, 'item_id': 0x6B, 'actor_type': 0x0E, 'object_id': 0x00BA, }), }