Merge branch 'rando-next' into rando-settings-menu-even-moar-changes

This commit is contained in:
aMannus 2022-08-28 20:19:19 +02:00
commit 1c59995feb
18 changed files with 441 additions and 175 deletions

View File

@ -260,5 +260,6 @@ extern GraphicsContext* __gfxCtx;
#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1)
#define NUM_TRIALS 6
#endif

View File

@ -15,7 +15,8 @@ typedef enum {
TEXT_BLUE_RUPEE = 0xCC,
TEXT_RED_RUPEE = 0xF0,
TEXT_PURPLE_RUPEE = 0xF1,
TEXT_HUGE_RUPEE = 0xF2
TEXT_HUGE_RUPEE = 0xF2,
TEXT_BEAN_SALESMAN = 0x405E
} TextIDs;
#ifdef __cplusplus

View File

@ -2517,18 +2517,16 @@ namespace Settings {
BridgeRewardCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_REWARD_COUNT]);
BridgeDungeonCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT]);
BridgeTokenCount.SetSelectedIndex(cvarSettings[RSK_RAINBOW_BRIDGE_TOKEN_COUNT]);
RandomGanonsTrials.SetSelectedIndex(cvarSettings[RSK_RANDOM_TRIALS]);
// RANDTODO: Switch this back once Ganon's Trials Count is properly implemented.
//GanonsTrialsCount.SetSelectedIndex(cvarSettings[RSK_TRIAL_COUNT]);
switch (cvarSettings[RSK_TRIAL_COUNT]) {
case 0:
GanonsTrialsCount.SetSelectedIndex(6);
break;
case 1:
GanonsTrialsCount.SetSelectedIndex(0);
break;
if (cvarSettings[RSK_RANDOM_TRIALS] == 2) {
RandomGanonsTrials.SetSelectedIndex(1);
} else {
RandomGanonsTrials.SetSelectedIndex(0);
}
if (cvarSettings[RSK_RANDOM_TRIALS] == 0) {
GanonsTrialsCount.SetSelectedIndex(0);
} else {
GanonsTrialsCount.SetSelectedIndex(cvarSettings[RSK_TRIAL_COUNT]);
}
ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]);
ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]);
Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]);
@ -2552,6 +2550,7 @@ namespace Settings {
ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]);
ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]);
ShuffleMagicBeans.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MAGIC_BEANS]);
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);

View File

