Add option to shuffle frog song rupees

This commit is contained in:
Garrett Cox 2022-08-05 09:52:11 -05:00
parent 2d22099805
commit ed3cddbeaf
11 changed files with 114 additions and 1 deletions

View File

@ -165,6 +165,11 @@ void LocationTable_Init() {
//Zoras River
locationTable[ZR_OPEN_GROTTO_CHEST] = ItemLocation::Chest (0x3E, 0x09, "ZR Open Grotto Chest", ZR_OPEN_GROTTO_CHEST, RED_RUPEE, {Category::cZorasRiver, Category::cGrotto,}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_MAGIC_BEAN_SALESMAN] = ItemLocation::Base (0x54, 0x16, "ZR Magic Bean Salesman", ZR_MAGIC_BEAN_SALESMAN, MAGIC_BEAN, {Category::cZorasRiver,}, SpoilerCollectionCheck::MagicBeans(0x54, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_ZELDAS_LULLABY] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Zelda's Lullaby", ZR_FROGS_ZELDAS_LULLABY, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_EPONAS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Epona's Song", ZR_FROGS_EPONAS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_SARIAS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Saria's Song", ZR_FROGS_SARIAS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_SUNS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Sun's Song", ZR_FROGS_SUNS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_SONG_OF_TIME] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Song of Time", ZR_FROGS_SONG_OF_TIME, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_IN_THE_RAIN] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs in the Rain", ZR_FROGS_IN_THE_RAIN, PIECE_OF_HEART, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_FROGS_OCARINA_GAME] = ItemLocation::Base (0x54, 0x76, "ZR Frogs Ocarina Game", ZR_FROGS_OCARINA_GAME, PIECE_OF_HEART, {Category::cZorasRiver, Category::cMinigame,}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
locationTable[ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = ItemLocation::Collectable(0x54, 0x04, "ZR Near Open Grotto Freestanding PoH", ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, PIECE_OF_HEART, {Category::cZorasRiver,}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
@ -1302,6 +1307,11 @@ std::vector<uint32_t> overworldLocations = {
//Zoras River
ZR_OPEN_GROTTO_CHEST,
ZR_MAGIC_BEAN_SALESMAN,
ZR_FROGS_ZELDAS_LULLABY,
ZR_FROGS_EPONAS_SONG,
ZR_FROGS_SARIAS_SONG,
ZR_FROGS_SUNS_SONG,
ZR_FROGS_SONG_OF_TIME,
ZR_FROGS_IN_THE_RAIN,
ZR_FROGS_OCARINA_GAME,
ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH,

View File

@ -729,6 +729,16 @@ void GenerateItemPool() {
PlaceItemInLocation(WASTELAND_BOMBCHU_SALESMAN, BOMBCHU_10, false, true);
}
if (ShuffleFrogSongRupees) {
AddItemToMainPool(PURPLE_RUPEE, 5);
} else {
PlaceItemInLocation(ZR_FROGS_ZELDAS_LULLABY, PURPLE_RUPEE, false, true);
PlaceItemInLocation(ZR_FROGS_EPONAS_SONG, PURPLE_RUPEE, false, true);
PlaceItemInLocation(ZR_FROGS_SARIAS_SONG, PURPLE_RUPEE, false, true);
PlaceItemInLocation(ZR_FROGS_SUNS_SONG, PURPLE_RUPEE, false, true);
PlaceItemInLocation(ZR_FROGS_SONG_OF_TIME, PURPLE_RUPEE, false, true);
}
if (ShuffleAdultTradeQuest) {
AddItemToMainPool(POCKET_EGG);
AddItemToMainPool(COJIRO);

View File

@ -472,6 +472,11 @@ typedef enum {
//ZORA'S_RIVER
ZR_MAGIC_BEAN_SALESMAN,
ZR_OPEN_GROTTO_CHEST,
ZR_FROGS_ZELDAS_LULLABY,
ZR_FROGS_EPONAS_SONG,
ZR_FROGS_SARIAS_SONG,
ZR_FROGS_SUNS_SONG,
ZR_FROGS_SONG_OF_TIME,
ZR_FROGS_IN_THE_RAIN,
ZR_FROGS_OCARINA_GAME,
ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH,

View File

@ -31,6 +31,21 @@ void AreaTable_Init_ZorasDomain() {
LocationAccess(ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SongOfStorms;}}),
LocationAccess(ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanPlay(ZeldasLullaby);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && ZeldasLullaby;}}),
LocationAccess(ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanPlay(EponasSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && EponasSong;}}),
LocationAccess(ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SariasSong;}}),
LocationAccess(ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SunsSong;}}),
LocationAccess(ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);},
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SongOfTime;}}),
LocationAccess(ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}),
LocationAccess(ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}),
LocationAccess(ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}),

View File

