mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-26 19:32:17 -05:00
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:
parent
2a52493d1f
commit
15ebcd30fb
@ -996,7 +996,7 @@ void RegisterAltTrapTypes() {
|
||||
void RegisterRandomizerSheikSpawn() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
|
||||
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));
|
||||
if (!IS_RANDO || !LINK_IS_ADULT || !canSheik) return;
|
||||
switch (gPlayState->sceneNum) {
|
||||
|
@ -1098,6 +1098,12 @@ int Fill() {
|
||||
printf("Done");
|
||||
ctx->CreateItemOverrides();
|
||||
CreateEntranceOverrides();
|
||||
//Always execute ganon hint generation for the funny line
|
||||
CreateGanonAndSheikText();
|
||||
CreateAltarText();
|
||||
CreateDampesDiaryText();
|
||||
CreateGregRupeeHint();
|
||||
CreateSariaText();
|
||||
if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) {
|
||||
printf("\x1b[10;10HCreating Hints...");
|
||||
CreateAllHints();
|
||||
@ -1106,13 +1112,6 @@ int Fill() {
|
||||
if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) {
|
||||
CreateMerchantsHints();
|
||||
}
|
||||
//Always execute ganon hint generation for the funny line
|
||||
CreateGanonText();
|
||||
CreateAltarText();
|
||||
CreateDampesDiaryText();
|
||||
CreateGregRupeeHint();
|
||||
CreateSheikText();
|
||||
CreateSariaText();
|
||||
CreateWarpSongTexts();
|
||||
return 1;
|
||||
}
|
||||
|
@ -48,22 +48,6 @@ void HintTable_Init() {
|
||||
| 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(
|
||||
{
|
||||
// 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",
|
||||
/*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({
|
||||
// obscure text
|
||||
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 " },
|
||||
});
|
||||
|
||||
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({
|
||||
// obscure text
|
||||
Text{ "your pocket", /*french*/ "tes poches", /*spanish*/ "tu bolsillo" },
|
||||
@ -3193,7 +3203,7 @@ int32_t TokensRequiredBySettings() {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
std::array<ConditionalAlwaysHint, 9> conditionalAlwaysHints = {
|
||||
std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints = {
|
||||
std::make_pair(RC_MARKET_10_BIG_POES,
|
||||
[]() {
|
||||
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_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }),
|
||||
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_40_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 40; }),
|
||||
std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 50; })
|
||||
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 && !Settings::Kak40GSHintText; }),
|
||||
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) {
|
||||
|
@ -275,6 +275,25 @@ static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCh
|
||||
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) {
|
||||
//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});
|
||||
@ -479,10 +498,6 @@ static void CreateRandomLocationHint(const bool goodItem = false) {
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateGoodItemHint() {
|
||||
CreateRandomLocationHint(true);
|
||||
}
|
||||
|
||||
static void CreateJunkHint() {
|
||||
//duplicate junk hints are possible for now
|
||||
const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk));
|
||||
@ -596,16 +611,20 @@ static void CreateTrialHints() {
|
||||
}
|
||||
}
|
||||
|
||||
void CreateGanonText() {
|
||||
void CreateGanonAndSheikText() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
//funny ganon line
|
||||
ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
|
||||
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
|
||||
|
||||
if(Settings::LightArrowHintText){
|
||||
//Get the location of the light arrows
|
||||
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
|
||||
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
|
||||
auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT);
|
||||
@ -613,24 +632,35 @@ void CreateGanonText() {
|
||||
ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText();
|
||||
lightArrowHintLoc = "Link's Pocket";
|
||||
} else {
|
||||
ganonHintText =
|
||||
hint.GetText() + "%r" +
|
||||
GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
|
||||
ganonHintText = hint.GetText() + "%r" + lightArrowArea;
|
||||
lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName();
|
||||
}
|
||||
ganonHintText = 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());
|
||||
|
||||
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
|
||||
static Text BuildDungeonRewardText(const RandomizerGet itemKey) {
|
||||
static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
|
||||
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) {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey;
|
||||
})[0];
|
||||
if (IsReachableWithout({altarLoc}, location, true) || ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)){ //RANDOTODO check if works properly
|
||||
ctx->GetItemLocation(location)->SetAsHinted();
|
||||
}
|
||||
|
||||
std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD);
|
||||
|
||||
@ -760,11 +790,11 @@ void CreateAltarText() {
|
||||
childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
|
||||
//Spiritual Stones
|
||||
(StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_KOKIRI_EMERALD)) +
|
||||
: BuildDungeonRewardText(RG_KOKIRI_EMERALD, true)) +
|
||||
(StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_GORON_RUBY)) +
|
||||
: BuildDungeonRewardText(RG_GORON_RUBY, true)) +
|
||||
(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
|
||||
BuildDoorOfTimeText();
|
||||
} else {
|
||||
@ -780,17 +810,17 @@ void CreateAltarText() {
|
||||
adultAltarText = adultAltarText +
|
||||
//Medallion Areas
|
||||
(StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_LIGHT_MEDALLION)) +
|
||||
: BuildDungeonRewardText(RG_LIGHT_MEDALLION, false)) +
|
||||
(StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FOREST_MEDALLION)) +
|
||||
: BuildDungeonRewardText(RG_FOREST_MEDALLION, false)) +
|
||||
(StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FIRE_MEDALLION)) +
|
||||
: BuildDungeonRewardText(RG_FIRE_MEDALLION, false)) +
|
||||
(StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_WATER_MEDALLION)) +
|
||||
: BuildDungeonRewardText(RG_WATER_MEDALLION, false)) +
|
||||
(StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION)) +
|
||||
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION, false)) +
|
||||
(StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SHADOW_MEDALLION));
|
||||
: BuildDungeonRewardText(RG_SHADOW_MEDALLION, false));
|
||||
}
|
||||
adultAltarText = adultAltarText +
|
||||
//Bridge requirement
|
||||
@ -846,6 +876,10 @@ void CreateDampesDiaryText() {
|
||||
RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item;
|
||||
})[0];
|
||||
if (IsReachableWithout({RC_DAMPE_HINT},location,true)){
|
||||
ctx->GetItemLocation(location)->SetAsHinted();
|
||||
}
|
||||
|
||||
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
|
||||
Text temp1 = Text{
|
||||
"Whoever reads this, please enter %r",
|
||||
@ -875,6 +909,9 @@ void CreateGregRupeeHint() {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE;
|
||||
})[0];
|
||||
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
|
||||
if (IsReachableWithout({RC_GREG_HINT},location,true)){
|
||||
ctx->GetItemLocation(location)->SetAsHinted();
|
||||
}
|
||||
|
||||
Text temp1 = Text{
|
||||
"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);
|
||||
}
|
||||
|
||||
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() {
|
||||
if(Settings::SariaHintText){
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
//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;});
|
||||
sariaHintLoc = Rando::StaticData::GetLocation(magicLocation[0])->GetName();
|
||||
Text area = GetHintRegion(ctx->GetItemLocation(magicLocation[0])->GetParentRegionKey())->GetHint().GetText();
|
||||
auto magicLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_PROGRESSIVE_MAGIC_METER;})[0];
|
||||
sariaHintLoc = Rando::StaticData::GetLocation(magicLocation)->GetName();
|
||||
Text area = GetHintRegion(ctx->GetItemLocation(magicLocation)->GetParentRegionKey())->GetHint().GetText();
|
||||
Text temp1 = Text{
|
||||
"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",
|
||||
@ -924,6 +948,11 @@ void CreateSariaText() {
|
||||
"%w.$C"
|
||||
};
|
||||
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 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
|
||||
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
|
||||
@ -990,14 +1042,14 @@ void CreateAllHints() {
|
||||
auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
|
||||
return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) ||
|
||||
// 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)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
|
||||
});
|
||||
|
||||
for (auto& hint : conditionalAlwaysHints) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1106,7 +1158,7 @@ void CreateAllHints() {
|
||||
CreateRandomLocationHint();
|
||||
|
||||
} else if (type == HINT_TYPE_ITEM) {
|
||||
CreateGoodItemHint();
|
||||
CreateRandomLocationHint(true);
|
||||
|
||||
} else if (type == HINT_TYPE_SONG) {
|
||||
std::vector<RandomizerCheck> songHintLocations =
|
||||
|
@ -114,7 +114,7 @@ public:
|
||||
|
||||
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};
|
||||
}
|
||||
} //RANDOTODO Concert to generic special hints?
|
||||
|
||||
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};
|
||||
@ -198,7 +198,7 @@ using ConditionalAlwaysHint = std::pair<RandomizerCheck, std::function<bool()>>;
|
||||
//10 dungeons as GTG and GC are excluded
|
||||
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 void CreateAllHints();
|
||||
@ -206,9 +206,8 @@ extern void CreateMerchantsHints();
|
||||
extern void CreateWarpSongTexts();
|
||||
extern void CreateDampesDiaryText();
|
||||
extern void CreateGregRupeeHint();
|
||||
extern void CreateSheikText();
|
||||
extern void CreateSariaText();
|
||||
extern void CreateGanonText();
|
||||
extern void CreateGanonAndSheikText();
|
||||
extern void CreateAltarText();
|
||||
|
||||
Text& GetChildAltarText();
|
||||
|
@ -260,6 +260,7 @@ void AreaTable_Init() {
|
||||
//Locations
|
||||
LocationAccess(RC_LINKS_POCKET, {[]{return true;}}),
|
||||
LocationAccess(RC_TRIFORCE_COMPLETED, {[]{return CanCompleteTriforce;}}),
|
||||
LocationAccess(RC_SARIA_SONG_HINT, {[]{return CanPlay(SariasSong);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_ROOT_EXITS, {[]{return true;}})
|
||||
|
@ -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, {}, {
|
||||
//Locations
|
||||
LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
|
||||
LocationAccess(RC_ALTAR_HINT_CHILD, {[]{return IsChild;}}),
|
||||
LocationAccess(RC_ALTAR_HINT_ADULT, {[]{return IsAdult;}}),
|
||||
}, {
|
||||
//Exits
|
||||
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, {}, {
|
||||
//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_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);}}),
|
||||
|
@ -22,7 +22,10 @@ void AreaTable_Init_GanonsCastle() {
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
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
|
||||
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(RR_GANONS_CASTLE_FOREST_TRIAL, {[]{return true;}}),
|
||||
@ -121,7 +124,10 @@ void AreaTable_Init_GanonsCastle() {
|
||||
| MASTER QUEST DUNGEON |
|
||||
---------------------------*/
|
||||
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
|
||||
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return (IsAdult || (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword))));}}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL, {[]{return true;}}),
|
||||
|
@ -267,7 +267,10 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
|
||||
});
|
||||
|
@ -858,6 +858,8 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
||||
extern Option HintDistribution;
|
||||
extern Option AltarHintText;
|
||||
extern Option LightArrowHintText;
|
||||
extern Option SariaHintText;
|
||||
extern Option FrogsHintText;
|
||||
extern Option DampeHintText;
|
||||
extern Option GregHintText;
|
||||
extern Option Kak10GSHintText;
|
||||
|
@ -689,12 +689,15 @@ static void WriteHints(int language) {
|
||||
unformattedGregText = GetGregHintText().GetEnglish();
|
||||
unformattedSheikText = GetSheikHintText().GetEnglish();
|
||||
unformattedSariaText = GetSariaHintText().GetEnglish();
|
||||
|
||||
if (Settings::ShuffleWarpSongs){
|
||||
jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish();
|
||||
jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish();
|
||||
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish();
|
||||
jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish();
|
||||
jsonData["warpNocturneText"] = GetWarpNocturneText().GetEnglish();
|
||||
jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish();
|
||||
}
|
||||
jsonData["childAltar"]["hintText"] = GetChildAltarText().GetEnglish();
|
||||
jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetEnglish();
|
||||
break;
|
||||
@ -705,12 +708,15 @@ static void WriteHints(int language) {
|
||||
unformattedGregText = GetGregHintText().GetFrench();
|
||||
unformattedSheikText = GetSheikHintText().GetFrench();
|
||||
unformattedSariaText = GetSariaHintText().GetFrench();
|
||||
|
||||
if (Settings::ShuffleWarpSongs){
|
||||
jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench();
|
||||
jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench();
|
||||
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench();
|
||||
jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench();
|
||||
jsonData["warpNocturneText"] = GetWarpNocturneText().GetFrench();
|
||||
jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench();
|
||||
}
|
||||
jsonData["childAltar"]["hintText"] = GetChildAltarText().GetFrench();
|
||||
jsonData["adultAltar"]["hintText"] = GetAdultAltarText().GetFrench();
|
||||
break;
|
||||
@ -756,16 +762,25 @@ static void WriteHints(int language) {
|
||||
std::string sariaText = AutoFormatHintTextString(unformattedSariaText);
|
||||
|
||||
jsonData["ganonText"] = ganonText;
|
||||
if (Settings::LightArrowHintText){
|
||||
jsonData["ganonHintText"] = ganonHintText;
|
||||
jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc();
|
||||
if (!Settings::GanonsTrialsCount.Is(0)){
|
||||
jsonData["sheikText"] = sheikText;
|
||||
}
|
||||
}
|
||||
if (Settings::DampeHintText){
|
||||
jsonData["dampeText"] = dampesText;
|
||||
jsonData["dampeHintLoc"] = GetDampeHintLoc();
|
||||
}
|
||||
if (Settings::GregHintText){
|
||||
jsonData["gregText"] = gregText;
|
||||
jsonData["gregLoc"] =
|
||||
Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName();
|
||||
jsonData["sheikText"] = sheikText;
|
||||
jsonData["gregLoc"] = Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName();
|
||||
}
|
||||
if (Settings::SariaHintText){
|
||||
jsonData["sariaText"] = sariaText;
|
||||
jsonData["sariaHintLoc"] = GetSariaHintLoc();
|
||||
}
|
||||
|
||||
if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) {
|
||||
return;
|
||||
|
@ -144,7 +144,9 @@ void Context::LocationReset() {
|
||||
GetItemLocation(il)->RemoveFromPool();
|
||||
}
|
||||
|
||||
GetItemLocation(RC_GANONDORF_HINT)->RemoveFromPool();
|
||||
for (RandomizerCheck il : Rando::StaticData::otherHintLocations) {
|
||||
GetItemLocation(il)->RemoveFromPool();
|
||||
}
|
||||
}
|
||||
|
||||
void Context::HintReset() {
|
||||
|
@ -235,11 +235,11 @@ Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest
|
||||
|
||||
Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_,
|
||||
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::vector<Category>&& categories, bool isVanillaCompletion_) {
|
||||
return Location(rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, actorParams_, flag_,
|
||||
std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, std::move(categories), isVanillaCompletion_);
|
||||
bool isVanillaCompletion_) {
|
||||
return Location(rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, 0x00, 0x00,
|
||||
std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, {}, isVanillaCompletion_);
|
||||
}
|
||||
|
||||
Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
|
||||
|
@ -253,9 +253,8 @@ class Location {
|
||||
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP, bool isVanillaCompletion_ = false);
|
||||
|
||||
static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
|
||||
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_,
|
||||
uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
|
||||
std::vector<Category>&& categories, bool isVanillaCompletion_ = false);
|
||||
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene,
|
||||
std::string&& shortName_, std::string&& spoilerName_, bool isVanillaCompletion_ = false);
|
||||
|
||||
static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene,
|
||||
int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
|
||||
|
@ -507,6 +507,17 @@ std::vector<RandomizerCheck> Rando::StaticData::gossipStoneLocations = {
|
||||
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 {
|
||||
DUNGEON_DEKU_TREE = 0,
|
||||
DUNGEON_DODONGOS_CAVERN,
|
||||
@ -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", {});
|
||||
|
||||
// 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);
|
||||
// clang-format on
|
||||
}
|
||||
|
@ -474,11 +474,15 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
);
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::randoMiscHintsTableID, TEXT_DAMPES_DIARY,
|
||||
CustomMessage(gSaveContext.dampeText, gSaveContext.dampeText, gSaveContext.dampeText)
|
||||
CustomMessage(gSaveContext.dampeText,
|
||||
gSaveContext.dampeText,
|
||||
gSaveContext.dampeText)
|
||||
);
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED,
|
||||
CustomMessage(gSaveContext.gregHintText, gSaveContext.gregHintText, gSaveContext.gregHintText)
|
||||
CustomMessage(gSaveContext.gregHintText,
|
||||
gSaveContext.gregHintText,
|
||||
gSaveContext.gregHintText)
|
||||
);
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER,
|
||||
@ -491,7 +495,6 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
CustomMessage("{{message}}", "{{message}}", "{{message}}", TEXTBOX_TYPE_BLUE)
|
||||
);
|
||||
|
||||
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT,
|
||||
CustomMessage("Warp to&{{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 += 0x02;
|
||||
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) {
|
||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
||||
if (!spoilerFileStream)
|
||||
return;
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Have all these use strncpy so that the null terminator is copied
|
||||
// and also set the last index to null for safety
|
||||
try {
|
||||
@ -1324,64 +1345,28 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
||||
gSaveContext.rewardCheck[7] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"]];
|
||||
gSaveContext.rewardCheck[8] = SpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"]];
|
||||
|
||||
std::string ganonHintJsonText = spoilerFileJson["ganonHintText"].get<std::string>();
|
||||
std::string formattedGanonHintJsonText = FormatJsonHintText(ganonHintJsonText);
|
||||
strncpy(gSaveContext.ganonHintText, formattedGanonHintJsonText.c_str(), sizeof(gSaveContext.ganonHintText) - 1);
|
||||
gSaveContext.ganonHintText[sizeof(gSaveContext.ganonHintText) - 1] = 0;
|
||||
gSaveContext.lightArrowHintCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"]];
|
||||
ParseSpoilerHintText(spoilerFileJson, "ganonHintText", gSaveContext.ganonHintText, true, sizeof(gSaveContext.ganonHintText));
|
||||
CheckNameToEnum(spoilerFileJson, "lightArrowHintLoc", &gSaveContext.lightArrowHintCheck);
|
||||
ParseSpoilerHintText(spoilerFileJson, "ganonText", gSaveContext.ganonText, true, sizeof(gSaveContext.ganonText));
|
||||
|
||||
std::string ganonJsonText = spoilerFileJson["ganonText"].get<std::string>();
|
||||
std::string formattedGanonJsonText = FormatJsonHintText(ganonJsonText);
|
||||
strncpy(gSaveContext.ganonText, formattedGanonJsonText.c_str(), sizeof(gSaveContext.ganonText) - 1);
|
||||
gSaveContext.ganonText[sizeof(gSaveContext.ganonText) - 1] = 0;
|
||||
ParseSpoilerHintText(spoilerFileJson, "dampeText", gSaveContext.dampeText, true, sizeof(gSaveContext.dampeText));
|
||||
CheckNameToEnum(spoilerFileJson, "dampeHintLoc", &gSaveContext.dampeCheck);
|
||||
|
||||
std::string dampeJsonText = spoilerFileJson["dampeText"].get<std::string>();
|
||||
std::string formattedDampeJsonText = FormatJsonHintText(dampeJsonText);
|
||||
strncpy(gSaveContext.dampeText, formattedDampeJsonText.c_str(), sizeof(gSaveContext.dampeText) - 1);
|
||||
gSaveContext.dampeText[sizeof(gSaveContext.dampeText) - 1] = 0;
|
||||
gSaveContext.dampeCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"]];
|
||||
ParseSpoilerHintText(spoilerFileJson, "gregText", gSaveContext.gregHintText, true, sizeof(gSaveContext.gregHintText));
|
||||
CheckNameToEnum(spoilerFileJson, "gregLoc", &gSaveContext.gregCheck);
|
||||
|
||||
std::string gregJsonText = spoilerFileJson["gregText"].get<std::string>();
|
||||
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"]];
|
||||
ParseSpoilerHintText(spoilerFileJson, "sheikText", gSaveContext.sheikText, true, sizeof(gSaveContext.sheikText));
|
||||
|
||||
std::string sheikJsonText = spoilerFileJson["sheikText"].get<std::string>();
|
||||
std::string formattedSheikJsonText = FormatJsonHintText(sheikJsonText);
|
||||
strncpy(gSaveContext.sheikText, formattedSheikJsonText.c_str(), sizeof(gSaveContext.sheikText) - 1);
|
||||
gSaveContext.sheikText[sizeof(gSaveContext.sheikText) - 1] = 0;
|
||||
gSaveContext.lightArrowHintCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"]];
|
||||
ParseSpoilerHintText(spoilerFileJson, "sariaText", gSaveContext.sariaText, true, sizeof(gSaveContext.sariaText));
|
||||
CheckNameToEnum(spoilerFileJson, "sariaHintLoc", &gSaveContext.sariaCheck);
|
||||
|
||||
std::string sariaJsonText = spoilerFileJson["sariaText"].get<std::string>();
|
||||
std::string formattedSariaJsonText = FormatJsonHintText(sariaJsonText);
|
||||
strncpy(gSaveContext.sariaText, formattedSariaJsonText.c_str(), sizeof(gSaveContext.sariaText) - 1);
|
||||
gSaveContext.sariaText[sizeof(gSaveContext.sariaText) - 1] = 0;
|
||||
gSaveContext.sariaCheck = SpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"]];
|
||||
ParseSpoilerHintText(spoilerFileJson, "warpMinuetText", gSaveContext.warpMinuetText, false, sizeof(gSaveContext.warpMinuetText));
|
||||
ParseSpoilerHintText(spoilerFileJson, "warpBoleroText", gSaveContext.warpBoleroText, false, sizeof(gSaveContext.warpBoleroText));
|
||||
ParseSpoilerHintText(spoilerFileJson, "warpSerenadeText", gSaveContext.warpSerenadeText, false, sizeof(gSaveContext.warpSerenadeText));
|
||||
ParseSpoilerHintText(spoilerFileJson, "warpRequiemText", gSaveContext.warpRequiemText, false, sizeof(gSaveContext.warpRequiemText));
|
||||
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"];
|
||||
int index = 0;
|
||||
@ -1416,7 +1401,6 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
||||
index++;
|
||||
}
|
||||
|
||||
success = true;
|
||||
} catch (const std::exception& e) {
|
||||
return;
|
||||
}
|
||||
|
@ -1348,7 +1348,14 @@ typedef enum {
|
||||
RC_ZR_NEAR_GROTTOS_GOSSIP_STONE,
|
||||
RC_ZR_OPEN_GROTTO_GOSSIP_STONE,
|
||||
RC_GANONDORF_HINT,
|
||||
RC_SHEIK_HINT_GC,
|
||||
RC_SHEIK_HINT_MQ_GC,
|
||||
RC_TRIFORCE_COMPLETED,
|
||||
RC_DAMPE_HINT,
|
||||
RC_GREG_HINT,
|
||||
RC_SARIA_SONG_HINT,
|
||||
RC_ALTAR_HINT_CHILD,
|
||||
RC_ALTAR_HINT_ADULT,
|
||||
RC_MAX
|
||||
} RandomizerCheck;
|
||||
|
||||
@ -3172,6 +3179,7 @@ typedef enum {
|
||||
RHT_VALIDATION_LINE,
|
||||
// Light Arrow Location
|
||||
RHT_LIGHT_ARROW_LOCATION_HINT,
|
||||
RHT_SHEIK_LIGHT_ARROW_HINT,
|
||||
// Your Pocket
|
||||
RHT_YOUR_POCKET,
|
||||
// Ganon Line
|
||||
|
@ -31,6 +31,7 @@ class StaticData {
|
||||
static std::vector<std::vector<RandomizerCheck>> shopLocationLists;
|
||||
static std::vector<RandomizerCheck> scrubLocations;
|
||||
static std::vector<RandomizerCheck> gossipStoneLocations;
|
||||
static std::vector<RandomizerCheck> otherHintLocations;
|
||||
StaticData();
|
||||
~StaticData();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user