@ -501,25 +501,23 @@ static void WriteMasterQuestDungeons(tinyxml2::XMLDocument& spoilerLog) {
}
}
// Writes the required trails to the spoiler log, if there are any.
static void WriteRequiredTrials(tinyxml2::XMLDocument& spoilerLog) {
auto parentNode = spoilerLog.NewElement("required-trials");
for (const auto* trial : Trial::trialList) {
if (trial->IsSkipped()) {
continue;
// Writes the required trials to the spoiler log, if there are any.
static void WriteRequiredTrials() {
for (const auto& trial : Trial::trialList) {
if (trial->IsRequired()) {
std::string trialName;
switch (gSaveContext.language) {
case LANGUAGE_FRA:
trialName = trial->GetName().GetFrench();
break;
case LANGUAGE_ENG:
default:
trialName = trial->GetName().GetEnglish();
break;
}
jsonData["requiredTrials"].push_back(RemoveLineBreaks(trialName));
}
}
auto node = parentNode->InsertNewChildElement("trial");
// PURPLE TODO: LOCALIZATION
std::string name = trial->GetName().GetEnglish();
name[0] = toupper(name[0]); // Capitalize T in "The"
node->SetAttribute("name", name.c_str());
}
if (!parentNode->NoChildren()) {
spoilerLog.RootElement()->InsertEndChild(parentNode);
}
}
// Writes the intended playthrough to the spoiler log, separated into spheres.
@ -723,7 +721,7 @@ const char* SpoilerLog_Write(int language) {
// WriteEnabledGlitches(spoilerLog);
//}
//WriteMasterQuestDungeons(spoilerLog);
//WriteRequiredTrials(spoilerLog);
WriteRequiredTrials();
WritePlaythrough();
//WriteWayOfTheHeroLocation(spoilerLog);
@ -773,7 +771,7 @@ bool PlacementLog_Write() {
WriteEnabledTricks(placementLog);
WriteEnabledGlitches(placementLog);
WriteMasterQuestDungeons(placementLog);
WriteRequiredTrials(placementLog);
//WriteRequiredTrials(placementLog);
placementtxt = "\n" + placementtxt;

View File

@ -7,12 +7,12 @@ TrialInfo::TrialInfo(Text name_)
TrialInfo::~TrialInfo() = default;
TrialInfo ForestTrial = TrialInfo(Text{"the Forest Trial", /*french*/"l'épreuve de la forêt", /*spanish*/"la prueba del bosque"});
TrialInfo FireTrial = TrialInfo(Text{"the Fire Trial", /*french*/"l'épreuve du feu", /*spanish*/"la prueba del fuego"});
TrialInfo WaterTrial = TrialInfo(Text{"the Water Trial", /*french*/"l'épreuve de l'eau", /*spanish*/"la prueba del agua"});
TrialInfo SpiritTrial = TrialInfo(Text{"the Spirit Trial", /*french*/"l'épreuve de l'esprit", /*spanish*/"la prueba del espíritu"});
TrialInfo ShadowTrial = TrialInfo(Text{"the Shadow Trial", /*french*/"l'épreuve de l'ombre", /*spanish*/"la prueba de las sombras"});
TrialInfo LightTrial = TrialInfo(Text{"the Light Trial", /*french*/"l'épreuve de la lumière", /*spanish*/"la prueba de la luz"});
TrialInfo ForestTrial = TrialInfo(Text{"the Forest Trial", /*french*/"l'épreuve de la Forêt", /*spanish*/"la prueba del bosque"});
TrialInfo FireTrial = TrialInfo(Text{"the Fire Trial", /*french*/"l'épreuve du Feu", /*spanish*/"la prueba del fuego"});
TrialInfo WaterTrial = TrialInfo(Text{"the Water Trial", /*french*/"l'épreuve de l'Eau", /*spanish*/"la prueba del agua"});
TrialInfo SpiritTrial = TrialInfo(Text{"the Spirit Trial", /*french*/"l'épreuve de l'Esprit", /*spanish*/"la prueba del espíritu"});
TrialInfo ShadowTrial = TrialInfo(Text{"the Shadow Trial", /*french*/"l'épreuve de l'Ombre", /*spanish*/"la prueba de las sombras"});
TrialInfo LightTrial = TrialInfo(Text{"the Light Trial", /*french*/"l'épreuve de la Lumière", /*spanish*/"la prueba de la luz"});
const TrialArray trialList = {
&ForestTrial,

View File

@ -32,7 +32,7 @@ u8 generated;
const std::string Randomizer::getItemMessageTableID = "Randomizer";
const std::string Randomizer::hintMessageTableID = "RandomizerHints";
const std::string Randomizer::scrubMessageTableID = "RandomizerScrubs";
const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants";
const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees";
const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi";
@ -107,6 +107,21 @@ Randomizer::~Randomizer() {
this->randomizerMerchantPrices.clear();
}
std::unordered_map<std::string, RandomizerInf> spoilerFileTrialToEnum = {
{ "the Forest Trial", RAND_INF_TRIALS_DONE_FOREST_TRIAL },
{ "l'épreuve de la Forêt", RAND_INF_TRIALS_DONE_FOREST_TRIAL },
{ "the Fire Trial", RAND_INF_TRIALS_DONE_FIRE_TRIAL },
{ "l'épreuve du Feu", RAND_INF_TRIALS_DONE_FIRE_TRIAL },
{ "the Water Trial", RAND_INF_TRIALS_DONE_WATER_TRIAL },
{ "l'épreuve de l'Eau", RAND_INF_TRIALS_DONE_WATER_TRIAL },
{ "the Spirit Trial", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL },
{ "l'épreuve de l'Esprit", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL },
{ "the Shadow Trial", RAND_INF_TRIALS_DONE_SHADOW_TRIAL },
{ "l'épreuve de l'Ombre", RAND_INF_TRIALS_DONE_SHADOW_TRIAL },
{ "the Light Trial", RAND_INF_TRIALS_DONE_LIGHT_TRIAL },
{ "l'épreuve de la Lumière", RAND_INF_TRIALS_DONE_LIGHT_TRIAL }
};
std::unordered_map<s16, s16> getItemIdToItemId = {
{ GI_BOW, ITEM_BOW },
{ GI_ARROW_FIRE, ITEM_ARROW_FIRE },
@ -551,6 +566,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
{ "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS},
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
@ -672,6 +688,12 @@ void Randomizer::LoadItemLocations(const char* spoilerFileName, bool silent) {
itemLocations[RC_UNKNOWN_CHECK] = RG_NONE;
}
void Randomizer::LoadRequiredTrials(const char* spoilerFileName) {
if (strcmp(spoilerFileName, "") != 0) {
ParseRequiredTrialsFile(spoilerFileName);
}
}
void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
if (!spoilerFileStream)
@ -788,6 +810,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
case RSK_SHUFFLE_COWS:
case RSK_SHUFFLE_ADULT_TRADE:
case RSK_SHUFFLE_MAGIC_BEANS:
case RSK_RANDOM_TRIALS:
case RSK_STARTING_DEKU_SHIELD:
case RSK_STARTING_KOKIRI_SWORD:
@ -1089,6 +1112,25 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
}
}
void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) {
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
if (!spoilerFileStream) {
return;
}
try {
json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
json trialsJson = spoilerFileJson["requiredTrials"];
for (auto it = trialsJson.begin(); it != trialsJson.end(); it++) {
this->trialsRequired[spoilerFileTrialToEnum[it.value()]] = true;
}
} catch (const std::exception& e) {
return;
}
}
void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent) {
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
if (!spoilerFileStream)
@ -1139,6 +1181,10 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
}
}
bool Randomizer::IsTrialRequired(RandomizerInf trial) {
return this->trialsRequired.contains(trial);
}
s16 Randomizer::GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) {
s16 itemId = GetItemFromActor(actorId, actorParams, sceneNum, ogId);
return itemId;
@ -1211,8 +1257,6 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) {
case RG_MAGIC_BEAN:
return GI_BEAN;
case RG_MAGIC_BEAN_PACK:
return GI_BEAN; //todo make it 10 of them
case RG_WEIRD_EGG:
return GI_WEIRD_EGG;
@ -2900,6 +2944,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_SCRUBS] = CVar_GetS32("gRandomizeShuffleScrubs", 0);
cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0);
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVar_GetS32("gRandomizeShuffleBeans", 0);
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
// if we skip child zelda, we start with zelda's letter, and malon starts
@ -2980,7 +3025,7 @@ void DrawRandoEditor(bool& open) {
const char* randoGerudoFortress[3] = { "Normal", "Fast", "Open" };
const char* randoRainbowBridge[7] = { "Vanilla", "Always open", "Stones", "Medallions",
"Dungeon rewards", "Dungeons", "Tokens" };
const char* randoGanonsTrial[2] = { "Off", "On" };
const char* randoGanonsTrial[3] = { "Skip", "Set Number", "Random Number" };
// World Settings
const char* randoStartingAge[3] = { "Child", "Adult", "Random" };
@ -3383,23 +3428,20 @@ void DrawRandoEditor(bool& open) {
PaddedSeparator();
// Random Ganon's Trials
/*
ImGui::Text("Random Ganon's Trials");
InsertHelpHoverText("Sets a random number or required trials to enter\nGanon's Tower.");
SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 2, 0);
if (CVar_GetS32("gRandomizeGanonTrial", 0) == 0) {
ImGui::PopItemWidth();
SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount",
"gRandomizeGanonTrialCount", 0, 6, "", 6);
InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower.");
RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted.
}
*/
SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount");
ImGui::Text("Ganon's Trials");
InsertHelpHoverText(
"Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower."
"Sets the number of Ganon's Trials required to dispel the barrier\n\n"
"Skip - No Trials are required and the barrier is already dispelled.\n\n"
"Set Number - Select a number of trials that will be required from the"
"slider below. Which specific trials you need to complete will be random.\n\n"
"Random Number - A Random number and set of trials will be required."
);
SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0);
if (CVar_GetS32("gRandomizeGanonTrial", 0) == 1) {
SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount",
"gRandomizeGanonTrialCount", 1, 6, "", 6);
InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower.");
}
PaddedSeparator();
@ -4182,10 +4224,10 @@ void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
// Currently these are generated at runtime, one for each price between 0-95. We're soon going to migrate this
// to being generated at save load, with only messages specific to each scrub.
void CreateScrubMessages() {
void CreateMerchantMessages() {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, 0,
customMessageManager->AddCustomMessageTable(Randomizer::merchantMessageTableID);
customMessageManager->CreateMessage(Randomizer::merchantMessageTableID, 0,
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"\x12\x38\x82\All right! You win! In return for&sparing me, I will give you a&%gmysterious item%w!&Please, take it!\x07\x10\xA3",
"\x12\x38\x82\In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen %gmysteriösen&Gegenstand%w geben! Bitte nimm ihn!\x07\x10\xA3",
@ -4193,7 +4235,7 @@ void CreateScrubMessages() {
});
for (u32 price = 5; price <= 95; price += 5) {
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
customMessageManager->CreateMessage(Randomizer::merchantMessageTableID, price,
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
@ -4204,6 +4246,18 @@ void CreateScrubMessages() {
std::to_string(price) + " Rubis%w!\x07\x10\xA3"
});
}
customMessageManager->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN,
{
TEXTBOX_TYPE_BLACK,
TEXTBOX_POS_BOTTOM,
"I tried to be a %rmagic bean%w salesman,&but it turns out my marketing skills&weren't worth "
"beans!^Anyway, want to buy my&%gmysterious item%w for 60 Rupees?\x1B&%gYes&No%w",
"Möchten Sie einen geheimnisvollen&Gegenstand für 60 Rubine?\x1B&%gJa&Nein%w",
"J'ai essayé d'être un vendeur de&%rharicots magiques%w, mais j'étais&mauvais au niveau du marketing et&ça "
"me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter un&"
"%gobjet mystérieux%w pour 60 Rubis?\x1B&%gOui&Non%w",
});
}
void CreateRupeeMessages() {
@ -4348,75 +4402,122 @@ void Randomizer::CreateCustomMessages() {
const std::vector<GetItemMessage> getItemMessages = {
GIMESSAGE(RG_ICE_TRAP, ITEM_NONE, "\x08\x06\x30You are a %bFOWL%w!\x0E\x20",
"\x08\x06\x15 Du bist ein %bDUMMKOPF%w!\x0E\x20", "\x08\x06\x50%bIDIOT%w\x0E\x20"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE,
"You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!",
"Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!",
"Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE,
"You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!",
"Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"),
"You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!",
"Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE,
"You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre %rénergie vitale%w&ainsi que votre %gmagie%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FISH, ITEM_FISH,
"You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!",
"Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu %wen&serait friand!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BUGS, ITEM_BUG,
"You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!",
"Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY,
"You got a %rFairy in a Bottle%w!&Use it wisely!",
"Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED,
"You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!",
"Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN,
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_POE, ITEM_POE,
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...",
"Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "),
"You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre "
"%rénergie vitale%w&ainsi que votre %gmagie%w!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_FISH, ITEM_FISH,
"You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!",
"Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu "
"%wen&serait friand!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_BUGS, ITEM_BUG, "You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!",
"Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY, "You got a %rFairy in a Bottle%w!&Use it wisely!",
"Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED,
"You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!",
"Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN,
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_POE, ITEM_POE,
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...",
"Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "),
GIMESSAGE_NO_GERMAN(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %Puits%w!"),
GIMESSAGE_NO_GERMAN(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training &Grounds %wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %Château de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pBottom of the &Well %wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %Puits%w!"),
GIMESSAGE_NO_GERMAN(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yGerudo Training &Grounds %wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %Château de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!", "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!", "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!", "Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!", "Vous obtenez la %rCarte %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!", "Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!", "Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!", "Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!", "Vous obtenez la %rBoussole %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the &Well %wCompass!", "Vous obtenez la %rBoussole %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!", "Vous obtenez la %rBoussole %wde &la %cCaverne Polaire%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!",
"Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!",
"Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!",
"Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!",
"Vous obtenez la %rCarte %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!",
"Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!",
"Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!",
"Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS,
"You found the %pBottom of the &Well %wCompass!",
"Vous obtenez la %rBoussole %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!",
"Vous obtenez la %rBoussole %wde &la %cCaverne Polaire%w!"),
GIMESSAGE(RG_MAGIC_BEAN_PACK, ITEM_BEAN,
"You got a %rPack of Magic Beans%w!&Find a suitable spot for a garden&and plant them. Then, wait for&something fun to happen!",
"Du hast eine %rPackung&Magic Beans%w! Finde&einen geeigneten Platz fur einen&Garten und pflanze sie. Dann^warte auf etwas Lustiges passiert!",
"Vous avez un %rPack de&haricots magiques%w ! Trouvez&un endroit convenable pour un&jardin et plantez-les.^Ensuite, attendez quelque&chose d'amusant doit arriver !")
};
CreateGetItemMessages(getItemMessages);
CreateScrubMessages();
CreateMerchantMessages();
CreateRupeeMessages();
CreateNaviRandoMessages();
}
@ -4513,6 +4614,7 @@ void InitRandoItemTable() {
GET_ITEM(RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_SHADOW_TEMPLE_COMPASS),
GET_ITEM(RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_BOTTOM_OF_THE_WELL_COMPASS),
GET_ITEM(RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_ICE_CAVERN_COMPASS),
GET_ITEM(RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_MAGIC_BEAN_PACK)
};
ItemTableManager::Instance->AddItemTable(MOD_RANDOMIZER);
for (int i = 0; i < ARRAY_COUNT(extendedVanillaGetItemTable); i++) {

View File

@ -14,6 +14,7 @@ class Randomizer {
private:
std::unordered_map<RandomizerCheck, RandomizerGet> itemLocations;
std::unordered_map<RandomizerCheck, std::string> hintLocations;
std::unordered_map<RandomizerInf, bool> trialsRequired;
std::string childAltarText;
std::string adultAltarText;
std::string ganonHintText;
@ -24,6 +25,7 @@ class Randomizer {
s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId);
void ParseRandomizerSettingsFile(const char* spoilerFileName);
void ParseHintLocationsFile(const char* spoilerFileName);
void ParseRequiredTrialsFile(const char* spoilerFileName);
void ParseItemLocationsFile(const char* spoilerFileName, bool silent);
bool IsItemVanilla(RandomizerGet randoGet);
@ -34,7 +36,7 @@ class Randomizer {
static const std::string getItemMessageTableID;
static const std::string hintMessageTableID;
static const std::string scrubMessageTableID;
static const std::string merchantMessageTableID;
static const std::string rupeeMessageTableID;
static const std::string NaviRandoMessageTableID;
@ -44,7 +46,9 @@ class Randomizer {
bool SpoilerFileExists(const char* spoilerFileName);
void LoadRandomizerSettings(const char* spoilerFileName);
void LoadHintLocations(const char* spoilerFileName);
void LoadItemLocations(const char* spoilerFileName, bool silent);
void LoadRequiredTrials(const char* spoilerFileName);
void LoadItemLocations(const char* spoilerFileName,bool silent);
bool IsTrialRequired(RandomizerInf trial);
u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams);
std::string GetChildAltarText() const;

View File

@ -1016,7 +1016,8 @@ typedef enum {
RSK_COMPLETE_MASK_QUEST,
RSK_ENABLE_GLITCH_CUTSCENES,
RSK_SKULLS_SUNS_SONG,
RSK_SHUFFLE_ADULT_TRADE
RSK_SHUFFLE_ADULT_TRADE,
RSK_SHUFFLE_MAGIC_BEANS
} RandomizerSettingKey;
typedef struct ScrubIdentity {

View File

@ -1562,10 +1562,18 @@ extern "C" void Randomizer_LoadHintLocations(const char* spoilerFileName) {
OTRGlobals::Instance->gRandomizer->LoadHintLocations(spoilerFileName);
}
extern "C" void Randomizer_LoadRequiredTrials(const char* spoilerFileName) {
OTRGlobals::Instance->gRandomizer->LoadRequiredTrials(spoilerFileName);
}
extern "C" void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent) {
OTRGlobals::Instance->gRandomizer->LoadItemLocations(spoilerFileName, silent);
}
extern "C" bool Randomizer_IsTrialRequired(RandomizerInf trial) {
return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trial);
}
extern "C" bool SpoilerFileExists(const char* spoilerFileName) {
return OTRGlobals::Instance->gRandomizer->SpoilerFileExists(spoilerFileName);
}
@ -1583,7 +1591,7 @@ extern "C" ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams,
}
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(s16 itemPrice) {
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, itemPrice);
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, itemPrice);
}
extern "C" CustomMessageEntry Randomizer_GetNaviMessage() {
@ -1721,6 +1729,8 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
// In rando, replace Navi's general overworld hints with rando-related gameplay tips
} else if (CVar_GetS32("gRandoRelevantNavi", 1) && textId >= 0x0140 && textId <= 0x015F) {
messageEntry = Randomizer_GetNaviMessage();
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN);
}
}
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {

View File

@ -98,7 +98,9 @@ u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum);
ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
void Randomizer_LoadHintLocations(const char* spoilerFileName);
void Randomizer_LoadRequiredTrials(const char* spoilerFileName);
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
bool Randomizer_IsTrialRequired(RandomizerInf trial);
GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor);

