diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index 60a89def5..bcea7d483 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -461,6 +461,7 @@ namespace SohImGui { io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->Fonts->AddFontDefault(); statsWindowOpen = CVar_GetS32("gStatsEnabled", 0); + CVar_RegisterS32("gRandoRelevantNavi", 1); #ifdef __SWITCH__ Ship::Switch::SetupFont(io->Fonts); #endif @@ -2005,6 +2006,11 @@ namespace SohImGui { "(medallions/stones/songs). Note that these fanfares\n" "are longer than usual." ); + EnhancementCheckbox("Rando-Relevant Navi Hints", "gRandoRelevantNavi"); + Tooltip( + "Replace Navi's overworld quest hints with rando-\n" + "related gameplay hints.\n" + ); ImGui::EndMenu(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 60c198ed4..c00ebf9f2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -33,6 +33,7 @@ u8 generated; const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::hintMessageTableID = "RandomizerHints"; const std::string Randomizer::scrubMessageTableID = "RandomizerScrubs"; +const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; Randomizer::Randomizer() { Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 }; @@ -3714,6 +3715,79 @@ void CreateScrubMessages() { } } +CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { + + { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", + "%cFehlt dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", + "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, + + { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", + "%cManchmal kannst du den %rStahlhammer&%cstatt Bomben verwenden!", + "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, + + { "%cThere are three %gbusiness scrubs %cin &Hyrule who sell %wmysterious items%c. Do&you know where they are?", + "%cEs gibt drei %gDeku-Händler %cin Hyrule&die mysteriöse Gegenstände&verkaufen. Weißt du wo Sie sind?", + "%cIl y a trois %gPestes Marchandes%c en&Hyrule qui vendent des %wobjets&mystérieux%c. Tu sais où elles sont?" }, + + { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", + "%cHängst du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", + "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, + + { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", + "%cWusstest du, dass du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", + "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables mouvants%c?" }, + + { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", + "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem du von&der Baustelle aus mit einem %rHuhn&%cspringst!", + "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec une&%rcocotte%c!" }, + + { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", + "%cDie %yGeister-Prüfung %cin %pGanons&Schloss %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?", + "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu le savais&déjà?" }, + + { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is junk!", + "%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört dass sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!", + "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont intéréssant?" }, + + { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", + "%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen dass&man damit %rKrabbelminen %cdetonieren&kann!", + "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, + + { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your safety!", + "%cVielleicht verbleibt dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. Dies&ist zu deiner Sicherheit!", + "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. C'est pour ta&propre sécurité!" }, + + { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with %warrows%c!", + "%cNur weil du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&du sie immernoch mit %rFeuer %coder&%wPfeilen %cdetonieren!", + "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du %rFeu %cou avec des %wflèches%c!" }, + + { "%cEven an adult can't push large&blocks without some %wextra&strength%c!", + "%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!", + "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, + + { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", + "%cIch habe gehört dass der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?", + "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as essayé?" }, + + { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", + "%cFehlt dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuch&Sie mit einem %wKrug %cabzuwerfen!", + "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une %wjarre&%cà la figure?" }, + + { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", + "%cIch habe gehört dass die Stelle&%wfeuchten Bodens %cim %bZora-Fluss %cals&einzige keine %rSkulltula %cbeherbergt.", + "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne contienne pas&d'%raraignée%c." }, +}; + +void CreateNaviRandoMessages() { + CustomMessageManager* customMessageManager = CustomMessageManager::Instance; + customMessageManager->AddCustomMessageTable(Randomizer::NaviRandoMessageTableID); + for (u8 i = 0; i <= (NUM_NAVI_MESSAGES - 1); i++) { + customMessageManager->CreateMessage(Randomizer::NaviRandoMessageTableID, i, + { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, NaviMessages[i].english, + NaviMessages[i].german, NaviMessages[i].french }); + } +} + void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). @@ -3789,6 +3863,7 @@ void Randomizer::CreateCustomMessages() { }; CreateGetItemMessages(getItemMessages); CreateScrubMessages(); + CreateNaviRandoMessages(); } class ExtendedVanillaTableInvalidItemIdException: public std::exception { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 15394fbcb..fad56ca13 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -7,6 +7,8 @@ #include #include +#define NUM_NAVI_MESSAGES 15 + class Randomizer { private: std::unordered_map itemLocations; @@ -31,6 +33,7 @@ class Randomizer { static const std::string getItemMessageTableID; static const std::string hintMessageTableID; static const std::string scrubMessageTableID; + static const std::string NaviRandoMessageTableID; static Sprite* GetSeedTexture(uint8_t index); s16 GetItemModelFromId(s16 itemId); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index dd2126815..7bd704d99 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1591,6 +1591,11 @@ extern "C" CustomMessageEntry Randomizer_GetScrubMessage(u16 scrubTextId) { return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, price); } +extern "C" CustomMessageEntry Randomizer_GetNaviMessage() { + u16 naviTextId = rand() % NUM_NAVI_MESSAGES; + return CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); +} + extern "C" CustomMessageEntry Randomizer_GetAltarMessage() { return (LINK_IS_ADULT) ? CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT) @@ -1714,6 +1719,9 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { } } else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) { messageEntry = Randomizer_GetScrubMessage(textId); + // In rando, replace Navi's general overworld hints with rando-related gameplay tips + } else if (CVar_GetS32("gRandoRelevantNavi", 1) && textId >= 0x0140 && textId <= 0x015F) { + messageEntry = Randomizer_GetNaviMessage(); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {