Remove disabled special hints and warp song hints from the spoiler log (#3110)

* Initial implementation of no-duplicates of special hints

* stupid fixes

* fix always hints being suppressed by special hints

* Impa's song will no longer be hinted when you skip child zelda

* fix building

* Remove disabled special hints from the spoiler log

* Fix Loading spoiler logs causing corrupt hints, remove disabled warp song shuffle text from spoiler logs

* Fix not detecting text size correctly and badly named greg hint

* Remove disabled special hints from the spoiler log

* Fix Loading spoiler logs causing corrupt hints, remove disabled warp song shuffle text from spoiler logs

* Remove Sheik and Saria hints from the spoiler log when are not enabled

* Prevent Magic hinted by Saria and Light Arrows hinted by Sheik from being hinted elsewhere unless they are locked by that item.

* Prevent the Final Frogs gossip stone hint from spawning when the special final frogs hint is enabled.

* Fix building after rebasing in deduplication

* redelete keys.hpp
This commit is contained in:
Pepper0ni 2023-10-22 16:11:36 +01:00 committed by GitHub
parent 2a52493d1f
commit 15ebcd30fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 297 additions and 193 deletions

View File

@ -996,7 +996,7 @@ void RegisterAltTrapTypes() {
void RegisterRandomizerSheikSpawn() { void RegisterRandomizerSheikSpawn() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
if (!gPlayState) return; if (!gPlayState) return;
bool canSheik = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIAL_COUNT) != RO_GANONS_TRIALS_SKIP && bool canSheik = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIAL_COUNT) != 0 &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LIGHT_ARROWS_HINT)); OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LIGHT_ARROWS_HINT));
if (!IS_RANDO || !LINK_IS_ADULT || !canSheik) return; if (!IS_RANDO || !LINK_IS_ADULT || !canSheik) return;
switch (gPlayState->sceneNum) { switch (gPlayState->sceneNum) {

View File

@ -1098,6 +1098,12 @@ int Fill() {
printf("Done"); printf("Done");
ctx->CreateItemOverrides(); ctx->CreateItemOverrides();
CreateEntranceOverrides(); CreateEntranceOverrides();
//Always execute ganon hint generation for the funny line
CreateGanonAndSheikText();
CreateAltarText();
CreateDampesDiaryText();
CreateGregRupeeHint();
CreateSariaText();
if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) { if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) {
printf("\x1b[10;10HCreating Hints..."); printf("\x1b[10;10HCreating Hints...");
CreateAllHints(); CreateAllHints();
@ -1106,13 +1112,6 @@ int Fill() {
if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) { if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) {
CreateMerchantsHints(); CreateMerchantsHints();
} }
//Always execute ganon hint generation for the funny line
CreateGanonText();
CreateAltarText();
CreateDampesDiaryText();
CreateGregRupeeHint();
CreateSheikText();
CreateSariaText();
CreateWarpSongTexts(); CreateWarpSongTexts();
return 1; return 1;
} }

View File

