139 lines
4.3 KiB
Python
139 lines
4.3 KiB
Python
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
|
|
|