View File

@ -1290,6 +1290,7 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
switch (giEntry.itemId) {
case RG_MAGIC_SINGLE:
case RG_MAGIC_DOUBLE:
case RG_MAGIC_BEAN_PACK:
color_slot = 0;
break;
case RG_DOUBLE_DEFENSE:

View File

@ -2181,6 +2181,14 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return RG_NONE;
}
if (item == RG_MAGIC_BEAN_PACK) {
if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
AMMO(ITEM_BEAN) = 10;
}
return RG_NONE;
}
if (item == RG_DOUBLE_DEFENSE) {
gSaveContext.doubleDefense = true;
gSaveContext.inventory.defenseHearts = 20;
@ -2227,9 +2235,9 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
}
}
} else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) ||
(item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) ||
(item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) ||
(item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) {
(item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) ||
(item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) ||
(item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) {
int mapIndex = gSaveContext.mapIndex;
switch (item) {
case RG_DEKU_TREE_MAP:
@ -2327,7 +2335,6 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return temp;
}
u8 Item_CheckObtainability(u8 item) {
s16 i;
s16 slot = SLOT(item);

View File

@ -4,9 +4,9 @@
#include <string.h>
#include <soh/Enhancements/randomizer/randomizerTypes.h>
#include <soh/Enhancements/randomizer/randomizer_inf.h>
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define NUM_DUNGEONS 8
#define NUM_TRIALS 6
#define NUM_COWS 10
#define NUM_SCRUBS 35
@ -309,6 +309,11 @@ void GiveLinkDekuNutUpgrade(GetItemID giid) {
}
}
void GiveLinkSkullToken() {
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
gSaveContext.inventory.gsTokens++;
}
void GiveLinkMagic(GetItemID giid) {
if (giid == RG_MAGIC_SINGLE) {
gSaveContext.magicLevel = 1;
@ -508,6 +513,53 @@ void GiveLinkDungeonItem(GetItemID getItemId) {
}
}
void GiveLinkAdultTradeItem(GetItemID giid) {
ItemID item;
switch (giid) {
case GI_POCKET_EGG:
item = ITEM_POCKET_EGG;
break;
case GI_POCKET_CUCCO:
item = ITEM_POCKET_CUCCO;
break;
case GI_COJIRO:
item = ITEM_COJIRO;
break;
case GI_ODD_MUSHROOM:
item = ITEM_ODD_MUSHROOM;
break;
case GI_ODD_POTION:
item = ITEM_ODD_POTION;
break;
case GI_SAW:
item = ITEM_SAW;
break;
case GI_SWORD_BROKEN:
item = ITEM_SWORD_BROKEN;
break;
case GI_PRESCRIPTION:
item = ITEM_PRESCRIPTION;
break;
case GI_FROG:
item = ITEM_FROG;
break;
case GI_EYEDROPS:
item = ITEM_EYEDROPS;
break;
case GI_CLAIM_CHECK:
item = ITEM_CLAIM_CHECK;
break;
}
if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
if (item >= ITEM_POCKET_EGG) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item);
}
INV_CONTENT(ITEM_TRADE_ADULT) = item;
}
void GiveLinksPocketMedallion() {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
@ -709,6 +761,15 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.randomizerInf[i] = 0;
}
// Set all trials to cleared if trial count is random or anything other than 6
if (Randomizer_GetSettingValue(RSK_RANDOM_TRIALS) || (Randomizer_GetSettingValue(RSK_TRIAL_COUNT) != 6)) {
for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) {
if (!Randomizer_IsTrialRequired(i)) {
Flags_SetRandomizerInf(i);
}
}
}
// Set Cutscene flags to skip them
gSaveContext.eventChkInf[0xC] |= 0x10; // returned to tot with medallions
gSaveContext.eventChkInf[0xC] |= 0x20; //sheik at tot pedestal
@ -735,6 +796,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.eventChkInf[3] |= 0x800;
gSaveContext.eventChkInf[12] |= 1;
// shuffle adult trade quest
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
gSaveContext.adultTradeItems = 0;
}
// Give Link's pocket item
GiveLinksPocketMedallion();
@ -849,6 +915,10 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkDekuStickUpgrade(giid);
} else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) {
GiveLinkDekuNutUpgrade(giid);
} else if (giid == GI_SKULL_TOKEN) {
GiveLinkSkullToken();
} else if (giid >= GI_POCKET_EGG && giid <= GI_CLAIM_CHECK || giid == GI_COJIRO) {
GiveLinkAdultTradeItem(giid);
} else {
s32 iid = getItem.itemId;
if (iid != -1) INV_CONTENT(iid) = iid;
@ -965,11 +1035,6 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
}
}
// shuffle adult trade quest
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
gSaveContext.adultTradeItems = 0;
}
// complete mask quest
if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask

