diff --git a/HintList.py b/HintList.py index 99423c2636..990faeda10 100644 --- a/HintList.py +++ b/HintList.py @@ -216,8 +216,8 @@ def tokens_required_by_settings(world: World) -> int: conditional_always: dict[str, Callable[[World], bool]] = { 'Market 10 Big Poes': lambda world: world.settings.big_poe_count > 3 and 'big_poes' not in world.settings.misc_hints, 'Deku Theater Mask of Truth': lambda world: not world.settings.complete_mask_quest and 'Mask of Truth' not in world.settings.shuffle_child_trade and 'mask_of_truth' not in world.settings.misc_hints, - 'Song from Ocarina of Time': lambda world: stones_required_by_settings(world) < 2, - 'HF Ocarina of Time Item': lambda world: stones_required_by_settings(world) < 2, + 'Song from Ocarina of Time': lambda world: stones_required_by_settings(world) < 2 and 'song_of_time' not in world.settings.misc_hints, + 'HF Ocarina of Time Item': lambda world: stones_required_by_settings(world) < 2 and 'ocarina_of_time' not in world.settings.misc_hints, 'Sheik in Kakariko': lambda world: medallions_required_by_settings(world) < 5, 'DMT Biggoron': lambda world: ('Claim Check' not in world.settings.adult_trade_start or len(world.settings.adult_trade_start) != 1) and not world.settings.adult_trade_shuffle, 'Kak 30 Gold Skulltula Reward': lambda world: tokens_required_by_settings(world) < 30 and '30_skulltulas' not in world.settings.misc_hints, @@ -1949,6 +1949,20 @@ def rainbow_bridge_hint_kind(world: World) -> str: 'location_fallback': "\x08Hey, young man. What's happening \x01today? If you have a \x05\x41Poe\x05\x40, I will \x01buy it.\x04\x1AIf you earn \x05\x41{poe_points} points\x05\x40, you'll\x01be a happy man! Heh heh.\x04\x08Your card now has \x05\x45\x1E\x01 \x05\x40points.\x01Come back again!\x01Heh heh heh!\x02", 'text_style': 0x03, }, + 'ocarina_of_time': { + 'id': 0x707A, + 'hint_location': 'HF Ocarina of Time Item Hint', + 'item_location': 'HF Ocarina of Time Item', + 'location_text': 'The object retrieved under the drawbridge is \x05\x42{item}\x05\x40.', + 'text_style': 0x20, + }, + 'song_of_time': { + 'id': 0x707A, + 'hint_location': 'Song from Ocarina of Time Hint', + 'item_location': 'Song from Ocarina of Time', + 'location_text': 'The song learned after the reunification of the \x05\x41Spiritual Stones\x05\x40 is \x05\x42{item}\x05\x40.', + 'text_style': 0x20, + } } # Adds capability for dual misc hints. Only used when neither or both hints are enabled, uses corresponding misc_location_hint_table entries if only one is enabled. @@ -1961,6 +1975,11 @@ def rainbow_bridge_hint_kind(world: World) -> str: 'location_fallback': '\x05\x42\x06\x3dForest Stage\x04\x01\x05\x40\x06\x14We are waiting to see your\x01\x06\x32beautiful face!\x01\x06\x28Win fabulous prizes!', 'text_style': 0x13, }, + ('ocarina_of_time', 'song_of_time'): { + 'id': 0x707A, + 'location_text': 'Reuniting the \x05\x41Spiritual Stones\x05\x40 leads to \x05\x42{item_1}\x05\x40 and \x05\x42{item_2}\x05\x40.', + 'text_style': 0x20, + }, } # Separate table for goal names to avoid duplicates in the hint table. diff --git a/Hints.py b/Hints.py index bc7ebf39e5..808cf23559 100644 --- a/Hints.py +++ b/Hints.py @@ -1667,6 +1667,10 @@ def build_altar_hints(world: World, messages: list[Message], include_rewards: bo child_text += get_hint('Spiritual Stone Text Start', world.settings.clearer_hints).text + '\x04' for (reward, color) in boss_rewards_spiritual_stones: child_text += build_boss_string(reward, color, world) + sot_oot_misc_hint = build_oot_sot_hints(world) + if sot_oot_misc_hint is not None: + child_text += sot_oot_misc_hint + child_text += '\x04' child_text += get_hint('Child Altar Text End', world.settings.clearer_hints).text child_text += '\x0B' update_message_by_id(messages, 0x707A, get_raw_text(child_text), 0x20) @@ -1713,6 +1717,12 @@ def build_boss_string(reward: str, color: str, world: World) -> str: text = GossipText(f"\x08\x13{item_icon}One {location_text}...", [color], prefix='') return str(text) + '\x04' +def build_oot_sot_hints(world: World) -> str: + dual_data = misc_dual_hint_table.get(('ocarina_of_time', 'song_of_time')) + string = build_text_misc_dual_hints(world, dual_data, hint_type1='ocarina_of_time', hint_type2='song_of_time') + if string is None: + return None + return str(GossipText(string, ['Yellow', 'Blue', 'Blue'], prefix='')) def build_bridge_reqs_string(world: World) -> str: if world.settings.bridge == 'open': @@ -1849,26 +1859,33 @@ def build_misc_location_hints(world: World, messages: list[Message]) -> None: def build_misc_dual_hints(world: World, messages: list[Message]) -> None: for (hint_type1, hint_type2), data in misc_dual_hint_table.items(): - item_1 = world.misc_hint_location_items[hint_type1] - item_2 = world.misc_hint_location_items[hint_type2] - if hint_type1 in world.settings.misc_hints and hint_type1 in world.misc_hint_location_items: - if hint_type2 in world.settings.misc_hints and hint_type2 in world.misc_hint_location_items: - text = data['location_text'].format( - item_1=get_hint(get_item_generic_name(item_1), world.settings.clearer_hints).text, - item_2=get_hint(get_item_generic_name(item_2), world.settings.clearer_hints).text, - ) - else: - text = misc_location_hint_table[hint_type1]['location_text'].format( - item=get_hint(get_item_generic_name(item_1), world.settings.clearer_hints).text, - ) + if hint_type1 == 'ocarina_of_time': + continue + + text = build_text_misc_dual_hints(world, data, hint_type1, hint_type2) + update_message_by_id(messages, data['id'], str(GossipText(text, ['Green'], prefix='')), data['text_style']) + + +def build_text_misc_dual_hints(world: World, data, hint_type1: str, hint_type2: str) -> str: + item_1 = world.misc_hint_location_items[hint_type1] + item_2 = world.misc_hint_location_items[hint_type2] + if hint_type1 in world.settings.misc_hints and hint_type1 in world.misc_hint_location_items: + if hint_type2 in world.settings.misc_hints and hint_type2 in world.misc_hint_location_items: + return data['location_text'].format( + item_1=get_hint(get_item_generic_name(item_1), world.settings.clearer_hints).text, + item_2=get_hint(get_item_generic_name(item_2), world.settings.clearer_hints).text, + ) else: - if hint_type2 in world.settings.misc_hints and hint_type2 in world.misc_hint_location_items: - text = misc_location_hint_table[hint_type2]['location_text'].format( - item=get_hint(get_item_generic_name(item_2), world.settings.clearer_hints).text, - ) - else: - text = data['location_fallback'] - update_message_by_id(messages, data['id'], str(GossipText(text, ['Green'], prefix='')), data['text_style']) + return misc_location_hint_table[hint_type1]['location_text'].format( + item=get_hint(get_item_generic_name(item_1), world.settings.clearer_hints).text, + ) + else: + if hint_type2 in world.settings.misc_hints and hint_type2 in world.misc_hint_location_items: + return misc_location_hint_table[hint_type2]['location_text'].format( + item=get_hint(get_item_generic_name(item_2), world.settings.clearer_hints).text, + ) + else: + return data['location_fallback'] def get_raw_text(string: str) -> str: diff --git a/LocationList.py b/LocationList.py index b19553f7d1..032adc069c 100644 --- a/LocationList.py +++ b/LocationList.py @@ -2610,6 +2610,8 @@ def shop_address(shop_id: int, shelf_id: int) -> int: ("Market 10 Big Poes Hint", ("Hint", None, None, None, None, None)), ("Deku Theater Skull Mask Hint", ("Hint", None, None, None, None, None)), ("Deku Theater Mask of Truth Hint", ("Hint", None, None, None, None, None)), + ("HF Ocarina of Time Item Hint", ("Hint", None, None, None, None, None)), + ("Song from Ocarina of Time Hint", ("Hint", None, None, None, None, None)), ("Ganondorf Hint", ("Hint", None, None, None, None, None)), ]) diff --git a/SettingsList.py b/SettingsList.py index f02f8e6393..c95060bd79 100644 --- a/SettingsList.py +++ b/SettingsList.py @@ -3600,7 +3600,9 @@ class SettingInfos: misc_hints = MultipleSelect( gui_text = 'Misc. Hints', choices = { - 'altar': 'Temple of Time Altar', + 'altar': 'Temple of Time Altar (Win Conditions)', + 'ocarina_of_time': 'Temple of Time Altar (Ocarina of Time)', + 'song_of_time': 'Temple of Time Altar (Song of Time)', 'dampe_diary': "Dampé's Diary (Hookshot)", 'ganondorf': 'Ganondorf (Light Arrows)', 'warp_songs_and_owls': 'Warp Songs and Owls', @@ -3626,6 +3628,10 @@ class SettingInfos: Spiritual Stones (unless Maps and Compasses Give Information is enabled). + Reading the Temple of Time altar as a child will + tell you what item thrown by Zelda and what song + the Ocarina of Time teaches. + Reading the Temple of Time altar as adult will tell you the locations of the Medallions (unless Maps and Compasses Give Information diff --git a/World.py b/World.py index 95dd6599ca..8857df349b 100644 --- a/World.py +++ b/World.py @@ -11,7 +11,7 @@ from Dungeon import Dungeon from Entrance import Entrance from Goals import Goal, GoalCategory -from HintList import get_required_hints, misc_item_hint_table, misc_location_hint_table, misc_dual_hint_table +from HintList import get_required_hints, misc_item_hint_table, misc_location_hint_table from Hints import HintArea, hint_dist_keys, hint_dist_files from Item import Item, ItemFactory, ItemInfo, make_event_item from ItemList import REWARD_COLORS diff --git a/data/Glitched World/Overworld.json b/data/Glitched World/Overworld.json index 880db61a18..8b7057418b 100644 --- a/data/Glitched World/Overworld.json +++ b/data/Glitched World/Overworld.json @@ -1487,6 +1487,8 @@ "locations": { "ToT Light Arrows Cutscene": "is_adult and can_trigger_lacs", "ToT Child Altar Hint": "is_child", + "HF Ocarina of Time Item Hint": "is_child", + "Song from Ocarina of Time Hint": "is_child", "ToT Adult Altar Hint": "is_adult" }, "exits": { diff --git a/data/World/Overworld.json b/data/World/Overworld.json index fe6fd4442e..7423eca009 100644 --- a/data/World/Overworld.json +++ b/data/World/Overworld.json @@ -1308,6 +1308,8 @@ "locations": { "ToT Light Arrows Cutscene": "is_adult and can_trigger_lacs", "ToT Child Altar Hint": "is_child", + "HF Ocarina of Time Item Hint": "is_child", + "Song from Ocarina of Time Hint": "is_child", "ToT Adult Altar Hint": "is_adult" }, "exits": {