@ -385,6 +385,13 @@ string_view merchantsHintsDesc = "These hints will make Medigoron and the
"The Clearer Hints setting will affect how they\n" //
"refer to the item."; //
/*------------------------------ //
| SHUFFLE FROG SONG RUPEES | //
------------------------------*/ //
string_view frogSongRupeesDesc = "Enabling this adds 5 Purple Rupees to the item\n" //
"pool and shuffles the rewards from playing Zelda's\n"
"Lullaby, Epona's Song, Saria's Song, Sun's Song,\n"
"and Song of Time to the frogs in Zora's River.\n";//
/*------------------------------ //
| SHUFFLE ADULT TRADE | //
------------------------------*/ //
string_view adultTradeDesc = "Enabling this adds all of the adult trade quest\n"//

View File

@ -126,6 +126,8 @@ extern string_view magicBeansDesc;
extern string_view merchantsDesc;
extern string_view merchantsHintsDesc;
extern string_view frogSongRupeesDesc;
extern string_view adultTradeDesc;
extern string_view chestMinigameDesc;

View File

@ -166,6 +166,7 @@ namespace Settings {
Option ShuffleGerudoToken = Option::Bool("Shuffle Gerudo Card", {"Off", "On"}, {gerudoTokenDesc});
Option ShuffleMagicBeans = Option::Bool("Shuffle Magic Beans", {"Off", "On"}, {magicBeansDesc});
Option ShuffleMerchants = Option::U8 ("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, {merchantsDesc, merchantsHintsDesc});
Option ShuffleFrogSongRupees = Option::Bool("Shuffle Frog Song Rupees",{"Off", "On"}, {frogSongRupeesDesc});
Option ShuffleAdultTradeQuest = Option::Bool("Shuffle Adult Trade", {"Off", "On"}, {adultTradeDesc});
Option ShuffleChestMinigame = Option::U8 ("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}, {chestMinigameDesc});
std::vector<Option *> shuffleOptions = {
@ -183,6 +184,7 @@ namespace Settings {
&ShuffleGerudoToken,
&ShuffleMagicBeans,
&ShuffleMerchants,
&ShuffleFrogSongRupees,
&ShuffleAdultTradeQuest,
&ShuffleChestMinigame,
};
@ -1263,6 +1265,7 @@ namespace Settings {
ctx.shuffleGerudoToken = (ShuffleGerudoToken) ? 1 : 0;
ctx.shuffleMagicBeans = (ShuffleMagicBeans) ? 1 : 0;
ctx.shuffleMerchants = ShuffleMerchants.Value<uint8_t>();
ctx.shuffleFrogSongRupees= (ShuffleFrogSongRupees) ? 1 : 0;
ctx.shuffleAdultTradeQuest = (ShuffleAdultTradeQuest) ? 1 : 0;
ctx.shuffleChestMinigame = ShuffleChestMinigame.Value<uint8_t>();
@ -1724,6 +1727,21 @@ namespace Settings {
IncludeAndHide({WASTELAND_BOMBCHU_SALESMAN});
}
//Force include frog song rupees if they're not shuffled
if (ShuffleFrogSongRupees) {
Unhide({ZR_FROGS_ZELDAS_LULLABY});
Unhide({ZR_FROGS_EPONAS_SONG});
Unhide({ZR_FROGS_SARIAS_SONG});
Unhide({ZR_FROGS_SUNS_SONG});
Unhide({ZR_FROGS_SONG_OF_TIME});
} else {
IncludeAndHide({ZR_FROGS_ZELDAS_LULLABY});
IncludeAndHide({ZR_FROGS_EPONAS_SONG});
IncludeAndHide({ZR_FROGS_SARIAS_SONG});
IncludeAndHide({ZR_FROGS_SUNS_SONG});
IncludeAndHide({ZR_FROGS_SONG_OF_TIME});
}
//Force include adult trade quest if Shuffle Adult Trade Quest is off
std::vector<uint32_t> adultTradeLocations = {KAK_TRADE_POCKET_CUCCO, LW_TRADE_COJIRO, KAK_TRADE_ODD_MUSHROOM, LW_TRADE_ODD_POTION, GV_TRADE_SAW, DMT_TRADE_BROKEN_SWORD, ZD_TRADE_PRESCRIPTION, LH_TRADE_FROG, DMT_TRADE_EYEDROPS};
if (ShuffleAdultTradeQuest) {
@ -2261,6 +2279,7 @@ namespace Settings {
&ShuffleCows,
&ShuffleMagicBeans,
&ShuffleMerchants,
&ShuffleFrogSongRupees,
&ShuffleAdultTradeQuest,
&GossipStoneHints,
};
@ -2515,6 +2534,7 @@ namespace Settings {
SkipChildStealth.SetSelectedIndex(cvarSettings[RSK_SKIP_CHILD_STEALTH]);
ShuffleGerudoToken.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]);
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);

View File

@ -403,6 +403,7 @@ typedef struct {
uint8_t shuffleGerudoToken;
uint8_t shuffleMagicBeans;
uint8_t shuffleMerchants;
uint8_t shuffleFrogSongRupees;
uint8_t shuffleAdultTradeQuest;
uint8_t shuffleChestMinigame;
@ -904,6 +905,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
extern Option ShuffleGerudoToken;
extern Option ShuffleMagicBeans;
extern Option ShuffleMerchants;
extern Option ShuffleFrogSongRupees;
extern Option ShuffleAdultTradeQuest;
extern Option ShuffleChestMinigame;

View File

@ -184,6 +184,11 @@ std::unordered_map<std::string, RandomizerCheck> SpoilerfileCheckNameToEnum = {
{ "DMC Deku Scrub Grotto Center", RC_DMC_DEKU_SCRUB_GROTTO_CENTER },
{ "ZR Open Grotto Chest", RC_ZR_OPEN_GROTTO_CHEST },
{ "ZR Magic Bean Salesman", RC_ZR_MAGIC_BEAN_SALESMAN },
{ "ZR Frogs Zelda's Lullaby", RC_ZR_FROGS_ZELDAS_LULLABY },
{ "ZR Frogs Epona's Song", RC_ZR_FROGS_EPONAS_SONG },
{ "ZR Frogs Saria's Song", RC_ZR_FROGS_SARIAS_SONG },
{ "ZR Frogs Sun's Song", RC_ZR_FROGS_SUNS_SONG },
{ "ZR Frogs Song of Time", RC_ZR_FROGS_SONG_OF_TIME },
{ "ZR Frogs in the Rain", RC_ZR_FROGS_IN_THE_RAIN },
{ "ZR Frogs Ocarina Game", RC_ZR_FROGS_OCARINA_GAME },
{ "ZR Near Open Grotto Freestanding PoH", RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH },
@ -3445,6 +3450,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) && CVar_GetS32("gRandomizeShuffleWeirdEgg", 0));
cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVar_GetS32("gRandomizeShuffleGerudoToken", 0);
cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVar_GetS32("gRandomizeShuffleFrogSongRupees", 0);
cvarSettings[RSK_ITEM_POOL] = CVar_GetS32("gRandomizeItemPool", 1);
cvarSettings[RSK_ICE_TRAPS] = CVar_GetS32("gRandomizeIceTraps", 1);
cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVar_GetS32("gRandomizeGossipStoneHints", 1);
@ -3535,6 +3541,7 @@ void DrawRandoEditor(bool& open) {
const char* randoShuffleGerudoToken[2] = { "Off", "On" };
const char* randoShuffleMagicBeans[2] = { "Off", "On" };
const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" };
const char* randoShuffleFrogSongRupees[2] = { "Off", "On" };
const char* randoShuffleAdultTrade[2] = { "Off", "On" };
// Shuffle Dungeon Items Settings
@ -4017,6 +4024,18 @@ void DrawRandoEditor(bool& open) {
"The Gerudo Card is required to enter the Gerudo Training Grounds, opening "
"the gate to Haunted Wasteland and the Horseback Archery minigame."
);
PaddedSeparator();
// Shuffle Frog Song Rupees
SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees");
InsertHelpHoverText(
"Shuffles 5 Purple Rupees into to the item pool, and allows you\n"
"to earn items by playing songs at the Frog Choir.\n"
"\n"
"This setting does not effect the item earned from playing\n"
"the Song of Storms and the frog song minigame."
);
PaddedSeparator();
}
ImGui::PopItemWidth();

View File

@ -977,6 +977,7 @@ typedef enum {
RSK_SHUFFLE_TOKENS,
RSK_SHUFFLE_WEIRD_EGG,
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
RSK_SHUFFLE_FROG_SONG_RUPEES,
RSK_ITEM_POOL,
RSK_ICE_TRAPS,
RSK_GOSSIP_STONE_HINTS,

View File

@ -43,6 +43,7 @@ void EnFr_OcarinaMistake(EnFr* this, GlobalContext* globalCtx);
void EnFr_SetupReward(EnFr* this, GlobalContext* globalCtx, u8 unkCondition);
void EnFr_PrintTextBox(EnFr* this, GlobalContext* globalCtx);
void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx);
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex);
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx);
// Deactivate
@ -920,6 +921,23 @@ void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx) {
}
}
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) {
switch (songIndex) {
case FROG_ZL:
return RC_ZR_FROGS_ZELDAS_LULLABY;
case FROG_EPONA:
return RC_ZR_FROGS_EPONAS_SONG;
case FROG_SARIA:
return RC_ZR_FROGS_SARIAS_SONG;
case FROG_SUNS:
return RC_ZR_FROGS_SUNS_SONG;
case FROG_SOT:
return RC_ZR_FROGS_SONG_OF_TIME;
default:
return RC_UNKNOWN_CHECK;
}
}
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
u16 songIndex;
@ -930,7 +948,11 @@ void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) {
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
this->reward = GI_RUPEE_PURPLE;
if (!gSaveContext.n64ddFlag) {
this->reward = GI_RUPEE_PURPLE;
} else {
this->reward = Randomizer_GetItemIdFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE);
}
} else {
this->reward = GI_RUPEE_BLUE;
}