from enum import Enum from .LocationList import location_table from BaseClasses import Location non_indexed_location_types = {'Boss', 'Event', 'Drop', 'HintStone', 'Hint'} location_id_offset = 67000 locnames_pre_70 = { "Gift from Sages", "ZR Frogs Zeldas Lullaby", "ZR Frogs Eponas Song", "ZR Frogs Sarias Song", "ZR Frogs Suns Song", "ZR Frogs Song of Time", } loctypes_70 = {'Beehive', 'Pot', 'FlyingPot', 'Crate', 'SmallCrate', 'RupeeTower', 'Freestanding', 'ActorOverride'} new_name_order = sorted(location_table.keys(), key=lambda name: 2 if location_table[name][0] in loctypes_70 else 1 if name in locnames_pre_70 else 0) location_name_to_id = {name: (location_id_offset + index) for (index, name) in enumerate(new_name_order) if location_table[name][0] not in non_indexed_location_types} class DisableType(Enum): ENABLED = 0 PENDING = 1 DISABLED = 2 class OOTLocation(Location): game: str = 'Ocarina of Time' def __init__(self, player, name='', code=None, address1=None, address2=None, default=None, type='Chest', scene=None, parent=None, filter_tags=None, internal=False, vanilla_item=None ): super(OOTLocation, self).__init__(player, name, code, parent) self.address1 = address1 self.address2 = address2 self.default = default self.type = type self.scene = scene self.internal = internal self.vanilla_item = vanilla_item if filter_tags is None: self.filter_tags = None else: self.filter_tags = list(filter_tags) self.never = False # no idea what this does self.disabled = DisableType.ENABLED @property def dungeon(self): return self.parent_region.dungeon def LocationFactory(locations, player: int): ret = [] singleton = False if isinstance(locations, str): locations = [locations] singleton = True for location in locations: if location in location_table: match_location = location else: match_location = next(filter(lambda k: k.lower() == location.lower(), location_table), None) if match_location: type, scene, default, addresses, vanilla_item, filter_tags = location_table[match_location] if addresses is None: addresses = (None, None) address1, address2 = addresses ret.append(OOTLocation(player, match_location, location_name_to_id.get(match_location, None), address1, address2, default, type, scene, filter_tags=filter_tags, vanilla_item=vanilla_item)) else: raise KeyError('Unknown Location: %s', location) if singleton: return ret[0] return ret def build_location_name_groups() -> dict: def fix_sing(t) -> tuple: if isinstance(t, str): return (t,) return t def rename(d, k1, k2) -> None: d[k2] = d[k1] del d[k1] # whoever wrote the location table didn't realize they need to add a comma to mark a singleton as a tuple # so we have to check types unfortunately tags = set() for v in location_table.values(): if v[5] is not None: tags.update(fix_sing(v[5])) sorted_tags = sorted(list(tags)) ret = { tag: {k for k, v in location_table.items() if v[5] is not None and tag in fix_sing(v[5]) and v[0] not in non_indexed_location_types} for tag in sorted_tags } # Delete tags which are a combination of other tags del ret['Death Mountain'] del ret['Forest'] del ret['Gerudo'] del ret['Kakariko'] del ret['Market'] # Delete Vanilla and MQ tags because they are just way too broad del ret['Vanilla'] del ret['Master Quest'] rename(ret, 'Beehive', 'Beehives') rename(ret, 'Cow', 'Cows') rename(ret, 'Crate', 'Crates') rename(ret, 'Deku Scrub', 'Deku Scrubs') rename(ret, 'FlyingPot', 'Flying Pots') rename(ret, 'Freestanding', 'Freestanding Items') rename(ret, 'Pot', 'Pots') rename(ret, 'RupeeTower', 'Rupee Groups') rename(ret, 'SmallCrate', 'Small Crates') rename(ret, 'the Market', 'Market') rename(ret, 'the Graveyard', 'Graveyard') rename(ret, 'the Lost Woods', 'Lost Woods') return ret