Rando: Shuffle 100 Gold Skulltula Reward (#1944)

* Shuffle 100 token reward

* Add 100 token hint

* 100 GS Shuffle: Fix name inconsistency

* Add 10 tokens to plentiful pool

* Ganon's Boss Key on 100 GS Reward

* Golden Skull Token -> Gold Skulltula Token

* Properly disable 100 GS reward shuffle check box

* Use enums for 100 GS shuffle

* Fix mismatched LUS

* Fix CVar calls

* ADD: French translation

* Only add extra tokens in Tokensanity

Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
This commit is contained in:
lilDavid 2023-01-23 16:01:52 -06:00 committed by GitHub
parent e5bc5188e7
commit 2422c94f6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 140 additions and 9 deletions

View File

@ -496,5 +496,7 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD, "ADULT_TRADES_DMT_TRADE_BROKEN_SWORD" },
{ RAND_INF_ADULT_TRADES_LH_TRADE_FROG, "ADULT_TRADES_LH_TRADE_FROG" },
{ RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, "ADULT_TRADES_DMT_TRADE_EYEDROPS" },
{ RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, "KAK_100_GOLD_SKULLTULA_REWARD" },
} },
};

View File

@ -148,7 +148,10 @@ static int GetMaxGSCount() {
//Get the max amount of GS which could be useful from token reward locations
int maxUseful = 0;
//If the highest advancement item is a token, we know it is useless since it won't lead to an otherwise useful item
if (Location(KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && Location(KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {
if (Location(KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && Location(KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {
maxUseful = 100;
}
else if (Location(KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && Location(KAK_50_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {
maxUseful = 50;
}
else if (Location(KAK_40_GOLD_SKULLTULA_REWARD)->GetPlacedItem().IsAdvancement() && Location(KAK_40_GOLD_SKULLTULA_REWARD)->GetPlacedItem().GetItemType() != ITEMTYPE_TOKEN) {

View File

@ -74,6 +74,25 @@ void HintTable_Init() {
Text{ "#Malon's obstacle course# leads to", /*french*/ "la #course à obstacle de Malon# amène à",
/*spanish*/ "la #carrera de obstáculos de Malon# brinda" });
hintTable[KAK_100_GOLD_SKULLTULA_REWARD] = HintText::Always(
{
// obscure text
Text{ "#100 bug badges# rewards",
/*french*/ "#100 écussons# donnent",
/*spanish*/ "#100 medallas de insectos# otorgan" },
Text{ "#100 spider souls# yields",
/*french*/ "#100 âmes d'arachnide# donnent",
/*spanish*/ "#100 almas de araña# otorgan" },
Text{ "#100 auriferous arachnids# lead to",
/*french*/ "#100 arachnides aurifères# donnent",
/*spanish*/ "#100 arácnidos auríferos# otorgan" },
},
{},
// clear text
Text{ "slaying #100 Gold Skulltulas# reveals",
/*french*/ "détruire #100 Skulltulas d'or# donne",
/*spanish*/ "exterminar #100 skulltulas doradas# revela" });
/*--------------------------
| SOMETIMES HINT TEXT |
---------------------------*/
@ -2699,6 +2718,13 @@ void HintTable_Init() {
/*spanish*/ "Y el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#." },
});
hintTable[GANON_BK_SKULLTULA_HINT] = HintText::GanonsBossKey({
// obscure text
Text { "And the %revil one%w's key will be&provided by the cursed rich man&once %r100 Gold Skulltula Tokens%w&are retrieved.",
/*french*/ "Aussi, la %rclé du Malin%w sera&donnée par l'homme maudit une&fois que %r100 Symboles de&Skulltula d'or%w auront été trouvés.",
/*spanish*/ "Y el rico maldito entregará la llave&del #señor de mal# tras obtener&100 símbolos de skulltula dorada#."},
});
/*--------------------------
| LACS HINT TEXT |
---------------------------*/

View File

@ -653,6 +653,9 @@ static Text BuildGanonBossKeyText() {
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE)) {
ganonBossKeyText = Hint(GANON_BK_ANYWHERE_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
ganonBossKeyText = Hint(GANON_BK_SKULLTULA_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_VANILLA)) {
ganonBossKeyText = Hint(LACS_VANILLA_HINT).GetText();

View File

@ -116,6 +116,7 @@ void LocationTable_Init() {
locationTable[KAK_30_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_30_GOLD_SKULLTULA_REWARD, 0x50, 0x46, "Kak 30 Gold Skulltula Reward", KAK_30_GOLD_SKULLTULA_REWARD, PROGRESSIVE_WALLET, {Category::cKakarikoVillage, Category::cKakariko, Category::cSkulltulaHouse}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_40_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_40_GOLD_SKULLTULA_REWARD, 0x50, 0x03, "Kak 40 Gold Skulltula Reward", KAK_40_GOLD_SKULLTULA_REWARD, BOMBCHU_10, {Category::cKakarikoVillage, Category::cKakariko, Category::cSkulltulaHouse}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_50_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_50_GOLD_SKULLTULA_REWARD, 0x50, 0x3E, "Kak 50 Gold Skulltula Reward", KAK_50_GOLD_SKULLTULA_REWARD, PIECE_OF_HEART, {Category::cKakarikoVillage, Category::cKakariko, Category::cSkulltulaHouse}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_100_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_100_GOLD_SKULLTULA_REWARD, 0x50, 0x3E, "Kak 100 Gold Skulltula Reward", KAK_100_GOLD_SKULLTULA_REWARD, HUGE_RUPEE, {Category::cKakarikoVillage, Category::cKakariko, Category::cSkulltulaHouse}, SpoilerCollectionCheck::EventChkInf(0xDF), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_MAN_ON_ROOF] = ItemLocation::Base (RC_KAK_MAN_ON_ROOF, 0x52, 0x3E, "Kak Man on Roof", KAK_MAN_ON_ROOF, PIECE_OF_HEART, {Category::cKakarikoVillage, Category::cKakariko,}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_KAK_SHOOTING_GALLERY_REWARD, 0x42, 0x30, "Kak Shooting Gallery Reward", KAK_SHOOTING_GALLERY_REWARD, PROGRESSIVE_BOW, {Category::cKakarikoVillage, Category::cKakariko, Category::cMinigame}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
locationTable[KAK_TRADE_ODD_MUSHROOM] = ItemLocation::Base (RC_KAK_TRADE_ODD_MUSHROOM, 0x4E, 0x20, "Kak Trade Odd Mushroom", KAK_TRADE_ODD_MUSHROOM, ODD_POTION, {Category::cKakarikoVillage, Category::cKakariko, Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(56), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
@ -1276,6 +1277,7 @@ std::vector<uint32_t> overworldLocations = {
KAK_30_GOLD_SKULLTULA_REWARD,
KAK_40_GOLD_SKULLTULA_REWARD,
KAK_50_GOLD_SKULLTULA_REWARD,
KAK_100_GOLD_SKULLTULA_REWARD,
KAK_MAN_ON_ROOF,
KAK_SHOOTING_GALLERY_REWARD,
KAK_TRADE_ODD_MUSHROOM,

View File

@ -798,6 +798,15 @@ void GenerateItemPool() {
AddItemToMainPool(GOLD_SKULLTULA_TOKEN, 100);
}
if (Shuffle100GSReward) {
if (Tokensanity.IsNot(TOKENSANITY_OFF) && ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) {
AddItemToPool(PendingJunkPool, GOLD_SKULLTULA_TOKEN, 10);
}
AddItemToMainPool(HUGE_RUPEE);
} else {
PlaceItemInLocation(KAK_100_GOLD_SKULLTULA_REWARD, HUGE_RUPEE, false, true);
}
if (BombchusInLogic) {
AddItemToMainPool(PROGRESSIVE_BOMBCHUS, 5);
} else {
@ -1119,7 +1128,9 @@ void GenerateItemPool() {
AddItemToMainPool(SHADOW_TEMPLE_BOSS_KEY);
}
if (GanonsBossKey.Value<uint8_t>() >= GANONSBOSSKEY_LACS_VANILLA) {
if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
PlaceItemInLocation(KAK_100_GOLD_SKULLTULA_REWARD, GANONS_CASTLE_BOSS_KEY);
} else if (GanonsBossKey.Value<uint8_t>() >= GANONSBOSSKEY_LACS_VANILLA) {
PlaceItemInLocation(TOT_LIGHT_ARROWS_CUTSCENE, GANONS_CASTLE_BOSS_KEY);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
PlaceItemInLocation(GANONS_TOWER_BOSS_KEY_CHEST, GANONS_CASTLE_BOSS_KEY);

View File

@ -392,6 +392,7 @@ typedef enum {
KAK_30_GOLD_SKULLTULA_REWARD,
KAK_40_GOLD_SKULLTULA_REWARD,
KAK_50_GOLD_SKULLTULA_REWARD,
KAK_100_GOLD_SKULLTULA_REWARD,
KAK_IMPAS_HOUSE_COW,
KAK_GS_TREE,
KAK_GS_GUARDS_HOUSE,
@ -1762,6 +1763,7 @@ typedef enum {
GANON_BK_ANY_DUNGEON_HINT,
GANON_BK_ANYWHERE_HINT,
GANON_BK_TRIFORCE_HINT,
GANON_BK_SKULLTULA_HINT,
LACS_VANILLA_HINT,
LACS_MEDALLIONS_HINT,

View File

@ -97,6 +97,7 @@ void AreaTable_Init_Kakariko() {
LocationAccess(KAK_30_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 30;}}),
LocationAccess(KAK_40_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 40;}}),
LocationAccess(KAK_50_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 50;}}),
LocationAccess(KAK_100_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 100;}})
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),

View File

@ -368,7 +368,7 @@ string_view tokensOverworld = "This only shuffles the GS locations tha
"outside of dungeons."; //
string_view tokensAllTokens = "Effectively adds 100 new locations for items to\n"//
"appear."; //
//
/*------------------------------ //
| SCRUB SHUFFLE | //
------------------------------*/ //
@ -471,6 +471,15 @@ string_view chestMinigameDesc = "The 5 key chests in the Treasure Chest
"\n" //
"If you choose the \"pack\" option, you will get\n"//
"all the keys at once, in a single item."; //
//
/*------------------------------ //
| SHUFFLE 100 GS REWARD | //
------------------------------*/ //
string_view shuffle100GsDesc = "The cursed rich man in the House of Skulltula\n" //
"will give you a random item for collecting all\n" //
"100 Gold Skulltula Tokens, then he will give you\n"
"Huge Rupees."; //
//
/*------------------------------ //
| MAPS AND COMPASSES | //
------------------------------*/ //
@ -571,6 +580,9 @@ string_view ganonKeyAnywhere = "Ganon's Castle Boss Key can appear anyw
string_view ganonKeyLACS = "These settings put the boss key on the Light Arrow"
"Cutscene location, from Zelda in Temple of Time as"
"adult, with differing requirements."; //
string_view ganonKey100GS = "Ganon's Castle Boss Key is given to you by the\n" //
"cursed rich man in the House of Skulltula after\n"//
"you collect all 100 Gold Skulltula Tokens."; //
/*------------------------------ //
| LACS CONDITIONS | //
------------------------------*/ //

View File

@ -148,6 +148,8 @@ extern string_view adultTradeDesc;
extern string_view chestMinigameDesc;
extern string_view shuffle100GsDesc;
extern string_view mapCompassStartWith;
extern string_view mapCompassVanilla;
extern string_view mapCompassOwnDungeon;
@ -183,6 +185,7 @@ extern string_view ganonKeyAnyDungeon;
extern string_view ganonKeyOverworld;
extern string_view ganonKeyAnywhere;
extern string_view ganonKeyLACS;
extern string_view ganonKey100GS;
extern string_view lacsMedallionCountDesc;
extern string_view lacsStoneCountDesc;

View File

@ -190,6 +190,7 @@ namespace Settings {
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});
Option Shuffle100GSReward = Option::Bool("Shuffle 100 GS Reward", {"No", "Yes"}, {shuffle100GsDesc}, OptionCategory::Toggle);
std::vector<Option *> shuffleOptions = {
&RandomizeShuffle,
&ShuffleRewards,
@ -208,6 +209,7 @@ namespace Settings {
&ShuffleFrogSongRupees,
&ShuffleAdultTradeQuest,
&ShuffleChestMinigame,
&Shuffle100GSReward,
};
//Shuffle Dungeon Items
@ -220,8 +222,8 @@ namespace Settings {
{gerudoKeysVanilla, gerudoKeysAnyDungeon, gerudoKeysOverworld, gerudoKeysAnywhere});
Option BossKeysanity = Option::U8 ("Boss Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"},
{bossKeyStartWith, bossKeyVanilla, bossKeyOwnDungeon, bossKeyAnyDungeon, bossKeyOverworld, bossKeyAnywhere}, OptionCategory::Setting, BOSSKEYSANITY_OWN_DUNGEON);
Option GanonsBossKey = Option::U8 ("Ganon's Boss Key", {"Vanilla", "Own dungeon", "Start with", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Medallions", "LACS-Stones", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens"},
{ganonKeyVanilla, ganonKeyOwnDungeon, ganonKeyStartWith, ganonKeyAnyDungeon, ganonKeyOverworld, ganonKeyAnywhere, ganonKeyLACS}, OptionCategory::Setting, GANONSBOSSKEY_VANILLA);
Option GanonsBossKey = Option::U8 ("Ganon's Boss Key", {"Vanilla", "Own dungeon", "Start with", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Medallions", "LACS-Stones", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward"},
{ganonKeyVanilla, ganonKeyOwnDungeon, ganonKeyStartWith, ganonKeyAnyDungeon, ganonKeyOverworld, ganonKeyAnywhere, ganonKeyLACS, ganonKey100GS}, OptionCategory::Setting, GANONSBOSSKEY_VANILLA);
uint8_t LACSCondition = 0;
Option LACSMedallionCount = Option::U8 ("Medallion Count", {NumOpts(0, 6)}, {lacsMedallionCountDesc}, OptionCategory::Setting, 1, true);
Option LACSStoneCount = Option::U8 ("Stone Count", {NumOpts(0, 3)}, {lacsStoneCountDesc}, OptionCategory::Setting, 1, true);
@ -1327,6 +1329,7 @@ namespace Settings {
ctx.shuffleFrogSongRupees= (ShuffleFrogSongRupees) ? 1 : 0;
ctx.shuffleAdultTradeQuest = (ShuffleAdultTradeQuest) ? 1 : 0;
ctx.shuffleChestMinigame = ShuffleChestMinigame.Value<uint8_t>();
ctx.shuffle100GsReward = (Shuffle100GSReward) ? 1 : 0;
ctx.mapsAndCompasses = MapsAndCompasses.Value<uint8_t>();
ctx.keysanity = Keysanity.Value<uint8_t>();
@ -1823,6 +1826,13 @@ namespace Settings {
IncludeAndHide(ChestMinigameLocations);
}
//Force include 100 GS reward if it isn't shuffled
if (Shuffle100GSReward) {
Unhide({KAK_100_GOLD_SKULLTULA_REWARD});
} else {
IncludeAndHide({KAK_100_GOLD_SKULLTULA_REWARD});
}
//Force include Map and Compass Chests when Vanilla
std::vector<uint32_t> mapChests = GetLocations(everyPossibleLocation, Category::cVanillaMap);
std::vector<uint32_t> compassChests = GetLocations(everyPossibleLocation, Category::cVanillaCompass);
@ -2069,6 +2079,17 @@ namespace Settings {
}
}
//Only go through options if all settings are not randomized
if (!RandomizeShuffle) {
// Ganon's Boss Key on 100 GS reward must also have the reward shuffled
if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
Shuffle100GSReward.SetSelectedIndex(ON);
Shuffle100GSReward.Lock();
} else {
Shuffle100GSReward.Unlock();
}
}
//Force Link's Pocket Item to be a dungeon reward if Shuffle Rewards is end of dungeons
if (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)) {
LinksPocketItem.Lock();
@ -2411,6 +2432,7 @@ namespace Settings {
&ShuffleMerchants,
&ShuffleFrogSongRupees,
&ShuffleAdultTradeQuest,
&Shuffle100GSReward,
&GossipStoneHints,
};
@ -2720,6 +2742,13 @@ namespace Settings {
ShuffleMagicBeans.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MAGIC_BEANS]);
ShuffleMerchants.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MERCHANTS]);
// Force 100 GS Shuffle if that's where Ganon's Boss Key is
if (cvarSettings[RSK_GANONS_BOSS_KEY] == RO_GANON_BOSS_KEY_KAK_TOKENS) {
Shuffle100GSReward.SetSelectedIndex(1);
} else {
Shuffle100GSReward.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_100_GS_REWARD]);
}
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);

View File

@ -237,6 +237,7 @@ typedef enum {
GANONSBOSSKEY_LACS_REWARDS,
GANONSBOSSKEY_LACS_DUNGEONS,
GANONSBOSSKEY_LACS_TOKENS,
GANONSBOSSKEY_FINAL_GS_REWARD,
} GanonsBossKeySetting;
typedef enum {
@ -429,6 +430,7 @@ typedef struct {
uint8_t shuffleFrogSongRupees;
uint8_t shuffleAdultTradeQuest;
uint8_t shuffleChestMinigame;
uint8_t shuffle100GsReward;
uint8_t mapsAndCompasses;
uint8_t keysanity;
@ -945,6 +947,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
extern Option ShuffleFrogSongRupees;
extern Option ShuffleAdultTradeQuest;
extern Option ShuffleChestMinigame;
extern Option Shuffle100GSReward;
extern Option MapsAndCompasses;
extern Option Keysanity;

View File

@ -227,6 +227,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Shuffle Settings:Shuffle Weird Egg", RSK_SHUFFLE_WEIRD_EGG },
{ "Shuffle Settings:Shuffle Frog Song Rupees", RSK_SHUFFLE_FROG_SONG_RUPEES },
{ "Shuffle Settings:Shuffle Merchants", RSK_SHUFFLE_MERCHANTS },
{ "Shuffle Settings:Shuffle 100 GS Reward", RSK_SHUFFLE_100_GS_REWARD },
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
@ -739,6 +740,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
case RSK_SHUFFLE_KOKIRI_SWORD:
case RSK_SHUFFLE_WEIRD_EGG:
case RSK_SHUFFLE_FROG_SONG_RUPEES:
case RSK_SHUFFLE_100_GS_REWARD:
case RSK_RANDOM_MQ_DUNGEONS:
case RSK_STARTING_DEKU_SHIELD:
case RSK_STARTING_KOKIRI_SWORD:
@ -948,6 +950,8 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_DUNGEONS;
} else if(it.value() == "LACS-Tokens") {
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_LACS_TOKENS;
} else if(it.value() == "100 GS Reward") {
gSaveContext.randoSettings[index].value = RO_GANON_BOSS_KEY_KAK_TOKENS;
}
break;
case RSK_SKIP_CHILD_ZELDA:
@ -2812,6 +2816,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVarGetInteger("gRandomizeShuffleAdultTrade", 0);
cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger("gRandomizeShuffleBeans", 0);
cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger("gRandomizeShuffleMerchants", RO_SHUFFLE_MERCHANTS_OFF);
cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger("gRandomizeShuffle100GSReward", RO_GENERIC_OFF);
cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger("gRandomizeEnableBombchuDrops", 0);
cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger("gRandomizeBombchusInLogic", 0);
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger("gRandomizeSkipChildZelda", 0);
@ -2993,10 +2998,11 @@ void DrawRandoEditor(bool& open) {
static const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" };
static const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon",
"Any Dungeon", "Overworld", "Anywhere" };
static const char* randoShuffleGanonsBossKey[12] = {"Vanilla", "Own dungeon", "Start with",
static const char* randoShuffleGanonsBossKey[13] = {"Vanilla", "Own dungeon", "Start with",
"Any Dungeon", "Overworld", "Anywhere",
"LACS-Vanilla", "LACS-Medallions", "LACS-Stones",
"LACS-Rewards", "LACS-Dungeons", "LACS-Tokens"};
"LACS-Rewards", "LACS-Dungeons", "LACS-Tokens",
"100 GS Reward"};
static const char* randoShuffleKeyRings[4] = { "Off", "Random", "Count", "Selection" };
// Misc Settings
@ -3660,6 +3666,22 @@ void DrawRandoEditor(bool& open) {
UIWidgets::PaddedSeparator();
// Shuffle 100 GS Reward
// Forcefully enabled if Ganon's Boss Key is on the cursed man
bool forceEnable100GSShuffle =
(CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS);
const char* disable100GSRewardText = "This option is forcefully enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\"";
UIWidgets::EnhancementCheckbox(Settings::Shuffle100GSReward.GetName().c_str(), "gRandomizeShuffle100GSReward",
forceEnable100GSShuffle, disable100GSRewardText, UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::InsertHelpHoverText(
"Shuffle the item the cursed rich man in the House of Skulltula gives when you "
"have collected all 100 Gold Skulltula Tokens.\n"
"\n"
"You can still talk to him multiple times to get Huge Rupees."
);
UIWidgets::PaddedSeparator();
ImGui::PopItemWidth();
ImGui::EndChild();
@ -3820,7 +3842,9 @@ void DrawRandoEditor(bool& open) {
"- Stones: Obtain the specified amount of spiritual stones.\n"
"- Dungeon rewards: Obtain the specified total sum of spiritual stones or medallions.\n"
"- Dungeons: Complete the specified amount of dungeons. Dungeons are considered complete after stepping in to the blue warp after the boss.\n"
"- Tokens: Obtain the specified amount of Skulltula tokens."
"- Tokens: Obtain the specified amount of Skulltula tokens.\n"
"\n"
"100 GS Reward - Ganon's Boss Key will be awarded by the cursed rich man after you collect 100 Gold Skulltula Tokens."
);
UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, RO_GANON_BOSS_KEY_MAX, RO_GANON_BOSS_KEY_VANILLA);
ImGui::PopItemWidth();

View File

@ -164,6 +164,7 @@ typedef enum {
RC_KAK_30_GOLD_SKULLTULA_REWARD,
RC_KAK_40_GOLD_SKULLTULA_REWARD,
RC_KAK_50_GOLD_SKULLTULA_REWARD,
RC_KAK_100_GOLD_SKULLTULA_REWARD,
RC_KAK_IMPAS_HOUSE_COW,
RC_KAK_GS_TREE,
RC_KAK_GS_GUARDS_HOUSE,
@ -1091,6 +1092,7 @@ typedef enum {
RSK_STARTING_SKULLTULA_TOKEN,
RSK_ALL_LOCATIONS_REACHABLE,
RSK_SHUFFLE_BOSS_ENTRANCES,
RSK_SHUFFLE_100_GS_REWARD,
RSK_MAX
} RandomizerSettingKey;
@ -1235,7 +1237,7 @@ typedef enum {
} RandoOptionKeyrings;
//Ganon's Boss Key Settings (vanilla, own dungeon, start with,
//overworld, anywhere)
//overworld, anywhere, 100 GS reward)
typedef enum {
RO_GANON_BOSS_KEY_VANILLA,
RO_GANON_BOSS_KEY_OWN_DUNGEON,
@ -1249,6 +1251,7 @@ typedef enum {
RO_GANON_BOSS_KEY_LACS_REWARDS,
RO_GANON_BOSS_KEY_LACS_DUNGEONS,
RO_GANON_BOSS_KEY_LACS_TOKENS,
RO_GANON_BOSS_KEY_KAK_TOKENS,
RO_GANON_BOSS_KEY_MAX,
} RandoOptionGanonsBossKey;

View File

@ -220,6 +220,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
RC_OBJECT(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KINSUTA, 0x00, GI_NONE, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward"),
RC_OBJECT(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KINSUTA, 0x00, GI_NONE, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward"),
RC_OBJECT(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KINSUTA, 0x00, GI_NONE, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward"),
RC_OBJECT(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KINSUTA, 0x00, GI_NONE, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward"),
RC_OBJECT(RC_KAK_MAN_ON_ROOF, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Man on Roof", "Kak Man on Roof"),
RC_OBJECT(RC_KAK_SHOOTING_GALLERY_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SYATEKIJYOU, 0x00, GI_NONE, "Shooting Gallery Reward", "Kak Shooting Gallery Reward"),
RC_OBJECT(RC_KAK_TRADE_ODD_MUSHROOM, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_MAHOUYA, 0x00, GI_NONE, "Trade Odd Mushroom", "Kak Trade Odd Mushroom"),

View File

@ -149,6 +149,8 @@ typedef enum {
RAND_INF_ADULT_TRADES_LH_TRADE_FROG,
RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS,
RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD,
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,

View File

@ -244,6 +244,10 @@ void EnSth_GivePlayerItem(EnSth* this, PlayState* play) {
if (gSaveContext.n64ddFlag) {
switch (getItemId) {
case GI_RUPEE_GOLD:
if (!Flags_GetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD)) {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_100_GOLD_SKULLTULA_REWARD, GI_RUPEE_GOLD);
Flags_SetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD);
}
break;
case GI_WALLET_ADULT:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_10_GOLD_SKULLTULA_REWARD, GI_WALLET_ADULT);