diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 5e78c332a..e3c18dd34 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -265,6 +265,7 @@ typedef struct { /* */ char childAltarText[250]; /* */ char adultAltarText[750]; /* */ char ganonHintText[150]; + /* */ char gregHintText[250]; /* */ char ganonText[250]; /* */ char dampeText[150]; /* */ char warpMinuetText[100]; diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 408d50304..21f47000d 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -3,6 +3,7 @@ typedef enum { TEXT_CURSED_SKULLTULA_PEOPLE = 0x22, TEXT_DAMPES_DIARY = 0x5003, + TEXT_CHEST_GAME_PROCEED = 0x704C, TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C, TEXT_BUY_BOMBCHU_10_DESC = 0xBC, TEXT_GS_NO_FREEZE = 0xB4, diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 47ab9f4a7..a0824755b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -912,9 +912,7 @@ void VanillaFill() { CreateItemOverrides(); CreateEntranceOverrides(); CreateAlwaysIncludedMessages(); - if (ShuffleWarpSongs) { - CreateWarpSongTexts(); - } + CreateWarpSongTexts(); } void ClearProgress() { @@ -1079,13 +1077,10 @@ int Fill() { } //Always execute ganon hint generation for the funny line CreateGanonText(); - CreateAltarText(AltarHintText); - if (DampeHintText) { - CreateDampesDiaryText(); - } - if (ShuffleWarpSongs) { - CreateWarpSongTexts(); - } + CreateAltarText(); + CreateDampesDiaryText(); + CreateGregRupeeHint(); + CreateWarpSongTexts(); return 1; } //Unsuccessful placement diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 5b6be555b..f69bf3502 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -117,6 +117,7 @@ Text adultAltarText; Text ganonText; Text ganonHintText; Text dampesText; +Text gregText; Text warpMinuetText; Text warpBoleroText; Text warpSerenadeText; @@ -144,6 +145,10 @@ Text& GetDampeHintText() { return dampesText; } +Text& GetGregHintText() { + return gregText; +} + Text& GetWarpMinuetText() { return warpMinuetText; } @@ -681,10 +686,10 @@ static Text BuildGanonBossKeyText() { return Text()+"$b"+ganonBossKeyText+"^"; } -void CreateAltarText(Option withHints) { +void CreateAltarText() { //Child Altar Text - if (withHints) { + if (AltarHintText) { childAltarText = Hint(SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ //Spiritual Stones (StartingKokiriEmerald.Value() ? Text{ "##", "##", "##" } @@ -703,7 +708,7 @@ void CreateAltarText(Option withHints) { //Adult Altar Text adultAltarText = Hint(ADULT_ALTAR_TEXT_START).GetText() + "^"; - if (withHints) { + if (AltarHintText) { adultAltarText = adultAltarText + //Medallion Areas (StartingLightMedallion.Value() ? Text{ "##", "##", "##" } @@ -747,6 +752,11 @@ void CreateMerchantsHints() { } void CreateDampesDiaryText() { + if (!DampeHintText) { + dampesText = Text(); + return; + } + 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(); @@ -765,7 +775,41 @@ void CreateDampesDiaryText() { dampesText = temp1 + area + temp2; } +void CreateGregRupeeHint() { + if (!GregHintText) { + gregText = Text(); + return; + } + + uint32_t location = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlacedItemKey() == GREG_RUPEE;})[0]; + Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText(); + + Text temp1 = Text{ + "By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%g ", + "", + "" + }; + + Text temp2 = { + "%w.^It's said to have %rmysterious powers%w...^But then, it could just be another regular rupee.&Oh well.", + "", + "" + }; + + gregText = temp1 + area + temp2; +} + void CreateWarpSongTexts() { + if (!ShuffleWarpSongs) { + warpMinuetText = Text(); + warpBoleroText = Text(); + warpSerenadeText = Text(); + warpRequiemText = Text(); + warpNocturneText = Text(); + warpPreludeText = Text(); + return; + } + auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); for (auto entrance : warpSongEntrances) { @@ -817,7 +861,7 @@ void CreateAllHints() { auto alwaysHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){ return ((Location(loc)->GetHint().GetType() == HintCategory::Always) || // If we have Rainbow Bridge set to Greg, add a hint for where Greg is - (Bridge.Is(RAINBOWBRIDGE_GREG) && Location(loc)->GetPlacedItemKey() == GREG_RUPEE)) && + (Bridge.Is(RAINBOWBRIDGE_GREG) && !GregHintText && Location(loc)->GetPlacedItemKey() == GREG_RUPEE)) && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt()); }); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index a397d12ac..fe5a29805 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -222,14 +222,16 @@ extern void CreateAllHints(); extern void CreateMerchantsHints(); extern void CreateWarpSongTexts(); extern void CreateDampesDiaryText(); +extern void CreateGregRupeeHint(); extern void CreateGanonText(); -extern void CreateAltarText(Option withHints); +extern void CreateAltarText(); Text& GetChildAltarText(); Text& GetAdultAltarText(); Text& GetGanonText(); Text& GetGanonHintText(); Text& GetDampeHintText(); +Text& GetGregHintText(); Text& GetWarpMinuetText(); Text& GetWarpBoleroText(); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 07e17f7e9..ed69612a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -325,7 +325,8 @@ namespace Settings { 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 DampeHintText = Option::Bool("Dampe's Diary Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option GregHintText = Option::Bool("Greg the Rupee 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); @@ -354,6 +355,7 @@ namespace Settings { &AltarHintText, &GanondorfHintText, &DampeHintText, + &GregHintText, &WarpSongHints, &Kak10GSHintText, &Kak20GSHintText, @@ -2795,6 +2797,7 @@ namespace Settings { AltarHintText.SetSelectedIndex(cvarSettings[RSK_TOT_ALTAR_HINT]); GanondorfHintText.SetSelectedIndex(cvarSettings[RSK_GANONDORF_LIGHT_ARROWS_HINT]); DampeHintText.SetSelectedIndex(cvarSettings[RSK_DAMPES_DIARY_HINT]); + GregHintText.SetSelectedIndex(cvarSettings[RSK_GREG_HINT]); WarpSongHints.SetSelectedIndex(cvarSettings[RSK_WARP_SONG_HINTS]); Kak10GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_10_SKULLS_HINT]); Kak20GSHintText.SetSelectedIndex(cvarSettings[RSK_KAK_20_SKULLS_HINT]); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.hpp b/soh/soh/Enhancements/randomizer/3drando/settings.hpp index a4f788c81..dd394b832 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.hpp @@ -1000,6 +1000,7 @@ void UpdateSettings(std::unordered_map cvarSettin extern Option AltarHintText; extern Option GanondorfHintText; extern Option DampeHintText; + extern Option GregHintText; extern Option Kak10GSHintText; extern Option Kak20GSHintText; extern Option Kak30GSHintText; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index eeaf94722..6618fba8c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -650,6 +650,7 @@ static void WriteHints(int language) { std::string unformattedGanonText; std::string unformattedGanonHintText; std::string unformattedDampesText; + std::string unformattedGregText; switch (language) { case 0: @@ -657,6 +658,7 @@ static void WriteHints(int language) { unformattedGanonText = GetGanonText().GetEnglish(); unformattedGanonHintText = GetGanonHintText().GetEnglish(); unformattedDampesText = GetDampeHintText().GetEnglish(); + unformattedGregText = GetGregHintText().GetEnglish(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish(); @@ -670,6 +672,7 @@ static void WriteHints(int language) { unformattedGanonText = GetGanonText().GetFrench(); unformattedGanonHintText = GetGanonHintText().GetFrench(); unformattedDampesText = GetDampeHintText().GetFrench(); + unformattedGregText = GetGregHintText().GetFrench(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench(); @@ -684,10 +687,12 @@ static void WriteHints(int language) { std::string ganonText = AutoFormatHintTextString(unformattedGanonText); std::string ganonHintText = AutoFormatHintTextString(unformattedGanonHintText); std::string dampesText = AutoFormatHintTextString(unformattedDampesText); + std::string gregText = AutoFormatHintTextString(unformattedGregText); jsonData["ganonText"] = ganonText; jsonData["ganonHintText"] = ganonHintText; jsonData["dampeText"] = dampesText; + jsonData["gregText"] = gregText; 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 4a5be61f5..112d165a9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -280,6 +280,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "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:Greg the Rupee Hint", RSK_GREG_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 }, @@ -411,6 +412,16 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) { gSaveContext.dampeText } ); + CustomMessageManager::Instance->CreateMessage( + Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED, + { + TEXTBOX_TYPE_BLACK, + TEXTBOX_POS_VARIABLE, + gSaveContext.gregHintText, + gSaveContext.gregHintText, + gSaveContext.gregHintText + } + ); CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, @@ -783,6 +794,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_TOT_ALTAR_HINT: case RSK_GANONDORF_LIGHT_ARROWS_HINT: case RSK_DAMPES_DIARY_HINT: + case RSK_GREG_HINT: case RSK_KAK_10_SKULLS_HINT: case RSK_KAK_20_SKULLS_HINT: case RSK_KAK_30_SKULLS_HINT: @@ -1204,6 +1216,11 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { strncpy(gSaveContext.dampeText, formattedDampeJsonText.c_str(), sizeof(gSaveContext.dampeText) - 1); gSaveContext.dampeText[sizeof(gSaveContext.dampeText) - 1] = 0; + std::string gregJsonText = spoilerFileJson["gregText"].get(); + std::string formattedGregJsonText = FormatJsonHintText(gregJsonText); + strncpy(gSaveContext.gregHintText, formattedGregJsonText.c_str(), sizeof(gSaveContext.gregHintText) - 1); + gSaveContext.gregHintText[sizeof(gSaveContext.gregHintText) - 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; @@ -2861,6 +2878,7 @@ void GenerateRandomizerImgui(std::string seed = "") { 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_GREG_HINT] = CVarGetInteger("gRandomizeGregHint", 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); @@ -4157,6 +4175,8 @@ void DrawRandoEditor(bool& open) { 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("Greg the Green Rupee", "gRandomizeGregHint", true, false); + UIWidgets::InsertHelpHoverText("Talking to the chest game owner after buying a key will tell you the location of Greg the Green Rupee."); 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.)"); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 1dde6f23a..9ca256192 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1026,6 +1026,7 @@ typedef enum { RSK_TOT_ALTAR_HINT, RSK_GANONDORF_LIGHT_ARROWS_HINT, RSK_DAMPES_DIARY_HINT, + RSK_GREG_HINT, RSK_KAK_10_SKULLS_HINT, RSK_KAK_20_SKULLS_HINT, RSK_KAK_30_SKULLS_HINT, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7634d651b..ff008884b 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1645,6 +1645,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } 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_GREG_HINT) && (textId == 0x704C || textId == 0x6E || textId == 0x84)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED); } 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, Randomizer_GetSettingValue(RSK_WARP_SONG_HINTS) == RO_GENERIC_ON); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 41c455a65..d1328ab05 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -180,6 +180,9 @@ void SaveManager::LoadRandomizerVersion2() { std::string dampeText; SaveManager::Instance->LoadData("dampeText", dampeText); memcpy(gSaveContext.dampeText, dampeText.c_str(), dampeText.length()); + std::string gregHintText; + SaveManager::Instance->LoadData("gregHintText", gregHintText); + memcpy(gSaveContext.gregHintText, gregHintText.c_str(), gregHintText.length()); std::string warpMinuetText; SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText); memcpy(gSaveContext.warpMinuetText, warpMinuetText.c_str(), warpMinuetText.length()); @@ -272,6 +275,7 @@ void SaveManager::SaveRandomizer() { SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText); SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText); SaveManager::Instance->SaveData("dampeText", gSaveContext.dampeText); + SaveManager::Instance->SaveData("gregHintText", gSaveContext.gregHintText); SaveManager::Instance->SaveData("warpMinuetText", gSaveContext.warpMinuetText); SaveManager::Instance->SaveData("warpBoleroText", gSaveContext.warpBoleroText); SaveManager::Instance->SaveData("warpSerenadeText", gSaveContext.warpSerenadeText); diff --git a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c index c3967d9b3..017561ac3 100644 --- a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c +++ b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c @@ -97,17 +97,17 @@ void func_80B1778C(EnTakaraMan* this, PlayState* play) { } else { yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; if (play->roomCtx.curRoom.num == 6 && !this->unk_21A) { - this->actor.textId = 0x6E; + this->actor.textId = 0x6E; //Real Gambler this->unk_21A = 1; this->dialogState = TEXT_STATE_DONE; } if (!this->unk_21A && this->unk_214) { if (Flags_GetSwitch(play, 0x32)) { - this->actor.textId = 0x84; + this->actor.textId = 0x84; //Thanks a lot! (Lost) this->dialogState = TEXT_STATE_EVENT; } else { - this->actor.textId = 0x704C; + this->actor.textId = 0x704C; //Proceed this->dialogState = TEXT_STATE_DONE; } }