From 7964bde063ceb46ec9b329ff2a0613d631a3dfe8 Mon Sep 17 00:00:00 2001 From: Ralphie Morell Date: Thu, 19 Jan 2023 23:45:34 -0500 Subject: [PATCH] Rando: Misc. Hints (#1947) * Added too much * Added 3d settings and brought over to soh * fixed conditionals for replacing LA hint * whoops * Finshed making settings consistent; minor text edit * fix leftovers from adding warp hints * more fixes from merge * fix skull hint messages * Added fire temple goron junk hints; menu stuff * Address feedback * Added optional scrub text * whoops * Add hint cvars to clear preset func * whoops again * whoops the third * ADD: French Pass * FIXED: Dampe + Skull Reward * TWEAK: German skulltula hint * TWEAK: French oopsie * Address feedback * whoops * remove "staticness" from altar/ganon text funcs * ADD: German * actually add warp song hints to things; always generate ganon hint and let OTRGlobals handle showing it * Fix CVar Getters * whoops * for real this time * Actually implemented scrub text in 3d rando Co-authored-by: PurpleHato --- soh/include/z64save.h | 1 + .../custom-message/CustomMessageTypes.h | 2 + soh/soh/Enhancements/presets.h | 10 + .../Enhancements/randomizer/3drando/fill.cpp | 8 + .../Enhancements/randomizer/3drando/hints.cpp | 31 ++- .../Enhancements/randomizer/3drando/hints.hpp | 4 + .../Enhancements/randomizer/3drando/keys.hpp | 1 + .../randomizer/3drando/settings.cpp | 30 +++ .../randomizer/3drando/settings.hpp | 10 + .../randomizer/3drando/spoiler_log.cpp | 5 + .../Enhancements/randomizer/randomizer.cpp | 198 +++++++++++++++++- soh/soh/Enhancements/randomizer/randomizer.h | 6 + .../Enhancements/randomizer/randomizerTypes.h | 10 + soh/soh/OTRGlobals.cpp | 25 ++- soh/soh/SaveManager.cpp | 4 + soh/src/code/z_message_PAL.c | 11 +- 16 files changed, 335 insertions(+), 21 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index f1dd4b2a0..72303c580 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -264,6 +264,7 @@ typedef struct { /* */ char adultAltarText[750]; /* */ char ganonHintText[150]; /* */ char ganonText[250]; + /* */ char dampeText[150]; /* */ char warpMinuetText[100]; /* */ char warpBoleroText[100]; /* */ char warpSerenadeText[100]; diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 659b5fbb3..408d50304 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -1,6 +1,8 @@ #pragma once typedef enum { + TEXT_CURSED_SKULLTULA_PEOPLE = 0x22, + TEXT_DAMPES_DIARY = 0x5003, TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C, TEXT_BUY_BOMBCHU_10_DESC = 0xBC, TEXT_GS_NO_FREEZE = 0xB4, diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 3a86dc341..28c786a19 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -177,13 +177,20 @@ const std::vector enhancementsCvars = { }; const std::vector randomizerCvars = { + "gRandomize10GSHint", + "gRandomize20GSHint", + "gRandomize30GSHint", + "gRandomize40GSHint", + "gRandomize50GSHint", "gRandomizeAllLocationsReachable", + "gRandomizeAltarHint", "gRandomizeBigPoeTargetCount", "gRandomizeBlueFireArrows", "gRandomizeBombchusInLogic", "gRandomizeBossKeysanity", "gRandomizeCompleteMaskQuest", "gRandomizeCuccosToReturn", + "gRandomizeDampeHint", "gRandomizeDecoupleEntrances", "gRandomizeDoorOfTime", "gRandomizeDungeonCount", @@ -209,6 +216,7 @@ const std::vector randomizerCvars = { "gRandomizeLacsRewardCount", "gRandomizeLacsStoneCount", "gRandomizeLacsTokenCount", + "gRandomizeLAHint", "gRandomizeLinksPocket", "gRandomizeLogicRules", "gRandomizeMedallionCount", @@ -221,6 +229,7 @@ const std::vector randomizerCvars = { "gRandomizeMqDungeons", "gRandomizeRainbowBridge", "gRandomizeRewardCount", + "gRandomizeScrubText", "gRandomizeShopsanity", "gRandomizeShuffleAdultTrade", "gRandomizeShuffleBeans", @@ -280,6 +289,7 @@ const std::vector randomizerCvars = { "gRandomizeStoneCount", "gRandomizeSunlightArrows", "gRandomizeTokenCount", + "gRandomizeWarpSongText", "gRandomizeZorasFountain", }; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 7d166ef80..2baf26b8b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -1074,6 +1074,14 @@ int Fill() { if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) { CreateMerchantsHints(); } + //Always execute ganon hint generation for the funny line + CreateGanonText(); + if (AltarHintText) { + CreateAltarText(); + } + if (DampeHintText) { + CreateDampesDiaryText(); + } if (ShuffleWarpSongs) { CreateWarpSongTexts(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 8516ecb76..ac1aec641 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -116,6 +116,7 @@ Text childAltarText; Text adultAltarText; Text ganonText; Text ganonHintText; +Text dampesText; Text warpMinuetText; Text warpBoleroText; Text warpSerenadeText; @@ -139,6 +140,10 @@ Text& GetGanonHintText() { return ganonHintText; } +Text& GetDampeHintText() { + return dampesText; +} + Text& GetWarpMinuetText() { return warpMinuetText; } @@ -546,7 +551,7 @@ static void CreateTrialHints() { } } -static void CreateGanonText() { +void CreateGanonText() { //funny ganon line ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); @@ -680,7 +685,7 @@ static Text BuildGanonBossKeyText() { return Text()+"$b"+ganonBossKeyText+"^"; } -static void CreateAltarText() { +void CreateAltarText() { //Child Altar Text childAltarText = Hint(SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ @@ -737,6 +742,25 @@ void CreateMerchantsHints() { CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED})); } +void CreateDampesDiaryText() { + uint32_t item = PROGRESSIVE_HOOKSHOT; + uint32_t location = FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0]; + Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText(); + Text temp1 = Text{ + "Whoever reads this, please enter %g", + "Toi qui lit ce journal, rends-toi dans %g", + "Wer immer dies liest, der möge folgenden Ort aufsuchen: %g" + }; + + Text temp2 = { + "%w. I will let you have my stretching, shrinking keepsake.^I'm waiting for you.&--Dampé", + "%w. Et peut-être auras-tu droit à mon précieux %rtrésor%w.^Je t'attends...&--Igor", + "%w. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris" + }; + + dampesText = temp1 + area + temp2; +} + void CreateWarpSongTexts() { auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); @@ -777,9 +801,6 @@ void CreateWarpSongTexts() { void CreateAllHints() { - CreateGanonText(); - CreateAltarText(); - SPDLOG_DEBUG("\nNOW CREATING HINTS\n"); const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value()]; diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index 568708a79..5e8df5286 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -221,11 +221,15 @@ extern uint32_t GetHintRegionHintKey(const uint32_t area); extern void CreateAllHints(); extern void CreateMerchantsHints(); extern void CreateWarpSongTexts(); +extern void CreateDampesDiaryText(); +extern void CreateGanonText(); +extern void CreateAltarText(); Text& GetChildAltarText(); Text& GetAdultAltarText(); Text& GetGanonText(); Text& GetGanonHintText(); +Text& GetDampeHintText(); Text& GetWarpMinuetText(); Text& GetWarpBoleroText(); diff --git a/soh/soh/Enhancements/randomizer/3drando/keys.hpp b/soh/soh/Enhancements/randomizer/3drando/keys.hpp index 46486299a..1ef1e018e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/keys.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/keys.hpp @@ -1762,6 +1762,7 @@ typedef enum { VALIDATION_LINE, LIGHT_ARROW_LOCATION_HINT, + DAMPE_DIARY, YOUR_POCKET, GANON_LINE01, diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 213d8b602..673f6d97f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -314,6 +314,16 @@ namespace Settings { Option GossipStoneHints = Option::U8 ("Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, {gossipStonesHintsDesc}, OptionCategory::Setting, HINTS_NEED_NOTHING); Option ClearerHints = Option::U8 ("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, {obscureHintsDesc, ambiguousHintsDesc, clearHintsDesc}); Option HintDistribution = Option::U8 ("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, {uselessHintsDesc, balancedHintsDesc, strongHintsDesc, veryStrongHintsDesc}, OptionCategory::Setting, 1); // Balanced + Option AltarHintText = Option::Bool("ToT Altar Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 1); + Option GanondorfHintText = Option::Bool("Ganondorf LA Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 1); + Option DampeHintText = Option::Bool("Dampe's Diary Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option WarpSongHints = Option::Bool("Warp Songs Hints", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak10GSHintText = Option::Bool("10 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak20GSHintText = Option::Bool("20 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak30GSHintText = Option::Bool("30 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak40GSHintText = Option::Bool("40 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak50GSHintText = Option::Bool("50 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option ScrubHintText = Option::Bool("Scrub Hint Text", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); Option CompassesShowReward = Option::U8 ("Compasses Show Rewards", {"No", "Yes"}, {compassesShowRewardsDesc}, OptionCategory::Setting, 1); Option CompassesShowWotH = Option::U8 ("Compasses Show WotH", {"No", "Yes"}, {compassesShowWotHDesc}, OptionCategory::Setting, 1); Option MapsShowDungeonMode = Option::U8 ("Maps Show Dungeon Modes",{"No", "Yes"}, {mapsShowDungeonModesDesc}, OptionCategory::Setting, 1); @@ -332,6 +342,16 @@ namespace Settings { &GossipStoneHints, &ClearerHints, &HintDistribution, + &AltarHintText, + &GanondorfHintText, + &DampeHintText, + &WarpSongHints, + &Kak10GSHintText, + &Kak20GSHintText, + &Kak30GSHintText, + &Kak40GSHintText, + &Kak50GSHintText, + &ScrubHintText, &CompassesShowReward, &CompassesShowWotH, &MapsShowDungeonMode, @@ -2726,6 +2746,16 @@ namespace Settings { GossipStoneHints.SetSelectedIndex(cvarSettings[RSK_GOSSIP_STONE_HINTS]); ClearerHints.SetSelectedIndex(cvarSettings[RSK_HINT_CLARITY]); + AltarHintText.SetSelectedIndex(cvarSettings[RSK_TOT_ALTAR_HINT]); + GanondorfHintText.SetSelectedIndex(cvarSettings[RSK_GANONDORF_LIGHT_ARROWS_HINT]); + DampeHintText.SetSelectedIndex(cvarSettings[RSK_DAMPES_DIARY_HINT]); + WarpSongHints.SetSelectedIndex(cvarSettings[RSK_WARP_SONG_HINTS]); + Kak10GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_10_SKULLS_HINT]); + Kak20GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_20_SKULLS_HINT]); + Kak30GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_30_SKULLS_HINT]); + Kak40GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_40_SKULLS_HINT]); + Kak50GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_50_SKULLS_HINT]); + ScrubHintText.SetSelectedIndex(cvarSettings[RSK_SCRUB_TEXT_HINT]); HintDistribution.SetSelectedIndex(cvarSettings[RSK_HINT_DISTRIBUTION]); BlueFireArrows.SetSelectedIndex(cvarSettings[RSK_BLUE_FIRE_ARROWS]); SunlightArrows.SetSelectedIndex(cvarSettings[RSK_SUNLIGHT_ARROWS]); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.hpp b/soh/soh/Enhancements/randomizer/3drando/settings.hpp index ae5d58723..4f3287fa5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.hpp @@ -981,6 +981,16 @@ void UpdateSettings(std::unordered_map cvarSettin extern Option GossipStoneHints; extern Option ClearerHints; extern Option HintDistribution; + extern Option AltarHintText; + extern Option GanondorfHintText; + extern Option DampeHintText; + extern Option Kak10GSHintText; + extern Option Kak20GSHintText; + extern Option Kak30GSHintText; + extern Option Kak40GSHintText; + extern Option Kak50GSHintText; + extern Option ScrubHintText; + extern Option WarpSongHints; extern Option DamageMultiplier; extern Option StartingTime; extern Option ChestAnimations; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 7c74da34e..c5a2d4611 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -648,12 +648,14 @@ std::string AutoFormatHintTextString(std::string unformattedHintTextString) { static void WriteHints(int language) { std::string unformattedGanonText; std::string unformattedGanonHintText; + std::string unformattedDampesText; switch (language) { case 0: default: unformattedGanonText = GetGanonText().GetEnglish(); unformattedGanonHintText = GetGanonHintText().GetEnglish(); + unformattedDampesText = GetDampeHintText().GetEnglish(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish(); @@ -666,6 +668,7 @@ static void WriteHints(int language) { case 2: unformattedGanonText = GetGanonText().GetFrench(); unformattedGanonHintText = GetGanonHintText().GetFrench(); + unformattedDampesText = GetDampeHintText().GetFrench(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench(); @@ -679,9 +682,11 @@ static void WriteHints(int language) { std::string ganonText = AutoFormatHintTextString(unformattedGanonText); std::string ganonHintText = AutoFormatHintTextString(unformattedGanonHintText); + std::string dampesText = AutoFormatHintTextString(unformattedDampesText); jsonData["ganonText"] = ganonText; jsonData["ganonHintText"] = ganonHintText; + jsonData["dampeText"] = dampesText; if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) { return; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 67e0233c9..2a4f54ce9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -46,6 +46,7 @@ const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap"; +const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints"; static const char* englishRupeeNames[81] = { "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", @@ -249,6 +250,16 @@ std::unordered_map SpoilerfileSettingNameToEn { "World Settings:Decouple Entrances", RSK_DECOUPLED_ENTRANCES }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, + { "Misc Settings:ToT Altar Hint", RSK_TOT_ALTAR_HINT }, + { "Misc Settings:Ganondorf LA Hint", RSK_GANONDORF_LIGHT_ARROWS_HINT }, + { "Misc Settings:Dampe's Diary Hint", RSK_DAMPES_DIARY_HINT }, + { "Misc Settings:10 GS Hint", RSK_KAK_10_SKULLS_HINT }, + { "Misc Settings:20 GS Hint", RSK_KAK_20_SKULLS_HINT }, + { "Misc Settings:30 GS Hint", RSK_KAK_30_SKULLS_HINT }, + { "Misc Settings:40 GS Hint", RSK_KAK_40_SKULLS_HINT }, + { "Misc Settings:50 GS Hint", RSK_KAK_50_SKULLS_HINT }, + { "Misc Settings:Warp Song Hints", RSK_WARP_SONG_HINTS }, + { "Misc Settings:Scrub Hint Text", RSK_SCRUB_TEXT_HINT }, { "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, { "Misc Settings:Blue Fire Arrows", RSK_BLUE_FIRE_ARROWS }, { "Misc Settings:Sunlight Arrows", RSK_SUNLIGHT_ARROWS }, @@ -351,6 +362,29 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) { Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, hintLocation.hintText, hintLocation.hintText }); } + //Extra Hints + CustomMessageManager::Instance->ClearMessageTable(Randomizer::randoMiscHintsTableID); + CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::randoMiscHintsTableID); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_CURSED_SKULLTULA_PEOPLE, + { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + "Yeaaarrgh! I'm cursed!!^Please save me by destroying&%r{{params}} Spiders of the Curse%w&and I will give you my&%b{{check}}%w!", + "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem du %r{{params}} Skulltulas&%wzerstörst und ich werde dir dafür&%b{{check}} %wgeben!", + "Yeaaarrgh! Je suis maudit!^Détruit encore %r{{params}} Araignées de&la Malédiction%w et j'aurai quelque&chose à te donner!&%b({{check}})", + } + ); + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY, + { + TEXTBOX_TYPE_BLUE, + TEXTBOX_POS_TOP, + gSaveContext.dampeText, + gSaveContext.dampeText, + gSaveContext.dampeText + } + ); + CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, "Warp to&{{location}}?\x1B&%gOK&No%w\x02", @@ -704,6 +738,16 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_BLUE_FIRE_ARROWS: case RSK_SUNLIGHT_ARROWS: case RSK_BOMBCHUS_IN_LOGIC: + case RSK_TOT_ALTAR_HINT: + case RSK_GANONDORF_LIGHT_ARROWS_HINT: + case RSK_DAMPES_DIARY_HINT: + case RSK_KAK_10_SKULLS_HINT: + case RSK_KAK_20_SKULLS_HINT: + case RSK_KAK_30_SKULLS_HINT: + case RSK_KAK_40_SKULLS_HINT: + case RSK_KAK_50_SKULLS_HINT: + case RSK_WARP_SONG_HINTS: + case RSK_SCRUB_TEXT_HINT: case RSK_SHUFFLE_ENTRANCES: case RSK_SHUFFLE_OVERWORLD_ENTRANCES: case RSK_SHUFFLE_GROTTO_ENTRANCES: @@ -1101,6 +1145,11 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { strncpy(gSaveContext.ganonText, formattedGanonJsonText.c_str(), sizeof(gSaveContext.ganonText) - 1); gSaveContext.ganonText[sizeof(gSaveContext.ganonText) - 1] = 0; + std::string dampeJsonText = spoilerFileJson["dampeText"].get(); + std::string formattedDampeJsonText = FormatJsonHintText(dampeJsonText); + strncpy(gSaveContext.dampeText, formattedDampeJsonText.c_str(), sizeof(gSaveContext.dampeText) - 1); + gSaveContext.dampeText[sizeof(gSaveContext.dampeText) - 1] = 0; + std::string warpMinuetJsonText = spoilerFileJson["warpMinuetText"].get(); strncpy(gSaveContext.warpMinuetText, warpMinuetJsonText.c_str(), sizeof(gSaveContext.warpMinuetText) - 1); gSaveContext.warpMinuetText[sizeof(gSaveContext.warpMinuetText) - 1] = 0; @@ -2284,6 +2333,10 @@ std::string Randomizer::GetGanonHintText() const { return ganonHintText; } +std::string Randomizer::GetDampeText() const { + return dampeText; +} + // There has been some talk about potentially just using the RC identifier to store flags rather than randomizer inf, so // for now we're not going to store randomzierInf in the randomizer check objects, we're just going to map them 1:1 here std::map rcToRandomizerInf = { @@ -2454,6 +2507,17 @@ RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 scene break; } break; + case SCENE_KINSUTA: + if (actorId == ACTOR_EN_SSH) { + switch (actorParams) { // actor params are used to differentiate between textboxes + case 1: specialRc = RC_KAK_10_GOLD_SKULLTULA_REWARD; break; + case 2: specialRc = RC_KAK_20_GOLD_SKULLTULA_REWARD; break; + case 3: specialRc = RC_KAK_30_GOLD_SKULLTULA_REWARD; break; + case 4: specialRc = RC_KAK_40_GOLD_SKULLTULA_REWARD; break; + case 5: specialRc = RC_KAK_50_GOLD_SKULLTULA_REWARD; break; + } + } + break; case SCENE_SPOT01: switch (actorId) { case ACTOR_EN_NIW_LADY: @@ -2725,11 +2789,20 @@ void GenerateRandomizerImgui() { // at the ranch, so we should *not* shuffle the weird egg cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVarGetInteger("gRandomizeSkipChildZelda", 0) == 0) && CVarGetInteger("gRandomizeShuffleWeirdEgg", 0)); - cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVarGetInteger("gRandomizeShuffleGerudoToken", 0); cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVarGetInteger("gRandomizeShuffleFrogSongRupees", 0); cvarSettings[RSK_ITEM_POOL] = CVarGetInteger("gRandomizeItemPool", RO_ITEM_POOL_BALANCED); cvarSettings[RSK_ICE_TRAPS] = CVarGetInteger("gRandomizeIceTraps", RO_ICE_TRAPS_NORMAL); + cvarSettings[RSK_TOT_ALTAR_HINT] = CVarGetInteger("gRandomizeAltarHint", RO_GENERIC_ON); + cvarSettings[RSK_GANONDORF_LIGHT_ARROWS_HINT] = CVarGetInteger("gRandomizeLAHint", RO_GENERIC_ON); + cvarSettings[RSK_DAMPES_DIARY_HINT] = CVarGetInteger("gRandomizeDampeHint", RO_GENERIC_OFF); + cvarSettings[RSK_WARP_SONG_HINTS] = CVarGetInteger("gRandomizeWarpSongText", RO_GENERIC_OFF); + cvarSettings[RSK_SCRUB_TEXT_HINT] = CVarGetInteger("gRandomizeScrubText", RO_GENERIC_OFF); + cvarSettings[RSK_KAK_10_SKULLS_HINT] = CVarGetInteger("gRandomize10GSHint", RO_GENERIC_OFF); + cvarSettings[RSK_KAK_20_SKULLS_HINT] = CVarGetInteger("gRandomize20GSHint", RO_GENERIC_OFF); + cvarSettings[RSK_KAK_30_SKULLS_HINT] = CVarGetInteger("gRandomize30GSHint", RO_GENERIC_OFF); + cvarSettings[RSK_KAK_40_SKULLS_HINT] = CVarGetInteger("gRandomize40GSHint", RO_GENERIC_OFF); + cvarSettings[RSK_KAK_50_SKULLS_HINT] = CVarGetInteger("gRandomize50GSHint", RO_GENERIC_OFF); cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVarGetInteger("gRandomizeGossipStoneHints", RO_GOSSIP_STONES_NEED_NOTHING); cvarSettings[RSK_HINT_CLARITY] = CVarGetInteger("gRandomizeHintClarity", RO_HINT_CLARITY_CLEAR); cvarSettings[RSK_HINT_DISTRIBUTION] = CVarGetInteger("gRandomizeHintDistribution", RO_HINT_DIST_BALANCED); @@ -3915,6 +3988,37 @@ void DrawRandoEditor(bool& open) { ImGui::Unindent(); } + UIWidgets::PaddedSeparator(); + + //Extra Hints + ImGui::Text("Extra Hints"); + UIWidgets::InsertHelpHoverText( + "This setting adds some hints at locations other than Gossip Stones.\n\n" + "House of Skulltula: # - Talking to a cursed House of Skulltula resident will tell you the reward they will give you for obtaining that many tokens." + ); + + ImGui::Indent(); + //Altar, Light Arrows, and Warp Songs are enabled by default + UIWidgets::PaddedEnhancementCheckbox("Altar Text", "gRandomizeAltarHint", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::InsertHelpHoverText("Reading the Temple of Time altar as child will tell you the locations of the Spiritual Stones.\n" + "Reading the Temple of Time altar as adult will tell you the locations of the Medallions, as well as the conditions for building the Rainbow Bridge and getting the Boss Key for Ganon's Castle."); + UIWidgets::PaddedEnhancementCheckbox("Ganondorf (Light Arrows)", "gRandomizeLAHint", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::InsertHelpHoverText("Talking to Ganondorf in his boss room will tell you the location of the Light Arrows. If this option is enabled and Ganondorf is reachable without Light Arrows, Gossip Stones will never hint the Light Arrows."); + UIWidgets::PaddedEnhancementCheckbox("Dampe's Diary (Hookshot)", "gRandomizeDampeHint", true, false); + UIWidgets::InsertHelpHoverText("Reading the diary of Dampé the gravekeeper as adult will tell you the location of one of the Hookshots."); + UIWidgets::PaddedEnhancementCheckbox("Warp Song text", "gRandomizeWarpSongText", true, false, !CVarGetInteger("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF), + "This option is disabled since warp songs are not shuffled.", UIWidgets::CheckboxGraphics::Cross, true); + UIWidgets::InsertHelpHoverText("Playing a warp song will tell you where it leads. (If warp song destinations are vanilla, this is always enabled.)"); + UIWidgets::PaddedEnhancementCheckbox("Scrub Item text", "gRandomizeScrubText", true, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::InsertHelpHoverText("Business scrubs will reveal the identity of what they're selling."); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 10", "gRandomize10GSHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 20", "gRandomize20GSHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 30", "gRandomize30GSHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 40", "gRandomize40GSHint", true, false); + UIWidgets::PaddedEnhancementCheckbox("House of Skulltula: 50", "gRandomize50GSHint", true, false); + ImGui::Unindent(); + + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); @@ -4348,6 +4452,27 @@ CustomMessageEntry Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u return messageEntry; } +CustomMessageEntry Randomizer::GetCursedSkullMessage(s16 params) { + CustomMessageEntry messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_CURSED_SKULLTULA_PEOPLE); + RandomizerCheck rc = GetCheckFromActor(ACTOR_EN_SSH, SCENE_KINSUTA, params); + RandomizerGet itemGet = this->itemLocations[rc].rgID; + std::vector itemName; + if (itemGet == RG_ICE_TRAP) { + itemGet = this->itemLocations[rc].fakeRgID; + itemName = { + std::string(this->itemLocations[rc].trickName), + std::string(this->itemLocations[rc].trickName), + std::string(this->itemLocations[rc].trickName) + }; + } else { + itemName = EnumToSpoilerfileGetName[itemGet]; + } + + CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{params}}", std::to_string(params*10)); + CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{check}}", itemName[0], itemName[1], itemName[2]); + return messageEntry; +} + const char* mapGetItemHints[3][2] = { { " It's ordinary.", " It's masterful!" }, { "&Sieht aus wie immer.", " &Man kann darauf die Worte&%r\"Master Quest\"%w entziffern..." }, @@ -4650,6 +4775,76 @@ void CreateIceTrapRandoMessages() { "Pour Noël, cette année, tu&n'auras que du %BCHARBON!&%rJoyeux Noël%w!" }); } +CustomMessageMinimal FireTempleGoronMessages[NUM_GORON_MESSAGES] = { + { + "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", + "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst du&%rDarunias Kind.%w Bist du adoptiert?", + "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", + }, + { + "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home and see my parents.", + "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich nicht,&weißt du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", + "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que je&ressemble à n'importe quel Goron?", + }, + { + "How long has it been, do you know?^%r{{days}}%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my cake!!", + "Weißt du zufällig, wie viele Tage&vergangen sind?^%r{{days}}%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? Ich&muss dringend nach meinem Kuchen&sehen!!!", + "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r{{days}}%w JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", + }, + { + //0x39C7 - ganon laugh + "\x12\x39\xC7You fell into my %rtrap!%w&Foolish boy, it was me, Ganondorf!!!^...whoa, where am I?&What happened?^Weird.", + "\x12\x39\xC7""Du bist mir in die %rFalle%w gegangen!&Du Narr, ich bin es, %rGanondorf%w!!!^...Huch? Wo bin ich? Was ist passiert?^Seltsam...", + "\x12\x39\xC7Tu es tombé dans mon %rpiège%w!&Tu croyais que j'étais un Goron mais,&c'était moi! %rGanondorf%w!^...Hein? Où suis-je?&Que s'est-il passé?", + }, + { + "Thanks, but I don't know if I wanna go&just yet...^Hmm...^...^...^...^...^...maybe I can come back later.&Bye bye.", + "Danke für die Rettung, aber&eigentlich finde ich es hier ganz&nett...^Hmm...^...^...^...^...^...Naja, ich kann ja jederzeit&wiederkommen. Man sieht sich.", + "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y aller.&A plus tard.", + }, + { + "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you pressed it %b{{a_btn}}%w times.^Wow." + "Weißt du über %b\x9f%w bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen erschienen sind...^Es scheint, dass du sie schon&%b{{a_btn}}%w mal betätigt hast.^Faszinierend..." + "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves dernièrement...^Apparemment, tu as appuyé dessus&%b{{a_btn}}%w fois.^Wow..." + }, + { + "\x13\x1A""Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w rupees!", + "\x13\x1A""Hey, ist dir nicht zu warm?&Besorg dir doch eine Flasche&%rLon Lon-Milch%w, um dich&abzukühlen.^Kostet dich auch nur %g30%w Rubine!", + "\x13\x1A""Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 rubis%w?^Il n'y a rien de mieux pour s'hydrater!", + }, + { + "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g when&you're not looking for it.%w^Hope that helps!", + "Pass auf, ich geb dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, %gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps aufsuchen!", + "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le cherches pas.", + }, + { + "I dunno why I was thrown in here,&truth be told.&I'm just a %g\"PR\"%w person.", + "Wat weiß'n ich, wieso ich hier&eingepfercht wurd. Ich mach&doch nur %g\"Pull&Requests\"%w.", + "Je ne sais pas comment on m'a jeté&ici. Il faut croire que je dors comme&une pierre.", + }, +}; + +static int goronIDs[9] = {0x3052, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3070}; + +void CreateFireTempleGoronMessages() { + + CustomMessageManager* customMessageManager = CustomMessageManager::Instance; + customMessageManager->AddCustomMessageTable(customMessageTableID); + for (u8 i = 0; i <= NUM_GORON_MESSAGES - 1; i++) { + customMessageManager->CreateMessage(customMessageTableID, goronIDs[i], { + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + FireTempleGoronMessages[i].english, FireTempleGoronMessages[i].german, FireTempleGoronMessages[i].french + }); + } +} + +CustomMessageEntry Randomizer::GetGoronMessage(u16 index) { + CustomMessageEntry messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, goronIDs[index]); + CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{days}}", std::to_string(gSaveContext.totalDays)); + CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{a_btn}}", std::to_string(gSaveContext.sohStats.count[COUNT_BUTTON_PRESSES_A])); + return messageEntry; +} + void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). @@ -4885,6 +5080,7 @@ void Randomizer::CreateCustomMessages() { CreateRupeeMessages(); CreateNaviRandoMessages(); CreateIceTrapRandoMessages(); + CreateFireTempleGoronMessages(); } class ExtendedVanillaTableInvalidItemIdException: public std::exception { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 026e7a66d..32dda67e7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -14,6 +14,7 @@ #define NUM_NAVI_MESSAGES 19 #define NUM_ICE_TRAP_MESSAGES 23 +#define NUM_GORON_MESSAGES 9 class Randomizer { private: std::unordered_map itemLocations; @@ -22,6 +23,7 @@ class Randomizer { std::string adultAltarText; std::string ganonHintText; std::string ganonText; + std::string dampeText; std::unordered_map randoSettings; void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseHintLocationsFile(const char* spoilerFileName); @@ -43,6 +45,7 @@ class Randomizer { static const std::string rupeeMessageTableID; static const std::string NaviRandoMessageTableID; static const std::string IceTrapRandoMessageTableID; + static const std::string randoMiscHintsTableID; // Public for now to be accessed by SaveManager, will be made private again soon :tm: std::unordered_map trialsRequired; @@ -72,6 +75,7 @@ class Randomizer { std::string GetAdultAltarText() const; std::string GetGanonText() const; std::string GetGanonHintText() const; + std::string GetDampeText() const; RandomizerCheckObject GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams); ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData); ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex); @@ -83,6 +87,8 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessageEntry GetWarpSongMessage(u16 textId, bool mysterious = false); CustomMessageEntry GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false); + CustomMessageEntry GetCursedSkullMessage(s16 params); + CustomMessageEntry GetGoronMessage(u16 index); CustomMessageEntry GetMapGetItemMessageWithHint(GetItemEntry itemEntry); static void CreateCustomMessages(); static CustomMessageEntry GetRupeeMessage(u16 rupeeTextId); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 960b6a352..3274a021b 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1019,6 +1019,16 @@ typedef enum { RSK_ITEM_POOL, RSK_ICE_TRAPS, RSK_GOSSIP_STONE_HINTS, + RSK_TOT_ALTAR_HINT, + RSK_GANONDORF_LIGHT_ARROWS_HINT, + RSK_DAMPES_DIARY_HINT, + RSK_KAK_10_SKULLS_HINT, + RSK_KAK_20_SKULLS_HINT, + RSK_KAK_30_SKULLS_HINT, + RSK_KAK_40_SKULLS_HINT, + RSK_KAK_50_SKULLS_HINT, + RSK_WARP_SONG_HINTS, + RSK_SCRUB_TEXT_HINT, RSK_HINT_CLARITY, RSK_HINT_DISTRIBUTION, RSK_KEYSANITY, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 14dbdae2f..435cdc6c1 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1440,6 +1440,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { char* buffer = font->msgBuf; const int maxBufferSize = sizeof(font->msgBuf); CustomMessageEntry messageEntry; + s16 actorParams = 0; if (gSaveContext.n64ddFlag) { if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) { Player* player = GET_PLAYER(play); @@ -1460,7 +1461,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { Player_GetMask(play) == PLAYER_MASK_TRUTH) || (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { - s16 actorParams = msgCtx->talkActor->params; + Actor* stone = GET_PLAYER(play)->targetActor; + actorParams = stone->params; // if we're in a generic grotto if (play->sceneNum == 62 && actorParams == 14360) { @@ -1479,16 +1481,16 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } RandomizerCheck hintCheck = - Randomizer_GetCheckFromActor(msgCtx->talkActor->id, play->sceneNum, actorParams); + Randomizer_GetCheckFromActor(stone->id, play->sceneNum, actorParams); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, hintCheck); - } else if (textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) { + } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) && Randomizer_GetSettingValue(RSK_TOT_ALTAR_HINT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT) : CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD); } else if (textId == TEXT_GANONDORF) { - if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { + if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT || !Randomizer_GetSettingValue(RSK_GANONDORF_LIGHT_ARROWS_HINT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT); } else { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF); @@ -1496,7 +1498,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) } else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) { RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Player_GetMask(play) != PLAYER_MASK_TRUTH); + messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) @@ -1526,11 +1528,22 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); + } else if (textId == TEXT_CURSED_SKULLTULA_PEOPLE) { + actorParams = GET_PLAYER(play)->targetActor->params; + RandomizerSettingKey rsk = (RandomizerSettingKey)(RSK_KAK_10_SKULLS_HINT + (actorParams - 1)); + if (Randomizer_GetSettingValue(rsk)) { + messageEntry = OTRGlobals::Instance->gRandomizer->GetCursedSkullMessage(actorParams); + } + } else if (Randomizer_GetSettingValue(RSK_DAMPES_DIARY_HINT) && textId == TEXT_DAMPES_DIARY) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY); } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) && (textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, false); + messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, Randomizer_GetSettingValue(RSK_WARP_SONG_HINTS) == RO_GENERIC_ON); } else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId); + } else if (textId == 0x3052 || (textId >= 0x3069 && textId <= 0x3070)) { //Fire Temple gorons + u16 choice = Random(0, NUM_GORON_MESSAGES); + messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 9df4a72b4..b1eef677a 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -176,6 +176,9 @@ void SaveManager::LoadRandomizerVersion2() { std::string ganonText; SaveManager::Instance->LoadData("ganonText", ganonText); memcpy(gSaveContext.ganonText, ganonText.c_str(), ganonText.length()); + std::string dampeText; + SaveManager::Instance->LoadData("dampeText", dampeText); + memcpy(gSaveContext.dampeText, dampeText.c_str(), dampeText.length()); std::string warpMinuetText; SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText); memcpy(gSaveContext.warpMinuetText, warpMinuetText.c_str(), warpMinuetText.length()); @@ -265,6 +268,7 @@ void SaveManager::SaveRandomizer() { SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText); SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText); SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText); + SaveManager::Instance->SaveData("dampeText", gSaveContext.dampeText); SaveManager::Instance->SaveData("warpMinuetText", gSaveContext.warpMinuetText); SaveManager::Instance->SaveData("warpBoleroText", gSaveContext.warpBoleroText); SaveManager::Instance->SaveData("warpSerenadeText", gSaveContext.warpSerenadeText); diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index af2eb7366..0cd2bfd66 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1697,15 +1697,8 @@ void Message_StartTextbox(PlayState* play, u16 textId, Actor* actor) { osSyncPrintf(VT_RST); msgCtx->ocarinaAction = 0xFFFF; - // we need the talkActor for gossip stones in rando - // so we need to switch the order of these lines - if (gSaveContext.n64ddFlag && textId == 0x2053) { - msgCtx->talkActor = actor; - Message_OpenText(play, textId); - } else { - Message_OpenText(play, textId); - msgCtx->talkActor = actor; - } + Message_OpenText(play, textId); + msgCtx->talkActor = actor; msgCtx->msgMode = MSGMODE_TEXT_START; msgCtx->stateTimer = 0; msgCtx->textDelayTimer = 0;