@@ -83,6 +83,11 @@ class TunicWorld(World):
83
83
shop_num : int = 1 # need to make it so that you can walk out of shops, but also that they aren't all connected
84
84
er_regions : Dict [str , RegionInfo ] # absolutely needed so outlet regions work
85
85
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
+
86
91
def generate_early (self ) -> None :
87
92
if self .options .logic_rules >= LogicRules .option_no_major_glitches :
88
93
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:
387
392
if hint_text :
388
393
hint_data [self .player ][location .address ] = hint_text
389
394
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
+
390
407
def fill_slot_data (self ) -> Dict [str , Any ]:
391
408
slot_data : Dict [str , Any ] = {
392
409
"seed" : self .random .randint (0 , 2147483647 ),
@@ -412,12 +429,34 @@ def fill_slot_data(self) -> Dict[str, Any]:
412
429
"disable_local_spoiler" : int (self .settings .disable_local_spoiler or self .multiworld .is_race ),
413
430
}
414
431
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
+
415
454
for tunic_item in filter (lambda item : item .location is not None and item .code is not None , self .slot_data_items ):
416
455
if tunic_item .name not in slot_data :
417
456
slot_data [tunic_item .name ] = []
418
457
if tunic_item .name == gold_hexagon and len (slot_data [gold_hexagon ]) >= 6 :
419
458
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 ) )
421
460
422
461
for start_item in self .options .start_inventory_from_pool :
423
462
if start_item in slot_data_item_names :
@@ -436,7 +475,7 @@ def fill_slot_data(self) -> Dict[str, Any]:
436
475
if item in slot_data_item_names :
437
476
slot_data [item ] = []
438
477
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 ) )
440
479
441
480
return slot_data
442
481
0 commit comments