LttP: add hint options "Vendors" and "Full"

LttP: fix hint grammar if a Location isn't an ALttPLocation
This commit is contained in:
Fabian Dill 2021-11-27 22:57:54 +01:00
parent 5ca737886b
commit 9f0a8e6d48
3 changed files with 183 additions and 164 deletions

View File

@ -255,14 +255,18 @@ class MultiWorld():
def get_items(self) -> list: def get_items(self) -> list:
return [loc.item for loc in self.get_filled_locations()] + self.itempool return [loc.item for loc in self.get_filled_locations()] + self.itempool
def find_items(self, item, player: int) -> List[Location]: def find_item_locations(self, item, player: int) -> List[Location]:
return [location for location in self.get_locations() if return [location for location in self.get_locations() if
location.item is not None and location.item.name == item and location.item.player == player] location.item and location.item.name == item and location.item.player == player]
def find_item(self, item, player: int) -> Location: def find_item(self, item, player: int) -> Location:
return next(location for location in self.get_locations() if return next(location for location in self.get_locations() if
location.item and location.item.name == item and location.item.player == player) location.item and location.item.name == item and location.item.player == player)
def find_items_in_locations(self, items: Set[str], player: int) -> List[Location]:
return [location for location in self.get_locations() if
location.item and location.item.name in items and location.item.player == player]
def create_item(self, item_name: str, player: int) -> Item: def create_item(self, item_name: str, player: int) -> Item:
return self.worlds[player].create_item(item_name) return self.worlds[player].create_item(item_name)

View File

@ -145,10 +145,17 @@ class RestrictBossItem(Toggle):
displayname = "Prevent Dungeon Item on Boss" displayname = "Prevent Dungeon Item on Boss"
class Hints(DefaultOnToggle): class Hints(Choice):
"""Put item and entrance placement hints on telepathic tiles and some NPCs. """Vendors: King Zora and Bottle Merchant say what they're selling.
Additionally King Zora and Bottle Merchant say what they're selling.""" On/Full: Put item and entrance placement hints on telepathic tiles and some NPCs, Full removes joke hints."""
displayname = "Hints" displayname = "Hints"
option_off = 0
option_vendors = 1
option_on = 2
option_full = 3
default = 2
alias_false = 0
alias_true = 2
class EnemyShuffle(Toggle): class EnemyShuffle(Toggle):

View File