View File

@ -64,12 +64,33 @@ static u8 sEnergyColors[] = {
/* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0,
};
// Translates from the barrier's actor params to their corresponding randInf flags.
RandomizerInf trialParamToRandInf(u16 params) {
switch (params) {
case KEKKAI_LIGHT:
return RAND_INF_TRIALS_DONE_LIGHT_TRIAL;
case KEKKAI_FOREST:
return RAND_INF_TRIALS_DONE_FOREST_TRIAL;
case KEKKAI_FIRE:
return RAND_INF_TRIALS_DONE_FIRE_TRIAL;
case KEKKAI_WATER:
return RAND_INF_TRIALS_DONE_WATER_TRIAL;
case KEKKAI_SPIRIT:
return RAND_INF_TRIALS_DONE_SPIRIT_TRIAL;
case KEKKAI_SHADOW:
return RAND_INF_TRIALS_DONE_SHADOW_TRIAL;
}
}
s32 DemoKekkai_CheckEventFlag(s32 params) {
static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB };
if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) {
return true;
}
if (gSaveContext.n64ddFlag) {
return Flags_GetRandomizerInf(trialParamToRandInf(params));
}
return Flags_GetEventChkInf(eventFlags[params]);
}
@ -128,8 +149,7 @@ void DemoKekkai_Init(Actor* thisx, GlobalContext* globalCtx) {
this->collider2.dim.yShift = 300;
if (gSaveContext.n64ddFlag) {
int trialsToComplete = Randomizer_GetSettingValue(RSK_TRIAL_COUNT);
if (trialsToComplete <= TrialsDoneCount()) {
if (TrialsDoneCount() == NUM_TRIALS) {
Actor_Kill(thisx);
return;
}
@ -141,6 +161,10 @@ void DemoKekkai_Init(Actor* thisx, GlobalContext* globalCtx) {
case KEKKAI_SHADOW:
case KEKKAI_SPIRIT:
case KEKKAI_FOREST:
if (gSaveContext.n64ddFlag && Flags_GetRandomizerInf(trialParamToRandInf(thisx->params))) {
Actor_Kill(thisx);
return;
}
this->energyAlpha = 1.0f;
this->orbScale = 1.0f;
Actor_SetScale(thisx, 0.1f);
@ -247,27 +271,10 @@ void DemoKekkai_TrialBarrierDispel(Actor* thisx, GlobalContext* globalCtx) {
DemoKekkai* this = (DemoKekkai*)thisx;
if (gSaveContext.n64ddFlag) {
switch (thisx->params) {
case KEKKAI_WATER:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL);
break;
case KEKKAI_LIGHT:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL);
break;
case KEKKAI_FIRE:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL);
break;
case KEKKAI_SHADOW:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL);
break;
case KEKKAI_SPIRIT:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL);
break;
case KEKKAI_FOREST:
Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL);
break;
}
Flags_SetEventChkInf(eventFlags[thisx->params]);
Flags_SetRandomizerInf(trialParamToRandInf(thisx->params));
// May or may not be needed. Not sure if needed for anything
// that randoInf isn't already covering. Leaving it for safety.
Flags_SetEventChkInf(eventFlags[thisx->params]);
}
if (globalCtx->csCtx.frames == csFrames[this->actor.params]) {

View File

@ -90,7 +90,16 @@ static void* sEyeTextures[] = {
gMalonChildEyeClosedTex,
};
bool Randomizer_ObtainedMalonHCReward() {
return Flags_GetEventChkInf(0x12);
}
u16 EnMa1_GetText(GlobalContext* globalCtx, Actor* thisx) {
// Special case for Malon Hyrule Castle Text. Placing it here at the beginning
// has the added benefit of circumventing mask text if wearing bunny hood.
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_SPOT15) {
return Randomizer_ObtainedMalonHCReward() ? 0x2044 : 0x2043;
}
u16 faceReaction = Text_GetFaceReaction(globalCtx, 0x17);
if (faceReaction != 0) {
@ -191,25 +200,34 @@ s32 func_80AA08C4(EnMa1* this, GlobalContext* globalCtx) {
if (!LINK_IS_CHILD) {
return 0;
}
// Causes Malon to appear in the market if you haven't met her yet.
if (((globalCtx->sceneNum == SCENE_MARKET_NIGHT) || (globalCtx->sceneNum == SCENE_MARKET_DAY)) &&
!(gSaveContext.eventChkInf[1] & 0x10) && !(gSaveContext.infTable[8] & 0x800)) {
return 1;
}
if ((globalCtx->sceneNum == SCENE_SPOT15) && !(gSaveContext.eventChkInf[1] & 0x10)) {
if (gSaveContext.infTable[8] & 0x800) {
return 1;
} else {
gSaveContext.infTable[8] |= 0x800;
return 0;
if ((globalCtx->sceneNum == SCENE_SPOT15) && // if we're at hyrule castle
(!(gSaveContext.eventChkInf[1] & 0x10) || // and talon hasn't left
(gSaveContext.n64ddFlag &&
!Randomizer_ObtainedMalonHCReward()))) { // or we're rando'd and haven't gotten malon's HC check
if (gSaveContext.infTable[8] & 0x800) { // if we've met malon
return 1; // make her appear at the castle
} else { // if we haven't met malon
gSaveContext.infTable[8] |= 0x800; // set the flag for meeting malon
return 0; // don't make her appear at the castle
}
}
// Malon asleep in her bed if Talon has left Hyrule Castle and it is nighttime.
if ((globalCtx->sceneNum == SCENE_SOUKO) && IS_NIGHT && (gSaveContext.eventChkInf[1] & 0x10)) {
return 1;
}
// Don't spawn Malon if none of the above are true and we are not in Lon Lon Ranch.
if (globalCtx->sceneNum != SCENE_SPOT20) {
return 0;
}
if ((this->actor.shape.rot.z == 3) && IS_DAY && (gSaveContext.eventChkInf[1] & 0x10)) {
// If we've gotten this far, we're in Lon Lon Ranch. Spawn Malon if it is daytime, Talon has left Hyrule Castle, and
// either we are not randomized, or we are and we have received Malon's item at Hyrule Castle.
if ((this->actor.shape.rot.z == 3) && IS_DAY && (gSaveContext.eventChkInf[1] & 0x10) &&
((gSaveContext.n64ddFlag && Randomizer_ObtainedMalonHCReward()) || !gSaveContext.n64ddFlag)) {
return 1;
}
return 0;
@ -290,10 +308,16 @@ void EnMa1_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actor.targetMode = 6;
this->unk_1E8.unk_00 = 0;
if (!(gSaveContext.eventChkInf[1] & 0x10) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag) ||
// To avoid missing a check, we want Malon to have the actionFunc for singing, but not reacting to Ocarina, if any of
// the following are true.
// 1. Talon has not left Hyrule Castle.
// 2. We are Randomized and have not obtained Malon's Weird Egg Check.
// 3. We are not Randomized and have obtained Epona's Song
if (!(gSaveContext.eventChkInf[1] & 0x10) || (gSaveContext.n64ddFlag && !Randomizer_ObtainedMalonHCReward()) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag) ||
(gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F))) {
this->actionFunc = func_80AA0D88;
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
// If none of the above conditions were true, set Malon up to teach Epona's Song.
} else {
if (gSaveContext.n64ddFlag) { // Skip straight to "let's sing it together" textbox in the ranch
gSaveContext.eventChkInf[1] |= 0x40;
@ -322,9 +346,16 @@ void func_80AA0D88(EnMa1* this, GlobalContext* globalCtx) {
}
}
if ((globalCtx->sceneNum == SCENE_SPOT15) && (gSaveContext.eventChkInf[1] & 0x10)) {
// We want to Kill Malon's Actor outside of randomizer when Talon is freed. In Randomizer we don't kill Malon's
// Actor here, otherwise if we wake up Talon first and then get her check she will spontaneously
// disappear.
if ((globalCtx->sceneNum == SCENE_SPOT15) && (!gSaveContext.n64ddFlag && gSaveContext.eventChkInf[1] & 0x10)) {
Actor_Kill(&this->actor);
} else if (!(gSaveContext.eventChkInf[1] & 0x10) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag)) {
// We want Malon to give the Weird Egg Check (see function below) in the following situations:
// 1. Talon as not left Hyrule Castle (Vanilla) OR
// 2. We haven't obtained Malon's Weird Egg Check (Randomizer only) OR
// 3. We have Epona's Song? (Vanilla only, not sure why it's here but I didn't write that one)
} else if ((!(gSaveContext.eventChkInf[1] & 0x10) || (gSaveContext.n64ddFlag && !Randomizer_ObtainedMalonHCReward())) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag)) {
if (this->unk_1E8.unk_00 == 2) {
this->actionFunc = func_80AA0EA0;
globalCtx->msgCtx.stateTimer = 4;

View File

@ -125,11 +125,19 @@ void EnMs_Talk(EnMs* this, GlobalContext* globalCtx) {
} else if (Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0: // yes
if (gSaveContext.rupees < sPrices[BEANS_BOUGHT]) {
if (gSaveContext.rupees <
((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS))
? 60
: sPrices[BEANS_BOUGHT])) {
Message_ContinueTextbox(globalCtx, 0x4069); // not enough rupees text
return;
}
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
GiveItemEntryFromActor(&this->actor, globalCtx,
Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
}
this->actionFunc = EnMs_Sell;
return;
case 1: // no
@ -142,11 +150,18 @@ void EnMs_Talk(EnMs* this, GlobalContext* globalCtx) {
void EnMs_Sell(EnMs* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]);
Rupees_ChangeBy((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sPrices[BEANS_BOUGHT]);
this->actor.parent = NULL;
this->actionFunc = EnMs_TalkAfterPurchase;
this->actionFunc =
(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase;
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
GiveItemEntryFromActor(&this->actor, globalCtx,
Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f);
BEANS_BOUGHT = 10;
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
}
}
}

View File

@ -135,6 +135,27 @@ void ObjectKankyo_Init(Actor* thisx, GlobalContext* globalCtx) {
this->effects[5].size = 0.0f;
}
if (gSaveContext.n64ddFlag) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) {
this->effects[0].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) {
this->effects[1].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) {
this->effects[2].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) {
this->effects[3].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) {
this->effects[4].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) {
this->effects[5].size = 0.0f;
}
}
if (gSaveContext.cutsceneTrigger != 0) {
if (gSaveContext.entranceIndex == 0x0538) {
this->effects[0].size = 0.1f;

View File

@ -433,6 +433,7 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
const char* fileLoc = CVar_GetString("gSpoilerLog", "");
Randomizer_LoadSettings(fileLoc);
Randomizer_LoadHintLocations(fileLoc);
Randomizer_LoadRequiredTrials(fileLoc);
Randomizer_LoadItemLocations(fileLoc, silent);
fileSelectSpoilerFileLoaded = true;
}