mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-23 01:42:19 -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();
|
||||
|
@ -259,7 +259,8 @@ void AreaTable_Init() {
|
||||
areaTable[RR_ROOT] = Area("Root", "", RHT_LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
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
|
||||
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,
|
||||
@ -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
|
||||
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_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);
|
||||
@ -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