@ -21,8 +21,7 @@ import concurrent.futures
import bsdiff4 import bsdiff4
from typing import Optional from typing import Optional
from BaseClasses import CollectionState, Region from BaseClasses import CollectionState, Region, Location
from worlds.alttp.SubClasses import ALttPLocation
from worlds.alttp.Shops import ShopType, ShopPriceType from worlds.alttp.Shops import ShopType, ShopPriceType
from worlds.alttp.Dungeons import dungeon_music_addresses from worlds.alttp.Dungeons import dungeon_music_addresses
from worlds.alttp.Regions import location_table, old_location_address_to_new_location_address from worlds.alttp.Regions import location_table, old_location_address_to_new_location_address
@ -1535,7 +1534,7 @@ def patch_rom(world, rom, player, enemized):
} }
def get_reveal_bytes(itemName): def get_reveal_bytes(itemName):
locations = world.find_items(itemName, player) locations = world.find_item_locations(itemName, player)
if len(locations) < 1: if len(locations) < 1:
return 0x0000 return 0x0000
location = locations[0] location = locations[0]
@ -2114,7 +2113,7 @@ def write_strings(rom, world, player):
if dest.player != player: if dest.player != player:
if ped_hint: if ped_hint:
hint += f" for {world.player_name[dest.player]}!" hint += f" for {world.player_name[dest.player]}!"
elif type(dest) in [Region, ALttPLocation]: elif isinstance(dest, (Region, Location)):
hint += f" in {world.player_name[dest.player]}'s world" hint += f" in {world.player_name[dest.player]}'s world"
else: else:
hint += f" for {world.player_name[dest.player]}" hint += f" for {world.player_name[dest.player]}"
@ -2130,7 +2129,10 @@ def write_strings(rom, world, player):
vendor_location = world.get_location("Bottle Merchant", player) vendor_location = world.get_location("Bottle Merchant", player)
tt['bottle_vendor_choice'] = f"I gots {hint_text(vendor_location.item)}\nYous gots 100 rupees?" \ tt['bottle_vendor_choice'] = f"I gots {hint_text(vendor_location.item)}\nYous gots 100 rupees?" \
f"\n ≥ I want\n no way!\n{{CHOICE}}" f"\n ≥ I want\n no way!\n{{CHOICE}}"
if world.hints[player].value >= 2:
if world.hints[player] == "full":
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles have hints!'
else:
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!' tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
hint_locations = HintLocations.copy() hint_locations = HintLocations.copy()
local_random.shuffle(hint_locations) local_random.shuffle(hint_locations)
@ -2172,7 +2174,8 @@ def write_strings(rom, world, player):
else: else:
break break
# Next we handle hints for randomly selected other entrances, curating the selection intelligently based on shuffle. # Next we handle hints for randomly selected other entrances,
# curating the selection intelligently based on shuffle.
if world.shuffle[player] not in ['simple', 'restricted', 'restricted_legacy']: if world.shuffle[player] not in ['simple', 'restricted', 'restricted_legacy']:
entrances_to_hint.update(ConnectorEntrances) entrances_to_hint.update(ConnectorEntrances)
entrances_to_hint.update(DungeonEntrances) entrances_to_hint.update(DungeonEntrances)
@ -2275,18 +2278,23 @@ def write_strings(rom, world, player):
if world.bigkey_shuffle[player]: if world.bigkey_shuffle[player]:
items_to_hint.extend(BigKeys) items_to_hint.extend(BigKeys)
local_random.shuffle(items_to_hint) local_random.shuffle(items_to_hint)
if world.hints[player] == "full":
hint_count = len(hint_locations) # fill all remaining hint locations with Item hints.
else:
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull', hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull',
'dungeonscrossed'] else 8 'dungeonscrossed'] else 8
while hint_count > 0 and items_to_hint: hint_count = min(hint_count, len(items_to_hint), len(hint_locations))
this_item = items_to_hint.pop(0) if hint_count:
this_location = world.find_items(this_item, player) locations = world.find_items_in_locations(set(items_to_hint), player)
if this_location: local_random.shuffle(locations)
local_random.shuffle(this_location) for x in range(hint_count):
this_hint = this_location[0].item.hint_text + ' can be found ' + hint_text(this_location[0]) + '.' this_location = locations.pop()
this_hint = this_location.item.hint_text + ' can be found ' + hint_text(this_location) + '.'
tt[hint_locations.pop(0)] = this_hint tt[hint_locations.pop(0)] = this_hint
hint_count -= 1
# All remaining hint slots are filled with junk hints. It is done this way to ensure the same junk hint isn't selected twice. if hint_locations:
# All remaining hint slots are filled with junk hints.
# It is done this way to ensure the same junk hint isn't selected twice.
junk_hints = junk_texts.copy() junk_hints = junk_texts.copy()
local_random.shuffle(junk_hints) local_random.shuffle(junk_hints)
for location, text in zip(hint_locations, junk_hints): for location, text in zip(hint_locations, junk_hints):
@ -2294,7 +2302,7 @@ def write_strings(rom, world, player):
# We still need the older hints of course. Those are done here. # We still need the older hints of course. Those are done here.
silverarrows = world.find_items('Silver Bow', player) silverarrows = world.find_item_locations('Silver Bow', player)
local_random.shuffle(silverarrows) local_random.shuffle(silverarrows)
silverarrow_hint = ( silverarrow_hint = (
' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!' ' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
@ -2302,7 +2310,7 @@ def write_strings(rom, world, player):
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
if world.worlds[player].has_progressive_bows and (world.difficulty_requirements[player].progressive_bow_limit >= 2 or ( if world.worlds[player].has_progressive_bows and (world.difficulty_requirements[player].progressive_bow_limit >= 2 or (
world.swordless[player] or world.logic[player] == 'noglitches')): world.swordless[player] or world.logic[player] == 'noglitches')):
prog_bow_locs = world.find_items('Progressive Bow', player) prog_bow_locs = world.find_item_locations('Progressive Bow', player)
world.slot_seeds[player].shuffle(prog_bow_locs) world.slot_seeds[player].shuffle(prog_bow_locs)
found_bow = False found_bow = False
found_bow_alt = False found_bow_alt = False