rando: vanilla dungeon rewards (#4836)

* rando: vanilla dungeon rewards

* gift from rauru is dungeon location, not pocket

* missing apostrophe in preset description

* neither pocket nor gift should be listed in dungeonRewardLocations
This commit is contained in:
Philip Dubé 2025-02-03 09:57:35 +00:00 committed by GitHub
parent e5ddcce7f2
commit e7e02735b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 33 additions and 35 deletions

View File

@ -1403,7 +1403,7 @@ const std::map<PresetType, PresetTypeDefinition> 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<PresetType, PresetTypeDefinition> 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,

View File

@ -900,7 +900,6 @@ 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();
std::array<uint32_t, 9> rDungeonRewardOverrides{};
//quest item bit mask of each stone/medallion for the savefile
// static constexpr std::array<uint32_t, 9> 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<RandomizerGet> 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

View File

@ -698,8 +698,8 @@ void CreateChildAltarHint() {
if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()){
std::vector<RandomizerCheck> 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<RandomizerArea> 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<RandomizerCheck> 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<RandomizerArea> 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));
}

View File

@ -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() {

View File

@ -8,8 +8,8 @@ std::multimap<std::tuple<s16, s16, s32>, RandomizerCheck> Rando::StaticData::Che
std::vector<RandomizerCheck> 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;

View File

@ -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"

View File

@ -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,

View File

@ -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);