@ -48,22 +48,6 @@ void HintTable_Init() {
| ALWAYS HINT TEXT | | ALWAYS HINT TEXT |
---------------------------*/ ---------------------------*/
hintTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText::Always(
{
// obscure text
Text{ "an #amphibian feast# yields", /*french*/ "un #festin d'amphibiens# donne",
/*spanish*/ "una #fiesta anfibia# brinda" },
Text{ "the #croaking choir's magnum opus# awards", /*french*/ "la #chorale coassante# donne",
/*spanish*/ "un #coro maestro de ancas# premia" },
Text{ "the #froggy finale# yields", /*french*/ "la #finale amphibienne# donne",
/*spanish*/ "el #gran final batracio# brinda" },
},
{},
// clear text
Text{ "the final reward from the #Frogs of Zora's River# is",
/*french*/ "la dernière récompense des #grenouilles de la Rivière Zora# est",
/*spanish*/ "la recompensa final de las #ranas del Río Zora# premia" });
hintTable[RHT_KF_LINKS_HOUSE_COW] = HintText::Always( hintTable[RHT_KF_LINKS_HOUSE_COW] = HintText::Always(
{ {
// obscure text // obscure text
@ -488,6 +472,22 @@ void HintTable_Init() {
Text{ "a #cow behind webs# in a grotto gifts", /*french*/ "la #vache derrière les toiles# d'une grotte donne", Text{ "a #cow behind webs# in a grotto gifts", /*french*/ "la #vache derrière les toiles# d'une grotte donne",
/*spanish*/ "una #vaca tras la telaraña# de una cueva brinda" }); /*spanish*/ "una #vaca tras la telaraña# de una cueva brinda" });
hintTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText::Always(
{
// obscure text
Text{ "an #amphibian feast# yields", /*french*/ "un #festin d'amphibiens# donne",
/*spanish*/ "una #fiesta anfibia# brinda" },
Text{ "the #croaking choir's magnum opus# awards", /*french*/ "la #chorale coassante# donne",
/*spanish*/ "un #coro maestro de ancas# premia" },
Text{ "the #froggy finale# yields", /*french*/ "la #finale amphibienne# donne",
/*spanish*/ "el #gran final batracio# brinda" },
},
{},
// clear text
Text{ "the final reward from the #Frogs of Zora's River# is",
/*french*/ "la dernière récompense des #grenouilles de la Rivière Zora# est",
/*spanish*/ "la recompensa final de las #ranas del Río Zora# premia" });
hintTable[RHT_ZF_GS_HIDDEN_CAVE] = HintText::Sometimes({ hintTable[RHT_ZF_GS_HIDDEN_CAVE] = HintText::Sometimes({
// obscure text // obscure text
Text{ "a spider high #above the icy waters# holds", /*french*/ "l'araignée #en haut des eaux glacées# donne", Text{ "a spider high #above the icy waters# holds", /*french*/ "l'araignée #en haut des eaux glacées# donne",
@ -2959,6 +2959,16 @@ void HintTable_Init() {
"Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de " }, "Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de " },
}); });
hintTable[RHT_SHEIK_LIGHT_ARROW_HINT] = HintText::LightArrow({
// obscure text
Text{
"I overheard Ganondorf say that he misplaced the %yLight Arrows%w in&%r",
/*french*/
"J'ai entendu dire que Ganondorf aurait caché les %yFlèches de Lumière%w dans %r",
/*spanish*/
""},
});
hintTable[RHT_YOUR_POCKET] = HintText::Exclude({ hintTable[RHT_YOUR_POCKET] = HintText::Exclude({
// obscure text // obscure text
Text{ "your pocket", /*french*/ "tes poches", /*spanish*/ "tu bolsillo" }, Text{ "your pocket", /*french*/ "tes poches", /*spanish*/ "tu bolsillo" },
@ -3193,7 +3203,7 @@ int32_t TokensRequiredBySettings() {
return tokens; return tokens;
} }
std::array<ConditionalAlwaysHint, 9> conditionalAlwaysHints = { std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints = {
std::make_pair(RC_MARKET_10_BIG_POES, std::make_pair(RC_MARKET_10_BIG_POES,
[]() { []() {
return Settings::BigPoeTargetCount.Value<uint8_t>() >= 3; return Settings::BigPoeTargetCount.Value<uint8_t>() >= 3;
@ -3203,9 +3213,10 @@ std::array<ConditionalAlwaysHint, 9> conditionalAlwaysHints = {
std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }),
std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }),
std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { return false; }), std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { return false; }),
std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 30; }), std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 30 && !Settings::Kak30GSHintText; }),
std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 40; }), std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 40 && !Settings::Kak40GSHintText; }),
std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 50; }) std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 50 && !Settings::Kak50GSHintText; }),
std::make_pair(RC_ZR_FROGS_OCARINA_GAME, []() { return !Settings::FrogsHintText; }),
}; };
const HintText& Hint(const RandomizerHintTextKey hintKey) { const HintText& Hint(const RandomizerHintTextKey hintKey) {

View File

@ -275,6 +275,25 @@ static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCh
return accessibleGossipStones; return accessibleGossipStones;
} }
bool IsReachableWithout(std::vector<RandomizerCheck> locsToCheck, RandomizerCheck excludedCheck, bool resetAfter = true){
//temporarily remove the hinted location's item, and then perform a
//reachability search for this check
auto ctx = Rando::Context::GetInstance();
RandomizerGet originalItem = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet();
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE);
LogicReset();
const auto rechableWithout = GetAccessibleLocations(locsToCheck);
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(originalItem);
if (resetAfter){
//if resetAfter is on, reset logic we are done
LogicReset();
}
if (rechableWithout.empty()) {
return false;
}
return true;
}
static void AddHint(Text hint, const RandomizerCheck gossipStone, const std::vector<uint8_t>& colors = {}, HintType hintType = HINT_TYPE_ITEM, const RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK) { static void AddHint(Text hint, const RandomizerCheck gossipStone, const std::vector<uint8_t>& colors = {}, HintType hintType = HINT_TYPE_ITEM, const RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK) {
//save hints as dummy items for writing to the spoiler log //save hints as dummy items for writing to the spoiler log
//NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE}); //NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE});
@ -479,10 +498,6 @@ static void CreateRandomLocationHint(const bool goodItem = false) {
} }
} }
static void CreateGoodItemHint() {
CreateRandomLocationHint(true);
}
static void CreateJunkHint() { static void CreateJunkHint() {
//duplicate junk hints are possible for now //duplicate junk hints are possible for now
const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk)); const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk));
@ -596,16 +611,20 @@ static void CreateTrialHints() {
} }
} }
void CreateGanonText() { void CreateGanonAndSheikText() {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
//funny ganon line //funny ganon line
ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
if(Settings::LightArrowHintText){
//Get the location of the light arrows //Get the location of the light arrows
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS; return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS;
}); });
Text lightArrowArea = GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
std::vector<RandomizerCheck> locsToCheck = {RC_GANONDORF_HINT};
//If there is no light arrow location, it was in the player's inventory at the start //If there is no light arrow location, it was in the player's inventory at the start
auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT); auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT);
@ -613,24 +632,35 @@ void CreateGanonText() {
ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText(); ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText();
lightArrowHintLoc = "Link's Pocket"; lightArrowHintLoc = "Link's Pocket";
} else { } else {
ganonHintText = ganonHintText = hint.GetText() + "%r" + lightArrowArea;
hint.GetText() + "%r" +
GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName(); lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName();
} }
ganonHintText = ganonHintText + "!"; ganonHintText = ganonHintText + "!";
CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText)); CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
ctx->AddHint(RH_GANONDORF_HINT, ganonHintText, lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText()); ctx->AddHint(RH_GANONDORF_HINT, ganonHintText, lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText());
if(!Settings::GanonsTrialsCount.Is(0)){
sheikText = Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + lightArrowArea + "%w.";
locsToCheck = {RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC};
}
if (IsReachableWithout(locsToCheck,lightArrowLocation[0],true)){
ctx->GetItemLocation(lightArrowLocation[0])->SetAsHinted();
}
}
} }
//Find the location which has the given itemKey and create the generic altar text for the reward //Find the location which has the given itemKey and create the generic altar text for the reward
static Text BuildDungeonRewardText(const RandomizerGet itemKey) { static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
RandomizerCheck altarLoc = RC_ALTAR_HINT_ADULT;
if(isChild){altarLoc = RC_ALTAR_HINT_CHILD;}
RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) { RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey; return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey;
})[0]; })[0];
if (IsReachableWithout({altarLoc}, location, true) || ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)){ //RANDOTODO check if works properly
ctx->GetItemLocation(location)->SetAsHinted(); ctx->GetItemLocation(location)->SetAsHinted();
}
std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD); std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD);
@ -760,11 +790,11 @@ void CreateAltarText() {
childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
//Spiritual Stones //Spiritual Stones
(StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_KOKIRI_EMERALD)) + : BuildDungeonRewardText(RG_KOKIRI_EMERALD, true)) +
(StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_GORON_RUBY)) + : BuildDungeonRewardText(RG_GORON_RUBY, true)) +
(StartingZoraSapphire.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingZoraSapphire.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_ZORA_SAPPHIRE)) + : BuildDungeonRewardText(RG_ZORA_SAPPHIRE, true)) +
//How to open Door of Time, the event trigger is necessary to read the altar multiple times //How to open Door of Time, the event trigger is necessary to read the altar multiple times
BuildDoorOfTimeText(); BuildDoorOfTimeText();
} else { } else {
@ -780,17 +810,17 @@ void CreateAltarText() {
adultAltarText = adultAltarText + adultAltarText = adultAltarText +
//Medallion Areas //Medallion Areas
(StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_LIGHT_MEDALLION)) + : BuildDungeonRewardText(RG_LIGHT_MEDALLION, false)) +
(StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_FOREST_MEDALLION)) + : BuildDungeonRewardText(RG_FOREST_MEDALLION, false)) +
(StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_FIRE_MEDALLION)) + : BuildDungeonRewardText(RG_FIRE_MEDALLION, false)) +
(StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_WATER_MEDALLION)) + : BuildDungeonRewardText(RG_WATER_MEDALLION, false)) +
(StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION)) + : BuildDungeonRewardText(RG_SPIRIT_MEDALLION, false)) +
(StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" } (StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(RG_SHADOW_MEDALLION)); : BuildDungeonRewardText(RG_SHADOW_MEDALLION, false));
} }
adultAltarText = adultAltarText + adultAltarText = adultAltarText +
//Bridge requirement //Bridge requirement
@ -846,6 +876,10 @@ void CreateDampesDiaryText() {
RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) { RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item; return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item;
})[0]; })[0];
if (IsReachableWithout({RC_DAMPE_HINT},location,true)){
ctx->GetItemLocation(location)->SetAsHinted();
}
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText(); Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{ Text temp1 = Text{
"Whoever reads this, please enter %r", "Whoever reads this, please enter %r",
@ -875,6 +909,9 @@ void CreateGregRupeeHint() {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE; return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE;
})[0]; })[0];
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText(); Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
if (IsReachableWithout({RC_GREG_HINT},location,true)){
ctx->GetItemLocation(location)->SetAsHinted();
}
Text temp1 = Text{ Text temp1 = Text{
"By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%r ", "By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%r ",
@ -892,27 +929,14 @@ void CreateGregRupeeHint() {
ctx->AddHint(RH_GREG_RUPEE, gregText, location, HINT_TYPE_STATIC, area); ctx->AddHint(RH_GREG_RUPEE, gregText, location, HINT_TYPE_STATIC, area);
} }
void CreateSheikText() {
auto ctx = Rando::Context::GetInstance();
//Get the location of the light arrows
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS;});
lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName();
Text area = GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
"I overheard Ganondorf say that he misplaced the %yLight Arrows%w in&%r",
"J'ai entendu dire que Ganondorf aurait caché les %yFlèches de Lumière%w dans %r",
""
};
Text temp2 = Text{"%w.", "%w.", "%w."};
sheikText = temp1 + area + temp2;
}
void CreateSariaText() { void CreateSariaText() {
if(Settings::SariaHintText){
auto ctx = Rando::Context::GetInstance(); auto ctx = Rando::Context::GetInstance();
//Get the location of a magic upgrade //Get the location of a magic upgrade
auto magicLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_PROGRESSIVE_MAGIC_METER;}); auto magicLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_PROGRESSIVE_MAGIC_METER;})[0];
sariaHintLoc = Rando::StaticData::GetLocation(magicLocation[0])->GetName(); sariaHintLoc = Rando::StaticData::GetLocation(magicLocation)->GetName();
Text area = GetHintRegion(ctx->GetItemLocation(magicLocation[0])->GetParentRegionKey())->GetHint().GetText(); Text area = GetHintRegion(ctx->GetItemLocation(magicLocation)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{ Text temp1 = Text{
"Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %r", "Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %r",
"As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %r", "As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %r",
@ -924,6 +948,11 @@ void CreateSariaText() {
"%w.$C" "%w.$C"
}; };
sariaText = temp1 + area + temp2; sariaText = temp1 + area + temp2;
if (IsReachableWithout({RC_SARIA_SONG_HINT},magicLocation,true)){
ctx->GetItemLocation(magicLocation)->SetAsHinted();
}
}
} }
@ -983,6 +1012,29 @@ void CreateAllHints() {
uint8_t remainingDungeonWothHints = hintSetting.dungeonsWothLimit; uint8_t remainingDungeonWothHints = hintSetting.dungeonsWothLimit;
uint8_t remainingDungeonBarrenHints = hintSetting.dungeonsBarrenLimit; uint8_t remainingDungeonBarrenHints = hintSetting.dungeonsBarrenLimit;
// Apply Special hint exclusions with no requirements
if (Settings::Kak10GSHintText){
ctx->GetItemLocation(RC_KAK_10_GOLD_SKULLTULA_REWARD)->SetAsHinted();
}
if (Settings::Kak20GSHintText){
ctx->GetItemLocation(RC_KAK_20_GOLD_SKULLTULA_REWARD)->SetAsHinted();
}
if (Settings::Kak30GSHintText){
ctx->GetItemLocation(RC_KAK_30_GOLD_SKULLTULA_REWARD)->SetAsHinted();
}
if (Settings::Kak40GSHintText){
ctx->GetItemLocation(RC_KAK_40_GOLD_SKULLTULA_REWARD)->SetAsHinted();
}
if (Settings::Kak50GSHintText){
ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->SetAsHinted();
}
if (Settings::FrogsHintText){
ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME)->SetAsHinted();
}
if (Settings::skipChildZelda){
ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetAsHinted();
}
// Add 'always' location hints // Add 'always' location hints
if (hintSetting.distTable[static_cast<int>(HINT_TYPE_ALWAYS)].copies > 0) { if (hintSetting.distTable[static_cast<int>(HINT_TYPE_ALWAYS)].copies > 0) {
// Only filter locations that had a random item placed at them (e.g. don't get cow locations if shuffle cows is // Only filter locations that had a random item placed at them (e.g. don't get cow locations if shuffle cows is
@ -990,14 +1042,14 @@ void CreateAllHints() {
auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) || return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) ||
// If we have Rainbow Bridge set to Greg, add a hint for where Greg is // If we have Rainbow Bridge set to Greg, add a hint for where Greg is
(Bridge.Is(RAINBOWBRIDGE_GREG) && !GregHintText && (Bridge.Is(RAINBOWBRIDGE_GREG) &&
ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) && ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt()); ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
}); });
for (auto& hint : conditionalAlwaysHints) { for (auto& hint : conditionalAlwaysHints) {
RandomizerCheck loc = hint.first; RandomizerCheck loc = hint.first;
if (hint.second() && ctx->GetItemLocation(loc)->IsHintable() && !ctx->GetItemLocation(loc)->IsHintedAt()) { if (hint.second() && ctx->GetItemLocation(loc)->IsHintable()) {
alwaysHintLocations.push_back(loc); alwaysHintLocations.push_back(loc);
} }
} }
@ -1106,7 +1158,7 @@ void CreateAllHints() {
CreateRandomLocationHint(); CreateRandomLocationHint();
} else if (type == HINT_TYPE_ITEM) { } else if (type == HINT_TYPE_ITEM) {
CreateGoodItemHint(); CreateRandomLocationHint(true);
} else if (type == HINT_TYPE_SONG) { } else if (type == HINT_TYPE_SONG) {
std::vector<RandomizerCheck> songHintLocations = std::vector<RandomizerCheck> songHintLocations =

View File

@ -114,7 +114,7 @@ public:
static auto LightArrow(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) { static auto LightArrow(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LightArrow}; return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LightArrow};
} } //RANDOTODO Concert to generic special hints?
static auto GanonLine(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) { static auto GanonLine(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonLine}; return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonLine};
@ -198,7 +198,7 @@ using ConditionalAlwaysHint = std::pair<RandomizerCheck, std::function<bool()>>;
//10 dungeons as GTG and GC are excluded //10 dungeons as GTG and GC are excluded
extern std::array<DungeonInfo, 10> dungeonInfoData; extern std::array<DungeonInfo, 10> dungeonInfoData;
extern std::array<ConditionalAlwaysHint, 9> conditionalAlwaysHints; extern std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints;
extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area); extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area);
extern void CreateAllHints(); extern void CreateAllHints();
@ -206,9 +206,8 @@ extern void CreateMerchantsHints();
extern void CreateWarpSongTexts(); extern void CreateWarpSongTexts();
extern void CreateDampesDiaryText(); extern void CreateDampesDiaryText();
extern void CreateGregRupeeHint(); extern void CreateGregRupeeHint();
extern void CreateSheikText();
extern void CreateSariaText(); extern void CreateSariaText();
extern void CreateGanonText(); extern void CreateGanonAndSheikText();
extern void CreateAltarText(); extern void CreateAltarText();
Text& GetChildAltarText(); Text& GetChildAltarText();

