mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-04-23 08:14:31 +00:00
Dungeon Rewards Own Dungeon + Light Medallion Handling Refactor (#6500)
Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com>
This commit is contained in:
parent
17a8f460e0
commit
12dddc5e8e
|
|
@ -933,102 +933,96 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
|
|||
} while (unsuccessfulPlacement);
|
||||
}
|
||||
|
||||
static std::vector<RandomizerGet> GetStonesInPool(std::vector<RandomizerGet> pool) {
|
||||
return FilterFromPool(pool, [](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;
|
||||
});
|
||||
}
|
||||
|
||||
static std::vector<RandomizerGet> GetMedallionsInPool(std::vector<RandomizerGet> pool) {
|
||||
return FilterFromPool(pool, [](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;
|
||||
});
|
||||
}
|
||||
|
||||
// This function will specifically randomize dungeon rewards for the End of Dungeons
|
||||
// setting, or randomize one dungeon reward to Link's Pocket if that setting is on
|
||||
// RANDOTODO this function assumes only 1 of each reward can exist, fix it when starting items are refactored
|
||||
static void RandomizeDungeonRewards() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
// 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)) {
|
||||
// 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;
|
||||
});
|
||||
std::vector<RandomizerGet> rewards = FilterFromPool(itemPool, [](const auto i) {
|
||||
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
|
||||
});
|
||||
|
||||
if (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();
|
||||
if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD) && rewards.size() >= 9) {
|
||||
RandomizerGet pocketItem = RG_GREEN_RUPEE;
|
||||
std::vector<RandomizerGet> pocketPossibilities = {};
|
||||
|
||||
if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_ANY_STONE)) {
|
||||
// get existing stones
|
||||
pocketPossibilities = GetStonesInPool(rewards);
|
||||
} else if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_LIGHT_MEDALLION)) {
|
||||
// check if Light medallion exists
|
||||
std::vector<RandomizerGet> lightMedallion = FilterFromPool(rewards, [](const auto i) {
|
||||
return Rando::StaticData::RetrieveItem(i).GetRandomizerGet() == RG_LIGHT_MEDALLION;
|
||||
});
|
||||
// If there are no light med, then Link's pocket can't get one
|
||||
if (!lightMedallion.empty()) {
|
||||
pocketPossibilities = { RG_LIGHT_MEDALLION };
|
||||
}
|
||||
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 {
|
||||
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_REWARD).Is(RO_LINKS_POCKET_ANY_MEDALLION)) {
|
||||
// get existing medallions
|
||||
pocketPossibilities = GetMedallionsInPool(rewards);
|
||||
} else if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_ANY_REWARD)) {
|
||||
// get all existing rewards
|
||||
pocketPossibilities = rewards;
|
||||
}
|
||||
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) {
|
||||
// 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;
|
||||
});
|
||||
// If there are no remaining stones/medallions, then Link's pocket won't get one
|
||||
if (rewards.empty()) {
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE);
|
||||
return;
|
||||
}
|
||||
if (ctx->GetOption(RSK_LINKS_POCKET_REWARD).Is(RO_LINKS_POCKET_STONE)) {
|
||||
|
||||
if (!pocketPossibilities.empty()) {
|
||||
// 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);
|
||||
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
|
||||
// erase the stone/medallion from the Item Pool
|
||||
FilterAndEraseFromPool(itemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
|
||||
pocketItem = RandomElement(pocketPossibilities);
|
||||
}
|
||||
// erase from rewards so remaining are placed
|
||||
erase_if(rewards, [&](RandomizerGet r) { return r == pocketItem; });
|
||||
// and from the item pool so it's not placed twice
|
||||
FilterAndEraseFromPool(itemPool, [pocketItem](const RandomizerGet i) { return i == pocketItem; });
|
||||
// and add to the pocket
|
||||
ctx->PlaceItemInLocation(RC_LINKS_POCKET, pocketItem);
|
||||
}
|
||||
|
||||
// If we didn't place the Light Medallion on pocket, and we have rewards in their own dungeons or at the end of
|
||||
// dungeons...
|
||||
if ((ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA) ||
|
||||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OWN_DUNGEON)) &&
|
||||
ctx->GetOption(RSK_LINKS_POCKET).IsNot(RO_LINKS_POCKET_DUNGEON_REWARD)) {
|
||||
// place it on Gift From Rauru
|
||||
ctx->GetItemLocation(RC_GIFT_FROM_RAURU)->PlaceVanillaItem();
|
||||
// then erase from rewards so remaining are placed
|
||||
erase_if(rewards, [&](RandomizerGet r) { return r == RG_LIGHT_MEDALLION; });
|
||||
// and from the item pool so it's not placed twice
|
||||
FilterAndEraseFromPool(itemPool, [](const RandomizerGet i) { return i == RG_LIGHT_MEDALLION; });
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
||||
// Randomize dungeon rewards with assumed fill
|
||||
AssumedFill(rewards, Rando::StaticData::dungeonRewardLocations);
|
||||
// Then remove them from the item pool
|
||||
FilterAndEraseFromPool(itemPool, [](const auto i) {
|
||||
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
|
||||
});
|
||||
} else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
|
||||
for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) {
|
||||
ctx->GetItemLocation(loc)->PlaceVanillaItem();
|
||||
}
|
||||
// Then remove rewards from the item pool
|
||||
FilterAndEraseFromPool(itemPool, [](const auto i) {
|
||||
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1078,6 +1072,12 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
|
|||
});
|
||||
AddElementsToPool(dungeonItems, dungeonSmallKeys);
|
||||
}
|
||||
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OWN_DUNGEON) &&
|
||||
dungeon->GetReward() != RG_NONE) {
|
||||
std::vector<RandomizerGet> dungeonReward =
|
||||
FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) { return (i == dungeon->GetReward()); });
|
||||
AddElementsToPool(dungeonItems, dungeonReward);
|
||||
}
|
||||
|
||||
if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) &&
|
||||
dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) ||
|
||||
|
|
@ -1088,7 +1088,7 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
|
|||
AddElementsToPool(dungeonItems, dungeonBossKey);
|
||||
}
|
||||
|
||||
// randomize boss key and small keys together for even distribution
|
||||
// randomize boss key, small keys, and rewards together for even distribution
|
||||
AssumedFill(dungeonItems, dungeonLocations);
|
||||
|
||||
// randomize map and compass separately since they're not progressive
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ void GenerateItemPool() {
|
|||
ctx->PlaceItemInLocation(RC_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, false, true);
|
||||
}
|
||||
|
||||
bool rewardIceTraps = ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Get() >= RO_DUNGEON_REWARDS_ANY_DUNGEON;
|
||||
bool rewardIceTraps = ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Get() >= RO_DUNGEON_REWARDS_OWN_DUNGEON;
|
||||
AddFixedItemToPool(RG_KOKIRI_EMERALD, 1, rewardIceTraps);
|
||||
AddFixedItemToPool(RG_GORON_RUBY, 1, rewardIceTraps);
|
||||
AddFixedItemToPool(RG_ZORA_SAPPHIRE, 1, rewardIceTraps);
|
||||
|
|
|
|||
|
|
@ -7,14 +7,16 @@
|
|||
namespace Rando {
|
||||
DungeonInfo::DungeonInfo(std::string name_, const RandomizerHintTextKey hintKey_, const RandomizerGet map_,
|
||||
const RandomizerGet compass_, const RandomizerGet smallKey_, const RandomizerGet keyRing_,
|
||||
const RandomizerGet bossKey_, RandomizerArea area_, const uint8_t vanillaKeyCount_,
|
||||
const uint8_t mqKeyCount_, const RandomizerSettingKey mqSetting_)
|
||||
const RandomizerGet bossKey_, RandomizerGet reward_, RandomizerArea area_,
|
||||
const uint8_t vanillaKeyCount_, const uint8_t mqKeyCount_,
|
||||
const RandomizerSettingKey mqSetting_)
|
||||
: name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_),
|
||||
bossKey(bossKey_), area(area_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_),
|
||||
bossKey(bossKey_), reward(reward_), area(area_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_),
|
||||
mqSetting(mqSetting_) {
|
||||
}
|
||||
DungeonInfo::DungeonInfo()
|
||||
: hintKey(RHT_NONE), map(RG_NONE), compass(RG_NONE), smallKey(RG_NONE), keyRing(RG_NONE), bossKey(RG_NONE) {
|
||||
: hintKey(RHT_NONE), map(RG_NONE), compass(RG_NONE), smallKey(RG_NONE), keyRing(RG_NONE), bossKey(RG_NONE),
|
||||
reward(RG_NONE) {
|
||||
}
|
||||
DungeonInfo::~DungeonInfo() = default;
|
||||
|
||||
|
|
@ -82,6 +84,10 @@ RandomizerGet DungeonInfo::GetBossKey() const {
|
|||
return bossKey;
|
||||
}
|
||||
|
||||
RandomizerGet DungeonInfo::GetReward() const {
|
||||
return reward;
|
||||
}
|
||||
|
||||
RandomizerSettingKey DungeonInfo::GetMQSetting() const {
|
||||
return mqSetting;
|
||||
}
|
||||
|
|
@ -147,40 +153,44 @@ std::vector<RandomizerCheck> DungeonInfo::GetDungeonLocations() const {
|
|||
|
||||
Dungeons::Dungeons() {
|
||||
dungeonList[DEKU_TREE] = DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE,
|
||||
RG_NONE, RG_NONE, RA_DEKU_TREE, 0, 0, RSK_MQ_DEKU_TREE);
|
||||
RG_NONE, RG_NONE, RG_KOKIRI_EMERALD, RA_DEKU_TREE, 0, 0, RSK_MQ_DEKU_TREE);
|
||||
dungeonList[DODONGOS_CAVERN] =
|
||||
DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_COMPASS,
|
||||
RG_NONE, RG_NONE, RG_NONE, RA_DODONGOS_CAVERN, 0, 0, RSK_MQ_DODONGOS_CAVERN);
|
||||
RG_NONE, RG_NONE, RG_NONE, RG_GORON_RUBY, RA_DODONGOS_CAVERN, 0, 0, RSK_MQ_DODONGOS_CAVERN);
|
||||
dungeonList[JABU_JABUS_BELLY] =
|
||||
DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_COMPASS,
|
||||
RG_NONE, RG_NONE, RG_NONE, RA_JABU_JABUS_BELLY, 0, 0, RSK_MQ_JABU_JABU);
|
||||
dungeonList[FOREST_TEMPLE] = DungeonInfo(
|
||||
"Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_SMALL_KEY,
|
||||
RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, RA_FOREST_TEMPLE, 5, 6, RSK_MQ_FOREST_TEMPLE);
|
||||
RG_NONE, RG_NONE, RG_NONE, RG_ZORA_SAPPHIRE, RA_JABU_JABUS_BELLY, 0, 0, RSK_MQ_JABU_JABU);
|
||||
dungeonList[FOREST_TEMPLE] =
|
||||
DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS,
|
||||
RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY,
|
||||
RG_FOREST_MEDALLION, RA_FOREST_TEMPLE, 5, 6, RSK_MQ_FOREST_TEMPLE);
|
||||
dungeonList[FIRE_TEMPLE] = DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS,
|
||||
RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY,
|
||||
RA_FIRE_TEMPLE, 8, 5, RSK_MQ_FIRE_TEMPLE);
|
||||
dungeonList[WATER_TEMPLE] = DungeonInfo(
|
||||
"Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_SMALL_KEY,
|
||||
RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, RA_WATER_TEMPLE, 6, 2, RSK_MQ_WATER_TEMPLE);
|
||||
dungeonList[SPIRIT_TEMPLE] = DungeonInfo(
|
||||
"Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_SMALL_KEY,
|
||||
RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, RA_SPIRIT_TEMPLE, 5, 7, RSK_MQ_SPIRIT_TEMPLE);
|
||||
dungeonList[SHADOW_TEMPLE] = DungeonInfo(
|
||||
"Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_SMALL_KEY,
|
||||
RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, RA_SHADOW_TEMPLE, 5, 6, RSK_MQ_SHADOW_TEMPLE);
|
||||
RG_FIRE_MEDALLION, RA_FIRE_TEMPLE, 8, 5, RSK_MQ_FIRE_TEMPLE);
|
||||
dungeonList[WATER_TEMPLE] =
|
||||
DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS,
|
||||
RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, RG_WATER_MEDALLION,
|
||||
RA_WATER_TEMPLE, 6, 2, RSK_MQ_WATER_TEMPLE);
|
||||
dungeonList[SPIRIT_TEMPLE] =
|
||||
DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS,
|
||||
RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY,
|
||||
RG_SPIRIT_MEDALLION, RA_SPIRIT_TEMPLE, 5, 7, RSK_MQ_SPIRIT_TEMPLE);
|
||||
dungeonList[SHADOW_TEMPLE] =
|
||||
DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS,
|
||||
RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY,
|
||||
RG_SHADOW_MEDALLION, RA_SHADOW_TEMPLE, 5, 6, RSK_MQ_SHADOW_TEMPLE);
|
||||
dungeonList[BOTTOM_OF_THE_WELL] =
|
||||
DungeonInfo("Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP,
|
||||
RG_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING,
|
||||
RG_NONE, RA_BOTTOM_OF_THE_WELL, 3, 2, RSK_MQ_BOTTOM_OF_THE_WELL);
|
||||
RG_NONE, RG_NONE, RA_BOTTOM_OF_THE_WELL, 3, 2, RSK_MQ_BOTTOM_OF_THE_WELL);
|
||||
dungeonList[ICE_CAVERN] = DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS,
|
||||
RG_NONE, RG_NONE, RG_NONE, RA_ICE_CAVERN, 0, 0, RSK_MQ_ICE_CAVERN);
|
||||
RG_NONE, RG_NONE, RG_NONE, RG_NONE, RA_ICE_CAVERN, 0, 0, RSK_MQ_ICE_CAVERN);
|
||||
dungeonList[GERUDO_TRAINING_GROUND] = DungeonInfo(
|
||||
"Gerudo Training Ground", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE, RG_GERUDO_TRAINING_GROUND_SMALL_KEY,
|
||||
RG_GERUDO_TRAINING_GROUND_KEY_RING, RG_NONE, RA_GERUDO_TRAINING_GROUND, 9, 3, RSK_MQ_GTG);
|
||||
dungeonList[GANONS_CASTLE] =
|
||||
DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY,
|
||||
RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, RA_GANONS_CASTLE, 2, 3, RSK_MQ_GANONS_CASTLE);
|
||||
RG_GERUDO_TRAINING_GROUND_KEY_RING, RG_NONE, RG_NONE, RA_GERUDO_TRAINING_GROUND, 9, 3, RSK_MQ_GTG);
|
||||
dungeonList[GANONS_CASTLE] = DungeonInfo(
|
||||
"Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_KEY_RING,
|
||||
RG_GANONS_CASTLE_BOSS_KEY, RG_NONE, RA_GANONS_CASTLE, 2, 3, RSK_MQ_GANONS_CASTLE);
|
||||
}
|
||||
|
||||
Dungeons::~Dungeons() = default;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace Rando {
|
|||
class DungeonInfo {
|
||||
public:
|
||||
DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_,
|
||||
RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, RandomizerArea area_,
|
||||
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, RandomizerSettingKey mqSetting_);
|
||||
RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, RandomizerGet reward_,
|
||||
RandomizerArea area_, uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, RandomizerSettingKey mqSetting_);
|
||||
DungeonInfo();
|
||||
~DungeonInfo();
|
||||
|
||||
|
|
@ -32,6 +32,7 @@ class DungeonInfo {
|
|||
RandomizerGet GetMap() const;
|
||||
RandomizerGet GetCompass() const;
|
||||
RandomizerGet GetBossKey() const;
|
||||
RandomizerGet GetReward() const;
|
||||
RandomizerSettingKey GetMQSetting() const;
|
||||
void SetDungeonKnown(bool known);
|
||||
void PlaceVanillaMap() const;
|
||||
|
|
@ -50,6 +51,7 @@ class DungeonInfo {
|
|||
RandomizerGet smallKey;
|
||||
RandomizerGet keyRing;
|
||||
RandomizerGet bossKey;
|
||||
RandomizerGet reward;
|
||||
RandomizerSettingKey mqSetting;
|
||||
bool isDungeonModeKnown = true;
|
||||
uint8_t vanillaKeyCount{};
|
||||
|
|
|
|||
|
|
@ -804,6 +804,16 @@ void Settings::CreateOptionDescriptions() {
|
|||
"of 20. The second one will upgrade this capacity to 30, and the final one will upgrade the capacity to the "
|
||||
"usual 50.\n\n"
|
||||
"Bombchu Bowling is opened by obtaining the first Bombchu bag.";
|
||||
mOptionDescriptions[RSK_LINKS_POCKET] =
|
||||
"Dungeon Reward - Link will start with a Spiritual Stone or Medallion, and specific options will open up\n\n"
|
||||
"Advancement - Link will start with a useful item.\n\n"
|
||||
"Anything - Link will start with a random item.\n\n"
|
||||
"Nothing - Link will not start with a bonus item.";
|
||||
mOptionDescriptions[RSK_LINKS_POCKET_REWARD] =
|
||||
"Any Reward - Link starts with a random Spiritual Stone or Medallion\n\n"
|
||||
"Stone - Link starts with a random Spiritual Stone.\n\n"
|
||||
"Any Medallion - Link starts with a random Medallion.\n\n"
|
||||
"Light Medallion - Link starts with the Light Medallion.";
|
||||
mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS] = "Once you obtain a Bombchu Bag, refills will sometimes replace "
|
||||
"Bomb drops that would spawn."
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ RANDO_ENUM_END(RandoOptionDungeonItemLocation)
|
|||
RANDO_ENUM_BEGIN(RandoOptionDungeonRewards)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_VANILLA)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_END_OF_DUNGEON)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_OWN_DUNGEON)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_ANY_DUNGEON)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_OVERWORLD)
|
||||
RANDO_ENUM_ITEM(RO_DUNGEON_REWARDS_ANYWHERE)
|
||||
|
|
@ -415,9 +416,10 @@ 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_ITEM(RO_LINKS_POCKET_ANY_REWARD)
|
||||
RANDO_ENUM_ITEM(RO_LINKS_POCKET_ANY_STONE)
|
||||
RANDO_ENUM_ITEM(RO_LINKS_POCKET_ANY_MEDALLION)
|
||||
RANDO_ENUM_ITEM(RO_LINKS_POCKET_LIGHT_MEDALLION)
|
||||
RANDO_ENUM_END(RandoOptionLinksPocketReward)
|
||||
|
||||
// Logic (glitchless/no logic)
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ void Settings::CreateOptions() {
|
|||
OPT_U8(RSK_MQ_ICE_CAVERN, "Ice Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
||||
OPT_U8(RSK_MQ_GTG, "Gerudo Training Ground Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
||||
OPT_U8(RSK_MQ_GANONS_CASTLE, "Ganon's Castle Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA);
|
||||
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], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
|
||||
OPT_U8(RSK_SHUFFLE_DUNGEON_REWARDS, "Shuffle Dungeon Rewards", {"Vanilla", "End of Dungeons", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
|
||||
OPT_CALLBACK(RSK_SHUFFLE_DUNGEON_REWARDS, {
|
||||
// Link's Pocket - Disabled when Dungeon Rewards are shuffled to End of Dungeon
|
||||
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
||||
|
|
@ -573,32 +573,39 @@ void Settings::CreateOptions() {
|
|||
"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("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
||||
RO_DUNGEON_REWARDS_OWN_DUNGEON) {
|
||||
mOptions[RSK_LINKS_POCKET].Enable();
|
||||
mOptions[RSK_LINKS_POCKET_REWARD].Disable(
|
||||
"As \"Link's Pocket\" is set to \"Dungeon Reward\" while \"Dungeon Rewards\" is set to \"Own Dungeon\", Link's Pocket will always have the Light Medallion");
|
||||
}else if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
||||
RO_DUNGEON_REWARDS_VANILLA) {
|
||||
mOptions[RSK_LINKS_POCKET].Enable();
|
||||
mOptions[RSK_LINKS_POCKET_REWARD].Disable(
|
||||
"As \"Link's Pocket\" is set to \"Dungeon Reward\" while \"Dungeon Rewards\" is set to \"Vanilla\", Link's Pocket will always have the Light Medallion");
|
||||
} 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();
|
||||
}
|
||||
} else {
|
||||
mOptions[RSK_LINKS_POCKET_REWARD].Hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
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_U8(RSK_LINKS_POCKET, "Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), mOptionDescriptions[RSK_LINKS_POCKET], 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) {
|
||||
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_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_LINKS_POCKET_REWARD, "Link's Pocket Reward Type", {"Any Reward", "Any Stone", "Any Medallion", "Light Medallion"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocketReward"), mOptionDescriptions[RSK_LINKS_POCKET_REWARD], WIDGET_CVAR_COMBOBOX, RO_LINKS_POCKET_ANY_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, {
|
||||
|
|
@ -2519,6 +2526,13 @@ void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocation
|
|||
|
||||
if (mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
||||
mOptions[RSK_LINKS_POCKET].Set(RO_LINKS_POCKET_DUNGEON_REWARD);
|
||||
} else if (mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_OWN_DUNGEON) ||
|
||||
mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_VANILLA)) {
|
||||
mOptions[RSK_LINKS_POCKET_REWARD].Set(RO_LINKS_POCKET_LIGHT_MEDALLION);
|
||||
}
|
||||
|
||||
if (mOptions[RSK_LINKS_POCKET].IsNot(RO_LINKS_POCKET_DUNGEON_REWARD)) {
|
||||
mOptions[RSK_LINKS_POCKET_REWARD].Set(RO_LINKS_POCKET_ANY_REWARD);
|
||||
}
|
||||
|
||||
for (const auto locationKey : this->everyPossibleLocation) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue