diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 31df92831..b7b7100b9 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -1403,7 +1403,7 @@ const std::map presetTypes = { "Spock Race", "Race preset used for the official Ship of Harkinian race on June 3rd 2023. The following settings are notable:\n" \ "- Rainbow Bridge is set to Greg\n" \ - "- Ganons Boss Key is 5 dungeon rewards\n" \ + "- Ganon's Boss Key is 5 dungeon rewards\n" \ "- Shopsanity and Scrubsanity enabled\n" \ "- All locations reachable is off\n", \ spockRacePresetEntries, @@ -1413,7 +1413,7 @@ const std::map presetTypes = { "No Logic Race preset used for official Ship of Harkinian No Logic races. The following settings are " "notable:\n" "- Rainbow Bridge is set to Greg\n" - "- Ganons Boss Key is 5 dungeon rewards\n" + "- Ganon's Boss Key is 5 dungeon rewards\n" "- Shopsanity and Scrubsanity enabled\n" "- All locations reachable is off\n", spockRaceNoLogicPresetEntries, diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 234bd6a8e..9c2bff044 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -900,7 +900,6 @@ static void AssumedFill(const std::vector& items, const std::vect //setting, or randomize one dungeon reward to Link's Pocket if that setting is on static void RandomizeDungeonRewards() { auto ctx = Rando::Context::GetInstance(); - std::array rDungeonRewardOverrides{}; //quest item bit mask of each stone/medallion for the savefile // static constexpr std::array bitMaskTable = { // 0x00040000, //Kokiri Emerald @@ -916,34 +915,24 @@ static void RandomizeDungeonRewards() { int baseOffset = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetItemID(); //End of Dungeons includes Link's Pocket - if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { //get stones and medallions std::vector rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;}); - // If there are less than 9 dungeon rewards, prioritize the actual dungeons - // for placement instead of Link's Pocket - if (rewards.size() < 9) { - ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE); - } - - if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { // Place dungeon rewards in vanilla locations for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) { ctx->GetItemLocation(loc)->PlaceVanillaItem(); } - } else { //Randomize dungeon rewards with assumed fill - AssumedFill(rewards, Rando::StaticData::dungeonRewardLocations); - } - - for (size_t i = 0; i < Rando::StaticData::dungeonRewardLocations.size(); i++) { - const auto index = ctx->GetItemLocation(Rando::StaticData::dungeonRewardLocations[i])->GetPlacedItem().GetItemID() - baseOffset; - rDungeonRewardOverrides[i] = index; - - //set the player's dungeon reward on file creation instead of pushing it to them at the start. - //This is done mainly because players are already familiar with seeing their dungeon reward - //before opening up their file - // if (i == Rando::StaticData::dungeonRewardLocations.size()-1) { - // LinksPocketRewardBitMask = bitMaskTable[index]; - // } + ctx->GetItemLocation(RC_GIFT_FROM_RAURU)->PlaceVanillaItem(); + } else { // Randomize dungeon rewards with assumed fill + std::vector rewardLocations(Rando::StaticData::dungeonRewardLocations); + // If there are less than 9 dungeon rewards, prioritize actual dungeons for placement + if (rewards.size() < 9) { + ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE); + } else { + rewardLocations.push_back(RC_LINKS_POCKET); + } + AssumedFill(rewards, rewardLocations); } } else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) { //get 1 stone/medallion diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 634c2ca56..b9e9f4688 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -698,8 +698,8 @@ void CreateChildAltarHint() { if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()){ std::vector stoneLocs = {}; if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { - //force marking the rewards as hinted if they are at the end of dungeons as they can be inffered - if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ + //force marking the rewards as hinted if they are at the end of dungeons as they can be inferred + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { stoneLocs = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {}); } else { stoneLocs = FindItemsAndMarkHinted({RG_KOKIRI_EMERALD, RG_GORON_RUBY, RG_ZORA_SAPPHIRE}, {RC_ALTAR_HINT_CHILD}); @@ -707,7 +707,9 @@ void CreateChildAltarHint() { } std::vector stoneAreas = {}; for (auto loc : stoneLocs){ - stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + if (loc != RC_UNKNOWN_CHECK) { + stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs, stoneAreas)); } @@ -718,9 +720,9 @@ void CreateAdultAltarHint() { if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()){ std::vector medallionLocs = {}; if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { - //force marking the rewards as hinted if they are at the end of dungeons as they can be inffered - if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ - medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, + //force marking the rewards as hinted if they are at the end of dungeons as they can be inferred + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { + medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, {}); } else { medallionLocs = FindItemsAndMarkHinted({RG_LIGHT_MEDALLION, RG_FOREST_MEDALLION, RG_FIRE_MEDALLION, RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION}, @@ -729,7 +731,9 @@ void CreateAdultAltarHint() { } std::vector medallionAreas = {}; for (auto loc : medallionLocs){ - medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + if (loc != RC_UNKNOWN_CHECK) { + medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs, medallionAreas)); } diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index 79a60cc70..cd4914aaf 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -214,6 +214,9 @@ void Context::ItemReset() { for (const RandomizerCheck il : StaticData::dungeonRewardLocations) { GetItemLocation(il)->ResetVariables(); } + + GetItemLocation(RC_GIFT_FROM_RAURU)->ResetVariables(); + GetItemLocation(RC_LINKS_POCKET)->ResetVariables(); } void Context::LocationReset() { diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 54c1d8f81..1fe52b897 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -8,8 +8,8 @@ std::multimap, RandomizerCheck> Rando::StaticData::Che std::vector Rando::StaticData::dungeonRewardLocations = { // Bosses - RC_QUEEN_GOHMA, RC_KING_DODONGO, RC_BARINADE, RC_PHANTOM_GANON, RC_VOLVAGIA, - RC_MORPHA, RC_TWINROVA, RC_BONGO_BONGO, RC_LINKS_POCKET, + RC_QUEEN_GOHMA, RC_KING_DODONGO, RC_BARINADE, + RC_PHANTOM_GANON, RC_VOLVAGIA, RC_MORPHA, RC_TWINROVA, RC_BONGO_BONGO, }; using namespace Rando; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 8abdd2634..a3184765f 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -451,6 +451,7 @@ void Settings::CreateOptionDescriptions() { "Shuffle fairy locations."; mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS] = "Shuffles the location of Spiritual Stones and medallions.\n" + "Vanilla - Spiritual Stones and medallions will be given from their respective boss.\n" "\n" "End of dungeons - Spiritual Stones and medallions will be given as rewards " "for beating major dungeons. Link will always start with one stone or medallion.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 0561ce54d..dabfedac7 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -5388,6 +5388,7 @@ typedef enum { //Dungeon reward settings typedef enum { + RO_DUNGEON_REWARDS_VANILLA, RO_DUNGEON_REWARDS_END_OF_DUNGEON, RO_DUNGEON_REWARDS_ANY_DUNGEON, RO_DUNGEON_REWARDS_OVERWORLD, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 2ca325635..cf1acdd7f 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -170,7 +170,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_MQ_ICE_CAVERN, "Ice Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); OPT_U8(RSK_MQ_GTG, "Gerudo Training Ground Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE); OPT_U8(RSK_MQ_GANONS_CASTLE, "Ganon's Castle Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA); - OPT_U8(RSK_SHUFFLE_DUNGEON_REWARDS, "Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON); + OPT_U8(RSK_SHUFFLE_DUNGEON_REWARDS, "Shuffle Dungeon Rewards", {"Vanilla", "End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON); OPT_U8(RSK_LINKS_POCKET, "Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD); OPT_U8(RSK_SHUFFLE_SONGS, "Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS); OPT_U8(RSK_SHOPSANITY, "Shop Shuffle", {"Off", "Specific Count", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF);