Files
Shipwright/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp
T
Pepe20129 1785a70f22 Clean OTRGlobals 2 (#6636)
The main effect of this PR is completely decoupling OTRGlobals.h from any non-std header making it so that the "everything is being rebuilt because I changed a header that at some point gets included in OTRGlobals" problem doesn't happen anymore.
2026-05-23 20:32:51 +00:00

512 lines
26 KiB
C++

// RANDOTODO: Consider breaking this up into the different actors
// That speak these hints, like 2Ship does with ActorBehavior
/**
* File for registering hooks for "Static" hints, i.e. hints that
* are always given by a specific NPC and/or for a specific item.
*/
#include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "z64scene.h"
#include <soh/OTRGlobals.h>
#include "soh/Enhancements/randomizer/randomizer.h"
extern "C" {
extern PlayState* gPlayState;
#include <macros.h>
#include <functions.h>
#include <variables.h>
}
#define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh)
#define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)
#define ANY_SKULLTULA_HINTS \
RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \
RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \
RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)
void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg;
if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) {
msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1);
} else {
msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2);
}
} else {
if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) {
msg = RAND_GET_HINT(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT);
} else {
msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0);
}
}
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg;
switch (gPlayState->sceneNum) {
case SCENE_TEMPLE_OF_TIME:
if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()) {
msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW);
} else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) {
msg = CustomMessage(
"@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.",
"@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.",
"Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w.");
} else {
msg = CustomMessage("The time has come. Prepare yourself.", "Die Zeit ist gekommen.&Mach Dich bereit.",
"Le moment est venu @.&Tu ferais bien de te préparer.");
}
break;
case SCENE_INSIDE_GANONS_CASTLE:
if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) {
msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW);
} else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) &&
INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CUR_CAPACITY(UPG_QUIVER) >= 30 &&
gSaveContext.isMagicAcquired)) {
msg = CustomMessage(
"You are still ill-equipped to face %rGanondorf%w."
"^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the "
"%ylight%w.",
"Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^"
"Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu "
"geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.",
"@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^"
"Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour "
"invoquer la %ylumière%w.");
} else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) &&
RAND_GET_OPTION(RSK_TRIAL_COUNT)) {
msg = CustomMessage(
"You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still "
"stands.^Complete the remaining %gtrials%w to destroy it.",
"Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w "
"steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.",
"@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours "
"actives.^Termine les épreuves restantes pour les détruire.");
} else {
msg = CustomMessage("If you're ready, then proceed.^Good luck.",
"Wenn Du bereit bist, so schreite&voran.^Viel Glück.",
"Si tu es prêt, tu peux y aller.^Bonne chance.");
}
break;
}
msg.AutoFormat();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildChildAltarMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_ALTAR_CHILD)->GetHintMessage();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildAdultAltarMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_ALTAR_ADULT)->GetHintMessage();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) {
uint8_t count = 0;
RandomizerCheck rc = RC_UNKNOWN_CHECK;
int16_t actorParams = GET_PLAYER(gPlayState)->talkActor->params;
if (actorParams == 1 && RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT)) {
rc = RC_KAK_10_GOLD_SKULLTULA_REWARD;
count = 10;
} else if (actorParams == 2 && RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT)) {
rc = RC_KAK_20_GOLD_SKULLTULA_REWARD;
count = 20;
} else if (actorParams == 3 && RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT)) {
rc = RC_KAK_30_GOLD_SKULLTULA_REWARD;
count = 30;
} else if (actorParams == 4 && RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT)) {
rc = RC_KAK_40_GOLD_SKULLTULA_REWARD;
count = 40;
} else if (actorParams == 5 && RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)) {
rc = RC_KAK_50_GOLD_SKULLTULA_REWARD;
count = 50;
} else {
return;
}
Rando::Item& item = Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(rc)->GetPlacedRandomizerGet());
CustomMessage msg = CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying %y[[d]] Spiders of the "
"Curse%w and I will give you my [[color]][[1]]%w!",
/*german*/
"Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y[[d]] Skulltulas%w "
"zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!",
/*french*/
"Yeaaarrgh! Je suis maudit!^Détruit encore %y[[d]] Araignées de la Malédiction%w "
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
msg.InsertNumber(count);
msg.Replace("[[color]]", item.GetColor());
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
msg.AutoFormat();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying %y100 Spiders of the "
"Curse%w and I will give you my [[color]][[1]]%w!",
/*german*/
"Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y100 Skulltulas%w "
"zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!",
/*french*/
"Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w "
"et j'aurai quelque chose à te donner! [[color]]([[1]])%w");
Rando::Item& item =
Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet());
msg.Replace("[[color]]", item.GetColor());
msg.InsertNames({ item.GetHint().GetHintMessage().GetForCurrentLanguage() });
msg.AutoFormat();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildDampesDiaryMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (gPlayState->sceneNum == SCENE_TREASURE_BOX_SHOP) {
CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
}
void BuildMysteriousWarpMessage() {
CustomMessage msg = CustomMessage(
"Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w",
"Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w",
"Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w");
msg.LoadIntoFont();
}
void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_MINUET_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildBoleroWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildSerenadeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildRequiemWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildNocturneWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildPreludeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!RAND_GET_OPTION(RSK_WARP_SONG_HINTS)) {
BuildMysteriousWarpMessage();
*loadFromMessageTable = false;
return;
}
CustomMessage msg = RAND_GET_HINT(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildFrogsHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildLoachHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildFishingPoleHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) {
return;
}
CustomMessage msg = CustomMessage(
"Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!",
"Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht "
"fischen!",
"Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!");
if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) {
msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage();
}
if (*textId == TEXT_FISHING_POND_START_MET) {
msg = CustomMessage("Hey, mister! I remember you!&It's been a long time!^",
"Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!",
"Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!") +
msg;
}
msg.AutoFormat();
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildSariaMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg;
if (*textId == TEXT_SARIA_SFM) {
msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0);
} else {
msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1);
}
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildMidoMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_MIDO_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildBigPoesHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildChickensHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildMalonHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg;
int id;
if (*textId == TEXT_MALON_EVERYONE_TURNING_EVIL || *textId == TEXT_MALON_I_SING_THIS_SONG) {
id = 0;
} else if (*textId == TEXT_MALON_HOW_IS_EPONA_DOING) {
id = 1;
} else if (*textId == TEXT_MALON_OBSTICLE_COURSE) {
id = 2;
} else if (*textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED) {
id = 3;
} else {
assert(!"This should not be reachable");
return;
}
msg = RAND_GET_HINT(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, id);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildHorsebackArcheryMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg;
int id;
if (*textId == TEXT_GF_HBA_SIGN) {
id = 0;
} else if (*textId == TEXT_HBA_NOT_ON_HORSE) {
id = 1;
} else if (*textId == TEXT_HBA_INITIAL_EXPLAINATION) {
id = 2;
} else if (*textId == TEXT_HBA_ALREADY_HAVE_1000) {
id = 3;
} else {
assert(!"This should not be reachable");
return;
}
msg = RAND_GET_HINT(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, id);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildMaskShopSignMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
void BuildBossKeyHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
RandomizerHint rh = RH_NONE;
switch (gPlayState->sceneNum) {
case SCENE_FOREST_TEMPLE:
rh = RH_FOREST_BOSS_KEY_HINT;
break;
case SCENE_FIRE_TEMPLE:
rh = RH_FIRE_BOSS_KEY_HINT;
break;
case SCENE_WATER_TEMPLE:
rh = RH_WATER_BOSS_KEY_HINT;
break;
case SCENE_SHADOW_TEMPLE:
rh = RH_SHADOW_BOSS_KEY_HINT;
break;
case SCENE_SPIRIT_TEMPLE:
rh = RH_SPIRIT_BOSS_KEY_HINT;
break;
case SCENE_GANONS_TOWER:
rh = RH_GANONS_BOSS_KEY_HINT;
break;
default:
break;
}
if (rh != RH_NONE) {
CustomMessage msg = RAND_GET_HINT(rh)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont();
*loadFromMessageTable = false;
}
}
void RegisterStaticHints() {
// Ganondorf
COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint);
// Sheik
COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage);
COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage);
// Altar
COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage);
COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage);
// Skulltula
COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage);
COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT),
Build100SkullsHintMessage);
// Dampe's Diary
COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage);
// Chest Game
COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_PROCEED, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_REAL_GAMBLER, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_THANKS_A_LOT, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage);
// Warp
COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
BuildSerenadeWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
BuildRequiemWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
BuildNocturneWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage);
// Frogs
COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage);
// Loach
COND_ID_HOOK(OnOpenText, TEXT_FISHING_CLOUDY, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_SECRETS, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT),
BuildLoachHintMessage);
// Fishing Pole
COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE),
BuildFishingPoleHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE),
BuildFishingPoleHintMessage);
// Saria
COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_SOUNDS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_MR_DARUNIA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_WATER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_FIRE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DREAD_CASTLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DIFFERENT_OCARINA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_EYES_DARKNESS_STORM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DESERT_GODDESS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_TEMPLES, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_TEMPLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
// Mido
COND_ID_HOOK(OnOpenText, TEXT_MIDO_SPEAK_TO_MIDO_FIRST_TIME, RAND_GET_OPTION(RSK_MIDO_HINT), BuildMidoMessage);
COND_ID_HOOK(OnOpenText, TEXT_MIDO_SPEAK_TO_MIDO_AGAIN, RAND_GET_OPTION(RSK_MIDO_HINT), BuildMidoMessage);
COND_ID_HOOK(OnOpenText, TEXT_MIDO_HOME_AFTER_ZELDAS_LETTER, RAND_GET_OPTION(RSK_MIDO_HINT), BuildMidoMessage);
COND_ID_HOOK(OnOpenText, TEXT_MIDO_HOME_BEFORE_ZELDAS_LETTER, RAND_GET_OPTION(RSK_MIDO_HINT), BuildMidoMessage);
// Biggoron
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
// Big Poes
COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT),
BuildBigPoesHintMessage);
// Anju
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
// Malon
COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT),
BuildMalonHintMessage);
// Horseback Archery
COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT),
BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
// Mask Shop Sign
COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage);
// Boss Key Hints
COND_ID_HOOK(OnOpenText, TEXT_NEED_SPECIAL_KEY, RAND_GET_OPTION(RSK_BOSS_KEY_HINT), BuildBossKeyHintMessage);
}
static RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" });