View File

@ -259,7 +259,8 @@ void AreaTable_Init() {
areaTable[RR_ROOT] = Area("Root", "", RHT_LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_ROOT] = Area("Root", "", RHT_LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LocationAccess(RC_LINKS_POCKET, {[]{return true;}}), LocationAccess(RC_LINKS_POCKET, {[]{return true;}}),
LocationAccess(RC_TRIFORCE_COMPLETED, { [] { return CanCompleteTriforce;}}), LocationAccess(RC_TRIFORCE_COMPLETED, {[]{return CanCompleteTriforce;}}),
LocationAccess(RC_SARIA_SONG_HINT, {[]{return CanPlay(SariasSong);}}),
}, { }, {
//Exits //Exits
Entrance(RR_ROOT_EXITS, {[]{return true;}}) Entrance(RR_ROOT_EXITS, {[]{return true;}})

View File

@ -53,6 +53,8 @@ void AreaTable_Init_CastleTown() {
areaTable[RR_TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}), LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
LocationAccess(RC_ALTAR_HINT_CHILD, {[]{return IsChild;}}),
LocationAccess(RC_ALTAR_HINT_ADULT, {[]{return IsAdult;}}),
}, { }, {
//Exits //Exits
Entrance(RR_TOT_ENTRANCE, {[]{return true;}}), Entrance(RR_TOT_ENTRANCE, {[]{return true;}}),
@ -231,6 +233,7 @@ void AreaTable_Init_CastleTown() {
areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LocationAccess(RC_GREG_HINT, {[]{return true;}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),

View File

@ -22,7 +22,10 @@ void AreaTable_Init_GanonsCastle() {
| VANILLA DUNGEON | | VANILLA DUNGEON |
---------------------------*/ ---------------------------*/
if (Dungeon::GanonsCastle.IsVanilla()) { if (Dungeon::GanonsCastle.IsVanilla()) {
areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, { areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_SHEIK_HINT_GC, {[]{return true;}}),
}, {
//Exits //Exits
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_FOREST_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_FOREST_TRIAL, {[]{return true;}}),
@ -121,7 +124,10 @@ void AreaTable_Init_GanonsCastle() {
| MASTER QUEST DUNGEON | | MASTER QUEST DUNGEON |
---------------------------*/ ---------------------------*/
if (Dungeon::GanonsCastle.IsMQ()) { if (Dungeon::GanonsCastle.IsMQ()) {
areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, { areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_SHEIK_HINT_MQ_GC, {[]{return true;}}),
}, {
//Exits //Exits
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return (IsAdult || (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword))));}}), Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return (IsAdult || (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword))));}}),
Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL, {[]{return true;}}),

