diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp index f85e4ed2a..f23c78649 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp @@ -685,7 +685,7 @@ namespace Logic { MasterSword = MasterSword || IsAdult; BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2; - ScarecrowSong = ScarecrowSong || (ChildScarecrow && AdultScarecrow); + ScarecrowSong = ScarecrowSong || FreeScarecrow || (ChildScarecrow && AdultScarecrow); Scarecrow = Hookshot && CanPlay(ScarecrowSong); DistantScarecrow = Longshot && CanPlay(ScarecrowSong); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 634dc4250..b5efcfc70 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -258,7 +258,7 @@ namespace Settings { Option SkipTowerEscape = Option::Bool("Skip Tower Escape", {"Don't Skip", "Skip"}, {skipTowerEscapeDesc}, OptionCategory::Setting, SKIP); Option SkipEponaRace = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, {skipEponaRaceDesc}); Option SkipMinigamePhases = Option::Bool("Minigames repetitions", {"Don't Skip", "Skip"}, {skipMinigamePhasesDesc}); - Option FreeScarecrow = Option::Bool("Free Scarecrow", {"Off", "On"}, {freeScarecrowDesc}); + Option FreeScarecrow = Option::Bool("Skip Scarecrow's Song", {"Off", "On"}, {freeScarecrowDesc}); Option FourPoesCutscene = Option::Bool("Four Poes Cutscene", {"Don't Skip", "Skip"}, {fourPoesDesc}, OptionCategory::Setting, SKIP); Option LakeHyliaOwl = Option::Bool("Lake Hylia Owl", {"Don't Skip", "Skip"}, {lakeHyliaOwlDesc}, OptionCategory::Setting, SKIP); Option BigPoeTargetCount = Option::U8 ("Big Poe Target Count", {NumOpts(1, 10)}, {bigPoeTargetCountDesc}); @@ -2590,6 +2590,8 @@ namespace Settings { CompleteMaskQuest.SetSelectedIndex(cvarSettings[RSK_COMPLETE_MASK_QUEST]); + FreeScarecrow.SetSelectedIndex(cvarSettings[RSK_SKIP_SCARECROWS_SONG]); + EnableGlitchCutscenes.SetSelectedIndex(cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES]); NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 09f98f6ce..461b54cb9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -346,7 +346,8 @@ static void WriteSettings(const bool printAll = false) { setting->GetName() == "Skip Epona Race" || setting->GetName() == "Skip Tower Escape" || setting->GetName() == "Skip Child Stealth" || - setting->GetName() == "Complete Mask Quest" || + setting->GetName() == "Complete Mask Quest" || + setting->GetName() == "Skip Scarecrow's Song" || setting->GetName() == "Enable Glitch-Useful Cutscenes") { std::string settingName = menu->name + ":" + setting->GetName(); jsonData["settings"][settingName] = setting->GetSelectedOptionText(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b6caa3d3b..083e231d9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -596,6 +596,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }, { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, + { "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG }, { "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES }, }; @@ -824,6 +825,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_STARTING_DEKU_SHIELD: case RSK_STARTING_KOKIRI_SWORD: case RSK_COMPLETE_MASK_QUEST: + case RSK_SKIP_SCARECROWS_SONG: case RSK_ENABLE_GLITCH_CUTSCENES: case RSK_BOMBCHUS_IN_LOGIC: if(it.value() == "Off") { @@ -3484,6 +3486,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SKIP_EPONA_RACE] = CVar_GetS32("gRandomizeSkipEponaRace", 0); cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVar_GetS32("gRandomizeSkipTowerEscape", 0); cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVar_GetS32("gRandomizeCompleteMaskQuest", 0); + cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVar_GetS32("gRandomizeSkipScarecrowsSong", 0); cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVar_GetS32("gRandomizeEnableGlitchCutscenes", 0); cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); @@ -4196,6 +4199,15 @@ void DrawRandoEditor(bool& open) { UIWidgets::PaddedSeparator(); + // Skip Scarecrow Song + UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), + "gRandomizeSkipScarecrowsSong"); + UIWidgets::InsertHelpHoverText( + "Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will automatically summon him." + ); + + UIWidgets::PaddedSeparator(); + ImGui::EndChild(); // COLUMN 2 - Item Pool & Hint Settings diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index ea7446f36..71933fe86 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1014,6 +1014,7 @@ typedef enum { RSK_SKIP_EPONA_RACE, RSK_SKIP_TOWER_ESCAPE, RSK_COMPLETE_MASK_QUEST, + RSK_SKIP_SCARECROWS_SONG, RSK_ENABLE_GLITCH_CUTSCENES, RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 93c816d8d..b202b6a05 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -689,8 +689,13 @@ namespace GameMenuBar { UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + bool forceSkipScarecrow = gSaveContext.n64ddFlag && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); + const char* forceSkipScarecrowText = + "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, + forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); UIWidgets::Tooltip("Allow Link to put items away without having to wait around"); diff --git a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c index a7be7866d..5e3992fc1 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c @@ -118,10 +118,12 @@ void func_80A90264(EnKakasi2* this, GlobalContext* globalCtx) { this->unk_194++; - if (((BREG(1) != 0) || ((CVar_GetS32("gSkipScarecrow", 0) != 0) && - (globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY) && gSaveContext.scarecrowSpawnSongSet)) && - (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && - (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)){ + bool skipScarecrow = globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY && + ((CVar_GetS32("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet) || + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG))); + + if ((BREG(1) != 0) || skipScarecrow && (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && + (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)) { this->actor.draw = func_80A90948; Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);