mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-07 02:40:30 -05:00
Streamline hint generation (#3401)
* reimplement 3drando's hashtag color replacement system. Also generates merchant text at seed gen time instead of runtime. By merchants, I mean Bean Salesman, Medigoron, Granny, and Wasteland Bombchu guy. Scrubs and shops are still dynamic at runtime. * Improved auto-formatting and fixed altar text. * Gets hint text for spoiler direct from context. * Removal of now unused code. * Change warp song hint generation/retrieval Generates full warp location text instead of just location names and stores all six in the custom message tables for later retrieval as opposed to dynamically swapping in the location names every time the text is rendered. * Change Frog Ocarina Game Hint generation/retrieval Similar to previous changes, removes the on-the-fly generation aspect of it and just generates the full hint text once during seed generation. * Update soh/soh/Enhancements/randomizer/3drando/text.hpp Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> * Fix submodules appearing as changed files. * Fix WOTH/Foolish colors to match develop-macready. * Fixes backwards colors for area and item in some hints. --------- Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com>
This commit is contained in:
parent
467ee7ad12
commit
a196dd6b7e
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -6,4 +6,4 @@
|
||||
url = https://github.com/harbourmasters/ZAPDTR
|
||||
[submodule "OTRExporter"]
|
||||
path = OTRExporter
|
||||
url = https://github.com/harbourmasters/OTRExporter/
|
||||
url = https://github.com/harbourmasters/OTRExporter
|
||||
|
@ -17,6 +17,24 @@ static const std::unordered_map<std::string, char> textBoxSpecialCharacters = {
|
||||
static const std::unordered_map<std::string, char> colors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN },
|
||||
{ "b", QM_BLUE }, { "c", QM_LBLUE }, { "p", QM_PINK },
|
||||
{ "y", QM_YELLOW }, { "B", QM_BLACK } };
|
||||
static const std::unordered_map<std::string, ItemID> altarIcons = {
|
||||
{ "0", ITEM_KOKIRI_EMERALD },
|
||||
{ "1", ITEM_GORON_RUBY },
|
||||
{ "2", ITEM_ZORA_SAPPHIRE },
|
||||
{ "8", ITEM_MEDALLION_LIGHT },
|
||||
{ "3", ITEM_MEDALLION_FOREST },
|
||||
{ "4", ITEM_MEDALLION_FIRE },
|
||||
{ "5", ITEM_MEDALLION_WATER },
|
||||
{ "6", ITEM_MEDALLION_SPIRIT },
|
||||
{ "7", ITEM_MEDALLION_SHADOW },
|
||||
{ "l", ITEM_ARROW_LIGHT },
|
||||
{ "b", ITEM_KEY_BOSS },
|
||||
{ "o", ITEM_SWORD_MASTER },
|
||||
{ "c", ITEM_OCARINA_FAIRY },
|
||||
{ "i", ITEM_OCARINA_TIME },
|
||||
{ "L", ITEM_BOW_ARROW_LIGHT },
|
||||
{ "k", ITEM_TUNIC_KOKIRI }
|
||||
};
|
||||
|
||||
CustomMessage::CustomMessage(std::string english_, std::string german_, std::string french_, TextBoxType type_,
|
||||
TextBoxPosition position_)
|
||||
@ -116,6 +134,7 @@ void CustomMessage::Format(ItemID iid) {
|
||||
}
|
||||
ReplaceSpecialCharacters();
|
||||
ReplaceColors();
|
||||
ReplaceAltarIcons();
|
||||
*this += MESSAGE_END();
|
||||
}
|
||||
|
||||
@ -127,6 +146,7 @@ void CustomMessage::Format() {
|
||||
}
|
||||
ReplaceSpecialCharacters();
|
||||
ReplaceColors();
|
||||
ReplaceAltarIcons();
|
||||
*this += MESSAGE_END();
|
||||
}
|
||||
|
||||
@ -171,7 +191,7 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) {
|
||||
|
||||
void CustomMessage::ReplaceColors() {
|
||||
for (std::string* str : { &english, &french, &german }) {
|
||||
for (auto colorPair : colors) {
|
||||
for (const auto& colorPair : colors) {
|
||||
std::string textToReplace = "%";
|
||||
textToReplace += colorPair.first;
|
||||
size_t start_pos = 0;
|
||||
@ -183,27 +203,41 @@ void CustomMessage::ReplaceColors() {
|
||||
}
|
||||
}
|
||||
|
||||
const std::string CustomMessage::MESSAGE_END() const {
|
||||
void CustomMessage::ReplaceAltarIcons() {
|
||||
for (std::string* str : { &english, &french, &german }) {
|
||||
for (const auto& iconPair : altarIcons) {
|
||||
std::string textToReplace = "$";
|
||||
textToReplace += iconPair.first;
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str->find(textToReplace, start_pos)) != std::string::npos) {
|
||||
str->replace(start_pos, textToReplace.length(), ITEM_OBTAINED(iconPair.second));
|
||||
start_pos += textToReplace.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string CustomMessage::MESSAGE_END() {
|
||||
return "\x02"s;
|
||||
}
|
||||
|
||||
const std::string CustomMessage::ITEM_OBTAINED(uint8_t x) const {
|
||||
std::string CustomMessage::ITEM_OBTAINED(uint8_t x) {
|
||||
return "\x13"s + char(x);
|
||||
}
|
||||
|
||||
const std::string CustomMessage::NEWLINE() const {
|
||||
std::string CustomMessage::NEWLINE() {
|
||||
return "\x01"s;
|
||||
}
|
||||
|
||||
const std::string CustomMessage::COLOR(uint8_t x) const {
|
||||
std::string CustomMessage::COLOR(uint8_t x) {
|
||||
return "\x05"s + char(x);
|
||||
}
|
||||
|
||||
const std::string CustomMessage::WAIT_FOR_INPUT() const {
|
||||
std::string CustomMessage::WAIT_FOR_INPUT() {
|
||||
return "\x04"s;
|
||||
}
|
||||
|
||||
const std::string CustomMessage::PLAYER_NAME() const {
|
||||
std::string CustomMessage::PLAYER_NAME() {
|
||||
return "\x0F"s;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,13 @@ class CustomMessage {
|
||||
CustomMessage(std::string english_, std::string german_, std::string french_,
|
||||
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
|
||||
|
||||
static std::string MESSAGE_END() ;
|
||||
static std::string ITEM_OBTAINED(uint8_t x) ;
|
||||
static std::string NEWLINE() ;
|
||||
static std::string COLOR(uint8_t x) ;
|
||||
static std::string WAIT_FOR_INPUT() ;
|
||||
static std::string PLAYER_NAME() ;
|
||||
|
||||
const std::string& GetEnglish() const;
|
||||
const std::string& GetFrench() const;
|
||||
const std::string& GetGerman() const;
|
||||
@ -80,6 +87,11 @@ class CustomMessage {
|
||||
*/
|
||||
void ReplaceColors();
|
||||
|
||||
/**
|
||||
* @brief Replaces `$<char>` variable strings with OoT control codes.
|
||||
*/
|
||||
void ReplaceAltarIcons();
|
||||
|
||||
/**
|
||||
* @brief Replaces various symbols with the control codes necessary to
|
||||
* display them in OoT's textboxes. i.e. special characters, colors, newlines,
|
||||
@ -97,13 +109,6 @@ class CustomMessage {
|
||||
void Format();
|
||||
|
||||
private:
|
||||
const std::string MESSAGE_END() const;
|
||||
const std::string ITEM_OBTAINED(uint8_t x) const;
|
||||
const std::string NEWLINE() const;
|
||||
const std::string COLOR(uint8_t x) const;
|
||||
const std::string WAIT_FOR_INPUT() const;
|
||||
const std::string PLAYER_NAME() const;
|
||||
|
||||
std::string english = "";
|
||||
std::string french = "";
|
||||
std::string german = "";
|
||||
|
@ -283,7 +283,7 @@ constexpr std::array DungeonColors = {
|
||||
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
|
||||
std::string CURRENT_TIME() { return "\x7F\x17"s; }
|
||||
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
|
||||
std::string TWO_WAY_CHOICE() { return "\x7F\x1A\xFF\xFF\xFF\xFF"s; }
|
||||
std::string TWO_WAY_CHOICE() { return "\x1B"s; }
|
||||
std::string NEWLINE() { return "\x7F\x1C"s; }
|
||||
std::string COLOR(uint8_t x) { return "\x7F\x1D"s + char(x); }
|
||||
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
|
||||
|
@ -31,12 +31,12 @@ void HintTable_Init() {
|
||||
hintTable[RHT_PREFIX] =
|
||||
HintText::Exclude({ Text{ "They say that ", /*french*/ "Selon moi, ", /*spanish*/ "Según dicen, " } });
|
||||
hintTable[RHT_WAY_OF_THE_HERO] =
|
||||
HintText::Exclude({ Text{ " is on %cthe way of the hero%w.", /*french*/ " est sur %cla voie du héros%w.",
|
||||
HintText::Exclude({ Text{ " is on #the way of the hero#.", /*french*/ " est sur #la voie du héros#.",
|
||||
/*spanish*/ " conduce a la senda del héroe." } });
|
||||
hintTable[RHT_PLUNDERING] =
|
||||
HintText::Exclude({ Text{ "plundering ", /*french*/ "explorer ", /*spanish*/ "inspeccionar " } });
|
||||
hintTable[RHT_FOOLISH] = HintText::Exclude(
|
||||
{ Text{ " is %pa foolish choice%w.", /*french*/ " est %pfutile%w.", /*spanish*/ " no es una sabia decisión." } });
|
||||
{ Text{ " is #a foolish choice#.", /*french*/ " est #futile#.", /*spanish*/ " #no es una sabia decisión#." } });
|
||||
hintTable[RHT_CAN_BE_FOUND_AT] =
|
||||
HintText::Exclude({ Text{ "can be found at", /*french*/ "se trouve dans", /*spanish*/ "aguarda en" } });
|
||||
hintTable[RHT_HOARDS] = HintText::Exclude({ Text{ "hoards", /*french*/ "recèle", /*spanish*/ "acapara" } });
|
||||
@ -2671,66 +2671,73 @@ void HintTable_Init() {
|
||||
|
||||
hintTable[RHT_BRIDGE_OPEN_HINT] = HintText::Bridge({
|
||||
// obscure text
|
||||
Text{ "The awakened ones have already&created a bridge to the castle&where the evil dwells.",
|
||||
/*french*/ "Les êtres de sagesse ont&déjà créé un pont vers&le repaire du mal.",
|
||||
/*spanish*/ "Los sabios #ya habrán creado un puente#&al castillo, de donde emana el mal." },
|
||||
Text{ "The awakened ones have #already created a bridge# to the castle where the evil dwells.",
|
||||
/*french*/ "Les êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.",
|
||||
/*spanish*/ "Los sabios #ya habrán creado un puente#&al castillo, de donde emana el mal.",
|
||||
/*german*/"Die Weisen haben #bereits&eine Brücke zum Portal von&Ganons Schloss gelegt#..." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_VANILLA_HINT] = HintText::Bridge({
|
||||
// obscure text
|
||||
Text{ "The awakened ones require&the Shadow and Spirit Medallions&as well as the Light Arrows.",
|
||||
Text{ "The awakened ones require the #Shadow and Spirit Medallions# as well as the #Light Arrows#.",
|
||||
/*french*/
|
||||
"Les êtres de sagesse attendront&le héros muni des %rMédaillons de&l'Ombre et l'Esprit%w et des&%yFlèches de Lumière%w.",
|
||||
"Les êtres de sagesse attendront le héros muni des #Médaillons de l'Ombre et l'Esprit# et des #Flèches de Lumière#.",
|
||||
/*spanish*/
|
||||
"Los sabios aguardarán a que el héroe&obtenga tanto el #Medallón de las&Sombras y el del Espíritu# junto "
|
||||
"a la #flecha de luz#." },
|
||||
"Los sabios aguardarán a que el héroe obtenga tanto el #Medallón de las Sombras y el del Espíritu# junto "
|
||||
"a la #flecha de luz#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held das #Amulett des Schattens, Amulett der Geister# und die #Licht-Pfeile# sammelt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_STONES_HINT] = HintText::Bridge({
|
||||
// obscure text singular plural
|
||||
Text{
|
||||
"The awakened ones will&await for the Hero to collect&%d |Spiritual Stone|Spiritual Stones|.",
|
||||
/*french*/ "Les êtres de sagesse attendront&le héros muni de %r%d |Pierre&Ancestrale|Pierres&Ancestrales|%w.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |piedra espiritual|piedras espirituales|#." },
|
||||
"The awakened ones will await for the Hero to collect #%d |Spiritual Stone|Spiritual Stones|#.",
|
||||
/*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Pierre Ancestrale|Pierres Ancestrales|#.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |piedra espiritual|piedras espirituales|#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held #%d |Heiligen Stein|Heilige Steine|# sammelt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_MEDALLIONS_HINT] = HintText::Bridge({
|
||||
// obscure text singular plural
|
||||
Text{ "The awakened ones will await&for the Hero to collect&%d |Medallion|Medallions|.",
|
||||
/*french*/ "Les êtres de sagesse attendront&le héros muni de %r#%d |Médaillon|Médaillons|%w.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |medallón|medallones|#." },
|
||||
Text{ "The awakened ones will await for the Hero to collect #%d |Medallion|Medallions|#.",
|
||||
/*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Médaillon|Médaillons|#.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |medallón|medallones|#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held #%d |Amulett|Amulette|# sammelt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_REWARDS_HINT] = HintText::Bridge({
|
||||
// obscure text singular plural
|
||||
Text{ "The awakened ones will await&for the Hero to collect&%d |Spiritual Stone or Medallion|Spiritual Stones "
|
||||
"and Medallions|.",
|
||||
Text{ "The awakened ones will await for the Hero to collect #%d |Spiritual Stone or Medallion|Spiritual Stones "
|
||||
"and Medallions|#.",
|
||||
/*french*/
|
||||
"Les êtres de sagesse attendront&le héros muni de %r%d |Pierre&Ancestrale ou Médaillon|Pierres&Ancestrales ou Médaillons|%w.",
|
||||
"Les êtres de sagesse attendront le héros muni de #%d |Pierre Ancestrale ou Médaillon|Pierres Ancestrales ou Médaillons|#.",
|
||||
/*spanish*/
|
||||
"Los sabios aguardarán a que el héroe&obtenga #%d |piedra espiritual o medallón|piedras espirtuales y "
|
||||
"medallones|#." },
|
||||
"Los sabios aguardarán a que el héroe obtenga #%d |piedra espiritual o medallón|piedras espirtuales y "
|
||||
"medallones|#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held #%d |Heiligen Stein oder Amulett|Heilige Steine oder Amulette|# sammelt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_DUNGEONS_HINT] = HintText::Bridge({
|
||||
// obscure text singular plural
|
||||
Text{ "The awakened ones will await&for the Hero to conquer&%d |Dungeon|Dungeons|.",
|
||||
/*french*/ "Les êtres de sagesse attendront&la conquête de %r%d |Donjon|Donjons|%w.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe& complete #%d |mazmorra|mazmorras|#." },
|
||||
Text{ "The awakened ones will await for the Hero to conquer #%d |Dungeon|Dungeons|#.",
|
||||
/*french*/ "Les êtres de sagesse attendront la conquête de #%d |Donjon|Donjons|#.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe complete #%d |mazmorra|mazmorras|#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held #%d |Labyrinth|Labyrinthe|# abschließt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_TOKENS_HINT] = HintText::Bridge({
|
||||
// obscure text
|
||||
Text{ "The awakened ones will await&for the Hero to collect&%d |Gold Skulltula Token|Gold Skulltula Tokens|.",
|
||||
/*french*/ "Les êtres de sagesse attendront&le héros muni de %r%d |Symbole|Symboles| &de Skulltula d'or%w.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe&obtenga #%d |símbolo|símbolos| de&skulltula dorada#." },
|
||||
Text{ "The awakened ones will await for the Hero to collect #%d |Gold Skulltula Token|Gold Skulltula Tokens|#.",
|
||||
/*french*/ "Les êtres de sagesse attendront le héros muni de #%d |Symbole|Symboles| de Skulltula d'or#.",
|
||||
/*spanish*/ "Los sabios aguardarán a que el héroe obtenga #%d |símbolo|símbolos| de skulltula dorada#.",
|
||||
/*german*/"Die Weisen werden darauf warten, dass der Held #%d |Skulltula-Symbol|Skulltula-Symbole|# sammelt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_BRIDGE_GREG_HINT] = HintText::Bridge({
|
||||
// obscure text
|
||||
Text{ "The awakened ones will await&for the Hero to find %gGreg%w.",
|
||||
/*french*/ "The awakened ones will await&for the Hero to find %gGreg%w.",
|
||||
/*spanish*/ "The awakened ones will await&for the Hero to find %gGreg%w." },
|
||||
Text{ "The awakened ones will await for the Hero to find %gGreg%w.",
|
||||
/*french*/ "The awakened ones will await for the Hero to find %gGreg%w.",
|
||||
/*spanish*/ "The awakened ones will await for the Hero to find %gGreg%w." },
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
@ -2739,57 +2746,64 @@ void HintTable_Init() {
|
||||
|
||||
hintTable[RHT_GANON_BK_START_WITH_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be given %rfrom the start%w.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&possession %rmême du héros%w.",
|
||||
/*spanish*/ "Y obtendrás la llave del #señor del mal# desde el #inicio#." },
|
||||
Text{ "And the #evil one#'s key will be #given from the start#.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera #possession même du héros#.",
|
||||
/*spanish*/ "Y obtendrás la llave del #señor del mal# desde el #inicio#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird #von Anfang an, im Besitz des Helden# sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_VANILLA_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be kept in a big chest&%rinside its tower%w.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&encoffrée %rdans sa tour%w.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en un gran cofre de #su torre#." },
|
||||
Text{ "And the #evil one#'s key will be kept in a big chest #inside its tower#.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera encoffrée #dans sa tour#.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en un gran cofre de #su torre#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird in der großen Truhe #im Teufelsturm# zu finden sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_OWN_DUNGEON_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be hidden somewhere %rinside&its castle%w.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&cachée %rdans son vaste château%w.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en #algún lugar de su castillo#." },
|
||||
Text{ "And the #evil one#'s key will be hidden somewhere #inside its castle#.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera cachée #dans son vaste château#.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en #algún lugar de su castillo#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Ganons Schloss# zu finden sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_OVERWORLD_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be hidden %routside of&dungeons%w in Hyrule.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w se&trouve %rhors des donjons%w d'Hyrule.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará #fuera de las mazmorras# de Hyrule." },
|
||||
Text{ "And the #evil one#'s key will be hidden #outside of dungeons# in Hyrule.",
|
||||
/*french*/ "Aussi, la #clé du Malin# se trouve #hors des donjons# d'Hyrule.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará #fuera de las mazmorras# de Hyrule.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, außerhalb von Labyrinthen# zu finden sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_ANY_DUNGEON_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be hidden %rinside a&dungeon%w in Hyrule.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w se&trouve %rdans un donjon%w d'Hyrule.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará #en una mazmorra# de Hyrule." },
|
||||
Text{ "And the #evil one#'s key will be hidden #inside a dungeon# in Hyrule.",
|
||||
/*french*/ "Aussi, la #clé du Malin# se trouve #dans un donjon# d'Hyrule.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará #en una mazmorra# de Hyrule.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule, innerhalb eines Labyrinths# zu finden sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_ANYWHERE_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be hidden somewhere&%rin Hyrule%w.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w se&trouve quelque part %rdans Hyrule%w.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en #cualquier lugar de Hyrule#." },
|
||||
Text{ "And the #evil one#'s key will be hidden somewhere&#in Hyrule#.",
|
||||
/*french*/ "Aussi, la #clé du Malin# se trouve quelque part #dans Hyrule#.",
|
||||
/*spanish*/ "Y la llave del #señor del mal# aguardará en #cualquier lugar de Hyrule#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen#, wird irgendwo #in Hyrule# zu finden sein." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_TRIFORCE_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text{ "And the %revil one%w's key will&be given to the Hero once&the %rTriforce%w is completed.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w se&révèlera une fois la %rTriforce%w&assemblée.",
|
||||
/*spanish*/ "Y el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#." },
|
||||
Text{ "And the #evil one#'s key will be given to the Hero once the #Triforce## is completed.",
|
||||
/*french*/ "Aussi, la #clé du Malin# se&révèlera une fois la #Triforce#&assemblée.",
|
||||
/*spanish*/ "Y el héroe recibirá la llave del #señor del mal# cuando haya completado la #Trifuerza#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird verliehen, sobald das #Triforce# vervollständigt wurde." },
|
||||
});
|
||||
|
||||
hintTable[RHT_GANON_BK_SKULLTULA_HINT] = HintText::GanonsBossKey({
|
||||
// obscure text
|
||||
Text { "And the %revil one%w's key will be&provided by the cursed rich man&once %r100 Gold Skulltula Tokens%w&are retrieved.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&donnée par l'homme maudit une&fois que %r100 Symboles de&Skulltula d'or%w auront été trouvés.",
|
||||
Text { "And the #evil one#'s key will be provided by the cursed rich man once #100 Gold Skulltula Tokens# are retrieved.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera&donnée par l'homme maudit une fois que #100 Symboles de Skulltula d'or# auront été trouvés.",
|
||||
/*spanish*/ "Y el rico maldito entregará la llave&del #señor de mal# tras obtener&100 símbolos de skulltula dorada#."},
|
||||
});
|
||||
|
||||
@ -2800,57 +2814,63 @@ void HintTable_Init() {
|
||||
hintTable[RHT_LACS_VANILLA_HINT] = HintText::LACS({
|
||||
// obscure text
|
||||
Text{
|
||||
"And the %revil one%w's key will be&provided by Zelda once the&%rShadow and Spirit Medallions%w&are retrieved.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois que &les %rMédaillons de l'Ombre et de&l'Esprit%w seront récupérés.",
|
||||
"And the #evil one#'s key will be provided by Zelda once the #Shadow and Spirit Medallions# are retrieved.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois que les #Médaillons de l'Ombre et de l'Esprit# seront récupérés.",
|
||||
/*spanish*/
|
||||
"Y Zelda entregará la llave&del #señor del mal# tras obtener&#el medallón de las sombras y del "
|
||||
"espíritu#." },
|
||||
"Y Zelda entregará la llave del #señor del mal# tras obtener #el medallón de las sombras y del "
|
||||
"espíritu#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #die Amulette des Schattens und der Geister# geborgen wurden." },
|
||||
});
|
||||
|
||||
hintTable[RHT_LACS_MEDALLIONS_HINT] = HintText::LACS({
|
||||
// obscure text singular plural
|
||||
Text{ "And the %revil one%w's key will be&provided by Zelda once %r%d&|Medallion%w is|Medallions%w are| retrieved.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois |qu'&%r%d Médaillon%w aura été&récupéré|que&%r%d Médaillons%w auront été&récupérés|.",
|
||||
/*spanish*/ "Y Zelda entregará la llave&del #señor del mal# tras obtener&#%d |medallón|medallones|#." },
|
||||
Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Medallion# is|Medallions# are| retrieved.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Médaillon# aura été récupéré|que #%d Médaillons# auront été récupérés|.",
|
||||
/*spanish*/ "Y Zelda entregará la llave&del #señor del mal# tras obtener #%d |medallón|medallones|#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Amulett# geborgen wurde|Amulette# geborgen wurden|." },
|
||||
});
|
||||
|
||||
hintTable[RHT_LACS_STONES_HINT] = HintText::LACS({
|
||||
// obscure text singular plural
|
||||
Text{
|
||||
"And the %revil one%w's key will be&provided by Zelda once %r%d&|Spiritual Stone%w is|Spiritual Stones%w are| "
|
||||
"And the #evil one#'s key will be provided by Zelda once #%d |Spiritual Stone# is|Spiritual Stones# are| "
|
||||
"retrieved.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois |qu'&%r%d Pierre Ancestrale%w aura été&récupérée|que&%r%d Pierres Ancestrales%w auront été&récupérées|.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Pierre Ancestrale# aura été&récupérée|que #%d Pierres Ancestrales# auront été récupérées|.",
|
||||
/*spanish*/
|
||||
"Y Zelda entregará la llave&del #señor del mal# tras obtener&#%d |piedra espiritual|piedras "
|
||||
"espirituales|#." },
|
||||
"Y Zelda entregará la llave del #señor del mal# tras obtener #%d |piedra espiritual|piedras "
|
||||
"espirituales|#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Heiliger Stein# geborgen wurde|Heilige Steine# geborgen wurden|." },
|
||||
});
|
||||
|
||||
hintTable[RHT_LACS_REWARDS_HINT] = HintText::LACS({
|
||||
// obscure text singular plural
|
||||
Text{ "And the %revil one%w's key will be&provided by Zelda once %r%d&|Spiritual Stone or Medallion%w&"
|
||||
"is|Spiritual Stones and Medallions%w&are| retrieved.",
|
||||
Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Spiritual Stone or Medallion# "
|
||||
"is|Spiritual Stones and Medallions# are| retrieved.",
|
||||
/*french*/
|
||||
"Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois |qu'&%r%d Pierre Ancestrale ou %d&Médaillon%w sera récupéré|que&%r%d Pierres Ancestrales et&Médaillons%w seront récupérés|.",
|
||||
"Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d Pierre Ancestrale ou %d Médaillon# sera récupéré|que&#%d Pierres Ancestrales et&Médaillons# seront récupérés|.",
|
||||
/*spanish*/
|
||||
"Y Zelda entregará la llave&del #señor del mal# tras obtener&#%d |piedra espiritual o medallón|piedras "
|
||||
"espirituales o medallones|#." },
|
||||
"Y Zelda entregará la llave del #señor del mal# tras obtener #%d |piedra espiritual o medallón|piedras "
|
||||
"espirituales o medallones|#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Heiliger Stein oder Amulett#&geborgen wurde|Heilige Steine oder Amulette#&geborgen wurden|." },
|
||||
});
|
||||
|
||||
hintTable[RHT_LACS_DUNGEONS_HINT] = HintText::LACS({
|
||||
// obscure text singular plural
|
||||
Text{ "And the %revil one%w's key will be&provided by Zelda once %r%d&|Dungeon%w is|Dungeons%w are| conquered.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois |qu'&%r%d donjon %wsera conquis|que&%r%d donjons%w seront conquis|.",
|
||||
/*spanish*/ "Y Zelda entregará la llave&del #señor del mal# tras completar&#%d |mazmorra|mazmorras|#." },
|
||||
Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Dungeon# is|Dungeons# are| conquered.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d donjon #sera conquis|que #%d donjons# seront conquis|.",
|
||||
/*spanish*/ "Y Zelda entregará la llave del #señor del mal# tras completar #%d |mazmorra|mazmorras|#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Labyrinth# abgeschlossen wurde|Labyrinthe# abgeschlossen wurden|." },
|
||||
});
|
||||
|
||||
hintTable[RHT_LACS_TOKENS_HINT] = HintText::LACS({
|
||||
// obscure text singular plural
|
||||
Text{ "And the %revil one%w's key will be&provided by Zelda once %r%d |Gold&Skulltula Token%w is|Gold&Skulltula "
|
||||
"Tokens%w are| retrieved.",
|
||||
/*french*/ "Aussi, la %rclé du Malin%w sera&fournie par Zelda une fois |qu'&%r%d symbole de Skulltula d'or&%wsera récupuéré|que &%r%d symboles de Skulltula d'or&%wseront recupérés|.",
|
||||
Text{ "And the #evil one#'s key will be provided by Zelda once #%d |Gold&Skulltula Token# is|Gold Skulltula "
|
||||
"Tokens# are| retrieved.",
|
||||
/*french*/ "Aussi, la #clé du Malin# sera fournie par Zelda une fois |qu' #%d symbole de Skulltula d'or #sera récupuéré|que &#%d symboles de Skulltula d'or&#seront recupérés|.",
|
||||
/*spanish*/
|
||||
"Y Zelda entregará la llave&del #señor del mal# tras obtener&#%d |símbolo|símbolos| de&skulltula "
|
||||
"dorada#." },
|
||||
"Y Zelda entregará la llave del #señor del mal# tras obtener #%d |símbolo|símbolos| de skulltula "
|
||||
"dorada#.",
|
||||
/*german*/"Und der #Schlüssel des Bösen# wird von Zelda verliehen, sobald #%d |Skulltula-Symbol# gesammelt wurde|Skulltula-Symbole# gesammelt wurden|." },
|
||||
});
|
||||
/*--------------------------
|
||||
| TRIAL HINT TEXT |
|
||||
@ -2860,26 +2880,30 @@ void HintTable_Init() {
|
||||
// obscure text
|
||||
Text{ "#Ganon's Tower# is protected by a powerful barrier.",
|
||||
/*french*/ "#la Tour de Ganon# est protégée par une puissante barrière",
|
||||
/*spanish*/ "la #torre de Ganon# está protegida por una poderosa barrera" },
|
||||
/*spanish*/ "la #torre de Ganon# está protegida por una poderosa barrera",
|
||||
/*german*/"der #Teufelsturm# sei von einer mächtigen Barriere geschützt." },
|
||||
});
|
||||
|
||||
hintTable[RHT_ZERO_TRIALS] = HintText::Exclude({
|
||||
// obscure text
|
||||
Text{ "Sheik dispelled the barrier around #Ganon's Tower#.",
|
||||
/*french*/ "Sheik a dissipé la barrière autour de #la Tour de Ganon#",
|
||||
/*spanish*/ "Sheik disipó la barrera alrededor de la #torre de Ganon#." },
|
||||
/*spanish*/ "Sheik disipó la barrera alrededor de la #torre de Ganon#.",
|
||||
/*german*/"Shiek habe die Barriere um den #Teufelsturm# aufgelöst." },
|
||||
});
|
||||
|
||||
hintTable[RHT_FOUR_TO_FIVE_TRIALS] = HintText::Exclude({
|
||||
// obscure text
|
||||
Text{ " was dispelled by Sheik.", /*french*/ " a été dissipée par Sheik.",
|
||||
/*spanish*/ " se disipó gracias a Sheik." },
|
||||
/*spanish*/ " se disipó gracias a Sheik.",
|
||||
/*german*/" sei von Shiek aufgelöst worden." },
|
||||
});
|
||||
|
||||
hintTable[RHT_ONE_TO_THREE_TRIALS] = HintText::Exclude({
|
||||
// obscure text
|
||||
Text{ " protects Ganons Tower.", /*french*/ " protège la Tour de Ganon.",
|
||||
/*spanish*/ " protege la torre de Ganon" },
|
||||
/*spanish*/ " protege la torre de Ganon",
|
||||
/*german*/" schütze den Teufelsturm." },
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
@ -2890,14 +2914,16 @@ void HintTable_Init() {
|
||||
// obscure text
|
||||
Text{ "3 Spiritual Stones found in Hyrule...",
|
||||
/*french*/ "Les trois Pierres Ancestrales cachées&dans Hyrule...",
|
||||
/*spanish*/ "Tres piedras espirituales halladas por Hyrule..." },
|
||||
/*spanish*/ "Tres piedras espirituales halladas por Hyrule...",
|
||||
/*german*/"Drei Heilige Steine, zu finden in Hyrule..." },
|
||||
});
|
||||
|
||||
hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN] = HintText::Altar({
|
||||
// obscure text
|
||||
Text{ "Ye who may become a Hero...&The path to the future is open...",
|
||||
/*french*/ "À celui qui a quête de devenir&héros...&Le futur vous accueille béant...",
|
||||
/*spanish*/ "Para aquel que se convierta en el héroe...&La puerta al futuro está a su disposición..." },
|
||||
/*spanish*/ "Para aquel que se convierta en el héroe...&La puerta al futuro está a su disposición...",
|
||||
/*german*/"Jener auf dem Weg des Helden...&Der Pfad zur Zukunft sei geöffnet..." },
|
||||
});
|
||||
|
||||
hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY] = HintText::Altar({
|
||||
@ -2905,7 +2931,8 @@ void HintTable_Init() {
|
||||
Text{
|
||||
"Ye who may become a Hero...&Stand with the Ocarina and&play the Song of Time.",
|
||||
/*french*/ "À celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.",
|
||||
/*spanish*/ "Para aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo." },
|
||||
/*spanish*/ "Para aquel que se convierta en el héroe...&Tome la ocarina y&entone la Canción del Tiempo.",
|
||||
/*german*/"Jener auf dem Weg des Helden...&Nehme er seine Okarina zur Hand und&spiele hier die Hymne der Zeit." },
|
||||
});
|
||||
|
||||
hintTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED] = HintText::Altar({
|
||||
@ -2915,30 +2942,32 @@ void HintTable_Init() {
|
||||
"À celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.",
|
||||
/*spanish*/
|
||||
"Para aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del "
|
||||
"Tiempo." },
|
||||
"Tiempo.",
|
||||
/*german*/"Jener mit den drei Heiligen Steinen&nehme seine Okarina zur Hand und&spiele hier die Hymne der Zeit." },
|
||||
});
|
||||
|
||||
hintTable[RHT_ADULT_ALTAR_TEXT_START] = HintText::Altar({
|
||||
// obscure text
|
||||
Text{ "An awakening voice from the Sacred&Realm will call those destined to be&Sages, who dwell in the five "
|
||||
"temples.",
|
||||
Text{ "An awakening voice from the Sacred Realm will call those destined to be Sages, who dwell in the #five temples#.",
|
||||
/*french*/
|
||||
"Quand le mal aura triomphé, une voix&du Saint Royaume appellera ceux&cachés dans les cinq temples, "
|
||||
"Quand le mal aura triomphé, une voix du Saint Royaume appellera ceux cachés dans les #cinq temples#, "
|
||||
"destinés^à être Sages.",
|
||||
/*spanish*/
|
||||
"Cuando el mal lo impregne todo, desde el Reino Sagrado surgirá una voz que hará despertar a los sabios "
|
||||
"que moran en los #cinco templos#." },
|
||||
"que moran en los #cinco templos#.",
|
||||
/*german*/"Beherrscht das Böse die Welt, weilen&jene Weisen, die von der Stimme des Heiligen Reiches erweckt werden, noch&in den #fünf Tempeln#." },
|
||||
});
|
||||
|
||||
hintTable[RHT_ADULT_ALTAR_TEXT_END] = HintText::Altar({
|
||||
// obscure text
|
||||
Text{
|
||||
"$kTogether with the Hero of Time,&the awakened ones will return&the light of peace to the world...",
|
||||
"$kTogether with the Hero of Time, the awakened ones will return the light of peace to the world...",
|
||||
/*french*/
|
||||
"$kEnsemble avec le Héros du &Temps, ces Sages emprisonneront&le mal et réinstaureront la&lumière de paix "
|
||||
"$kEnsemble avec le Héros du Temps, ces Sages emprisonneront le mal et réinstaureront la lumière de paix "
|
||||
"dans le monde...",
|
||||
/*spanish*/
|
||||
"Con el Héroe del Tiempo, aquellos&que despierten detendrán el mal y&volverán al mundo de luz la paz..." },
|
||||
"Con el Héroe del Tiempo, aquellos&que despierten detendrán el mal y&volverán al mundo de luz la paz...",
|
||||
/*german*/"$kZusammen mit dem Auserwählten wer-den diese ihre Kräfte einsetzen, um der Welt den Frieden wiederzugeben." },
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
@ -3054,7 +3083,7 @@ void HintTable_Init() {
|
||||
hintTable[RHT_SARIA_TEXT01] = HintText::OtherHint({
|
||||
// obscure text
|
||||
Text{
|
||||
"Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %g",
|
||||
"Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %g",
|
||||
/*french*/
|
||||
"As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %g",
|
||||
/*spanish*/
|
||||
@ -3071,6 +3100,35 @@ void HintTable_Init() {
|
||||
"%w.$C"},
|
||||
});
|
||||
|
||||
hintTable[RHT_WARP_TO] = HintText::OtherHint({
|
||||
Text{
|
||||
"Warp to&#",
|
||||
"Se téléporter vers&#",
|
||||
"",
|
||||
"Zu&#"},
|
||||
});
|
||||
hintTable[RHT_WARP_CHOICE] = HintText::OtherHint({
|
||||
Text{
|
||||
"#?&" + TWO_WAY_CHOICE() + "#OK&No#",
|
||||
"#?&" + TWO_WAY_CHOICE() + "#OK!&Non#",
|
||||
"###",
|
||||
"#?&" + TWO_WAY_CHOICE() + "#OK&No#"
|
||||
}
|
||||
});
|
||||
|
||||
hintTable[RHT_FROGS_HINT01] = HintText::OtherHint({Text{
|
||||
"Some frogs holding #",
|
||||
"Des grenouilles se trouvant sous l'eau vous fixent attentivement, tenant fermement #",
|
||||
"",
|
||||
"Unter Wasser gibt es Frösche, die #"
|
||||
}});
|
||||
hintTable[RHT_FROGS_HINT02] = HintText::OtherHint({Text{
|
||||
"# are looking at you from underwater...",
|
||||
"#.",
|
||||
"",
|
||||
"# bei sich haben und Dich neugierig beobachten..."
|
||||
}});
|
||||
|
||||
/*--------------------------
|
||||
| GANON LINE TEXT |
|
||||
---------------------------*/
|
||||
@ -3179,67 +3237,100 @@ void HintTable_Init() {
|
||||
| MERCHANTS' ITEMS |
|
||||
---------------------------*/
|
||||
|
||||
hintTable[RHT_BEAN_SALESMAN_FIRST] = HintText::MerchantsDialogs({
|
||||
Text{
|
||||
"I tried to be a #magic bean#&salesman, but it turns out my&marketing skills weren't worth&"
|
||||
"beans!^Anyway, want to buy #",
|
||||
/*french*/ "J'ai essayé d'être un vendeur&de #haricots magiques#, mais&j'étais mauvais au niveau du&marketing et ça "
|
||||
"me courait sur&le haricot...^Enfin bref, ça te dirait de m'acheter #",
|
||||
/*spanish*/ "",
|
||||
/*german*/ "Möchten Sie #"
|
||||
}
|
||||
});
|
||||
hintTable[RHT_BEAN_SALESMAN_SECOND] = HintText::MerchantsDialogs({
|
||||
Text{
|
||||
"# for #60 Rupees#?&" + TWO_WAY_CHOICE() + "#Yes&No#",
|
||||
/*french*/ "# pour #60 Rubis#?&" + TWO_WAY_CHOICE() + "#Oui&Non#",
|
||||
/*spanish*/ "",
|
||||
/*german*/ "# für #60 Rubine#?&" + TWO_WAY_CHOICE() + "#Ja&Nein#"
|
||||
}
|
||||
});
|
||||
|
||||
hintTable[RHT_MEDIGORON_DIALOG_FIRST] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ "How about buying ",
|
||||
/*french*/ "Veux-tu acheter ",
|
||||
/*spanish*/ "¿Me compras " },
|
||||
Text{ "How about buying #",
|
||||
/*french*/ "Veux-tu acheter #",
|
||||
/*spanish*/ "¿Me compras #",
|
||||
/*german*/ "Möchtest du #" },
|
||||
});
|
||||
|
||||
hintTable[RHT_MEDIGORON_DIALOG_SECOND] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ " for #200 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/ " pour #200 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/ " por #200 rupias#?&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#" },
|
||||
Text{ "# for #200 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/ "# pour #200 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/ "# por #200 rupias#?&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#",
|
||||
/*german*/ "# für #200 Rubine# kaufen?&" + TWO_WAY_CHOICE() + "#Klar!&Nie im Leben!#" },
|
||||
});
|
||||
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_FIRST] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ "Welcome!^I am selling stuff, strange and rare, from&all over the world to everybody. Today's&special "
|
||||
"is...^",
|
||||
Text{ "Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special "
|
||||
"is...^#",
|
||||
/*french*/
|
||||
"Bienvenue!^Je vends des objets rares et merveilleux du&monde entier. En spécial aujourd'hui...^",
|
||||
"Bienvenue!^Je vends des objets rares et merveilleux du&monde entier. En spécial aujourd'hui...^#",
|
||||
/*spanish*/
|
||||
"¡Acércate!^Vendo productos extraños y difíciles de&encontrar... De todo el mundo a todo el&mundo. La "
|
||||
"oferta de hoy es...^¡" },
|
||||
"oferta de hoy es...^#¡",
|
||||
/* german */
|
||||
"Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten.&Stets sonderliche und seltene Ware&aus "
|
||||
"aller Welt für jedermann.&Das heutige Angebot bleibt...^#" },
|
||||
});
|
||||
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_SECOND] = HintText::MerchantsDialogs({
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{
|
||||
"! Terrifying!&I won't tell you what it is until I see the&money...^How about #200 Rupees#?&&" +
|
||||
TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/
|
||||
"! Un&concentré de puissance! Mais montre tes&rubis avant que je te dise ce que c'est...^Disons #200 "
|
||||
"rubis#?&&" +
|
||||
TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/
|
||||
"! ¡Terrorífico!&No te revelaré su nombre hasta que&vea el dinero...^#200 rupias#, ¿qué te parece?&&" +
|
||||
TWO_WAY_CHOICE() + "#Comprar&No comprar#" },
|
||||
Text{ "!# Terrifying! I won't tell you what it is until I see the #money#...^How about #200 Rupees#?&&" +
|
||||
TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/
|
||||
"!# Un concentré de puissance! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #200 "
|
||||
"rubis#?&&" +
|
||||
TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/
|
||||
"!# ¡Terrorífico! No te revelaré su nombre hasta que vea el #dinero#...^#200 rupias#, ¿qué te parece?&&" +
|
||||
TWO_WAY_CHOICE() + "#Comprar&No comprar#",
|
||||
/*german*/
|
||||
"!# Furchterregend oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #200 Rubinen#?&&" +
|
||||
TWO_WAY_CHOICE() + "#Aber sicher!&Ich bin weg!#" },
|
||||
});
|
||||
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_THIRD] = HintText::MerchantsDialogs({
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_HINTED] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ "Thank you very much!^What I'm selling is... #",
|
||||
/*french*/ "Merci beaucoup!^Cet objet extraordinaire est... #",
|
||||
/*spanish*/ "¡Muchas gracias!^Lo que vendo es... #¡" },
|
||||
Text{ "!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^"
|
||||
"How about #200 Rupees#?&&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/
|
||||
"!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #200 "
|
||||
"rubis#?&&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/ // TODO: Flesh this out with the flavor text if we ever support spanish translations
|
||||
"#!^###200 rupias#, ¿qué te parece?&&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#",
|
||||
/*german*/
|
||||
"#! Ich kann versichern es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich doch "
|
||||
"nicht #anlügen#, oder?^Wie wär's mit #200 Rubinen#?&&" + TWO_WAY_CHOICE() +
|
||||
"#Aber sicher!&Ich bin weg!#" },
|
||||
});
|
||||
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_FOURTH] = HintText::MerchantsDialogs({
|
||||
hintTable[RHT_CARPET_SALESMAN_DIALOG_FINAL] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ "!#^The mark that will lead you to the #Spirit&Temple# is the #flag on the " + IF_NOT_MQ() + "left" +
|
||||
MQ_ELSE() + "right" + MQ_END() + "# outside the shop. Be seeing you!",
|
||||
/*french*/ "!#^La marque qui te mènera au #Temple de l'Esprit# est le #drapeau " + IF_NOT_MQ() +
|
||||
"gauche" + MQ_ELSE() + "droite" + MQ_END() + "# en sortant d'ici. À la prochaine!",
|
||||
/*spanish*/ "!#^La marca que te guiará al #Templo del&Espíritu# es la #bandera que está a la&" +
|
||||
IF_NOT_MQ() + "izquierda" + MQ_ELSE() + "derecha" + MQ_END() + "# al salir de aquí. ¡Nos vemos!" },
|
||||
Text{ "Finally! Now I can go back to being &an %rarms dealer%w!",
|
||||
/*french*/ "Squalala! Je vais enfin pouvoir &%rprendre des vacances%w!",
|
||||
/*spanish*/ "", // TODO: Flesh this out with the flavor text if we ever support spanish translations
|
||||
/*german*/ "Endlich! Schon bald kann ich wieder &%rKrabbelminen-Händler%w sein!" },
|
||||
});
|
||||
|
||||
hintTable[RHT_GRANNY_DIALOG] = HintText::MerchantsDialogs({
|
||||
// obscure text
|
||||
Text{ "! How about #100 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#",
|
||||
/*french*/ "! Que dis-tu de #100 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#",
|
||||
/*spanish*/ ". Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#" },
|
||||
/*spanish*/ ". Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#",
|
||||
/*german*/ "! Sagen wir #100 Rubine#!&" + TWO_WAY_CHOICE() + "#Gerne!&Auf keinen Fall!#" },
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2115,6 +2115,10 @@ void HintTable_Init_Item() {
|
||||
//clear text
|
||||
Text{"Epona", /*french*/"Epona", /*spanish*/"a Epona"}
|
||||
);
|
||||
hintTable[RHT_HINT_MYSTERIOUS] = HintText::Item({
|
||||
Text{"something mysterious", /*french*/"un sacré mystère", /*spanish*/"algo misterioso", /*german*/"etwas Unvorhergesehenes"},
|
||||
Text{"an unknown treasure", /*french*/"un trésor inconnu", /*spanish*/"un desconocido tesoro", /*german*/"ein unbekannter Schatz"},
|
||||
});
|
||||
|
||||
// [RHT_HINT_ERROR] = HintText::Item({
|
||||
// //obscure text
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "hints.hpp"
|
||||
|
||||
#include "custom_messages.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "random.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
@ -14,7 +13,15 @@
|
||||
#include "../context.h"
|
||||
#include "pool_functions.hpp"
|
||||
|
||||
using namespace CustomMessages;
|
||||
#define QM_WHITE "%w"
|
||||
#define QM_RED "%r"
|
||||
#define QM_GREEN "%g"
|
||||
#define QM_BLUE "%b"
|
||||
#define QM_LBLUE "%c"
|
||||
#define QM_PINK "%p"
|
||||
#define QM_YELLOW "%y"
|
||||
#define QM_BLACK "%B"
|
||||
|
||||
using namespace Rando;
|
||||
|
||||
const Text& HintText::GetText() const {
|
||||
@ -90,7 +97,7 @@ const std::array<HintSetting, 4> hintSettingTable{{
|
||||
.alwaysCopies = 0,
|
||||
.trialCopies = 0,
|
||||
.junkWeight = 1, //RANDOTODO when the hint pool is not implicitly an itemLocations, handle junk like other hint types
|
||||
.distTable = {} /*RANDOTODO Instead of loading a function into this,
|
||||
.distTable = {} /*RANDOTODO Instead of loading a function into this,
|
||||
apply this filter on all possible hintables in advance and then filter by what is acually in the seed at the start of generation.
|
||||
This allows the distTable to hold the current status in hint generation (reducing potential doubled work) and
|
||||
will make handling custom hint pools easier later*/
|
||||
@ -109,7 +116,7 @@ const std::array<HintSetting, 4> hintSettingTable{{
|
||||
{"Dungeon", HINT_TYPE_ITEM_LOCATION, 3, 0, 1, FilterDungeonLocations},
|
||||
{"Named Item", HINT_TYPE_ITEM_AREA, 10, 0, 1, FilterGoodItems},
|
||||
{"Random" , HINT_TYPE_ITEM_AREA, 12, 0, 1, NoFilter}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Strong hints
|
||||
{
|
||||
@ -144,37 +151,109 @@ const std::array<HintSetting, 4> hintSettingTable{{
|
||||
},
|
||||
}};
|
||||
|
||||
Text AutoFormatHintText(Text unformattedHintText) {
|
||||
std::array<std::string, LANGUAGE_MAX> strings;
|
||||
for (int i = 0; i < LANGUAGE_MAX; i++) {
|
||||
std::string textStr = unformattedHintText.GetForLanguage(i);
|
||||
// RANDOTODO: don't just make manual exceptions
|
||||
bool needsAutomaticNewlines = true;
|
||||
if (textStr == "Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!" ||
|
||||
textStr == "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda" ||
|
||||
textStr == "What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the hungry,&and my castle floats." ||
|
||||
textStr == "Many tricks are up my sleeve,&to save yourself&you'd better leave!" ||
|
||||
textStr == "I've learned this spell,&it's really neat,&I'll keep it later&for your treat!" ||
|
||||
textStr == "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!" ||
|
||||
textStr == "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!" ||
|
||||
textStr == "Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?" ||
|
||||
textStr == "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?" ||
|
||||
textStr == "They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of the script...&will be me.\"") {
|
||||
needsAutomaticNewlines = false;
|
||||
}
|
||||
static std::map<std::string, int> pixelWidthTable = {
|
||||
{ " ", 6 }, { "!", 6 }, { "\"", 5 }, { "#", 7 }, { "$", 7 }, { "%", 11 }, { "&", 9 }, { "\'", 3 },
|
||||
{ "(", 6 }, { ")", 6 }, { "*", 6 }, { "+", 7 }, { ",", 3 }, { "-", 5 }, { ".", 3 }, { "/", 7 },
|
||||
{ "0", 8 }, { "1", 4 }, { "2", 7 }, { "3", 7 }, { "4", 8 }, { "5", 7 }, { "6", 7 }, { "7", 7 },
|
||||
{ "8", 7 }, { "9", 7 }, { ":", 5 }, { ";", 5 }, { "<", 7 }, { "=", 9 }, { ">", 7 }, { "?", 9 },
|
||||
{ "@", 10 }, { "A", 9 }, { "B", 7 }, { "C", 9 }, { "D", 9 }, { "E", 6 }, { "F", 6 }, { "G", 9 },
|
||||
{ "H", 8 }, { "I", 3 }, { "J", 6 }, { "K", 8 }, { "L", 6 }, { "M", 10 }, { "N", 9 }, { "O", 10 },
|
||||
{ "P", 7 }, { "Q", 10 }, { "R", 8 }, { "S", 8 }, { "T", 7 }, { "U", 8 }, { "V", 9 }, { "W", 12 },
|
||||
{ "X", 9 }, { "Y", 8 }, { "Z", 8 }, { "[", 6 }, { "\\", 8 }, { "]", 6 }, { "^", 8 }, { "_", 7 },
|
||||
{ "`", 4 }, { "a", 6 }, { "b", 7 }, { "c", 6 }, { "d", 7 }, { "e", 7 }, { "f", 5 }, { "g", 7 },
|
||||
{ "h", 6 }, { "i", 3 }, { "j", 5 }, { "k", 6 }, { "l", 3 }, { "m", 9 }, { "n", 7 }, { "o", 7 },
|
||||
{ "p", 7 }, { "q", 7 }, { "r", 6 }, { "s", 6 }, { "t", 6 }, { "u", 6 }, { "v", 7 }, { "w", 9 },
|
||||
{ "x", 6 }, { "y", 7 }, { "z", 6 }, { "{", 6 }, { "¦", 4 }, { "}", 6 }, { "¡", 5 }, { "¢", 7 },
|
||||
{ "£", 8 }, { "¤", 7 }, { "¥", 8 }, { "|", 4 }, { "§", 12 }, { "¨", 12 }, { "©", 10 }, { "ª", 5 },
|
||||
{ "«", 8 }, { "¬", 7 }, { "\u00AD", 6 }, { "®", 10 }, { "¯", 8 }, { "°", 12 }, { "±", 12 }, { "²", 5 },
|
||||
{ "³", 5 }, { "µ", 6 }, { "¶", 8 }, { "·", 4 }, { "¹", 4 }, { "º", 5 }, { "»", 9 }, { "¼", 9 },
|
||||
{ "½", 9 }, { "¾", 10 }, { "¿", 7 }, { "À", 11 }, { "Á", 9 }, { "Â", 9 }, { "Ã", 9 }, { "Ä", 9 },
|
||||
{ "Å", 9 }, { "Æ", 12 }, { "Ç", 9 }, { "È", 6 }, { "É", 6 }, { "Ê", 6 }, { "Ë", 6 }, { "Ì", 5 },
|
||||
{ "Í", 5 }, { "Î", 5 }, { "Ï", 5 }, { "Ð", 10 }, { "Ñ", 9 }, { "Ò", 10 }, { "Ó", 10 }, { "Ô", 10 },
|
||||
{ "Õ", 10 }, { "Ö", 10 }, { "×", 9 }, { "Ø", 10 }, { "Ù", 8 }, { "Ú", 8 }, { "Û", 8 }, { "Ü", 8 },
|
||||
{ "Ý", 10 }, { "Þ", 8 }, { "ß", 7 }, { "à", 6 }, { "á", 6 }, { "â", 6 }, { "ã", 6 }, { "ä", 6 },
|
||||
{ "å", 6 }, { "æ", 11 }, { "ç", 6 }, { "è", 7 }, { "é", 7 }, { "ê", 7 }, { "ë", 7 }, { "ì", 5 },
|
||||
{ "í", 5 }, { "î", 5 }, { "ï", 5 }, { "ð", 7 }, { "ñ", 7 }, { "ò", 7 }, { "ó", 7 }, { "ô", 7 },
|
||||
{ "õ", 7 }, { "ö", 7 }, { "÷", 11 }, { "ø", 9 }, { "ù", 7 }, { "ú", 7 }, { "û", 7 }, { "ü", 7 },
|
||||
{ "ý", 8 }, { "þ", 8 }, { "ÿ", 8 }, { "Œ", 11 }, { "œ", 11 }, { "„", 5 }, { "”", 5 }, { "€", 10 },
|
||||
{ "Ÿ", 10 }, { "~", 8 }
|
||||
};
|
||||
|
||||
static size_t NextLineLength(const std::string* textStr, const size_t lastNewline, bool hasIcon = false) {
|
||||
const size_t maxLinePixelWidth = hasIcon ? 200 : 216;
|
||||
|
||||
|
||||
size_t totalPixelWidth = 0;
|
||||
size_t currentPos = lastNewline;
|
||||
|
||||
// Looping through the string from the lastNewline until the total
|
||||
// width of counted characters exceeds the maximum pixels in a line.
|
||||
size_t nextPosJump = 0;
|
||||
while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) {
|
||||
// Skip over control codes
|
||||
if (textStr->at(currentPos) == '%') {
|
||||
nextPosJump = 2;
|
||||
} else if (textStr->at(currentPos) == '$') {
|
||||
nextPosJump = 2;
|
||||
} else if (textStr->at(currentPos) == '@') {
|
||||
nextPosJump = 1;
|
||||
// Assume worst case for player name 12 * 8 (widest character * longest name length)
|
||||
totalPixelWidth += 96;
|
||||
} else {
|
||||
// Some characters only one byte while others are two bytes
|
||||
// So check both possibilities when checking for a character
|
||||
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) {
|
||||
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)];
|
||||
nextPosJump = 1;
|
||||
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
|
||||
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
|
||||
nextPosJump = 2;
|
||||
} else {
|
||||
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2));
|
||||
SPDLOG_DEBUG("Full string: " + *textStr);
|
||||
nextPosJump = 1;
|
||||
}
|
||||
}
|
||||
currentPos += nextPosJump;
|
||||
}
|
||||
// return the total number of characters we looped through
|
||||
if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') {
|
||||
return currentPos - lastNewline - nextPosJump;
|
||||
} else {
|
||||
return currentPos - lastNewline;
|
||||
}
|
||||
}
|
||||
|
||||
Text AutoFormatHintText(const Text& unformattedHintText, const std::vector<std::string>& colors = {}) {
|
||||
std::array<std::string, LANGUAGE_MAX> strings;
|
||||
for (int i = 0; i < LANGUAGE_MAX; i++) {
|
||||
std::string textStr = unformattedHintText.GetForLanguage(i);
|
||||
|
||||
for (const auto& color: colors) {
|
||||
if (const size_t firstHashtag = textStr.find('#'); firstHashtag != std::string::npos) {
|
||||
textStr.replace(firstHashtag, 1, color);
|
||||
if (const size_t secondHashtag = textStr.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
|
||||
textStr.replace(secondHashtag, 1, QM_WHITE);
|
||||
} else {
|
||||
SPDLOG_DEBUG("non-matching hashtags in string: \"%s\"", textStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove any remaining '#' characters.
|
||||
std::erase(textStr, '#');
|
||||
|
||||
if (needsAutomaticNewlines) {
|
||||
// insert newlines either manually or when encountering a '&'
|
||||
constexpr size_t lineLength = 34;
|
||||
size_t lastNewline = 0;
|
||||
const bool hasIcon = textStr.find('$', 0) != std::string::npos;
|
||||
size_t lineLength = NextLineLength(&textStr, lastNewline, hasIcon);
|
||||
while (lastNewline + lineLength < textStr.length()) {
|
||||
size_t carrot = textStr.find('^', lastNewline);
|
||||
size_t ampersand = textStr.find('&', lastNewline);
|
||||
size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength);
|
||||
size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength);
|
||||
const size_t carrot = textStr.find('^', lastNewline);
|
||||
const size_t ampersand = textStr.find('&', lastNewline);
|
||||
const size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength);
|
||||
const size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength);
|
||||
// replace '&' first if it's within the newline range
|
||||
if (ampersand < lastNewline + lineLength) {
|
||||
lastNewline = ampersand;
|
||||
lastNewline = ampersand + 1;
|
||||
// or move the lastNewline cursor to the next line if a '^' is encountered
|
||||
} else if (carrot < lastNewline + lineLength) {
|
||||
lastNewline = carrot + 1;
|
||||
@ -186,15 +265,12 @@ Text AutoFormatHintText(Text unformattedHintText) {
|
||||
textStr.replace(lastSpace, 1, "&");
|
||||
lastNewline = lastSpace + 1;
|
||||
}
|
||||
lineLength = NextLineLength(&textStr, lastNewline, hasIcon);
|
||||
}
|
||||
strings[i] = textStr;
|
||||
}
|
||||
|
||||
// todo add colors (see `AddColorsAndFormat` in `custom_messages.cpp`)
|
||||
textStr.erase(std::remove(textStr.begin(), textStr.end(), '#'), textStr.end());
|
||||
strings[i] = textStr;
|
||||
}
|
||||
|
||||
return Text(strings[0], strings[1], strings[2]);
|
||||
return {strings[0], strings[1], ""/*spanish*/, strings[2]};
|
||||
}
|
||||
|
||||
std::array<DungeonHintInfo, 10> dungeonInfoData;
|
||||
@ -220,67 +296,10 @@ std::string dampeHintLoc;
|
||||
std::string gregHintLoc;
|
||||
std::string sariaHintLoc;
|
||||
|
||||
|
||||
Text& GetChildAltarText() {
|
||||
return childAltarText;
|
||||
}
|
||||
|
||||
Text& GetAdultAltarText() {
|
||||
return adultAltarText;
|
||||
}
|
||||
|
||||
void SetGanonText(Text text){
|
||||
ganonText = text;
|
||||
}
|
||||
|
||||
Text& GetGanonText() {
|
||||
return ganonText;
|
||||
}
|
||||
|
||||
Text& GetGanonHintText() {
|
||||
return ganonHintText;
|
||||
}
|
||||
|
||||
Text& GetDampeHintText() {
|
||||
return dampesText;
|
||||
}
|
||||
|
||||
Text& GetGregHintText() {
|
||||
return gregText;
|
||||
}
|
||||
|
||||
Text& GetSheikHintText() {
|
||||
return sheikText;
|
||||
}
|
||||
|
||||
Text& GetSariaHintText() {
|
||||
return sariaText;
|
||||
}
|
||||
|
||||
Text& GetWarpMinuetText() {
|
||||
return warpMinuetText;
|
||||
}
|
||||
|
||||
Text& GetWarpBoleroText() {
|
||||
return warpBoleroText;
|
||||
}
|
||||
|
||||
Text& GetWarpSerenadeText() {
|
||||
return warpSerenadeText;
|
||||
}
|
||||
|
||||
Text& GetWarpRequiemText() {
|
||||
return warpRequiemText;
|
||||
}
|
||||
|
||||
Text& GetWarpNocturneText() {
|
||||
return warpNocturneText;
|
||||
}
|
||||
|
||||
Text& GetWarpPreludeText() {
|
||||
return warpPreludeText;
|
||||
}
|
||||
|
||||
std::string GetMasterSwordHintLoc() {
|
||||
return masterSwordHintLoc;
|
||||
}
|
||||
@ -350,9 +369,9 @@ static void SetAllInRegionAsHinted(RandomizerArea area, std::vector<RandomizerCh
|
||||
}
|
||||
}
|
||||
|
||||
static void AddGossipStoneHint(Text hint,
|
||||
static void AddGossipStoneHint(Text hint,
|
||||
const RandomizerCheck gossipStone,
|
||||
const std::vector<uint8_t>& colors,
|
||||
const std::vector<std::string>& colors,
|
||||
HintType hintType,
|
||||
std::string distributionName,
|
||||
const RandomizerCheck hintedLocation) {
|
||||
@ -361,16 +380,16 @@ static void AddGossipStoneHint(Text hint,
|
||||
//GetLocation(gossipStone)->SetPlacedItem(gossipStone);
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->AddHint((RandomizerHintKey)((gossipStone - RC_COLOSSUS_GOSSIP_STONE) + 1), AutoFormatHintText(hint), hintedLocation, hintType, distributionName, ctx->GetItemLocation(hintedLocation)->GetArea());
|
||||
ctx->AddHint((RandomizerHintKey)((gossipStone - RC_COLOSSUS_GOSSIP_STONE) + 1), AutoFormatHintText(hint, colors), hintedLocation, hintType, distributionName, ctx->GetItemLocation(hintedLocation)->GetArea());
|
||||
ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT); //RANDOTODO, better gossip stone to location to hint key system
|
||||
}
|
||||
|
||||
static void AddGossipStoneHintCopies(uint8_t copies,
|
||||
Text hint,
|
||||
std::vector<uint8_t> colours,
|
||||
HintType type,
|
||||
static void AddGossipStoneHintCopies(uint8_t copies,
|
||||
Text hint,
|
||||
std::vector<std::string> colours,
|
||||
HintType type,
|
||||
std::string distributionName,
|
||||
RandomizerCheck location = RC_UNKNOWN_CHECK,
|
||||
RandomizerCheck location = RC_UNKNOWN_CHECK,
|
||||
RandomizerCheck firstStone = RC_UNKNOWN_CHECK){
|
||||
if (firstStone != RC_UNKNOWN_CHECK && copies > 0){
|
||||
AddGossipStoneHint(hint, firstStone, colours, type, distributionName, location);
|
||||
@ -405,32 +424,32 @@ static bool CreateHint(RandomizerCheck hintedLocation, uint8_t copies, HintType
|
||||
//make hint text
|
||||
Text finalHint;
|
||||
Text prefix = ::Hint(RHT_PREFIX).GetText();
|
||||
std::vector<uint8_t> colours;
|
||||
std::vector<std::string> colours;
|
||||
if (type == HINT_TYPE_WOTH){
|
||||
Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText();
|
||||
finalHint = prefix + "%r#" + areaText + "#%w" + ::Hint(RHT_WAY_OF_THE_HERO).GetText();
|
||||
colours = {QM_LBLUE};
|
||||
finalHint = prefix + "#" + areaText + "#" + ::Hint(RHT_WAY_OF_THE_HERO).GetText();
|
||||
colours = {QM_RED, QM_LBLUE};
|
||||
}
|
||||
else if(type == HINT_TYPE_BARREN){
|
||||
Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText();
|
||||
finalHint = prefix + ::Hint(RHT_PLUNDERING).GetText() + "%r#" + areaText + "#%w" + ::Hint(RHT_FOOLISH).GetText();
|
||||
colours = {QM_PINK};
|
||||
finalHint = prefix + ::Hint(RHT_PLUNDERING).GetText() + "#" + areaText + "#" + ::Hint(RHT_FOOLISH).GetText();
|
||||
colours = {QM_RED, QM_PINK};
|
||||
}
|
||||
else {
|
||||
Text itemText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText();
|
||||
if (type == HINT_TYPE_ITEM_LOCATION){
|
||||
Text locationText = Rando::StaticData::GetLocation(hintedLocation)->GetHint()->GetText();
|
||||
finalHint = prefix + "%r" + locationText + " %g#"+itemText+"#%w.";
|
||||
colours = {QM_GREEN, QM_RED};
|
||||
finalHint = prefix + locationText + " #"+itemText+"#.";
|
||||
colours = {QM_RED, QM_GREEN};
|
||||
}
|
||||
else if (type == HINT_TYPE_ITEM_AREA){
|
||||
Text areaText = ::Hint(ctx->GetItemLocation(hintedLocation)->GetArea()).GetText();
|
||||
if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
|
||||
finalHint = prefix+"%r#"+areaText+"#%w "+::Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w.";
|
||||
colours = {QM_GREEN, QM_RED};
|
||||
} else {
|
||||
finalHint = prefix+"%r#"+itemText+"#%w "+::Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+areaText+"#%w.";
|
||||
finalHint = prefix+"#"+areaText+"# "+::Hint(RHT_HOARDS).GetText()+" #"+itemText+"#.";
|
||||
colours = {QM_RED, QM_GREEN};
|
||||
} else {
|
||||
finalHint = prefix+"#"+itemText+"# "+::Hint(RHT_CAN_BE_FOUND_AT).GetText()+" #"+areaText+"#.";
|
||||
colours = {QM_GREEN, QM_RED};
|
||||
}
|
||||
}
|
||||
else{
|
||||
@ -451,7 +470,7 @@ static bool CreateHint(RandomizerCheck hintedLocation, uint8_t copies, HintType
|
||||
}
|
||||
|
||||
|
||||
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations,
|
||||
static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHintLocations,
|
||||
uint8_t copies,
|
||||
HintType type,
|
||||
std::string distributionName) {
|
||||
@ -488,7 +507,7 @@ static RandomizerCheck CreateRandomHint(std::vector<RandomizerCheck>& possibleHi
|
||||
return hintedLocation;
|
||||
}
|
||||
|
||||
static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerCheck>& locations,
|
||||
static std::vector<RandomizerCheck> FilterHintability(std::vector<RandomizerCheck>& locations,
|
||||
std::function<bool(RandomizerCheck)> extraFilter = NoFilter){
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return FilterFromPool(locations, [extraFilter, ctx](const RandomizerCheck loc) {
|
||||
@ -595,10 +614,9 @@ void CreateGanonAndSheikText() {
|
||||
ganonHintText = ganonHintText + "!";
|
||||
}
|
||||
|
||||
//CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
|
||||
ctx->AddHint(RH_GANONDORF_HINT, AutoFormatHintText(ganonHintText), lightArrowLocation[0], HINT_TYPE_STATIC, "Static", lightArrowArea);
|
||||
|
||||
if(!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){
|
||||
if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) {
|
||||
sheikText = ::Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + LightArrowAreaText + "%w.";
|
||||
locsToCheck = {RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC};
|
||||
|
||||
@ -622,11 +640,13 @@ void CreateGanonAndSheikText() {
|
||||
}
|
||||
|
||||
//Find the location which has the given itemKey and create the generic altar text for the reward
|
||||
static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
|
||||
static Text BuildDungeonRewardText(const ItemID itemID, const RandomizerGet itemKey) {
|
||||
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) {
|
||||
if (itemKey == RG_KOKIRI_EMERALD || itemKey == RG_GORON_RUBY || itemKey == RG_ZORA_SAPPHIRE) {
|
||||
altarLoc = RC_ALTAR_HINT_CHILD;
|
||||
}
|
||||
const RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) {
|
||||
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey;
|
||||
})[0];
|
||||
if (IsReachableWithout({altarLoc}, location, true) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ //RANDOTODO check if works properly
|
||||
@ -636,9 +656,9 @@ static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) {
|
||||
std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD);
|
||||
|
||||
// RANDOTODO implement colors for locations
|
||||
return Text() + rewardString +
|
||||
return Text() + rewardString + "#" +
|
||||
::Hint(ctx->GetItemLocation(location)->GetArea()).GetText().Capitalize() +
|
||||
"...^";
|
||||
"#...^";
|
||||
}
|
||||
|
||||
static Text BuildDoorOfTimeText() {
|
||||
@ -765,17 +785,17 @@ void CreateAltarText() {
|
||||
//Spiritual Stones
|
||||
// TODO: Starting Inventory Dungeon Rewards
|
||||
(/*StartingKokiriEmerald.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_KOKIRI_EMERALD, true)) +
|
||||
: BuildDungeonRewardText(ITEM_KOKIRI_EMERALD, RG_KOKIRI_EMERALD)) +
|
||||
(/*StartingGoronRuby.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_GORON_RUBY, true)) +
|
||||
: BuildDungeonRewardText(ITEM_GORON_RUBY, RG_GORON_RUBY)) +
|
||||
(/*StartingZoraSapphire.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_ZORA_SAPPHIRE, true)) +
|
||||
: BuildDungeonRewardText(ITEM_ZORA_SAPPHIRE, RG_ZORA_SAPPHIRE)) +
|
||||
//How to open Door of Time, the event trigger is necessary to read the altar multiple times
|
||||
BuildDoorOfTimeText();
|
||||
} else {
|
||||
childAltarText = BuildDoorOfTimeText();
|
||||
}
|
||||
ctx->AddHint(RH_ALTAR_CHILD, childAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
ctx->AddHint(RH_ALTAR_CHILD, AutoFormatHintText(childAltarText, { QM_GREEN, QM_RED, QM_BLUE }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
|
||||
//CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE}));
|
||||
|
||||
@ -785,17 +805,17 @@ void CreateAltarText() {
|
||||
adultAltarText = adultAltarText +
|
||||
//Medallion Areas
|
||||
(/*StartingLightMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_LIGHT_MEDALLION, false)) +
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_LIGHT, RG_LIGHT_MEDALLION)) +
|
||||
(/*StartingForestMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FOREST_MEDALLION, false)) +
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_FOREST, RG_FOREST_MEDALLION)) +
|
||||
(/*StartingFireMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_FIRE_MEDALLION, false)) +
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_FIRE, RG_FIRE_MEDALLION)) +
|
||||
(/*StartingWaterMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_WATER_MEDALLION, false)) +
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_WATER, RG_WATER_MEDALLION)) +
|
||||
(/*StartingSpiritMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION, false)) +
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_SPIRIT, RG_SPIRIT_MEDALLION)) +
|
||||
(/*StartingShadowMedallion.Value<uint8_t>()*/false ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(RG_SHADOW_MEDALLION, false));
|
||||
: BuildDungeonRewardText(ITEM_MEDALLION_SHADOW, RG_SHADOW_MEDALLION));
|
||||
}
|
||||
adultAltarText = adultAltarText +
|
||||
//Bridge requirement
|
||||
@ -807,35 +827,61 @@ void CreateAltarText() {
|
||||
//End
|
||||
::Hint(RHT_ADULT_ALTAR_TEXT_END).GetText();
|
||||
//CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED}));
|
||||
ctx->AddHint(RH_ALTAR_ADULT, adultAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
ctx->AddHint(RH_ALTAR_ADULT, AutoFormatHintText(adultAltarText, { QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
}
|
||||
|
||||
void CreateMerchantsHints() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
Text medigoronItemText = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedItem().GetHint().GetText();
|
||||
Text grannyItemText = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText().Capitalize();
|
||||
Text carpetSalesmanItemText =
|
||||
ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText();
|
||||
Text carpetSalesmanItemClearText =
|
||||
ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetClear();
|
||||
|
||||
Text beanSalesmanItemText, medigoronItemText, grannyItemText, carpetSalesmanItemText, carpetSalesmanAfterItemText;
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) {
|
||||
RandomizerGet beanSalesmanItem = ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetPlacedRandomizerGet();
|
||||
beanSalesmanItemText = ctx->GetItemLocation(RC_ZR_MAGIC_BEAN_SALESMAN)->GetPlacedItem().GetHint().GetText();
|
||||
if (beanSalesmanItem == RG_ICE_TRAP) {
|
||||
beanSalesmanItemText = ctx->overrides[RC_ZR_MAGIC_BEAN_SALESMAN].GetTrickName();
|
||||
}
|
||||
RandomizerGet medigoronItem = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedRandomizerGet();
|
||||
medigoronItemText = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedItem().GetHint().GetText();
|
||||
if (medigoronItem == RG_ICE_TRAP) {
|
||||
medigoronItemText = ctx->overrides[RC_GC_MEDIGORON].GetTrickName();
|
||||
}
|
||||
RandomizerGet grannyItem = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedRandomizerGet();
|
||||
grannyItemText = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText().Capitalize();
|
||||
if (grannyItem == RG_ICE_TRAP) {
|
||||
grannyItemText = ctx->overrides[RC_KAK_GRANNYS_SHOP].GetTrickName();
|
||||
}
|
||||
RandomizerGet carpetSalesmanItem = ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedRandomizerGet();
|
||||
carpetSalesmanItemText =
|
||||
ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText();
|
||||
if (carpetSalesmanItem == RG_ICE_TRAP) {
|
||||
carpetSalesmanItemText = ctx->overrides[RC_WASTELAND_BOMBCHU_SALESMAN].GetTrickName();
|
||||
}
|
||||
carpetSalesmanAfterItemText = ::Hint(RHT_CARPET_SALESMAN_DIALOG_HINTED).GetText();
|
||||
} else {
|
||||
medigoronItemText = grannyItemText = carpetSalesmanItemText = hintTable[RHT_HINT_MYSTERIOUS].GetTextCopy();
|
||||
carpetSalesmanAfterItemText = ::Hint(RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS).GetText();
|
||||
beanSalesmanItemText = Text{ "mysterious item", "objet mystérieux", "objeto misterioso", "mysteriöser gegenstand" };
|
||||
}
|
||||
|
||||
Text medigoronText =
|
||||
::Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + ::Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText();
|
||||
Text grannyText = grannyItemText + ::Hint(RHT_GRANNY_DIALOG).GetText();
|
||||
Text grannyText = Text{"#"} + grannyItemText + "#" + ::Hint(RHT_GRANNY_DIALOG).GetText();
|
||||
Text carpetSalesmanTextOne = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText +
|
||||
::Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText();
|
||||
Text carpetSalesmanTextTwo = ::Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText +
|
||||
::Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText();
|
||||
|
||||
// CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN }));
|
||||
// CreateMessageFromTextObject(0x6078, 0, 2, 3,
|
||||
// AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED }));
|
||||
// ctx->AddHint(RH_MEDIGORON, AutoFormatHintText(medigoronText), RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText());
|
||||
// ctx->AddHint(RH_GRANNYS_SHOP, AutoFormatHintText(grannyText), RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText());
|
||||
// ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, AutoFormatHintText(carpetSalesmanTextOne), RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText());
|
||||
carpetSalesmanAfterItemText;
|
||||
Text carpetSalesmanTextTwo = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FINAL).GetText();
|
||||
medigoronText = AutoFormatHintText(medigoronText, {QM_GREEN, QM_YELLOW, QM_GREEN });
|
||||
grannyText = AutoFormatHintText(grannyText, { QM_GREEN, QM_YELLOW, QM_GREEN });
|
||||
carpetSalesmanTextOne = AutoFormatHintText(carpetSalesmanTextOne, { QM_GREEN, QM_RED, QM_YELLOW, QM_GREEN });
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) {
|
||||
Text beanSalesmanText = ::Hint(RHT_BEAN_SALESMAN_FIRST).GetText() + beanSalesmanItemText + ::Hint(RHT_BEAN_SALESMAN_SECOND).GetText();
|
||||
ctx->AddHint(RH_BEAN_SALESMAN, AutoFormatHintText(beanSalesmanText, { QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN }), RC_ZR_MAGIC_BEAN_SALESMAN, HINT_TYPE_STATIC, "Static", RA_ZORAS_RIVER);
|
||||
}
|
||||
|
||||
ctx->AddHint(RH_MEDIGORON, medigoronText, RC_GC_MEDIGORON, HINT_TYPE_STATIC, "Static", RA_GORON_CITY);
|
||||
ctx->AddHint(RH_GRANNYS_SHOP, grannyText, RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, "Static", RA_KAKARIKO_VILLAGE);
|
||||
ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, carpetSalesmanTextOne, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, "Static", RA_HAUNTED_WASTELAND);
|
||||
// Technically not a hint but this is probably the best place we have to store it for now.
|
||||
ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST, carpetSalesmanTextTwo, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, "Static", RA_HAUNTED_WASTELAND);
|
||||
}
|
||||
|
||||
//RANDOTODO add Better Links Pocket and starting item handling once more starting items are added
|
||||
@ -862,18 +908,8 @@ void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector
|
||||
|
||||
void CreateWarpSongTexts() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
if (!ctx->GetOption(RSK_WARP_SONG_HINTS)) {
|
||||
warpMinuetText = Text();
|
||||
warpBoleroText = Text();
|
||||
warpSerenadeText = Text();
|
||||
warpRequiemText = Text();
|
||||
warpNocturneText = Text();
|
||||
warpPreludeText = Text();
|
||||
return;
|
||||
}
|
||||
|
||||
auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false);
|
||||
|
||||
for (auto entrance : warpSongEntrances) {
|
||||
auto destination = entrance->GetConnectedRegion()->GetArea();
|
||||
Text resolvedHint = ::Hint(destination).GetText();
|
||||
@ -881,33 +917,31 @@ void CreateWarpSongTexts() {
|
||||
if (destination == RA_NONE) {
|
||||
resolvedHint = Text{"","",""} + entrance->GetConnectedRegion()->regionName;
|
||||
}
|
||||
|
||||
resolvedHint = ::Hint(RHT_WARP_TO).GetText() + resolvedHint + ::Hint(RHT_WARP_CHOICE).GetText();
|
||||
RandomizerHintKey hintKey = RH_NONE;
|
||||
switch (entrance->GetIndex()) {
|
||||
case 0x0600: // minuet RANDOTODO make an entrance enum and use it here
|
||||
warpMinuetText = resolvedHint;
|
||||
ctx->AddHint(RH_MINUET_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
case 0x0600: // minuet
|
||||
hintKey = RH_MINUET_WARP_LOC;
|
||||
break;
|
||||
case 0x04F6: // bolero
|
||||
warpBoleroText = resolvedHint;
|
||||
ctx->AddHint(RH_BOLERO_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
hintKey = RH_BOLERO_WARP_LOC;
|
||||
break;
|
||||
case 0x0604: // serenade
|
||||
warpSerenadeText = resolvedHint;
|
||||
ctx->AddHint(RH_SERENADE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
hintKey = RH_SERENADE_WARP_LOC;
|
||||
break;
|
||||
case 0x01F1: // requiem
|
||||
warpRequiemText = resolvedHint;
|
||||
ctx->AddHint(RH_REQUIEM_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
hintKey = RH_REQUIEM_WARP_LOC;
|
||||
break;
|
||||
case 0x0568: // nocturne
|
||||
warpNocturneText = resolvedHint;
|
||||
ctx->AddHint(RH_NOCTURNE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
break;
|
||||
hintKey = RH_NOCTURNE_WARP_LOC;
|
||||
break;
|
||||
case 0x05F4: // prelude
|
||||
warpPreludeText = resolvedHint;
|
||||
ctx->AddHint(RH_PRELUDE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
hintKey = RH_PRELUDE_WARP_LOC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ctx->AddHint(hintKey, AutoFormatHintText(resolvedHint, { QM_RED, QM_GREEN }), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", destination);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1071,6 +1105,19 @@ void CreateStoneHints() {
|
||||
GetAccessibleLocations({});
|
||||
}
|
||||
|
||||
void CreateFrogsHint() {
|
||||
const auto ctx = Rando::Context::GetInstance();
|
||||
Rando::ItemLocation* itemLoc = ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME);
|
||||
Text itemText = itemLoc->GetPlacedItem().GetHint().GetText();
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
||||
itemText = ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].GetTrickName();
|
||||
}
|
||||
Text hintText = ::Hint(RHT_FROGS_HINT01).GetText() + itemText + ::Hint(RHT_FROGS_HINT02).GetText();
|
||||
RandomizerArea area = itemLoc->GetArea();
|
||||
itemLoc->SetAsHinted();
|
||||
ctx->AddHint(RH_FROGS, AutoFormatHintText(hintText, { QM_GREEN }), RC_ZR_FROGS_OCARINA_GAME, HINT_TYPE_STATIC, "Static", area);
|
||||
}
|
||||
|
||||
void CreateAllHints(){
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
CreateGanonAndSheikText();
|
||||
@ -1082,6 +1129,9 @@ void CreateAllHints(){
|
||||
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) {
|
||||
CreateMerchantsHints();
|
||||
}
|
||||
if (ctx->GetOption(RSK_FROGS_HINT)) {
|
||||
CreateFrogsHint();
|
||||
}
|
||||
if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) {
|
||||
printf("\x1b[10;10HCreating Hints...");
|
||||
CreateStoneHints();
|
||||
|
@ -217,23 +217,7 @@ extern std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints;
|
||||
extern void CreateAllHints();
|
||||
extern void CreateWarpSongTexts();
|
||||
|
||||
|
||||
Text& GetChildAltarText();
|
||||
Text& GetAdultAltarText();
|
||||
Text& GetGanonText();
|
||||
void SetGanonText(Text text);
|
||||
Text& GetGanonHintText();
|
||||
Text& GetDampeHintText();
|
||||
Text& GetGregHintText();
|
||||
Text& GetSheikHintText();
|
||||
Text& GetSariaHintText();
|
||||
|
||||
Text& GetWarpMinuetText();
|
||||
Text& GetWarpBoleroText();
|
||||
Text& GetWarpSerenadeText();
|
||||
Text& GetWarpRequiemText();
|
||||
Text& GetWarpNocturneText();
|
||||
Text& GetWarpPreludeText();
|
||||
|
||||
std::string GetMasterSwordHintLoc();
|
||||
std::string GetLightArrowHintLoc();
|
||||
|
@ -36,3 +36,7 @@ template <typename T, typename Container>
|
||||
bool ElementInContainer(T& element, const Container& container) {
|
||||
return std::find(container.begin(), container.end(), element) != container.end();
|
||||
}
|
||||
|
||||
template <typename First, typename... T> bool IsAnyOf(First&& first, T&&... t) {
|
||||
return ((first == t) || ...);
|
||||
}
|
||||
|
@ -541,56 +541,6 @@ static void WriteShuffledEntrances() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string AutoFormatHintTextString(std::string unformattedHintTextString) {
|
||||
std::string textStr = unformattedHintTextString;
|
||||
|
||||
// RANDOTODO: don't just make manual exceptions
|
||||
bool needsAutomaicNewlines = true;
|
||||
if (textStr == "Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!" ||
|
||||
textStr == "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda" ||
|
||||
textStr == "What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the hungry,&and my castle floats." ||
|
||||
textStr == "Many tricks are up my sleeve,&to save yourself&you'd better leave!" ||
|
||||
textStr == "I've learned this spell,&it's really neat,&I'll keep it later&for your treat!" ||
|
||||
textStr == "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!" ||
|
||||
textStr == "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!" ||
|
||||
textStr == "Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?" ||
|
||||
textStr == "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?" ||
|
||||
textStr == "They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of the script...&will be me.\"") {
|
||||
needsAutomaicNewlines = false;
|
||||
}
|
||||
|
||||
if (needsAutomaicNewlines) {
|
||||
//insert newlines either manually or when encountering a '&'
|
||||
constexpr size_t lineLength = 34;
|
||||
size_t lastNewline = 0;
|
||||
while (lastNewline + lineLength < textStr.length()) {
|
||||
size_t carrot = textStr.find('^', lastNewline);
|
||||
size_t ampersand = textStr.find('&', lastNewline);
|
||||
size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength);
|
||||
size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength);
|
||||
//replace '&' first if it's within the newline range
|
||||
if (ampersand < lastNewline + lineLength) {
|
||||
lastNewline = ampersand + 1;
|
||||
//or move the lastNewline cursor to the next line if a '^' is encountered
|
||||
} else if (carrot < lastNewline + lineLength) {
|
||||
lastNewline = carrot + 1;
|
||||
//some lines need to be split but don't have spaces, look for periods instead
|
||||
} else if (lastSpace == std::string::npos) {
|
||||
textStr.replace(lastPeriod, 1, ".&");
|
||||
lastNewline = lastPeriod + 2;
|
||||
} else {
|
||||
textStr.replace(lastSpace, 1, "&");
|
||||
lastNewline = lastSpace + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo add colors (see `AddColorsAndFormat` in `custom_messages.cpp`)
|
||||
textStr.erase(std::remove(textStr.begin(), textStr.end(), '#'), textStr.end());
|
||||
|
||||
return textStr;
|
||||
}
|
||||
|
||||
Rando::ItemLocation* GetItemLocation(RandomizerGet item) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
return ctx->GetItemLocation(FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
|
||||
@ -601,54 +551,17 @@ Rando::ItemLocation* GetItemLocation(RandomizerGet item) {
|
||||
// Writes the hints to the spoiler log, if they are enabled.
|
||||
static void WriteHints() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
std::string unformattedGanonText;
|
||||
std::string unformattedGanonHintText;
|
||||
std::string unformattedDampesText;
|
||||
std::string unformattedGregText;
|
||||
std::string unformattedSheikText;
|
||||
std::string unformattedSariaText;
|
||||
|
||||
switch (ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex()) {
|
||||
case 0:
|
||||
default:
|
||||
unformattedGanonText = GetGanonText().GetEnglish();
|
||||
unformattedGanonHintText = GetGanonHintText().GetEnglish();
|
||||
unformattedDampesText = GetDampeHintText().GetEnglish();
|
||||
unformattedGregText = GetGregHintText().GetEnglish();
|
||||
unformattedSheikText = GetSheikHintText().GetEnglish();
|
||||
unformattedSariaText = GetSariaHintText().GetEnglish();
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)){
|
||||
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;
|
||||
case 2:
|
||||
unformattedGanonText = GetGanonText().GetFrench();
|
||||
unformattedGanonHintText = GetGanonHintText().GetFrench();
|
||||
unformattedDampesText = GetDampeHintText().GetFrench();
|
||||
unformattedGregText = GetGregHintText().GetFrench();
|
||||
unformattedSheikText = GetSheikHintText().GetFrench();
|
||||
unformattedSariaText = GetSariaHintText().GetFrench();
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)){
|
||||
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;
|
||||
int language = ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex();
|
||||
if (ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) {
|
||||
jsonData["warpMinuetText"] = ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
jsonData["warpBoleroText"] = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
jsonData["warpSerenadeText"] = ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
jsonData["warpRequiemText"] = ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
jsonData["warpNocturneText"] = ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
jsonData["warpPreludeText"] = ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetForLanguage(language);
|
||||
}
|
||||
jsonData["childAltar"]["hintText"] = ctx->GetHint(RH_ALTAR_CHILD)->GetText().GetForLanguage(language);
|
||||
jsonData["adultAltar"]["hintText"] = ctx->GetHint(RH_ALTAR_ADULT)->GetText().GetForLanguage(language);
|
||||
|
||||
Rando::ItemLocation* emeraldLoc = GetItemLocation(RG_KOKIRI_EMERALD);
|
||||
Rando::ItemLocation* rubyLoc = GetItemLocation(RG_GORON_RUBY);
|
||||
@ -682,35 +595,28 @@ static void WriteHints() {
|
||||
jsonData["adultAltar"]["rewards"]["lightMedallionLoc"] =
|
||||
Rando::StaticData::GetLocation(lightMedallionLoc->GetRandomizerCheck())->GetName();
|
||||
|
||||
std::string ganonText = AutoFormatHintTextString(unformattedGanonText);
|
||||
std::string ganonHintText = AutoFormatHintTextString(unformattedGanonHintText);
|
||||
std::string dampesText = AutoFormatHintTextString(unformattedDampesText);
|
||||
std::string gregText = AutoFormatHintTextString(unformattedGregText);
|
||||
std::string sheikText = AutoFormatHintTextString(unformattedSheikText);
|
||||
std::string sariaText = AutoFormatHintTextString(unformattedSariaText);
|
||||
|
||||
jsonData["ganonText"] = ganonText;
|
||||
jsonData["ganonText"] = ctx->GetHint(RH_GANONDORF_NOHINT)->GetText().GetForLanguage(language);
|
||||
if (ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){
|
||||
jsonData["ganonHintText"] = ganonHintText;
|
||||
jsonData["ganonHintText"] = ctx->GetHint(RH_GANONDORF_HINT)->GetText().GetForLanguage(language);
|
||||
jsonData["lightArrowHintLoc"] = GetLightArrowHintLoc();
|
||||
jsonData["lightArrowArea"] = ::Hint(ctx->GetHint(RH_GANONDORF_HINT)->GetHintedArea()).GetText().GetEnglish();
|
||||
jsonData["masterSwordHintLoc"] = GetMasterSwordHintLoc();
|
||||
if (!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) {
|
||||
jsonData["sheikText"] = sheikText;
|
||||
jsonData["sheikText"] = ctx->GetHint(RH_SHEIK_LIGHT_ARROWS)->GetText().GetForLanguage(language);
|
||||
}
|
||||
}
|
||||
if (ctx->GetOption(RSK_DAMPES_DIARY_HINT)){
|
||||
jsonData["dampeText"] = dampesText;
|
||||
jsonData["dampeText"] = ctx->GetHint(RH_DAMPES_DIARY)->GetText().GetForLanguage(language);
|
||||
jsonData["dampeHintLoc"] = GetDampeHintLoc();
|
||||
jsonData["dampeRegion"] = ::Hint(ctx->GetHint(RH_DAMPES_DIARY)->GetHintedArea()).GetText().GetEnglish();
|
||||
}
|
||||
if (ctx->GetOption(RSK_GREG_HINT)){
|
||||
jsonData["gregText"] = gregText;
|
||||
jsonData["gregText"] = ctx->GetHint(RH_GREG_RUPEE)->GetText().GetForLanguage(language);
|
||||
jsonData["gregLoc"] = GetGregHintLoc();
|
||||
jsonData["gregRegion"] = ::Hint(ctx->GetHint(RH_GREG_RUPEE)->GetHintedArea()).GetText().GetEnglish();
|
||||
}
|
||||
if (ctx->GetOption(RSK_SARIA_HINT)){
|
||||
jsonData["sariaText"] = sariaText;
|
||||
jsonData["sariaText"] = ctx->GetHint(RH_SARIA)->GetText().GetForLanguage(language);
|
||||
jsonData["sariaHintLoc"] = GetSariaHintLoc();
|
||||
jsonData["sariaRegion"] = ::Hint(ctx->GetHint(RH_SARIA)->GetHintedArea()).GetText().GetEnglish();
|
||||
}
|
||||
@ -721,17 +627,7 @@ static void WriteHints() {
|
||||
for (const RandomizerCheck key : Rando::StaticData::gossipStoneLocations) { //RANDOTODO should be merged with static hints, iterate over hint keys
|
||||
Rando::Hint* hint = ctx->GetHint((RandomizerHintKey)(key - RC_COLOSSUS_GOSSIP_STONE + 1));
|
||||
Rando::ItemLocation* hintedLocation = ctx->GetItemLocation(hint->GetHintedLocation());
|
||||
std::string hintTextString;
|
||||
switch (ctx->GetOption(RSK_LANGUAGE).GetSelectedOptionIndex()) {
|
||||
case 0:
|
||||
default:
|
||||
hintTextString = hint->GetText().GetEnglish();
|
||||
break;
|
||||
case 2:
|
||||
hintTextString = hint->GetText().GetFrench();
|
||||
break;
|
||||
}
|
||||
|
||||
std::string hintTextString = hint->GetText().GetForLanguage(language);
|
||||
HintType hintType = hint->GetHintType();
|
||||
|
||||
std::string textStr = hintTextString;
|
||||
|
@ -12,8 +12,14 @@ public:
|
||||
Text(std::string english_, std::string french_, std::string spanish_)
|
||||
: english(std::move(english_)),
|
||||
french(std::move(french_)),
|
||||
spanish(std::move(spanish_)) {}
|
||||
Text(std::string english_) : english(std::move(english_)), french(std::move("")), spanish(std::move("")) {}
|
||||
spanish(std::move(spanish_)),
|
||||
german(std::move("")) {}
|
||||
Text(std::string english_, std::string french_, std::string spanish_, std::string german_)
|
||||
: english(std::move(english_)),
|
||||
french(std::move(french_)),
|
||||
spanish(std::move(spanish_)),
|
||||
german(std::move(german_)) {}
|
||||
Text(std::string english_) : english(std::move(english_)), french(std::move("")), spanish(std::move("")), german(std::move("")) {}
|
||||
|
||||
const std::string& GetEnglish() const {
|
||||
return english;
|
||||
@ -33,6 +39,13 @@ public:
|
||||
return english;
|
||||
}
|
||||
|
||||
const std::string& GetGerman() const {
|
||||
if (german.length() > 0) {
|
||||
return german;
|
||||
}
|
||||
return english;
|
||||
}
|
||||
|
||||
const std::string& GetForLanguage(uint8_t language) const {
|
||||
switch (language) {
|
||||
case LANGUAGE_ENG:
|
||||
@ -40,17 +53,19 @@ public:
|
||||
case LANGUAGE_FRA:
|
||||
return french;
|
||||
case LANGUAGE_GER:
|
||||
return german;
|
||||
default:
|
||||
return english; // TODO: German
|
||||
return english;
|
||||
}
|
||||
}
|
||||
|
||||
Text operator+ (const Text& right) const {
|
||||
return Text{english + right.GetEnglish(), french + right.GetFrench(), spanish + right.GetSpanish()};
|
||||
return Text{english + right.GetEnglish(), french + right.GetFrench(), spanish + right.GetSpanish(),
|
||||
german + right.GetGerman()};
|
||||
}
|
||||
|
||||
Text operator+ (const std::string& right) const {
|
||||
return Text{english + right, french + right, spanish + right};
|
||||
return Text{english + right, french + right, spanish + right, german + right};
|
||||
}
|
||||
|
||||
bool operator==(const Text& right) const {
|
||||
@ -58,7 +73,7 @@ public:
|
||||
}
|
||||
|
||||
bool operator==(const std::string& right) const {
|
||||
return english == right || french == right || spanish == right;
|
||||
return english == right || french == right || spanish == right || german == right;
|
||||
}
|
||||
|
||||
bool operator!=(const Text& right) const {
|
||||
@ -67,7 +82,7 @@ public:
|
||||
|
||||
void Replace(std::string oldStr, std::string newStr) {
|
||||
|
||||
for (std::string* str : {&english, &french, &spanish}) {
|
||||
for (std::string* str : {&english, &french, &spanish, &german}) {
|
||||
size_t position = str->find(oldStr);
|
||||
while (position != std::string::npos) {
|
||||
str->replace(position, oldStr.length(), newStr);
|
||||
@ -79,7 +94,7 @@ public:
|
||||
// Convert first char to upper case
|
||||
Text Capitalize(void) const {
|
||||
Text cap = *this + "";
|
||||
for (std::string* str : {&cap.english, &cap.french, &cap.spanish}) {
|
||||
for (std::string* str : {&cap.english, &cap.french, &cap.spanish, &cap.german}) {
|
||||
(*str)[0] = std::toupper((*str)[0]);
|
||||
}
|
||||
return cap;
|
||||
@ -87,7 +102,7 @@ public:
|
||||
|
||||
//find the appropriate bars that separate singular from plural
|
||||
void SetForm(int form) {
|
||||
for (std::string* str : {&english, &french, &spanish}) {
|
||||
for (std::string* str : {&english, &french, &spanish, &german}) {
|
||||
|
||||
size_t firstBar = str->find('|');
|
||||
if (firstBar != std::string::npos) {
|
||||
@ -114,4 +129,5 @@ public:
|
||||
std::string english = "";
|
||||
std::string french = "";
|
||||
std::string spanish = "";
|
||||
std::string german = "";
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ Context::Context() {
|
||||
{ "Item Location", HINT_TYPE_ITEM_LOCATION },
|
||||
{ "Junk", HINT_TYPE_JUNK },
|
||||
};
|
||||
|
||||
|
||||
mSpoilerfileAreaNameToEnum = {
|
||||
{"No Hint", RA_NONE},
|
||||
{"Link's Pocket", RA_LINKS_POCKET},
|
||||
@ -423,187 +423,97 @@ void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string AltarIconString(const char iconChar) {
|
||||
std::string iconString;
|
||||
iconString += '\x13';
|
||||
switch (iconChar) {
|
||||
case '0':
|
||||
// Kokiri Emerald
|
||||
iconString += '\x6C';
|
||||
break;
|
||||
case '1':
|
||||
// Goron Ruby
|
||||
iconString += '\x6D';
|
||||
break;
|
||||
case '2':
|
||||
// Zora Sapphire
|
||||
iconString += '\x6E';
|
||||
break;
|
||||
case '3':
|
||||
// Forest Medallion
|
||||
iconString += '\x66';
|
||||
break;
|
||||
case '4':
|
||||
// Fire Medallion
|
||||
iconString += '\x67';
|
||||
break;
|
||||
case '5':
|
||||
// Water Medallion
|
||||
iconString += '\x68';
|
||||
break;
|
||||
case '6':
|
||||
// Spirit Medallion
|
||||
iconString += '\x69';
|
||||
break;
|
||||
case '7':
|
||||
// Shadow Medallion
|
||||
iconString += '\x6A';
|
||||
break;
|
||||
case '8':
|
||||
// Light Medallion
|
||||
iconString += '\x6B';
|
||||
break;
|
||||
case 'o':
|
||||
// Open DOT (master sword)
|
||||
iconString += '\x3C';
|
||||
break;
|
||||
case 'c':
|
||||
// Closed DOT (fairy ocarina)
|
||||
iconString += '\x07';
|
||||
break;
|
||||
case 'i':
|
||||
// Intended DOT (oot)
|
||||
iconString += '\x08';
|
||||
break;
|
||||
case 'l':
|
||||
// Light Arrow (for bridge reqs)
|
||||
iconString += '\x12';
|
||||
break;
|
||||
case 'b':
|
||||
// Boss Key (ganon boss key location)
|
||||
iconString += '\x74';
|
||||
break;
|
||||
case 'L':
|
||||
// Bow with Light Arrow
|
||||
iconString += '\x3A';
|
||||
break;
|
||||
case 'k':
|
||||
// Kokiri Tunic
|
||||
iconString += '\x41';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return iconString;
|
||||
}
|
||||
|
||||
std::string FormatJsonHintText(const std::string& jsonHint) {
|
||||
std::string formattedHintMessage = jsonHint;
|
||||
|
||||
// add icons to altar text
|
||||
for (const char iconChar : { '0', '1', '2', '3', '4', '5', '6', '7', '8', 'o', 'c', 'i', 'l', 'b', 'L', 'k' }) {
|
||||
std::string textToReplace = "$";
|
||||
textToReplace += iconChar;
|
||||
if (const size_t start_pos = formattedHintMessage.find(textToReplace); start_pos != std::string::npos) {
|
||||
std::string iconString = AltarIconString(iconChar);
|
||||
formattedHintMessage.replace(start_pos, textToReplace.length(), iconString);
|
||||
}
|
||||
}
|
||||
return formattedHintMessage;
|
||||
}
|
||||
|
||||
void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
|
||||
// Child Altar
|
||||
std::string childAltarJsonText = spoilerFileJson["childAltar"]["hintText"].get<std::string>();
|
||||
std::string formattedChildAltarText = FormatJsonHintText(childAltarJsonText);
|
||||
AddHint(RH_ALTAR_CHILD, Text(formattedChildAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
std::string childAltarText = spoilerFileJson["childAltar"]["hintText"].get<std::string>();
|
||||
AddHint(RH_ALTAR_CHILD, Text(childAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE);
|
||||
mEmeraldLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["emeraldLoc"]];
|
||||
mRubyLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["rubyLoc"]];
|
||||
mSapphireLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["childAltar"]["rewards"]["sapphireLoc"]];
|
||||
|
||||
// Adult Altar
|
||||
std::string adultAltarJsonText = spoilerFileJson["adultAltar"]["hintText"].get<std::string>();
|
||||
std::string formattedAdultAltarText = FormatJsonHintText(adultAltarJsonText);
|
||||
AddHint(RH_ALTAR_ADULT, Text(formattedAdultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
|
||||
std::string adultAltarText = spoilerFileJson["adultAltar"]["hintText"].get<std::string>();
|
||||
AddHint(RH_ALTAR_ADULT, Text(adultAltarText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", RA_NONE);
|
||||
mForestMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["forestMedallionLoc"].get<std::string>()];
|
||||
mFireMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["fireMedallionLoc"].get<std::string>()];
|
||||
mWaterMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["waterMedallionLoc"].get<std::string>()];
|
||||
mShadowMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["shadowMedallionLoc"].get<std::string>()];
|
||||
mSpiritMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["spiritMedallionLoc"].get<std::string>()];
|
||||
mLightMedallionLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["adultAltar"]["rewards"]["lightMedallionLoc"].get<std::string>()];
|
||||
|
||||
|
||||
// Ganondorf and Sheik Light Arrow Hints
|
||||
std::string ganonHintText = FormatJsonHintText(spoilerFileJson["ganonHintText"].get<std::string>());
|
||||
std::string ganonHintText = spoilerFileJson["ganonHintText"].get<std::string>();
|
||||
RandomizerCheck lightArrowLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["lightArrowHintLoc"].get<std::string>()];
|
||||
std::string lightArrowRegion = spoilerFileJson["lightArrowArea"].get<std::string>();
|
||||
AddHint(RH_GANONDORF_HINT, Text(ganonHintText), lightArrowLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[lightArrowRegion]);
|
||||
if (spoilerFileJson.contains("sheikText")) {
|
||||
std::string sheikText = FormatJsonHintText(spoilerFileJson["sheikText"].get<std::string>());
|
||||
std::string sheikText = spoilerFileJson["sheikText"].get<std::string>();
|
||||
AddHint(RH_SHEIK_LIGHT_ARROWS, Text(sheikText), lightArrowLoc, HINT_TYPE_STATIC, lightArrowRegion);
|
||||
}
|
||||
std::string ganonText = FormatJsonHintText(spoilerFileJson["ganonText"].get<std::string>());
|
||||
std::string ganonText = spoilerFileJson["ganonText"].get<std::string>();
|
||||
AddHint(RH_GANONDORF_NOHINT, Text(ganonText), RC_UNKNOWN_CHECK, HINT_TYPE_JUNK, "Static", RA_GANONS_CASTLE);
|
||||
|
||||
|
||||
// Dampe Hookshot Hint
|
||||
if (spoilerFileJson.contains("dampeText")) {
|
||||
std::string dampeText = FormatJsonHintText(spoilerFileJson["dampeText"].get<std::string>());
|
||||
std::string dampeText = spoilerFileJson["dampeText"].get<std::string>();
|
||||
std::string dampeRegion = spoilerFileJson["dampeRegion"].get<std::string>();
|
||||
RandomizerCheck dampeHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["dampeHintLoc"].get<std::string>()];
|
||||
AddHint(RH_DAMPES_DIARY, Text(dampeText), dampeHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[dampeRegion]);
|
||||
}
|
||||
|
||||
|
||||
// Greg Hint
|
||||
if (spoilerFileJson.contains("gregText")) {
|
||||
std::string gregText = FormatJsonHintText(spoilerFileJson["gregText"].get<std::string>());
|
||||
std::string gregText = spoilerFileJson["gregText"].get<std::string>();
|
||||
std::string gregRegion = spoilerFileJson["gregRegion"].get<std::string>();
|
||||
RandomizerCheck gregLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["gregLoc"].get<std::string>()];
|
||||
AddHint(RH_GREG_RUPEE, Text(gregText), gregLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[gregRegion]);
|
||||
}
|
||||
|
||||
|
||||
// Saria Magic Hint
|
||||
if (spoilerFileJson.contains("sariaText")) {
|
||||
std::string sariaText = FormatJsonHintText(spoilerFileJson["sariaText"].get<std::string>());
|
||||
std::string sariaText = spoilerFileJson["sariaText"].get<std::string>();
|
||||
std::string sariaRegion = spoilerFileJson["sariaRegion"].get<std::string>();
|
||||
RandomizerCheck sariaHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["sariaHintLoc"].get<std::string>()];
|
||||
AddHint(RH_SARIA, Text(sariaText), sariaHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[sariaRegion]);
|
||||
}
|
||||
|
||||
|
||||
// Warp Songs
|
||||
if (spoilerFileJson.contains("warpMinuetText")) {
|
||||
std::string warpMinuetText = FormatJsonHintText(spoilerFileJson["warpMinuetText"].get<std::string>()); //RANDOTODO fall back for if location is used
|
||||
std::string warpMinuetText = spoilerFileJson["warpMinuetText"].get<std::string>(); //RANDOTODO fall back for if location is used
|
||||
AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpMinuetText]);
|
||||
}
|
||||
if (spoilerFileJson.contains("warpBoleroText")) {
|
||||
std::string warpBoleroText = FormatJsonHintText(spoilerFileJson["warpBoleroText"].get<std::string>());
|
||||
std::string warpBoleroText = spoilerFileJson["warpBoleroText"].get<std::string>();
|
||||
AddHint(RH_BOLERO_WARP_LOC, Text(warpBoleroText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpBoleroText]);
|
||||
}
|
||||
if (spoilerFileJson.contains("warpSerenadeText")) {
|
||||
std::string warpSerenadeText = FormatJsonHintText(spoilerFileJson["warpSerenadeText"].get<std::string>());
|
||||
std::string warpSerenadeText = spoilerFileJson["warpSerenadeText"].get<std::string>();
|
||||
AddHint(RH_SERENADE_WARP_LOC, Text(warpSerenadeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpSerenadeText]);
|
||||
}
|
||||
if (spoilerFileJson.contains("warpRequiemText")) {
|
||||
std::string warpRequiemText = FormatJsonHintText(spoilerFileJson["warpRequiemText"].get<std::string>());
|
||||
std::string warpRequiemText = spoilerFileJson["warpRequiemText"].get<std::string>();
|
||||
AddHint(RH_REQUIEM_WARP_LOC, Text(warpRequiemText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpRequiemText]);
|
||||
}
|
||||
if (spoilerFileJson.contains("warpNocturneText")) {
|
||||
std::string warpNocturneText = FormatJsonHintText(spoilerFileJson["warpNocturneText"].get<std::string>());
|
||||
std::string warpNocturneText = spoilerFileJson["warpNocturneText"].get<std::string>();
|
||||
AddHint(RH_NOCTURNE_WARP_LOC, Text(warpNocturneText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpNocturneText]);
|
||||
}
|
||||
if (spoilerFileJson.contains("warpPreludeText")) {
|
||||
std::string warpPreludeText = FormatJsonHintText(spoilerFileJson["warpPreludeText"].get<std::string>());
|
||||
std::string warpPreludeText = spoilerFileJson["warpPreludeText"].get<std::string>();
|
||||
AddHint(RH_PRELUDE_WARP_LOC, Text(warpPreludeText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[warpPreludeText]);
|
||||
}
|
||||
|
||||
|
||||
// Gossip Stones
|
||||
nlohmann::json hintsJson = spoilerFileJson["hints"];
|
||||
for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) {
|
||||
RandomizerCheck gossipStoneLoc = mSpoilerfileCheckNameToEnum[it.key()];
|
||||
nlohmann::json hintInfo = it.value();
|
||||
std::string hintText = FormatJsonHintText(hintInfo["hint"].get<std::string>());
|
||||
std::string hintText = hintInfo["hint"].get<std::string>();
|
||||
HintType hintType = mSpoilerfileHintTypeNameToEnum[hintInfo["type"].get<std::string>()];
|
||||
RandomizerCheck hintedLocation = hintInfo.contains("location") ? mSpoilerfileCheckNameToEnum[hintInfo["location"]] : RC_UNKNOWN_CHECK;
|
||||
std::string hintedArea = hintInfo.contains("area") ? hintInfo["area"].get<std::string>() : "";
|
||||
AddHint(static_cast<RandomizerHintKey>(gossipStoneLoc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), hintedLocation, hintType, hintedArea);
|
||||
RandomizerArea hintedArea = hintInfo.contains("area") ? mSpoilerfileAreaNameToEnum[hintInfo["area"].get<std::string>()] : RA_NONE;
|
||||
std::string distribution = hintInfo["distribution"].get<std::string>();
|
||||
AddHint(static_cast<RandomizerHintKey>(gossipStoneLoc - RC_COLOSSUS_GOSSIP_STONE + 1), Text(hintText), hintedLocation, hintType, distribution, hintedArea);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +297,7 @@ void Randomizer::LoadHintMessages() {
|
||||
CustomMessage("{{message}}", "{{message}}", "{{message}}"));
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_SARIAS_SONG_FACE_TO_FACE,
|
||||
CustomMessage(ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE));
|
||||
CustomMessage(ctx->GetHint(RH_SARIA)->GetText().GetEnglish(), ctx->GetHint(RH_SARIA)->GetText().GetGerman(), ctx->GetHint(RH_SARIA)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE));
|
||||
|
||||
for (int i : Rando::StaticData::gossipStoneLocations) {
|
||||
RandomizerHintKey rhk = RandomizerHintKey(i - RC_COLOSSUS_GOSSIP_STONE + 1);
|
||||
@ -329,19 +329,34 @@ void Randomizer::LoadHintMessages() {
|
||||
);
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::randoMiscHintsTableID, TEXT_FROGS_UNDERWATER,
|
||||
CustomMessage("Some frogs holding&%g{{item}}%w&are looking at you from underwater...",
|
||||
"Unter Wasser gibt es Frösche,&die %g{{item}}%w&bei sich haben und Dich neugierig&beobachten...",
|
||||
"Des grenouilles se trouvant&sous l'eau vous fixent attentivement,&tenant fermement&%g{{item}}%w.", TEXTBOX_TYPE_BLUE)
|
||||
CustomMessage(ctx->GetHint(RH_FROGS)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_FROGS)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_FROGS)->GetText().GetFrench(), TEXTBOX_TYPE_BLUE)
|
||||
);
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::randoMiscHintsTableID, TEXT_SARIAS_SONG_FACE_TO_FACE,
|
||||
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",
|
||||
"Se téléporter vers&{{location}}?\x1B&%gOK!&Non%w\x02"));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_MINUET_OF_FOREST,
|
||||
CustomMessage(ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_MINUET_WARP_LOC)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_BOLERO_OF_FIRE,
|
||||
CustomMessage(ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_BOLERO_WARP_LOC)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_SERENADE_OF_WATER,
|
||||
CustomMessage(ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_SERENADE_WARP_LOC)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_REQUIEM_OF_SPIRIT,
|
||||
CustomMessage(ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_NOCTURNE_OF_SHADOW,
|
||||
CustomMessage(ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::randoMiscHintsTableID, TEXT_WARP_PRELUDE_OF_LIGHT,
|
||||
CustomMessage(ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetText().GetFrench()));
|
||||
|
||||
// Bow Shooting Gallery reminder
|
||||
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW,
|
||||
@ -394,6 +409,7 @@ std::unordered_map<RandomizerGet, EnGirlAShopItem> randomizerGetToEnGirlShopItem
|
||||
};
|
||||
|
||||
void Randomizer::LoadMerchantMessages() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
CustomMessageManager::Instance->ClearMessageTable(Randomizer::merchantMessageTableID);
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::merchantMessageTableID);
|
||||
|
||||
@ -408,12 +424,9 @@ void Randomizer::LoadMerchantMessages() {
|
||||
"\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter&un %g{{item}}%w?&Ça fera %r{{price}} Rubis%w!\x07\x10\xA3"));
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10,
|
||||
CustomMessage("I tried to be a %rmagic bean%w salesman,&but it turns out my marketing skills&weren't worth "
|
||||
"beans!^Anyway, want to buy my&%gmysterious item%w for 60 Rupees?\x1B&%gYes&No%w",
|
||||
"Möchten Sie einen geheimnisvollen&Gegenstand für 60 Rubine?\x1B&%gJa&Nein%w",
|
||||
"J'ai essayé d'être un vendeur de&%rharicots magiques%w, mais j'étais&mauvais au niveau du marketing et&ça "
|
||||
"me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter un&"
|
||||
"%gobjet mystérieux%w pour 60 Rubis?\x1B&%gOui&Non%w"));
|
||||
CustomMessage(ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_BEAN_SALESMAN)->GetText().GetFrench()));
|
||||
|
||||
|
||||
//Setup for merchant text boxes
|
||||
@ -421,51 +434,30 @@ void Randomizer::LoadMerchantMessages() {
|
||||
//RANDOTODO: Implement obscure/ambiguous hints
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_MEDIGORON,
|
||||
CustomMessage("How about buying %g&{{item}}%w for %y200 rupees%w?\x1B&%gYes&No%w",
|
||||
"Wie wäre es mit %g&{{item}}%w für %y200 Rubine?%w\x1B&%gJa!&Nein!%w",
|
||||
"Veux-tu acheter %g&{{item}}%w pour %y200 rubis?%w\x1B&%gOui&Non&w"));
|
||||
CustomMessage(ctx->GetHint(RH_MEDIGORON)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_MEDIGORON)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_MEDIGORON)->GetText().GetFrench()));
|
||||
|
||||
//Granny Shopy
|
||||
//RANDOTODO: Implement obscure/ambiguous hints
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP,
|
||||
CustomMessage("%g{{item}}%w!&How about %y100 rupees%w?\x1B&%gYes&No%w",
|
||||
"%g{{item}}%w!&Wie wäre es mit %y100 Rubine?%w\x1B&%gJa!&Nein!%w",
|
||||
"%g{{item}}%w!&Que dis-tu de %y100 rubis?%w\x1B&%gOui&Non&w"));
|
||||
CustomMessage(ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_GRANNYS_SHOP)->GetText().GetFrench()));
|
||||
|
||||
//Carpet Salesman
|
||||
//RANDOTODO: Implement obscure/ambiguous hints
|
||||
std::vector<std::string> cgBoxTwoText;
|
||||
if (Randomizer::GetRandoSettingValue(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_ON_HINT) {
|
||||
cgBoxTwoText = {
|
||||
"!%w&It's real, I promise!&A lonely man such as myself&wouldn't %rlie%w to you, hmm?^",
|
||||
"!%w&Ich kann versichern es ist ein&aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich&doch nicht %ranlügen%w, oder?^",
|
||||
"!%w&C'est vrai! J'te jure!&Un gars comme moi ne te %rmentirai%w pas&tu ne crois pas?^"
|
||||
};
|
||||
} else {
|
||||
cgBoxTwoText = {
|
||||
"!%w&I won't tell you what it is until I see&the money...^",
|
||||
"!%w&Erst kommt das Geld, dann die Ware...^",
|
||||
"!%w&Je ne te dirai pas ce que c'est avant&d'être payé rubis sur l'ongle...^"
|
||||
};
|
||||
}
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1,
|
||||
CustomMessage("Welcome!^I am selling stuff, strange and rare, &from all over the world to "
|
||||
"everybody.&Today's special is...^%g{{item}}" +
|
||||
cgBoxTwoText[0] + "How about %y200 Rupees?%w\x1B&&%gYes&No%w",
|
||||
"Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten.&Stets sonderliche und seltene Ware&aus "
|
||||
"aller Welt für jedermann.&Das heutige Angebot bleibt...^%g{{item}}" +
|
||||
cgBoxTwoText[1] + "Wie wäre es mit %y200 Rubinen?%w\x1B&&%gJa!&Nein!%w",
|
||||
"Bienvenue!^Je vends des trucs étranges et rares,&de partout dans le monde et à tout "
|
||||
"le&monde! L'objet du jour est...^%g{{item}}" +
|
||||
cgBoxTwoText[2] + "Alors, marché conclu pour %y200 rubis?%w\x1B&&%gOui&Non%w"));
|
||||
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2,
|
||||
CustomMessage("Finally! Now I can go back to being &an %rarms dealer%w!",
|
||||
"Endlich! Schon bald kann ich wieder &%rKrabbelminen-Händler%w sein!",
|
||||
"Squalala! Je vais enfin pouvoir &%rprendre des vacances%w!"));
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1,
|
||||
CustomMessage(ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN)->GetText().GetFrench()));
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2,
|
||||
CustomMessage(ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetEnglish(),
|
||||
ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetGerman(),
|
||||
ctx->GetHint(RH_WASTELAND_BOMBCHU_SALESMAN_POST)->GetText().GetFrench()));
|
||||
|
||||
// Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are
|
||||
// prompted buy/don't buy
|
||||
@ -1145,7 +1137,7 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem
|
||||
return GI_HEART_PIECE_WIN;
|
||||
case RG_TREASURE_GAME_GREEN_RUPEE:
|
||||
return GI_RUPEE_GREEN_LOSE;
|
||||
|
||||
|
||||
//Ocarina Buttons
|
||||
case RG_OCARINA_A_BUTTON:
|
||||
return (GetItemID)RG_OCARINA_A_BUTTON;
|
||||
@ -2368,77 +2360,6 @@ void RandomizerSettingsWindow::UpdateElement() {
|
||||
}
|
||||
}
|
||||
|
||||
CustomMessage Randomizer::GetWarpSongMessage(u16 textId, bool mysterious) {
|
||||
CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT);
|
||||
if (mysterious) {
|
||||
std::array<const char*, LANGUAGE_MAX> locationName ={
|
||||
"a mysterious place",
|
||||
"ein mysteriöser Ort",
|
||||
"un endroit mystérieux",
|
||||
};
|
||||
|
||||
messageEntry.Replace("{{location}}", locationName[0],
|
||||
locationName[1], locationName[2]);
|
||||
return messageEntry;
|
||||
}
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
RandomizerHintKey locHintKey = RH_NONE;
|
||||
switch (textId) {
|
||||
case TEXT_WARP_MINUET_OF_FOREST:
|
||||
locHintKey = RH_MINUET_WARP_LOC;
|
||||
break;
|
||||
case TEXT_WARP_BOLERO_OF_FIRE:
|
||||
locHintKey = RH_BOLERO_WARP_LOC;
|
||||
break;
|
||||
case TEXT_WARP_SERENADE_OF_WATER:
|
||||
locHintKey = RH_SERENADE_WARP_LOC;
|
||||
break;
|
||||
case TEXT_WARP_REQUIEM_OF_SPIRIT:
|
||||
locHintKey = RH_REQUIEM_WARP_LOC;
|
||||
break;
|
||||
case TEXT_WARP_NOCTURNE_OF_SHADOW:
|
||||
locHintKey = RH_NOCTURNE_WARP_LOC;
|
||||
break;
|
||||
case TEXT_WARP_PRELUDE_OF_LIGHT:
|
||||
locHintKey = RH_PRELUDE_WARP_LOC;
|
||||
break;
|
||||
}
|
||||
std::string locationName = "";
|
||||
switch (gSaveContext.language) {
|
||||
case LANGUAGE_FRA:
|
||||
locationName = ctx->GetHint(locHintKey)->GetText().GetFrench();
|
||||
break;
|
||||
case LANGUAGE_ENG:
|
||||
default:
|
||||
locationName = ctx->GetHint(locHintKey)->GetText().GetEnglish();
|
||||
break;
|
||||
}
|
||||
|
||||
messageEntry.Replace("{{location}}", std::move(locationName));
|
||||
return messageEntry;
|
||||
}
|
||||
|
||||
CustomMessage Randomizer::GetFrogsMessage(u16 originalTextId) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, originalTextId);
|
||||
RandomizerGet frogsGet = ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME)->GetPlacedRandomizerGet();
|
||||
std::array<std::string, LANGUAGE_MAX> frogItemName;
|
||||
if (frogsGet == RG_ICE_TRAP) {
|
||||
frogsGet = ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].LooksLike();
|
||||
frogItemName = {
|
||||
ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].GetTrickName().english,
|
||||
ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].GetTrickName().french,
|
||||
ctx->overrides[RC_ZR_FROGS_OCARINA_GAME].GetTrickName().english
|
||||
};
|
||||
} else {
|
||||
frogItemName = EnumToSpoilerfileGetName[frogsGet];
|
||||
}
|
||||
messageEntry.Replace("{{item}}", std::move(frogItemName[0]), std::move(frogItemName[1]), std::move(frogItemName[2]));
|
||||
return messageEntry;
|
||||
}
|
||||
|
||||
CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, originalTextId);
|
||||
|
@ -58,9 +58,7 @@ class Randomizer {
|
||||
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
|
||||
ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
|
||||
ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck);
|
||||
CustomMessage GetWarpSongMessage(u16 textId, bool mysterious = false);
|
||||
CustomMessage GetSheikMessage(s16 scene, u16 originalTextId);
|
||||
CustomMessage GetFrogsMessage(u16 originalTextId);
|
||||
CustomMessage GetSariaMessage(u16 originalTextId);
|
||||
CustomMessage GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
|
||||
CustomMessage GetCursedSkullMessage(s16 params);
|
||||
|
@ -1951,9 +1951,11 @@ typedef enum {
|
||||
RH_GANONDORF_NOHINT,
|
||||
RH_DAMPES_DIARY,
|
||||
RH_GREG_RUPEE,
|
||||
RH_BEAN_SALESMAN,
|
||||
RH_MEDIGORON,
|
||||
RH_GRANNYS_SHOP,
|
||||
RH_WASTELAND_BOMBCHU_SALESMAN,
|
||||
RH_WASTELAND_BOMBCHU_SALESMAN_POST,
|
||||
RH_ALTAR_CHILD,
|
||||
RH_ALTAR_ADULT,
|
||||
RH_SARIA,
|
||||
@ -1964,6 +1966,7 @@ typedef enum {
|
||||
RH_REQUIEM_WARP_LOC,
|
||||
RH_NOCTURNE_WARP_LOC,
|
||||
RH_PRELUDE_WARP_LOC,
|
||||
RH_FROGS,
|
||||
RH_MAX,
|
||||
} RandomizerHintKey;
|
||||
|
||||
@ -3050,6 +3053,7 @@ typedef enum {
|
||||
RHT_BUY_RED_POTION_50,
|
||||
RHT_TRIFORCE,
|
||||
RHT_HINT,
|
||||
RHT_HINT_MYSTERIOUS,
|
||||
RHT_TYCOON_WALLET,
|
||||
RHT_HOOKSHOT,
|
||||
RHT_LONGSHOT,
|
||||
@ -3276,6 +3280,10 @@ typedef enum {
|
||||
RHT_GREG_HINT02,
|
||||
RHT_SARIA_TEXT01,
|
||||
RHT_SARIA_TEXT02,
|
||||
RHT_WARP_TO,
|
||||
RHT_WARP_CHOICE,
|
||||
RHT_FROGS_HINT01,
|
||||
RHT_FROGS_HINT02,
|
||||
// Ganon Line
|
||||
RHT_GANON_LINE01,
|
||||
RHT_GANON_LINE02,
|
||||
@ -3289,12 +3297,14 @@ typedef enum {
|
||||
RHT_GANON_LINE10,
|
||||
RHT_GANON_LINE11,
|
||||
// Merchants
|
||||
RHT_BEAN_SALESMAN_FIRST,
|
||||
RHT_BEAN_SALESMAN_SECOND,
|
||||
RHT_MEDIGORON_DIALOG_FIRST,
|
||||
RHT_MEDIGORON_DIALOG_SECOND,
|
||||
RHT_CARPET_SALESMAN_DIALOG_FIRST,
|
||||
RHT_CARPET_SALESMAN_DIALOG_SECOND,
|
||||
RHT_CARPET_SALESMAN_DIALOG_THIRD,
|
||||
RHT_CARPET_SALESMAN_DIALOG_FOURTH,
|
||||
RHT_CARPET_SALESMAN_DIALOG_MYSTERIOUS,
|
||||
RHT_CARPET_SALESMAN_DIALOG_HINTED,
|
||||
RHT_CARPET_SALESMAN_DIALOG_FINAL,
|
||||
RHT_GRANNY_DIALOG,
|
||||
RHT_MAX
|
||||
} RandomizerHintTextKey;
|
||||
|
@ -2585,15 +2585,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||
(Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) ||
|
||||
(textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) ||
|
||||
(textId == TEXT_CARPET_SALESMAN_2 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)))) {
|
||||
RandomizerInf randoInf;
|
||||
if (textId == TEXT_MEDIGORON) {
|
||||
randoInf = RAND_INF_MERCHANTS_MEDIGORON;
|
||||
} else if (textId == TEXT_GRANNYS_SHOP) {
|
||||
randoInf = RAND_INF_MERCHANTS_GRANNYS_SHOP;
|
||||
} else {
|
||||
randoInf = RAND_INF_MERCHANTS_CARPET_SALESMAN;
|
||||
}
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT);
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId);
|
||||
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
|
||||
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
||||
@ -2611,7 +2603,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_CHEST_GAME_PROCEED);
|
||||
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
|
||||
(textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT)) {
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, Randomizer_GetSettingValue(RSK_WARP_SONG_HINTS) == RO_GENERIC_OFF);
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textId);
|
||||
} else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) {
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId);
|
||||
} else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) {
|
||||
@ -2620,7 +2612,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||
u16 choice = Random(0, NUM_GORON_MESSAGES);
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice);
|
||||
} else if (Randomizer_GetSettingValue(RSK_FROGS_HINT) && textId == TEXT_FROGS_UNDERWATER) {
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetFrogsMessage(textId);
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, textId);
|
||||
} else if (Randomizer_GetSettingValue(RSK_SARIA_HINT)) {
|
||||
if ((gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) {
|
||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId);
|
||||
|
@ -339,7 +339,7 @@ void SaveManager::LoadRandomizerVersion3() {
|
||||
"french", randoContext->GetItemOverride(i).GetTrickName().french);
|
||||
});
|
||||
}
|
||||
uint16_t price = 0;
|
||||
uint16_t price = 0;
|
||||
SaveManager::Instance->LoadData("price", price, (uint16_t)0);
|
||||
if (price > 0) {
|
||||
// Technically an item with a custom price (scrub/shopsanity) could have
|
||||
@ -385,11 +385,11 @@ void SaveManager::LoadRandomizerVersion3() {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
RandomizerHintKey rhk = RH_NONE;
|
||||
SaveManager::Instance->LoadData("hintKey", rhk);
|
||||
std::string english, french;
|
||||
std::string english, french, german;
|
||||
SaveManager::Instance->LoadStruct("hintText", [&]() {
|
||||
SaveManager::Instance->LoadData("english", english);
|
||||
SaveManager::Instance->LoadData("french", french);
|
||||
// TODO: German Hint Translations
|
||||
SaveManager::Instance->LoadData("german", german);
|
||||
});
|
||||
RandomizerCheck rc = RC_UNKNOWN_CHECK;
|
||||
SaveManager::Instance->LoadData("hintedCheck", rc);
|
||||
@ -397,7 +397,7 @@ void SaveManager::LoadRandomizerVersion3() {
|
||||
SaveManager::Instance->LoadData("hintType", ht);
|
||||
RandomizerArea savedArea;
|
||||
SaveManager::Instance->LoadData("hintedArea", savedArea);
|
||||
randoContext->AddHint(rhk, Text(english, french, english), rc, ht, "Unknown", savedArea);//RANDOTODO, maybe store and load distrabution, but it's a string...
|
||||
randoContext->AddHint(rhk, Text(english, french, /*spanish*/"", german), rc, ht, "Unknown", savedArea);//RANDOTODO, maybe store and load distrabution, but it's a string...
|
||||
});
|
||||
});
|
||||
|
||||
@ -479,8 +479,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
|
||||
SaveManager::Instance->SaveStruct("hintText", [&]() {
|
||||
SaveManager::Instance->SaveData("english", hint->GetText().GetEnglish());
|
||||
SaveManager::Instance->SaveData("french", hint->GetText().GetFrench());
|
||||
SaveManager::Instance->SaveData("german", hint->GetText().GetEnglish());
|
||||
// TODO: German Translation of hints
|
||||
SaveManager::Instance->SaveData("german", hint->GetText().GetGerman());
|
||||
});
|
||||
SaveManager::Instance->SaveData("hintedCheck", hint->GetHintedLocation());
|
||||
SaveManager::Instance->SaveData("hintType", hint->GetHintType());
|
||||
@ -1113,13 +1112,13 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se
|
||||
if (std::filesystem::exists(fileName)) {
|
||||
std::filesystem::remove(fileName);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||
copy_file(tempFile.c_str(), fileName.c_str());
|
||||
#else
|
||||
std::filesystem::copy_file(tempFile, fileName);
|
||||
#endif
|
||||
|
||||
|
||||
if (std::filesystem::exists(tempFile)) {
|
||||
std::filesystem::remove(tempFile);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user