Skip to content

Commit 5729b78

Browse files
TUNIC: Fix it so item linked locations are correct in slot data (ArchipelagoMW#4105)
* Fix it so item linked locations are correct in slot data * List -> Set * Cache the locations instead * Just loop the multiworld once * Move it all to fill slot data and pretend we're doing a stage * Move groups up so it doesn't loop over the multiworld locations if no item links are present * Update worlds/tunic/__init__.py Co-authored-by: Mysteryem <Mysteryem@users.noreply.github.com> --------- Co-authored-by: Mysteryem <Mysteryem@users.noreply.github.com>
1 parent ba50c94 commit 5729b78

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

worlds/tunic/__init__.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ class TunicWorld(World):
8383
shop_num: int = 1 # need to make it so that you can walk out of shops, but also that they aren't all connected
8484
er_regions: Dict[str, RegionInfo] # absolutely needed so outlet regions work
8585

86+
# so we only loop the multiworld locations once
87+
# if these are locations instead of their info, it gives a memory leak error
88+
item_link_locations: Dict[int, Dict[str, List[Tuple[int, str]]]] = {}
89+
player_item_link_locations: Dict[str, List[Location]]
90+
8691
def generate_early(self) -> None:
8792
if self.options.logic_rules >= LogicRules.option_no_major_glitches:
8893
self.options.laurels_zips.value = LaurelsZips.option_true
@@ -387,6 +392,18 @@ def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]) -> None:
387392
if hint_text:
388393
hint_data[self.player][location.address] = hint_text
389394

395+
def get_real_location(self, location: Location) -> Tuple[str, int]:
396+
# if it's not in a group, it's not in an item link
397+
if location.player not in self.multiworld.groups or not location.item:
398+
return location.name, location.player
399+
try:
400+
loc = self.player_item_link_locations[location.item.name].pop()
401+
return loc.name, loc.player
402+
except IndexError:
403+
warning(f"TUNIC: Failed to parse item location for in-game hints for {self.player_name}. "
404+
f"Using a potentially incorrect location name instead.")
405+
return location.name, location.player
406+
390407
def fill_slot_data(self) -> Dict[str, Any]:
391408
slot_data: Dict[str, Any] = {
392409
"seed": self.random.randint(0, 2147483647),
@@ -412,12 +429,34 @@ def fill_slot_data(self) -> Dict[str, Any]:
412429
"disable_local_spoiler": int(self.settings.disable_local_spoiler or self.multiworld.is_race),
413430
}
414431

432+
# this would be in a stage if there was an appropriate stage for it
433+
self.player_item_link_locations = {}
434+
groups = self.multiworld.get_player_groups(self.player)
435+
if groups:
436+
if not self.item_link_locations:
437+
tunic_worlds: Tuple[TunicWorld] = self.multiworld.get_game_worlds("TUNIC")
438+
# figure out our groups and the items in them
439+
for tunic in tunic_worlds:
440+
for group in self.multiworld.get_player_groups(tunic.player):
441+
self.item_link_locations.setdefault(group, {})
442+
for location in self.multiworld.get_locations():
443+
if location.item and location.item.player in self.item_link_locations.keys():
444+
(self.item_link_locations[location.item.player].setdefault(location.item.name, [])
445+
.append((location.player, location.name)))
446+
447+
# if item links are on, set up the player's personal item link locations, so we can pop them as needed
448+
for group, item_links in self.item_link_locations.items():
449+
if group in groups:
450+
for item_name, locs in item_links.items():
451+
self.player_item_link_locations[item_name] = \
452+
[self.multiworld.get_location(location_name, player) for player, location_name in locs]
453+
415454
for tunic_item in filter(lambda item: item.location is not None and item.code is not None, self.slot_data_items):
416455
if tunic_item.name not in slot_data:
417456
slot_data[tunic_item.name] = []
418457
if tunic_item.name == gold_hexagon and len(slot_data[gold_hexagon]) >= 6:
419458
continue
420-
slot_data[tunic_item.name].extend([tunic_item.location.name, tunic_item.location.player])
459+
slot_data[tunic_item.name].extend(self.get_real_location(tunic_item.location))
421460

422461
for start_item in self.options.start_inventory_from_pool:
423462
if start_item in slot_data_item_names:
@@ -436,7 +475,7 @@ def fill_slot_data(self) -> Dict[str, Any]:
436475
if item in slot_data_item_names:
437476
slot_data[item] = []
438477
for item_location in self.multiworld.find_item_locations(item, self.player):
439-
slot_data[item].extend([item_location.name, item_location.player])
478+
slot_data[item].extend(self.get_real_location(item_location))
440479

441480
return slot_data
442481

0 commit comments

Comments
 (0)