View File

@ -267,7 +267,10 @@ void AreaTable_Init_Kakariko() {
Entrance(RR_KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);}}), Entrance(RR_KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);}}),
}); });
areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, { areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_DAMPE_HINT, {[]{return IsAdult;}}),
}, {
//Exits //Exits
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
}); });

View File

@ -858,6 +858,8 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
extern Option HintDistribution; extern Option HintDistribution;
extern Option AltarHintText; extern Option AltarHintText;
extern Option LightArrowHintText; extern Option LightArrowHintText;
extern Option SariaHintText;
extern Option FrogsHintText;
extern Option DampeHintText; extern Option DampeHintText;
extern Option GregHintText; extern Option GregHintText;
extern Option Kak10GSHintText; extern Option Kak10GSHintText;

View File

@ -689,12 +689,15 @@ static void WriteHints(int language) {
unformattedGregText = GetGregHintText().GetEnglish(); unformattedGregText = GetGregHintText().GetEnglish();
unformattedSheikText = GetSheikHintText().GetEnglish(); unformattedSheikText = GetSheikHintText().GetEnglish();
unformattedSariaText = GetSariaHintText().GetEnglish(); unformattedSariaText = GetSariaHintText().GetEnglish();
if (Settings::ShuffleWarpSongs){
jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish();
jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish();
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish();
jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish(); jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish();
jsonData["warpNocturneText"] = GetWarpNocturneText().GetEnglish(); jsonData["warpNocturneText"] = GetWarpNocturneText().GetEnglish();
jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish(); jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish();
}
jsonData["childAltar"]["hintText"] = GetChildAltarText().GetEnglish(); jsonData["childAltar"]["hintText"] = GetChildAltarText().GetEnglish();
jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetEnglish(); jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetEnglish();
break; break;
@ -705,12 +708,15 @@ static void WriteHints(int language) {
unformattedGregText = GetGregHintText().GetFrench(); unformattedGregText = GetGregHintText().GetFrench();
unformattedSheikText = GetSheikHintText().GetFrench(); unformattedSheikText = GetSheikHintText().GetFrench();
unformattedSariaText = GetSariaHintText().GetFrench(); unformattedSariaText = GetSariaHintText().GetFrench();
if (Settings::ShuffleWarpSongs){
jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench(); jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench();
jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench(); jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench();
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench(); jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench();
jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench(); jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench();
jsonData["warpNocturneText"] = GetWarpNocturneText().GetFrench(); jsonData["warpNocturneText"] = GetWarpNocturneText().GetFrench();
jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench(); jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench();
}
jsonData["childAltar"]["hintText"] = GetChildAltarText().GetFrench(); jsonData["childAltar"]["hintText"] = GetChildAltarText().GetFrench();
jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetFrench(); jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetFrench();
break; break;
@ -756,16 +762,25 @@ static void WriteHints(int language) {
std::string sariaText = AutoFormatHintTextString(unformattedSariaText); std::string sariaText = AutoFormatHintTextString(unformattedSariaText);
jsonData["ganonText"] = ganonText; jsonData["ganonText"] = ganonText;
if (Settings::LightArrowHintText){
jsonData["ganonHintText"] = ganonHintText; jsonData["ganonHintText"] = ganonHintText;
jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc(); jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc();
if (!Settings::GanonsTrialsCount.Is(0)){
jsonData["sheikText"] = sheikText;
}
}
if (Settings::DampeHintText){
jsonData["dampeText"] = dampesText; jsonData["dampeText"] = dampesText;
jsonData["dampeHintLoc"] = GetDampeHintLoc(); jsonData["dampeHintLoc"] = GetDampeHintLoc();
}
if (Settings::GregHintText){
jsonData["gregText"] = gregText; jsonData["gregText"] = gregText;
jsonData["gregLoc"] = jsonData["gregLoc"] = Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName();
Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName(); }
jsonData["sheikText"] = sheikText; if (Settings::SariaHintText){
jsonData["sariaText"] = sariaText; jsonData["sariaText"] = sariaText;
jsonData["sariaHintLoc"] = GetSariaHintLoc(); jsonData["sariaHintLoc"] = GetSariaHintLoc();
}
if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) { if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) {
return; return;

View File

@ -144,7 +144,9 @@ void Context::LocationReset() {
GetItemLocation(il)->RemoveFromPool(); GetItemLocation(il)->RemoveFromPool();
} }
GetItemLocation(RC_GANONDORF_HINT)->RemoveFromPool(); for (RandomizerCheck il : Rando::StaticData::otherHintLocations) {
GetItemLocation(il)->RemoveFromPool();
}
} }
void Context::HintReset() { void Context::HintReset() {

View File

@ -235,11 +235,11 @@ Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest
Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_, RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_, uint8_t scene_,
std::string&& shortName_, std::string&& spoilerName_, std::string&& shortName_, std::string&& spoilerName_,
std::vector<Category>&& categories, bool isVanillaCompletion_) { bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, actorParams_, flag_, return Location(rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, 0x00, 0x00,
std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, std::move(categories), isVanillaCompletion_); std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, {}, isVanillaCompletion_);
} }
Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,

