summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--soh/soh/Enhancements/randomizer/3drando/fill.cpp81
-rw-r--r--soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h7
-rw-r--r--soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h1
-rw-r--r--soh/soh/Enhancements/randomizer/settings.cpp33
4 files changed, 95 insertions, 27 deletions
diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp
index 522b37f34..6e38ca33d 100644
--- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp
@@ -944,24 +944,21 @@ static void AssumedFill(const std::vector<RandomizerGet>& 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();
- // quest item bit mask of each stone/medallion for the savefile
- // static constexpr std::array<uint32_t, 9> bitMaskTable = {
- // 0x00040000, //Kokiri Emerald
- // 0x00080000, //Goron Ruby
- // 0x00100000, //Zora Sapphire
- // 0x00000001, //Forest Medallion
- // 0x00000002, //Fire Medallion
- // 0x00000004, //Water Medallion
- // 0x00000008, //Spirit Medallion
- // 0x00000010, //Shadow Medallion
- // 0x00000020, //Light Medallion
- // };
- 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) ||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
- // get stones and medallions
+ // make temporary pools of stones and medallions, get rewards
+ std::vector<RandomizerGet> stones = FilterFromPool(itemPool, [](const auto i) {
+ return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() >= RG_KOKIRI_EMERALD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() <= RG_ZORA_SAPPHIRE;
+ });
+ std::vector<RandomizerGet> medallions = FilterFromPool(itemPool, [](const auto i) {
+ return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() >= RG_FOREST_MEDALLION &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() <= RG_LIGHT_MEDALLION;
+ });
std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
@@ -978,12 +975,38 @@ static void RandomizeDungeonRewards() {
if (rewards.size() < 9) {
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
} else {
- rewardLocations.push_back(RC_LINKS_POCKET);
+ if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).IsNot(RO_LINKS_POCKET_REWARD)) {
+ if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_STONE)) {
+ // get one stone
+ RandomizerGet startingStone = RandomElement(stones, true);
+ // erase from rewards so remaining are placed
+ erase_if(rewards, [&](RandomizerGet r) { return r == startingStone; });
+ ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingStone);
+ } else {
+ // get one medallion
+ RandomizerGet startingMedallion = RandomElement(medallions, true);
+ // erase from rewards so remaining are placed
+ erase_if(rewards, [&](RandomizerGet r) { return r == startingMedallion; });
+ ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingMedallion);
+ }
+ } 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
+ // make temporary pools of stones, medallions, and rewards
+ std::vector<RandomizerGet> stones = FilterFromPool(itemPool, [](const auto i) {
+ return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() >= RG_KOKIRI_EMERALD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() <= RG_ZORA_SAPPHIRE;
+ });
+ std::vector<RandomizerGet> medallions = FilterFromPool(itemPool, [](const auto i) {
+ return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() >= RG_FOREST_MEDALLION &&
+ Rando::StaticData::RetrieveItem(i).GetRandomizerGet() <= RG_LIGHT_MEDALLION;
+ });
std::vector<RandomizerGet> rewards = FilterFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
@@ -992,13 +1015,27 @@ static void RandomizeDungeonRewards() {
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
return;
}
- RandomizerGet startingReward = RandomElement(rewards, true);
+ if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_STONE)) {
+ // get one stone
+ RandomizerGet startingStone = RandomElement(stones, true);
+ ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingStone);
+ // erase stone from item pool
+ FilterAndEraseFromPool(itemPool, [startingStone](const RandomizerGet i) { return i == startingStone; });
+ } else if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_MEDALLION)) {
+ // get one medallion
+ RandomizerGet startingMedallion = RandomElement(medallions, true);
+ ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingMedallion);
+ // erase medallion from item pool
+ FilterAndEraseFromPool(itemPool,
+ [startingMedallion](const RandomizerGet i) { return i == startingMedallion; });
+ } else {
+ // get one reward
+ RandomizerGet startingReward = RandomElement(rewards, true);
- // LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() -
- // baseOffset];
- ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
- // erase the stone/medallion from the Item Pool
- FilterAndEraseFromPool(itemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
+ ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
+ // erase the stone/medallion from the Item Pool
+ FilterAndEraseFromPool(itemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
+ }
}
}
diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h
index 9cfd3971b..ac0c4dded 100644
--- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h
+++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h
@@ -397,6 +397,13 @@ RANDO_ENUM_ITEM(RO_LINKS_POCKET_ANYTHING)
RANDO_ENUM_ITEM(RO_LINKS_POCKET_NOTHING)
RANDO_ENUM_END(RandoOptionLinksPocket)
+// Link's Pocket Dungeon Reward Settings (dungeon reward, stone, medallion)
+RANDO_ENUM_BEGIN(RandoOptionLinksPocketReward)
+RANDO_ENUM_ITEM(RO_LINKS_POCKET_REWARD)
+RANDO_ENUM_ITEM(RO_LINKS_POCKET_STONE)
+RANDO_ENUM_ITEM(RO_LINKS_POCKET_MEDALLION)
+RANDO_ENUM_END(RandoOptionLinksPocketReward)
+
// Logic (glitchless/no logic)
RANDO_ENUM_BEGIN(RandoOptionLogic)
RANDO_ENUM_ITEM(RO_LOGIC_GLITCHLESS)
diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h
index 994d6d8f1..40ebb218d 100644
--- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h
+++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h
@@ -166,6 +166,7 @@ RANDO_ENUM_ITEM(RSK_SLINGBOW_BREAK_BEEHIVES)
RANDO_ENUM_ITEM(RSK_ENABLE_BOMBCHU_DROPS)
RANDO_ENUM_ITEM(RSK_BOMBCHU_BAG)
RANDO_ENUM_ITEM(RSK_LINKS_POCKET)
+RANDO_ENUM_ITEM(RSK_LINKS_POCKET_REWARD)
RANDO_ENUM_ITEM(RSK_MQ_DUNGEON_RANDOM)
RANDO_ENUM_ITEM(RSK_MQ_DUNGEON_COUNT)
RANDO_ENUM_ITEM(RSK_MQ_DUNGEON_SET)
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index cebca12a5..873f17b9d 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -574,11 +574,34 @@ void Settings::CreateOptions() {
RO_DUNGEON_REWARDS_END_OF_DUNGEON) {
mOptions[RSK_LINKS_POCKET].Disable(
"This option is disabled because \"Dungeon Rewards\" are shuffled to \"End of Dungeons\".");
+ mOptions[RSK_LINKS_POCKET_REWARD].Enable();
+ mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
+ } else if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
+ RO_DUNGEON_REWARDS_VANILLA) {
+ mOptions[RSK_LINKS_POCKET_REWARD].Disable("This option is disabled because \"Dungeon Rewards\" are shuffled to \"Vanilla\".");
+ mOptions[RSK_LINKS_POCKET_REWARD].Hide();
+ mOptions[RSK_LINKS_POCKET].Enable();
} else {
mOptions[RSK_LINKS_POCKET].Enable();
+ mOptions[RSK_LINKS_POCKET_REWARD].Enable();
+ if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) == RO_LINKS_POCKET_DUNGEON_REWARD) {
+ mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
+ }
}
});
OPT_U8(RSK_LINKS_POCKET, "Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WIDGET_CVAR_COMBOBOX, RO_LINKS_POCKET_DUNGEON_REWARD);
+ OPT_CALLBACK(RSK_LINKS_POCKET, {
+ // Only show the dungeon reward type if Link's Pocket is set to Dungeon Reward and Dungeon Rewards are not Vanilla, OR Dungeon Rewards are end of dungeon
+ if ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) ==
+ RO_LINKS_POCKET_DUNGEON_REWARD && CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) !=
+ RO_DUNGEON_REWARDS_VANILLA) || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
+ RO_DUNGEON_REWARDS_END_OF_DUNGEON) {
+ mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
+ } else {
+ mOptions[RSK_LINKS_POCKET_REWARD].Hide();
+ }
+ });
+ OPT_U8(RSK_LINKS_POCKET_REWARD, "Link's Pocket Reward Type", {"Dungeon Reward", "Stone", "Medallion"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocketReward"), "", WIDGET_CVAR_COMBOBOX, RO_LINKS_POCKET_REWARD);
OPT_U8(RSK_SHUFFLE_SONGS, "Shuffle Songs", {"Off", "Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WIDGET_CVAR_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], WIDGET_CVAR_COMBOBOX, RO_SHOPSANITY_OFF);
OPT_CALLBACK(RSK_SHOPSANITY, {
@@ -2547,11 +2570,11 @@ void Settings::CreateOptions() {
&mOptionGroups[RSG_MENU_COLUMN_STATIC_HINTS],
},
WidgetContainerType::TABLE);
- mOptionGroups[RSG_MENU_SECTION_STARTING_EQUIPS] =
- OptionGroup::SubGroup("Equips",
- { &mOptions[RSK_LINKS_POCKET], &mOptions[RSK_STARTING_KOKIRI_SWORD],
- &mOptions[RSK_STARTING_MASTER_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD] },
- WidgetContainerType::SECTION);
+ mOptionGroups[RSG_MENU_SECTION_STARTING_EQUIPS] = OptionGroup::SubGroup(
+ "Equips",
+ { &mOptions[RSK_LINKS_POCKET], &mOptions[RSK_LINKS_POCKET_REWARD], &mOptions[RSK_STARTING_KOKIRI_SWORD],
+ &mOptions[RSK_STARTING_MASTER_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD] },
+ WidgetContainerType::SECTION);
mOptionGroups[RSG_MENU_SECTION_STARTING_ITEMS] = OptionGroup::SubGroup("Items",
{
&mOptions[RSK_STARTING_OCARINA],