def add_default_hints_to_patches( rng: Random, patches: GamePatches, world_list: WorldList, ) -> GamePatches: """ Adds hints for the locations :param rng: :param patches: :param world_list: :return: """ for node in world_list.all_nodes: if isinstance( node, LogbookNode) and node.lore_type == LoreType.LUMINOTH_WARRIOR: patches = patches.assign_hint( node.resource(), Hint( HintType.KEYBEARER, PrecisionPair(HintLocationPrecision.DETAILED, HintItemPrecision.PRECISE_CATEGORY), PickupIndex(node.hint_index))) # TODO: this should be a flag in PickupNode indices_with_hint = [ (PickupIndex(24), HintType.LIGHT_SUIT_LOCATION), # Light Suit (PickupIndex(43), HintType.GUARDIAN), # Dark Suit (Amorbis) (PickupIndex(79), HintType.GUARDIAN), # Dark Visor (Chykka) (PickupIndex(115), HintType.GUARDIAN), # Annihilator Beam (Quadraxis) ] all_logbook_assets = [ node.resource() for node in world_list.all_nodes if isinstance(node, LogbookNode) and node.resource() not in patches.hints and node.lore_type.holds_generic_hint ] rng.shuffle(indices_with_hint) rng.shuffle(all_logbook_assets) for index, hint_type in indices_with_hint: if not all_logbook_assets: break logbook_asset = all_logbook_assets.pop() patches = patches.assign_hint( logbook_asset, Hint(hint_type, PrecisionPair.detailed(), index)) return patches
async def assign_joke_hints(self, patches: GamePatches, identifiers: list[NodeIdentifier], prefill: PreFillParams) -> GamePatches: all_hint_identifiers = [identifier for identifier in identifiers if identifier not in patches.hints] prefill.rng.shuffle(all_hint_identifiers) num_joke = self.num_joke_hints while num_joke > 0 and all_hint_identifiers: identifier = all_hint_identifiers.pop() patches = patches.assign_hint(identifier, Hint(HintType.JOKE, None)) num_joke -= 1 identifiers.remove(identifier) return patches
async def assign_guaranteed_indices_hints(self, patches: GamePatches, identifiers: list[NodeIdentifier], prefill: PreFillParams) -> GamePatches: # Specific Pickup/any LogbookNode Hints indices_with_hint = await self.get_guranteed_hints(patches, prefill) prefill.rng.shuffle(indices_with_hint) all_hint_identifiers = [identifier for identifier in identifiers if identifier not in patches.hints] prefill.rng.shuffle(all_hint_identifiers) for index, precision in indices_with_hint: if not all_hint_identifiers: break identifier = all_hint_identifiers.pop() patches = patches.assign_hint(identifier, Hint(HintType.LOCATION, precision, index)) identifiers.remove(identifier) return patches
async def assign_specific_location_hints(self, patches: GamePatches, prefill: PreFillParams) -> GamePatches: specific_location_precisions = await self.get_specific_pickup_precision_pair_overrides(patches, prefill) # TODO: this is an Echoes default. Should not have a default and all nodes have one in the DB. default_precision = PrecisionPair(HintLocationPrecision.KEYBEARER, HintItemPrecision.BROAD_CATEGORY, include_owner=True) wl = prefill.game.world_list for node in wl.iterate_nodes(): if isinstance(node, LogbookNode) and node.lore_type == LoreType.SPECIFIC_PICKUP: identifier = wl.identifier_for_node(node) patches = patches.assign_hint( identifier, Hint(HintType.LOCATION, specific_location_precisions.get(identifier, default_precision), PickupIndex(node.hint_index)) ) return patches
async def assign_other_hints(self, patches: GamePatches, identifiers: list[NodeIdentifier], prefill: PreFillParams) -> GamePatches: all_hint_identifiers = [ identifier for identifier in identifiers if identifier not in patches.hints ] prefill.rng.shuffle(all_hint_identifiers) # Dark Temple hints temple_hints = list(enum_lib.iterate_enum(HintDarkTemple)) while all_hint_identifiers and temple_hints: identifier = all_hint_identifiers.pop() patches = patches.assign_hint( identifier, Hint(HintType.RED_TEMPLE_KEY_SET, None, dark_temple=temple_hints.pop(0))) identifiers.remove(identifier) return patches
def add_echoes_default_hints_to_patches( rng: Random, patches: GamePatches, world_list: WorldList, num_joke: int, is_multiworld: bool, ) -> GamePatches: """ Adds hints that are present on all games. :param rng: :param patches: :param world_list: :param num_joke :param is_multiworld :return: """ for node in world_list.all_nodes: if isinstance( node, LogbookNode) and node.lore_type == LoreType.LUMINOTH_WARRIOR: patches = patches.assign_hint( node.resource(), Hint( HintType.LOCATION, PrecisionPair(HintLocationPrecision.KEYBEARER, HintItemPrecision.BROAD_CATEGORY, include_owner=True), PickupIndex(node.hint_index))) all_logbook_assets = [ node.resource() for node in world_list.all_nodes if isinstance(node, LogbookNode) and node.resource() not in patches.hints and node.lore_type.holds_generic_hint ] rng.shuffle(all_logbook_assets) # The 4 guaranteed hints indices_with_hint = [ (PickupIndex(24), HintLocationPrecision.LIGHT_SUIT_LOCATION), # Light Suit (PickupIndex(43), HintLocationPrecision.GUARDIAN), # Dark Suit (Amorbis) (PickupIndex(79), HintLocationPrecision.GUARDIAN), # Dark Visor (Chykka) (PickupIndex(115), HintLocationPrecision.GUARDIAN), # Annihilator Beam (Quadraxis) ] rng.shuffle(indices_with_hint) for index, location_type in indices_with_hint: if not all_logbook_assets: break logbook_asset = all_logbook_assets.pop() patches = patches.assign_hint( logbook_asset, Hint( HintType.LOCATION, PrecisionPair(location_type, HintItemPrecision.DETAILED, include_owner=False), index)) # Dark Temple hints temple_hints = list(iterate_enum(HintDarkTemple)) while all_logbook_assets and temple_hints: logbook_asset = all_logbook_assets.pop() patches = patches.assign_hint( logbook_asset, Hint(HintType.RED_TEMPLE_KEY_SET, None, dark_temple=temple_hints.pop(0))) # Jokes while num_joke > 0 and all_logbook_assets: logbook_asset = all_logbook_assets.pop() patches = patches.assign_hint(logbook_asset, Hint(HintType.JOKE, None)) num_joke -= 1 return patches