View File

@ -253,9 +253,8 @@ class Location {
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP, bool isVanillaCompletion_ = false); SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP, bool isVanillaCompletion_ = false);
static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_, RandomizerCheckArea area_, ActorID actorId_, uint8_t scene,
uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, std::string&& shortName_, std::string&& spoilerName_, bool isVanillaCompletion_ = false);
std::vector<Category>&& categories, bool isVanillaCompletion_ = false);
static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene, static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene,
int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,

View File

@ -507,6 +507,17 @@ std::vector<RandomizerCheck> Rando::StaticData::gossipStoneLocations = {
RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RC_ZR_OPEN_GROTTO_GOSSIP_STONE,
}; };
std::vector<RandomizerCheck> Rando::StaticData::otherHintLocations = {
RC_GANONDORF_HINT,
RC_SHEIK_HINT_GC,
RC_SHEIK_HINT_MQ_GC,
RC_DAMPE_HINT,
RC_GREG_HINT,
RC_SARIA_SONG_HINT,
RC_ALTAR_HINT_CHILD,
RC_ALTAR_HINT_ADULT
};
typedef enum { typedef enum {
DUNGEON_DEKU_TREE = 0, DUNGEON_DEKU_TREE = 0,
DUNGEON_DODONGOS_CAVERN, DUNGEON_DODONGOS_CAVERN,
@ -1221,7 +1232,7 @@ void Rando::StaticData::InitLocationTable() {
// Bosses Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Bosses Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression
locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::AlwaysCollected(), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::AlwaysCollected(), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true);
locationTable[RC_QUEEN_GOHMA] = Location::Reward( RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::Chest(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::Chest(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true);
locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::Chest(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::Chest(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true);
locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::Chest(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::Chest(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true);
locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true);
@ -1403,7 +1414,15 @@ void Rando::StaticData::InitLocationTable() {
locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {});
// Other Hints // Other Hints
locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, 0x00, 0x00, "Hint", "Ganondorf Hint", {}); locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint");
locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle");
locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle");
locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint");
locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint");
locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song");
locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text");
locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text");
locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP);
// clang-format on // clang-format on
} }

View File

@ -474,11 +474,15 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
); );
CustomMessageManager::Instance->CreateMessage( CustomMessageManager::Instance->CreateMessage(
Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY, Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY,
CustomMessage(gSaveContext.dampeText, gSaveContext.dampeText, gSaveContext.dampeText) CustomMessage(gSaveContext.dampeText,
gSaveContext.dampeText,
gSaveContext.dampeText)
); );
CustomMessageManager::Instance->CreateMessage( CustomMessageManager::Instance->CreateMessage(
Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED, Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED,
CustomMessage(gSaveContext.gregHintText, gSaveContext.gregHintText, gSaveContext.gregHintText) CustomMessage(gSaveContext.gregHintText,
gSaveContext.gregHintText,
gSaveContext.gregHintText)
); );
CustomMessageManager::Instance->CreateMessage( CustomMessageManager::Instance->CreateMessage(
Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER, Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER,
@ -491,7 +495,6 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
CustomMessage("{{message}}", "{{message}}", "{{message}}", TEXTBOX_TYPE_BLUE) CustomMessage("{{message}}", "{{message}}", "{{message}}", TEXTBOX_TYPE_BLUE)
); );
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT, CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT,
CustomMessage("Warp to&{{location}}?\x1B&%gOK&No%w\x02", CustomMessage("Warp to&{{location}}?\x1B&%gOK&No%w\x02",
"Zu {{location}}?\x1B&%gOK&No%w\x02", "Zu {{location}}?\x1B&%gOK&No%w\x02",
@ -1289,16 +1292,34 @@ std::string FormatJsonHintText(std::string jsonHint) {
formattedHintMessage.replace(start_pos, textToReplace.length(), iconString); formattedHintMessage.replace(start_pos, textToReplace.length(), iconString);
} }
} }
formattedHintMessage += 0x02;
return formattedHintMessage; return formattedHintMessage;
} }
void ParseSpoilerHintText(json Json, std::string field, char* saveLoc, bool format, int size){
auto jsonIter = Json.find(field);
if (jsonIter != Json.end()){
std::string jsonText = jsonIter.value().get<std::string>();
if (format){
jsonText = FormatJsonHintText(jsonText);
}
strncpy(saveLoc, jsonText.c_str(), size-1);
saveLoc[size - 1] = 0;
}
}
void CheckNameToEnum(json Json, std::string field, RandomizerCheck* saveLoc){
auto jsonIter = Json.find(field);
if (jsonIter != Json.end()){
*saveLoc = SpoilerfileCheckNameToEnum[jsonIter.value().get<std::string>()];
};
}
void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) { void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
std::ifstream spoilerFileStream(sanitize(spoilerFileName)); std::ifstream spoilerFileStream(sanitize(spoilerFileName));
if (!spoilerFileStream) if (!spoilerFileStream)
return; return;
bool success = false;
// Have all these use strncpy so that the null terminator is copied // Have all these use strncpy so that the null terminator is copied
// and also set the last index to null for safety // and also set the last index to null for safety
try { try {
@ -1324,64 +1345,28 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
gSaveContext.rewardCheck[7] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"]]; gSaveContext.rewardCheck[7] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"]];
gSaveContext.rewardCheck[8] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"]]; gSaveContext.rewardCheck[8] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"]];
std::string ganonHintJsonText = spoilerFileJson["ganonHintText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "ganonHintText", gSaveContext.ganonHintText, true, sizeof(gSaveContext.ganonHintText));
std::string formattedGanonHintJsonText = FormatJsonHintText(ganonHintJsonText); CheckNameToEnum(spoilerFileJson, "lightArrowHintLoc", &gSaveContext.lightArrowHintCheck);
strncpy(gSaveContext.ganonHintText, formattedGanonHintJsonText.c_str(), sizeof(gSaveContext.ganonHintText) - 1); ParseSpoilerHintText(spoilerFileJson, "ganonText", gSaveContext.ganonText, true, sizeof(gSaveContext.ganonText));
gSaveContext.ganonHintText[sizeof(gSaveContext.ganonHintText) - 1] = 0;
gSaveContext.lightArrowHintCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"]];
std::string ganonJsonText = spoilerFileJson["ganonText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "dampeText", gSaveContext.dampeText, true, sizeof(gSaveContext.dampeText));
std::string formattedGanonJsonText = FormatJsonHintText(ganonJsonText); CheckNameToEnum(spoilerFileJson, "dampeHintLoc", &gSaveContext.dampeCheck);
strncpy(gSaveContext.ganonText, formattedGanonJsonText.c_str(), sizeof(gSaveContext.ganonText) - 1);
gSaveContext.ganonText[sizeof(gSaveContext.ganonText) - 1] = 0;
std::string dampeJsonText = spoilerFileJson["dampeText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "gregText", gSaveContext.gregHintText, true, sizeof(gSaveContext.gregHintText));
std::string formattedDampeJsonText = FormatJsonHintText(dampeJsonText); CheckNameToEnum(spoilerFileJson, "gregLoc", &gSaveContext.gregCheck);
strncpy(gSaveContext.dampeText, formattedDampeJsonText.c_str(), sizeof(gSaveContext.dampeText) - 1);
gSaveContext.dampeText[sizeof(gSaveContext.dampeText) - 1] = 0;
gSaveContext.dampeCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"]];
std::string gregJsonText = spoilerFileJson["gregText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "sheikText", gSaveContext.sheikText, true, sizeof(gSaveContext.sheikText));
std::string formattedGregJsonText = FormatJsonHintText(gregJsonText);
strncpy(gSaveContext.gregHintText, formattedGregJsonText.c_str(), sizeof(gSaveContext.gregHintText) - 1);
gSaveContext.gregHintText[sizeof(gSaveContext.gregHintText) - 1] = 0;
gSaveContext.gregCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"]];
std::string sheikJsonText = spoilerFileJson["sheikText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "sariaText", gSaveContext.sariaText, true, sizeof(gSaveContext.sariaText));
std::string formattedSheikJsonText = FormatJsonHintText(sheikJsonText); CheckNameToEnum(spoilerFileJson, "sariaHintLoc", &gSaveContext.sariaCheck);
strncpy(gSaveContext.sheikText, formattedSheikJsonText.c_str(), sizeof(gSaveContext.sheikText) - 1);
gSaveContext.sheikText[sizeof(gSaveContext.sheikText) - 1] = 0;
gSaveContext.lightArrowHintCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"]];
std::string sariaJsonText = spoilerFileJson["sariaText"].get<std::string>(); ParseSpoilerHintText(spoilerFileJson, "warpMinuetText", gSaveContext.warpMinuetText, false, sizeof(gSaveContext.warpMinuetText));
std::string formattedSariaJsonText = FormatJsonHintText(sariaJsonText); ParseSpoilerHintText(spoilerFileJson, "warpBoleroText", gSaveContext.warpBoleroText, false, sizeof(gSaveContext.warpBoleroText));
strncpy(gSaveContext.sariaText, formattedSariaJsonText.c_str(), sizeof(gSaveContext.sariaText) - 1); ParseSpoilerHintText(spoilerFileJson, "warpSerenadeText", gSaveContext.warpSerenadeText, false, sizeof(gSaveContext.warpSerenadeText));
gSaveContext.sariaText[sizeof(gSaveContext.sariaText) - 1] = 0; ParseSpoilerHintText(spoilerFileJson, "warpRequiemText", gSaveContext.warpRequiemText, false, sizeof(gSaveContext.warpRequiemText));
gSaveContext.sariaCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"]]; ParseSpoilerHintText(spoilerFileJson, "warpNocturneText", gSaveContext.warpNocturneText, false, sizeof(gSaveContext.warpNocturneText));
ParseSpoilerHintText(spoilerFileJson, "warpPreludeText", gSaveContext.warpPreludeText, false, sizeof(gSaveContext.warpPreludeText));
std::string warpMinuetJsonText = spoilerFileJson["warpMinuetText"].get<std::string>();
strncpy(gSaveContext.warpMinuetText, warpMinuetJsonText.c_str(), sizeof(gSaveContext.warpMinuetText) - 1);
gSaveContext.warpMinuetText[sizeof(gSaveContext.warpMinuetText) - 1] = 0;
std::string warpBoleroJsonText = spoilerFileJson["warpBoleroText"].get<std::string>();
strncpy(gSaveContext.warpBoleroText, warpBoleroJsonText.c_str(), sizeof(gSaveContext.warpBoleroText) - 1);
gSaveContext.warpBoleroText[sizeof(gSaveContext.warpBoleroText) - 1] = 0;
std::string warpSerenadeJsonText = spoilerFileJson["warpSerenadeText"].get<std::string>();
strncpy(gSaveContext.warpSerenadeText, warpSerenadeJsonText.c_str(), sizeof(gSaveContext.warpSerenadeText) - 1);
gSaveContext.warpSerenadeText[sizeof(gSaveContext.warpSerenadeText) - 1] = 0;
std::string warpRequiemJsonText = spoilerFileJson["warpRequiemText"].get<std::string>();
strncpy(gSaveContext.warpRequiemText, warpRequiemJsonText.c_str(), sizeof(gSaveContext.warpRequiemText) - 1);
gSaveContext.warpRequiemText[sizeof(gSaveContext.warpRequiemText) - 1] = 0;
std::string warpNocturneJsonText = spoilerFileJson["warpNocturneText"].get<std::string>();
strncpy(gSaveContext.warpNocturneText, warpNocturneJsonText.c_str(), sizeof(gSaveContext.warpNocturneText) - 1);
gSaveContext.warpNocturneText[sizeof(gSaveContext.warpNocturneText) - 1] = 0;
std::string warpPreludeJsonText = spoilerFileJson["warpPreludeText"].get<std::string>();
strncpy(gSaveContext.warpPreludeText, warpPreludeJsonText.c_str(), sizeof(gSaveContext.warpPreludeText) - 1);
gSaveContext.warpPreludeText[sizeof(gSaveContext.warpPreludeText) - 1] = 0;
json hintsJson = spoilerFileJson["hints"]; json hintsJson = spoilerFileJson["hints"];
int index = 0; int index = 0;
@ -1416,7 +1401,6 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
index++; index++;
} }
success = true;
} catch (const std::exception& e) { } catch (const std::exception& e) {
return; return;
} }

View File

@ -1348,7 +1348,14 @@ typedef enum {
RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RC_ZR_NEAR_GROTTOS_GOSSIP_STONE,
RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RC_ZR_OPEN_GROTTO_GOSSIP_STONE,
RC_GANONDORF_HINT, RC_GANONDORF_HINT,
RC_SHEIK_HINT_GC,
RC_SHEIK_HINT_MQ_GC,
RC_TRIFORCE_COMPLETED, RC_TRIFORCE_COMPLETED,
RC_DAMPE_HINT,
RC_GREG_HINT,
RC_SARIA_SONG_HINT,
RC_ALTAR_HINT_CHILD,
RC_ALTAR_HINT_ADULT,
RC_MAX RC_MAX
} RandomizerCheck; } RandomizerCheck;
@ -3172,6 +3179,7 @@ typedef enum {
RHT_VALIDATION_LINE, RHT_VALIDATION_LINE,
// Light Arrow Location // Light Arrow Location
RHT_LIGHT_ARROW_LOCATION_HINT, RHT_LIGHT_ARROW_LOCATION_HINT,
RHT_SHEIK_LIGHT_ARROW_HINT,
// Your Pocket // Your Pocket
RHT_YOUR_POCKET, RHT_YOUR_POCKET,
// Ganon Line // Ganon Line

View File

@ -31,6 +31,7 @@ class StaticData {
static std::vector<std::vector<RandomizerCheck>> shopLocationLists; static std::vector<std::vector<RandomizerCheck>> shopLocationLists;
static std::vector<RandomizerCheck> scrubLocations; static std::vector<RandomizerCheck> scrubLocations;
static std::vector<RandomizerCheck> gossipStoneLocations; static std::vector<RandomizerCheck> gossipStoneLocations;
static std::vector<RandomizerCheck> otherHintLocations;
StaticData(); StaticData();
~StaticData(); ~StaticData();
}; };