Formatting and fixing bad merge conflict resolutions

This commit is contained in:
Christopher Leggett 2025-04-02 11:45:22 -04:00
commit ba7ffc9166
No known key found for this signature in database
GPG key ID: F2121C0AF9938ABF
18 changed files with 614 additions and 407 deletions

View file

@ -7,13 +7,13 @@ extern "C" {
#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk)
void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!",
"Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene "
"Skulltula-Symbole&gesammelt!", "Skulltula-Symbole&gesammelt!",
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en "
"tout!", "tout!",
TEXTBOX_TYPE_BLUE); TEXTBOX_TYPE_BLUE);
// The freeze text cannot be manually dismissed and must be auto-dismissed. // The freeze text cannot be manually dismissed and must be auto-dismissed.
// This is fine and even wanted when skull tokens are not shuffled, but when // This is fine and even wanted when skull tokens are not shuffled, but when
// when they are shuffled we don't want to be able to manually dismiss the box. // when they are shuffled we don't want to be able to manually dismiss the box.
@ -37,8 +37,7 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage(
"You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!",
"Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!",
"Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!" "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!");
);
msg.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); msg.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1));
msg.AutoFormat(ITEM_HEART_CONTAINER); msg.AutoFormat(ITEM_HEART_CONTAINER);
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -46,12 +45,11 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!",
"Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!",
"Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!",
TEXTBOX_TYPE_BLUE TEXTBOX_TYPE_BLUE);
);
msg.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); msg.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1));
msg.AutoFormat(ITEM_HEART_PIECE); msg.AutoFormat(ITEM_HEART_PIECE);
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -59,19 +57,24 @@ void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void InjectItemCounts_Register() { void InjectItemCounts_Register() {
COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0),
COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); BuildSkulltulaMessage);
COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0),
BuildSkulltulaMessage);
COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER,
CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage);
// Heart Pieces don't have documented text IDs after the first one, but // Heart Pieces don't have documented text IDs after the first one, but
// there are 3 more in between TEXT_HEART_PIECE and TEXT_HEART_CONTAINER. // there are 3 more in between TEXT_HEART_PIECE and TEXT_HEART_CONTAINER.
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0),
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); BuildHeartPieceMessage);
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0),
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); BuildHeartPieceMessage);
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0),
BuildHeartPieceMessage);
COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0),
BuildHeartPieceMessage);
} }
static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"),
CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"),
CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") });
CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece")
});

View file

@ -4,36 +4,36 @@ extern "C" {
#include <variables.h> #include <variables.h>
} }
//RANDOTODO: Port the rest of the behavior associated with this option here. // RANDOTODO: Port the rest of the behavior associated with this option here.
void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a "
"self-propelled time&bomb!\x09\x0A", "self-propelled time&bomb!\x09\x0A",
"\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als "
"Distanzwaffe&einsetzen kannst!\x09\x0A", "Distanzwaffe&einsetzen kannst!\x09\x0A",
"\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est "
"&destructrice!!!\x09\x0A" "&destructrice!!!\x09\x0A");
);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
} }
void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage("\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w",
"\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w",
"\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w");
"\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w"
);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
} }
void BetterBombchuShopping_Register() { void BetterBombchuShopping_Register() {
COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage); COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC,
COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage);
COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT,
IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage);
} }
static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register,
{ "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") });

View file

@ -7,18 +7,17 @@ extern "C" {
// RANDOTODO: Port the rest of the behavior for this enhancement here. // RANDOTODO: Port the rest of the behavior for this enhancement here.
void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w",
"You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w",
"Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w");
"Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w"
);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
} }
void MarketSneak_Register() { void MarketSneak_Register() {
COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0),
BuildNightGuardMessage);
} }
static RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); static RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") });

View file

@ -11,16 +11,17 @@ void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) {
// a brand new one. Might not be worth it. // a brand new one. Might not be worth it.
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage(
"Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w",
"Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du "
"Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w" "aufhören?&\x1B&%gJa&Nein%w",
); "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w");
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
} }
void QuitFishingAtDoor_Register() { void QuitFishingAtDoor_Register() {
COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0),
BuildQuitFishingMessage);
} }
static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") });

View file

@ -263,7 +263,8 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const {
int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) {
if (!inputStr.empty()) { if (!inputStr.empty()) {
// Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents
// negatives.
memset(buffer, 0, std::max<int>(0, maxBufferSize)); memset(buffer, 0, std::max<int>(0, maxBufferSize));
// Gaurentee that this value will be greater than 0, regardless of passed variables. // Gaurentee that this value will be greater than 0, regardless of passed variables.
const int copiedCharLen = std::min<int>(std::max<int>(0, maxBufferSize - 1), inputStr.length()); const int copiedCharLen = std::min<int>(std::max<int>(0, maxBufferSize - 1), inputStr.length());
@ -344,7 +345,7 @@ void CustomMessage::AutoFormat() {
} }
void CustomMessage::AutoFormat(ItemID iid) { void CustomMessage::AutoFormat(ItemID iid) {
for (std::string &str : messages) { for (std::string& str : messages) {
str.insert(0, ITEM_OBTAINED(iid)); str.insert(0, ITEM_OBTAINED(iid));
} }
AutoFormat(); AutoFormat();
@ -399,42 +400,44 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin
size_t totalPixelWidth = 0; size_t totalPixelWidth = 0;
size_t currentPos = lastNewline; size_t currentPos = lastNewline;
// Looping through the string from the lastNewline until the total // Looping through the string from the lastNewline until the total
// width of counted characters exceeds the maximum pixels in a line. // width of counted characters exceeds the maximum pixels in a line.
size_t nextPosJump = 0; size_t nextPosJump = 0;
while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) {
// Skip over control codes // Skip over control codes
if (textStr->at(currentPos) == '%') { if (textStr->at(currentPos) == '%') {
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x13') { } else if (textStr->at(currentPos) == '\x13') {
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '@') { } else if (textStr->at(currentPos) == '@') {
nextPosJump = 1; nextPosJump = 1;
// Assume worst case for player name 12 * 8 (widest character * longest name length) // Assume worst case for player name 12 * 8 (widest character * longest name length)
totalPixelWidth += 96; totalPixelWidth += 96;
} else if (textStr->at(currentPos) == '\x05') { } else if (textStr->at(currentPos) == '\x05') {
// Skip colour control characters. // Skip colour control characters.
nextPosJump = 2; nextPosJump = 2;
} else if (textStr->at(currentPos) == '\x1E') { } else if (textStr->at(currentPos) == '\x1E') {
//For the high score char, we have to take the next Char, then use that to get a worst case scenario. // For the high score char, we have to take the next Char, then use that to get a worst case scenario.
if (textStr->at(currentPos+1) == '\x01'){ if (textStr->at(currentPos + 1) == '\x01') {
totalPixelWidth += 28; totalPixelWidth += 28;
} }
nextPosJump = 2; nextPosJump = 2;
} else { } else {
// Some characters only one byte while others are two bytes // Some characters only one byte while others are two bytes
// So check both possibilities when checking for a character // So check both possibilities when checking for a character
if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { if (pixelWidthTable.count(textStr->substr(currentPos, 1))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)];
nextPosJump = 1; nextPosJump = 1;
} else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) {
totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)];
nextPosJump = 2; nextPosJump = 2;
} else { } else {
SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" +
SPDLOG_DEBUG("Full string: " + *textStr); textStr->substr(currentPos, 2));
nextPosJump = 1; SPDLOG_DEBUG("Full string: " + *textStr);
} nextPosJump = 1;
}
}
} }
} }

View file

@ -50,15 +50,16 @@ class CustomMessage {
TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
static std::string MESSAGE_END() ; static std::string MESSAGE_END();
static std::string ITEM_OBTAINED(uint8_t x) ; static std::string ITEM_OBTAINED(uint8_t x);
static std::string NEWLINE() ; static std::string NEWLINE();
static std::string COLOR(std::string x) ; static std::string COLOR(std::string x);
static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro static std::string POINTS(std::string x); // HIGH_SCORE is also a macro
static std::string WAIT_FOR_INPUT() ; static std::string WAIT_FOR_INPUT();
static std::string PLAYER_NAME() ; static std::string PLAYER_NAME();
static std::string TWO_WAY_CHOICE(); static std::string TWO_WAY_CHOICE();
CustomMessage LoadVanillaMessageTableEntry(uint16_t textId);
const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const;
const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const;
const std::string GetGerman(MessageFormat format = MF_FORMATTED) const; const std::string GetGerman(MessageFormat format = MF_FORMATTED) const;

View file

@ -67,4 +67,4 @@ DEFINE_HOOK(OnSetGameLanguage, ());
DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnFileDropped, (std::string filePath));
DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnAssetAltChange, ());
DEFINE_HOOK(OnKaleidoUpdate, ()); DEFINE_HOOK(OnKaleidoUpdate, ());
DEFINE_HOOK(OnOpenText, (uint16_t* textId, bool* loadFromMessageTable)); DEFINE_HOOK(OnOpenText, (uint16_t * textId, bool* loadFromMessageTable));

View file

@ -5,6 +5,7 @@
#include "z64save.h" #include "z64save.h"
#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_compass/object_gi_compass.h"
#include "objects/object_gi_map/object_gi_map.h" #include "objects/object_gi_map/object_gi_map.h"
#include "soh/OTRGlobals.h"
extern "C" { extern "C" {
extern SaveContext gSaveContext; extern SaveContext gSaveContext;

View file

@ -50,14 +50,12 @@ static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = {
"Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y "
"aller.&A plus tard.", "aller.&A plus tard.",
}, },
{ { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you "
"Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " "pressed it %b[[a_btn]]%w times.^Wow.",
"pressed it %b[[a_btn]]%w times.^Wow.", "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen "
"Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...",
"erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves "
"Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." },
"dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..."
},
{ {
"\x13\x1A" "\x13\x1A"
"Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w "

View file

@ -14,11 +14,11 @@ extern PlayState* gPlayState;
#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk)
void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) {
if ( if ((RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) &&
(RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) && Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) || Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) ||
(RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0) (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) &&
) { CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0)) {
return; return;
} }
CustomMessage msg; CustomMessage msg;
Actor* stone = GET_PLAYER(gPlayState)->talkActor; Actor* stone = GET_PLAYER(gPlayState)->talkActor;
@ -31,11 +31,11 @@ void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) {
int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]); int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]);
for (int i = 0; i < numOfActorLists; i++) { for (int i = 0; i < numOfActorLists; i++) {
if (gPlayState->actorCtx.actorLists[i].length) { if (gPlayState->actorCtx.actorLists[i].length) {
if ( if (gPlayState->actorCtx.actorLists[i].head->id == 10 &&
gPlayState->actorCtx.actorLists[i].head->id == 10 && Rando::StaticData::grottoChestParamsToHint.contains(
Rando::StaticData::grottoChestParamsToHint.contains(gPlayState->actorCtx.actorLists[i].head->params) gPlayState->actorCtx.actorLists[i].head->params)) {
) { stoneHint =
stoneHint = Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params]; Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params];
} }
} }
} }
@ -50,7 +50,8 @@ void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void RegisterGossipStoneHints() { void RegisterGossipStoneHints() {
COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS, RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage); COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS,
RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage);
} }
static RegisterShipInitFunc initFunc(RegisterGossipStoneHints, { "IS_RANDO" }); static RegisterShipInitFunc initFunc(RegisterGossipStoneHints, { "IS_RANDO" });

View file

@ -62,7 +62,7 @@ static const char* const englishIceTrapMessages[169] = {
"Would you like #ice# with that?", "Would you like #ice# with that?",
"You have obtained the #Ice# Medallion!", "You have obtained the #Ice# Medallion!",
"Quick, do a #Zora# impression!", "Quick, do a #Zora# impression!",
"One item #on the rocks#!",//would be better if it could display the name of the item "One item #on the rocks#!", // would be better if it could display the name of the item
"How much does a polar bear weigh?&Enough to break the #ice#.", "How much does a polar bear weigh?&Enough to break the #ice#.",
"You got Din's #Ice#!", "You got Din's #Ice#!",
"You got Nayru's #Cold#!", "You got Nayru's #Cold#!",
@ -125,12 +125,13 @@ static const char* const englishIceTrapMessages[169] = {
"STOP!&You violated the #Thaw#!", "STOP!&You violated the #Thaw#!",
"I wanted to give you a treasure, but it looks like you got #cold feet#.", "I wanted to give you a treasure, but it looks like you got #cold feet#.",
"You told me you wanted to deliver #just ice# to Ganondorf!", "You told me you wanted to deliver #just ice# to Ganondorf!",
"You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice trap. My bad.", "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice "
"trap. My bad.",
"Time to #cool off#!", "Time to #cool off#!",
"The #Ice Cavern# sends its regards.", "The #Ice Cavern# sends its regards.",
"Loading item, please #wait#...", "Loading item, please #wait#...",
"Mash A+B to not #die#.", "Mash A+B to not #die#.",
"Sorry, your item is in another location.", //would be better if it could have the name of the item "Sorry, your item is in another location.", // would be better if it could have the name of the item
"You only wish this was %gGreg%w.", "You only wish this was %gGreg%w.",
"Do you want to drink a hot chocolate?", "Do you want to drink a hot chocolate?",
"The #cold# never bothered me anyway.", "The #cold# never bothered me anyway.",
@ -151,7 +152,7 @@ static const char* const englishIceTrapMessages[169] = {
"Remember, there may be some momentary #discomfort#.", "Remember, there may be some momentary #discomfort#.",
"In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.",
"Gee, it sure is #cold# around here.", "Gee, it sure is #cold# around here.",
"You tested the item with your #ice detector#, it beeped.", //would be better if it could have the name of the item "You tested the item with your #ice detector#, it beeped.", // would be better if it could have the name of the item
"You have found the way of the zero. The #sub-zero#.", "You have found the way of the zero. The #sub-zero#.",
"Mweep... mweep... mweep...", "Mweep... mweep... mweep...",
"Scum, #freezebag#! I mean #freeze#, scumbag!", "Scum, #freezebag#! I mean #freeze#, scumbag!",
@ -170,19 +171,22 @@ static const char* const englishIceTrapMessages[169] = {
"Hydration break! Hey, who #froze# my water?", "Hydration break! Hey, who #froze# my water?",
"Oops, wrong #item model#.", "Oops, wrong #item model#.",
"Whoops! You have to put the item #in your inventory#.", "Whoops! You have to put the item #in your inventory#.",
"You dropped the item, shattering it into #shards of ice#!", //would be better if it could have the name of the item "You dropped the item, shattering it into #shards of ice#!", // would be better if it could have the name of the
// item
"Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.",
"You are the weakest @, #goodbye#!", "You are the weakest @, #goodbye#!",
"Ugh... Why did we even randomize #this item#?", "Ugh... Why did we even randomize #this item#?",
"The #Frost Moon# is rising...", "The #Frost Moon# is rising...",
"According to all known laws of physics and biology, there is no way that @ should be able to survive #getting fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video game, so @ survives anyway... #Probably#.", "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting "
"fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video "
"game, so @ survives anyway... #Probably#.",
"Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...",
"Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!",
"Gee, it sure is #BURR#ing around here.", "Gee, it sure is #BURR#ing around here.",
"Navi? Oh! I thought she was called #Névé#!", "Navi? Oh! I thought she was called #Névé#!",
"It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.",
"Unfortunately, the item has #stopped#.", //would be better if it could have the name of the item "Unfortunately, the item has #stopped#.", // would be better if it could have the name of the item
"This item is #not available# in your country.", //would be better if it could have the name of the item "This item is #not available# in your country.", // would be better if it could have the name of the item
"#Ice# try. #;)#", "#Ice# try. #;)#",
"D'oh, I #missed#!", "D'oh, I #missed#!",
"Where is my #super suit#?", "Where is my #super suit#?",
@ -241,12 +245,13 @@ static const char* const frenchIceTrapMessages[83] = {
"J'espère que ça ne te fait ni chaud, ni #froid#.", "J'espère que ça ne te fait ni chaud, ni #froid#.",
"Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#",
"Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!",
"Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un piège de glace.", "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un "
"piège de glace.",
"Il est temps de #te rafraîchir#!", "Il est temps de #te rafraîchir#!",
"La #Caverne Polaire# te passe le bonjour.", "La #Caverne Polaire# te passe le bonjour.",
"Chargement de l'objet, veuillez #patienter#...", "Chargement de l'objet, veuillez #patienter#...",
"Martèle A+B pour ne pas #mourir#.", "Martèle A+B pour ne pas #mourir#.",
"Désolé, ton objet est à un autre endroit.", //would be better if it could have the name of the item "Désolé, ton objet est à un autre endroit.", // would be better if it could have the name of the item
"Tu espérais que ce soit %gGreg%w.", "Tu espérais que ce soit %gGreg%w.",
"Tu veux boire un chocolat chaud?", "Tu veux boire un chocolat chaud?",
"Le #froid# ne m'a jamais dérangé, de toute façon.", "Le #froid# ne m'a jamais dérangé, de toute façon.",
@ -267,7 +272,8 @@ static const char* const frenchIceTrapMessages[83] = {
"Souviens-toi, il pourrait y avoir un léger #inconfort#.", "Souviens-toi, il pourrait y avoir un léger #inconfort#.",
"Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.", "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.",
"Mon dieu qu'il fait #froid# ici.", "Mon dieu qu'il fait #froid# ici.",
"Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", //would be better if it could have the name of the item "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", // would be better if it could have the name of the
// item
"Tu as découvert le chemin du zéro. Le #sub-zéro#.", "Tu as découvert le chemin du zéro. Le #sub-zéro#.",
"Mweep... mweep... mweep...", "Mweep... mweep... mweep...",
"Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!",
@ -286,16 +292,21 @@ static const char* const frenchIceTrapMessages[83] = {
"Pause hydratation ! Hé, qui a #gelé# mon eau?", "Pause hydratation ! Hé, qui a #gelé# mon eau?",
"Oups, mauvais #modèle d'objet#.", "Oups, mauvais #modèle d'objet#.",
"Oups! Tu dois mettre l'objet #dans ton inventaire#.", "Oups! Tu dois mettre l'objet #dans ton inventaire#.",
"Tu as fait tomber l'objet, le brisant en #éclats de glace#!", //would be better if it could have the name of the item "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", // would be better if it could have the name of the
// item
"Tu es le maillon faible @, #au revoir#!", "Tu es le maillon faible @, #au revoir#!",
"Ugh... Pourquoi avons-nous même randomisé #cet objet#?", "Ugh... Pourquoi avons-nous même randomisé #cet objet#?",
"La #Lune de Givre# se lève...", "La #Lune de Givre# se lève...",
"Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors @ survit... #Probablement#.", "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement "
"OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à lait...", "enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors "
"@ survit... #Probablement#.",
"OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à "
"lait...",
"Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!",
"Mon dieu qu'il fait #GLAGLA# ici.", "Mon dieu qu'il fait #GLAGLA# ici.",
"C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et manipuler la RNG.", "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et "
"Cet objet n'est #pas disponible# dans votre pays.", //would be better if it could have the name of the item "manipuler la RNG.",
"Cet objet n'est #pas disponible# dans votre pays.", // would be better if it could have the name of the item
"#Bonne# tentative. #;)#", "#Bonne# tentative. #;)#",
"Où est mon #Super Costume#?", "Où est mon #Super Costume#?",
"#La revanche du Titanic#.", "#La revanche du Titanic#.",
@ -305,17 +316,11 @@ void BuildIceTrapMessage(CustomMessage& msg) {
if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) {
msg = CustomMessage( msg = CustomMessage(
/*english*/ "This year for Christmas, all you get is #COAL#!", /*english*/ "This year for Christmas, all you get is #COAL#!",
/*german*/ "This year for Christmas, all you get is #COAL#!", /*german*/ "This year for Christmas, all you get is #COAL#!",
/*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", { QM_BLUE });
{ QM_BLUE }
);
} else { } else {
msg = CustomMessage( msg = CustomMessage(RandomElement(englishIceTrapMessages), RandomElement(germanIceTrapMessages),
RandomElement(englishIceTrapMessages), RandomElement(frenchIceTrapMessages), { QM_BLUE, QM_BLUE, QM_BLUE });
RandomElement(germanIceTrapMessages),
RandomElement(frenchIceTrapMessages),
{ QM_BLUE, QM_BLUE, QM_BLUE }
);
} }
msg.AutoFormat(); msg.AutoFormat();
@ -329,28 +334,36 @@ void BuildTriforcePieceMessage(CustomMessage& msg) {
if (percentageCollected <= 0.25) { if (percentageCollected <= 0.25) {
msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!",
"Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!",
"Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }; "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste "
"%c[[remaining]]%w à trouver. C'est un début!" };
} else if (percentageCollected <= 0.5) { } else if (percentageCollected <= 0.5) {
msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!",
"Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!",
"Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }; "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste "
"%c[[remaining]]%w à trouver. Ça avance!" };
} else if (percentageCollected <= 0.75) { } else if (percentageCollected <= 0.75) {
msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!",
"Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über "
"Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }; "die Hälfte!",
"Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste "
"%c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" };
} else if (percentageCollected < 1.0) { } else if (percentageCollected < 1.0) {
msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", msg = {
"You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!",
"Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!",
"Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }; "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w "
"à trouver. C'est presque&terminé!"
};
} else if (current == required) { } else if (current == required) {
msg = { "You completed the %yTriforce of&Courage%w! %gGG%w!", msg = { "You completed the %yTriforce of&Courage%w! %gGG%w!",
"Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!",
"Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }; "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" };
} else { } else {
msg = { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", msg = { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!",
"Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.",
"Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }; "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, "
"mais vous en avez %g[[current]]%w en&tout!" };
} }
msg.Replace("[[current]]", std::to_string(current)); msg.Replace("[[current]]", std::to_string(current));
msg.Replace("[[remaining]]", std::to_string(remaining)); msg.Replace("[[remaining]]", std::to_string(remaining));
@ -360,13 +373,15 @@ void BuildTriforcePieceMessage(CustomMessage& msg) {
void BuildCustomItemMessage(Player* player, CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) {
int16_t rgid; int16_t rgid;
msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", TEXTBOX_TYPE_BLUE); msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!",
TEXTBOX_TYPE_BLUE);
if (player->getItemEntry.objectId != OBJECT_INVALID) { if (player->getItemEntry.objectId != OBJECT_INVALID) {
rgid = player->getItemEntry.getItemId; rgid = player->getItemEntry.getItemId;
} else { } else {
rgid = player->getItemId; rgid = player->getItemId;
} }
CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast<RandomizerGet>(rgid)).GetName(), TEXTBOX_TYPE_BLUE); CustomMessage name =
CustomMessage(Rando::StaticData::RetrieveItem(static_cast<RandomizerGet>(rgid)).GetName(), TEXTBOX_TYPE_BLUE);
msg.Replace("[[name]]", name); msg.Replace("[[name]]", name);
msg.AutoFormat(); msg.AutoFormat();
} }
@ -389,12 +404,9 @@ void BuildItemMessage(u16* textId, bool* loadFromMessageTable) {
void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) {
GetItemEntry itemEntry = GET_PLAYER(gPlayState)->getItemEntry; GetItemEntry itemEntry = GET_PLAYER(gPlayState)->getItemEntry;
auto ctx = OTRGlobals::Instance->gRandoContext; auto ctx = OTRGlobals::Instance->gRandoContext;
CustomMessage msg = CustomMessage( CustomMessage msg =
"You found the %g[[name]]%w! [[typeHint]]", CustomMessage("You found the %g[[name]]%w! [[typeHint]]", "Du erhältst das %g[[name]]%w! [[typeHint]]",
"Du erhältst das %g[[name]]%w! [[typeHint]]", "Vous ebtenez %g[[name]]%w! [[typeHint]]", TEXTBOX_TYPE_BLUE);
"Vous ebtenez %g[[name]]%w! [[typeHint]]",
TEXTBOX_TYPE_BLUE
);
int sceneNum; int sceneNum;
switch (itemEntry.getItemId) { switch (itemEntry.getItemId) {
case RG_DEKU_TREE_MAP: case RG_DEKU_TREE_MAP:
@ -428,11 +440,9 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) {
sceneNum = SCENE_ICE_CAVERN; sceneNum = SCENE_ICE_CAVERN;
break; break;
} }
if ( if (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) ||
ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) ||
(ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_SET_NUMBER) && (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_SET_NUMBER) &&
ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12)) ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12))) {
) {
msg.Replace("[[typeHint]]", ""); msg.Replace("[[typeHint]]", "");
} else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) {
msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage());
@ -445,10 +455,12 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) {
void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY &&
!DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) {
return; return;
} }
if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY &&
!DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) {
return; return;
} }
CustomMessage msg; CustomMessage msg;
@ -459,10 +471,12 @@ void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) {
void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) {
Player* player = GET_PLAYER(gPlayState); Player* player = GET_PLAYER(gPlayState);
if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY && OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) { if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY &&
OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) {
return; return;
} }
if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY &&
DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) {
return; return;
} }
CustomMessage msg; CustomMessage msg;
@ -471,16 +485,20 @@ void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) {
msg.LoadIntoFont(); msg.LoadIntoFont();
} }
void RegisterItemMessages () { void RegisterItemMessages() {
COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage);
COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildMapMessage); COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS),
COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildItemMessage); BuildMapMessage);
COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS, COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS),
(DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) || BuildItemMessage);
DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)), BuildBossKeyMessage); COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS,
(DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) ||
DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)),
BuildBossKeyMessage);
COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_SMALL, COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_SMALL,
(OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) || (OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) ||
DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)), BuildSmallKeyMessage); DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)),
BuildSmallKeyMessage);
} }
static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" });

View file

@ -19,15 +19,16 @@ extern PlayState* gPlayState;
#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk)
#define RAND_GET_ITEM(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) #define RAND_GET_ITEM(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)
#define RAND_GET_OVERRIDE(rc) OTRGlobals::Instance->gRandoContext->overrides[rc] #define RAND_GET_OVERRIDE(rc) OTRGlobals::Instance->gRandoContext->overrides[rc]
#define NON_BEAN_MERCHANTS (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \ #define NON_BEAN_MERCHANTS \
RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \
RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL))
void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) {
RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet(); RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet();
uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); uint16_t price = RAND_GET_ITEM(rc)->GetPrice();
CustomMessage itemName; CustomMessage itemName;
bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) ||
CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0);
if (mysterious) { if (mysterious) {
itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage();
} else if (rgid == RG_ICE_TRAP) { } else if (rgid == RG_ICE_TRAP) {
@ -36,24 +37,23 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) {
} else { } else {
itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName());
} }
msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) });
} }
void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg; CustomMessage msg;
if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) {
msg = CustomMessage( msg = CustomMessage(
"I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no less.\x1B%gYes&No%w", "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no "
"Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 Rubine%w.\x1B&%gJa&Nein%w", "less.\x1B%gYes&No%w",
"Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w" "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 "
); "Rubine%w.\x1B&%gJa&Nein%w",
"Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w");
msg.Format(); msg.Format();
} else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) {
msg = CustomMessage( msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w",
"Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w",
"Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w");
"Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"
);
BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN);
msg.AutoFormat(); msg.AutoFormat();
} }
@ -62,11 +62,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w",
"Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w",
"Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w");
"Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"
);
BuildMerchantMessage(msg, RC_GC_MEDIGORON); BuildMerchantMessage(msg, RC_GC_MEDIGORON);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -75,13 +73,11 @@ void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) {
void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) &&
(RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) ||
INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w",
"Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w",
"Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w");
"Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"
);
BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -93,14 +89,12 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg; CustomMessage msg;
if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) {
msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!", msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!",
/*german*/"Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", /*german*/ "Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!",
/*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); /*french*/ "Squalala! Je vais enfin pouvoir %rprendre des vacances%w!");
} else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) {
msg = CustomMessage( msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w",
"Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w",
"Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w");
"Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"
);
BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN);
} }
msg.AutoFormat(); msg.AutoFormat();
@ -109,10 +103,9 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void BuildCarpetGuyFailToBuyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildCarpetGuyFailToBuyMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^" CustomMessage("I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^"
"Come back when you have had %gBombchus%w of your own." "Come back when you have had %gBombchus%w of your own.");
);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
@ -124,13 +117,22 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) {
uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); uint16_t price = RAND_GET_ITEM(rc)->GetPrice();
CustomMessage msg; CustomMessage msg;
if (price == 0) { if (price == 0) {
msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", msg = CustomMessage(
"\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", "\x12\x38\x82"
"\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3",
"\x12\x38\x82"
"In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w "
"geben!\x07\x10\xA3",
"\x12\x38\x82"
"J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3");
} else { } else {
msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", msg = CustomMessage("\x12\x38\x82"
"\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] "
"\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); "Rupees%w it is!\x07\x10\xA3",
"\x12\x38\x82"
"Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3",
"\x12\x38\x82"
"J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3");
} }
BuildMerchantMessage(msg, rc); BuildMerchantMessage(msg, rc);
msg.AutoFormat(); msg.AutoFormat();
@ -145,15 +147,17 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) {
// textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)
// textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS)
if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) {
rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast<RandomizerInf>((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(
static_cast<RandomizerInf>((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1));
msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02",
"\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02",
"\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02");
} else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) {
rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast<RandomizerInf>((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(
static_cast<RandomizerInf>((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1));
msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02",
"\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02",
"\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02");
} else { } else {
return; return;
} }
@ -164,10 +168,10 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void RegisterMerchantMessages() { void RegisterMerchantMessages() {
COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10,
(RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) ||
RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)), RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)),
BuildBeanGuyMessage); BuildBeanGuyMessage);
COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_100, IS_RANDO, BuildBeanGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_100, IS_RANDO, BuildBeanGuyMessage);
COND_ID_HOOK(OnOpenText, TEXT_MEDIGORON, NON_BEAN_MERCHANTS, BuildMedigoronMessage); COND_ID_HOOK(OnOpenText, TEXT_MEDIGORON, NON_BEAN_MERCHANTS, BuildMedigoronMessage);
COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage);

View file

@ -14,17 +14,15 @@ extern "C" {
void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg; CustomMessage msg;
if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI) { if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI) {
msg = CustomMessage( msg = CustomMessage("%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system "
"%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the %bWater Temple%c.", "in the %bWater Temple%c.",
"%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem im %bWassertempel%c nicht stimmen.", "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem "
"%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du %bTemple de l'Eau%c." "Leitungssystem im %bWassertempel%c nicht stimmen.",
); "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du "
"%bTemple de l'Eau%c.");
} else if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { } else if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) {
msg = CustomMessage( msg = CustomMessage("Water level control system.&Keep away!", "Wasserstand Kontrollsystem&Finger weg!",
"Water level control system.&Keep away!", "Système de contrôle du niveau&d'eau.&Ne pas toucher!");
"Wasserstand Kontrollsystem&Finger weg!",
"Système de contrôle du niveau&d'eau.&Ne pas toucher!"
);
} }
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -32,11 +30,10 @@ void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void BuildShootingGalleryNoBowMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShootingGalleryNoBowMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"Come back when you have your own bow and you'll get a %rdifferent prize%w!", CustomMessage("Come back when you have your own bow and you'll get a %rdifferent prize%w!",
"Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!", "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!",
"J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc." "J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc.");
);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;

View file

@ -120,34 +120,62 @@ void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void RegisterNaviMessages() { void RegisterNaviMessages() {
COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME,
COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage);
} }
static RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); static RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") });

View file

@ -8,82 +8,209 @@ extern "C" {
#include "variables.h" #include "variables.h"
} }
static const char* englishRupeeNames[175] = { static const char* englishRupeeNames[175] = { "[P]",
"[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", "Bad RNG Rolls",
"Beli", "Bells", "Berries", "Bison Dollars", "Bitcoin", "Bananas",
"Blue Essence", "Bolts", "Bones", "Boondollars", "Bottle Caps", "Beanbean Coins",
"Bratwürste", "Bucks", "BugFrags", "Canadian Dollars", "Cards", "Beans",
"Chaos Orbs", "Clams", "Coal", "Cocoa Beans", "Coins", "Beli",
"Cookies", "Copper", "Cor", "Cornflakes", "Credits", "Bells",
"Crimebucks", "Crystal Shards", "Cubits", "Cucumbers", "Dalmations", "Berries",
"Dampécoin", "Dark Elixir", "Darseks", "Dead Memes", "Diamonds", "Bison Dollars",
"DNA", "Doge", "Dogecoin", "Doll Hairs", "Dollars", "Bitcoin",
"Dollarydoos", "Dosh", "Doubloons", "Dwarfbucks", "Elexit", "Blue Essence",
"Emeralds", "Energon", "Eris", "Ether", "Euro", "Bolts",
"Experience", "Extinction Points", "Floopies", "Flurbos", "FPS", "Bones",
"Friends", "Frog Coins", "Gald", "Gekz", "Gems", "Boondollars",
"Geo", "Gil", "Glimmer", "Glitches", "Gold", "Bottle Caps",
"Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Grouses", "Bratwürste",
"Gummybears", "Hell", "Hyrule Loaches", "Ice Traps", "ISK", "Bucks",
"Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", "BugFrags",
"Leaves", "Lemmings", "Lien", "Lira", "Lumber", "Canadian Dollars",
"Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", "Cards",
"Meat Stacks", "Medaparts", "Meseta", "Mesetas", "Minerals", "Chaos Orbs",
"Monopoly Money", "Moons", "Mora", "Mumbo Tokens", "Munny", "Clams",
"Mushrooms", "Mysteries", "Neopoints", "Notes", "Nuyen", "Coal",
"Orbs", "Ore", "Pix", "Pixels", "Plastyks", "Cocoa Beans",
"Platinum", "Pokédollars", "Pokémon", "Poko", "Pokos", "Coins",
"Potch", "Pounds", "Power Pellets", "Primogems", "Réals", "Cookies",
"Refined Metal", "Remote Mines", "Retweets", "Rhinu", "Rings", "Copper",
"Riot Points", "Robux", "Rubies", "Rubles", "Runite Ore", "Cor",
"Rupees", "Saint Quartz", "Septims", "Shekels", "Shillings", "Cornflakes",
"Silver", "Simoleons", "Smackaroos", "Social Credit", "Souls", "Credits",
"Spent Casings", "Spice", "Spondulicks", "Spoons", "Star Bits", "Crimebucks",
"Star Chips", "Stars", "Stones of Jordan", "Store Credit", "Strawbs", "Crystal Shards",
"Studs", "Super Sea Snails", "Talent", "Teef", "Telecrystals", "Cubits",
"Tiberium", "TokKul", "Toys", "Turnips", "Upvotes", "Cucumbers",
"V-Bucks", "Vespene Gas", "Watts", "Widgets", "Woolongs", "Dalmations",
"World Dollars", "Wumpa Fruit", "Yen", "Zenny", "Zorkmids" "Dampécoin",
}; "Dark Elixir",
"Darseks",
"Dead Memes",
"Diamonds",
"DNA",
"Doge",
"Dogecoin",
"Doll Hairs",
"Dollars",
"Dollarydoos",
"Dosh",
"Doubloons",
"Dwarfbucks",
"Elexit",
"Emeralds",
"Energon",
"Eris",
"Ether",
"Euro",
"Experience",
"Extinction Points",
"Floopies",
"Flurbos",
"FPS",
"Friends",
"Frog Coins",
"Gald",
"Gekz",
"Gems",
"Geo",
"Gil",
"Glimmer",
"Glitches",
"Gold",
"Gold Dragons",
"Goober Dollars",
"Green Herbs",
"Greg Siblings",
"Grouses",
"Gummybears",
"Hell",
"Hyrule Loaches",
"Ice Traps",
"ISK",
"Jiggies",
"KF7 Ammo",
"Kinstones",
"Kremcoins",
"Kroner",
"Leaves",
"Lemmings",
"Lien",
"Lira",
"Lumber",
"Lungmen Dollars",
"Macca",
"Mana",
"Mann Co. Keys",
"Meat",
"Meat Stacks",
"Medaparts",
"Meseta",
"Mesetas",
"Minerals",
"Monopoly Money",
"Moons",
"Mora",
"Mumbo Tokens",
"Munny",
"Mushrooms",
"Mysteries",
"Neopoints",
"Notes",
"Nuyen",
"Orbs",
"Ore",
"Pix",
"Pixels",
"Plastyks",
"Platinum",
"Pokédollars",
"Pokémon",
"Poko",
"Pokos",
"Potch",
"Pounds",
"Power Pellets",
"Primogems",
"Réals",
"Refined Metal",
"Remote Mines",
"Retweets",
"Rhinu",
"Rings",
"Riot Points",
"Robux",
"Rubies",
"Rubles",
"Runite Ore",
"Rupees",
"Saint Quartz",
"Septims",
"Shekels",
"Shillings",
"Silver",
"Simoleons",
"Smackaroos",
"Social Credit",
"Souls",
"Spent Casings",
"Spice",
"Spondulicks",
"Spoons",
"Star Bits",
"Star Chips",
"Stars",
"Stones of Jordan",
"Store Credit",
"Strawbs",
"Studs",
"Super Sea Snails",
"Talent",
"Teef",
"Telecrystals",
"Tiberium",
"TokKul",
"Toys",
"Turnips",
"Upvotes",
"V-Bucks",
"Vespene Gas",
"Watts",
"Widgets",
"Woolongs",
"World Dollars",
"Wumpa Fruit",
"Yen",
"Zenny",
"Zorkmids" };
static const char* germanRupeeNames[65] = { static const char* germanRupeeNames[65] = {
"Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent", "Diamanten",
"Brötchen", "Cent", "Diamanten", "Diridari", "Dogecoin", "Diridari", "Dogecoin", "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", "EXP",
"ECU", "Elexit", "Erz", "Erzbrocken", "Euro", "Forint", "Franken", "Freunde", "Gil", "Gold", "Groschen", "Gulden", "Gummibären",
"EXP", "Forint", "Franken", "Freunde", "Gil", "Heller", "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", "Knochen", "Kohle",
"Gold", "Groschen", "Gulden", "Gummibären", "Heller", "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde",
"Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund",
"Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", "Pilze", "Plastiks", "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", "Schilling",
"Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", "Seelen", "Smaragde", "Steine", "Sterne", "Sternis", "Tael", "Taler", "Wagenchips",
"Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", "Zenny"
"Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks",
"Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire",
"Schilling", "Seelen", "Smaragde", "Steine", "Sterne",
"Sternis", "Tael", "Taler", "Wagenchips", "Zenny"
}; };
static const char* frenchRupeeNames[40] = { static const char* frenchRupeeNames[40] = {
"Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules",
"Blés", "Bling", "Capsules", "Centimes", "Champignons", "Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Dollars",
"Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Émeraudes", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils",
"Dollars", "Émeraudes", "Éthers", "Étoiles", "Euros", "Grouses", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens",
"Florens", "Francs", "Galds", "Gils", "Grouses", "Pépètes", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies"
"Halos", "Joyaux", "Lunes", "Mailles", "Munnies",
"Orbes", "Orens", "Pépètes", "Pièces", "Plastyks",
"Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies"
}; };
void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) { void BuildRupeeMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage(
"You found [[color]][[amount]] [[rupee]]\x05\x00!", "You found [[color]][[amount]] [[rupee]]\x05\x00!", "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!",
"Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", "Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM);
"Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!",
TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM
);
std::string color; std::string color;
std::string amount; std::string amount;
CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), RandomElement(germanRupeeNames),
RandomElement(germanRupeeNames),
RandomElement(frenchRupeeNames)); RandomElement(frenchRupeeNames));
switch (*textId) { switch (*textId) {
case TEXT_BLUE_RUPEE: case TEXT_BLUE_RUPEE:
@ -115,10 +242,14 @@ void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) {
} }
void RegisterRandomRupeeNames() { void RegisterRandomRupeeNames() {
COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE,
COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage);
COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE,
COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage);
COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage);
COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE,
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage);
} }
static RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); static RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") });

View file

@ -17,11 +17,10 @@ extern PlayState* gPlayState;
#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk)
#define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) #define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh)
#define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) #define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)
#define ANY_SKULLTULA_HINTS RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || \ #define ANY_SKULLTULA_HINTS \
RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \ RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \
RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || \ RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \
RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \ RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)
RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)
void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg; CustomMessage msg;
@ -47,41 +46,47 @@ void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg; CustomMessage msg;
switch (gPlayState->sceneNum) { switch (gPlayState->sceneNum) {
case SCENE_TEMPLE_OF_TIME: case SCENE_TEMPLE_OF_TIME:
if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()) {
msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW); msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW);
} else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) {
msg = CustomMessage( msg = CustomMessage(
"@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.",
"@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.",
"Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w.");
} else { } else {
msg = CustomMessage( msg = CustomMessage("The time has come. Prepare yourself.", "Die Zeit ist gekommen.&Mach Dich bereit.",
"The time has come. Prepare yourself.", "Le moment est venu @.&Tu ferais bien de te préparer.");
"Die Zeit ist gekommen.&Mach Dich bereit.",
"Le moment est venu @.&Tu ferais bien de te préparer.");
} }
break; break;
case SCENE_INSIDE_GANONS_CASTLE: case SCENE_INSIDE_GANONS_CASTLE:
if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) {
msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW);
} else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) &&
CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CUR_CAPACITY(UPG_QUIVER) >= 30 &&
msg = CustomMessage("You are still ill-equipped to face %rGanondorf%w." gSaveContext.isMagicAcquired)) {
"^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", msg = CustomMessage(
"You are still ill-equipped to face %rGanondorf%w."
"^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the "
"%ylight%w.",
"Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^"
"Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu "
"geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.",
"@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^"
"Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour "
} else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)){ "invoquer la %ylumière%w.");
} else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) &&
!RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)) {
msg = CustomMessage( msg = CustomMessage(
"You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still "
"Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", "stands.^Complete the remaining %gtrials%w to destroy it.",
"@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours actives.^Termine les épreuves restantes pour les détruire."); "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w "
"steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.",
"@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours "
"actives.^Termine les épreuves restantes pour les détruire.");
} else { } else {
msg = CustomMessage( msg = CustomMessage("If you're ready, then proceed.^Good luck.",
"If you're ready, then proceed.^Good luck.", "Wenn Du bereit bist, so schreite&voran.^Viel Glück.",
"Wenn Du bereit bist, so schreite&voran.^Viel Glück.", "Si tu es prêt, tu peux y aller.^Bonne chance.");
"Si tu es prêt, tu peux y aller.^Bonne chance.");
} }
break; break;
} }
@ -149,8 +154,7 @@ void BuildMysteriousWarpMessage() {
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage(
"Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", "Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w",
"Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", "Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w",
"Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w" "Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w");
);
msg.LoadIntoFont(); msg.LoadIntoFont();
} }
@ -238,18 +242,17 @@ void BuildFishingPoleHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
CustomMessage msg = CustomMessage( CustomMessage msg = CustomMessage(
"Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!",
"Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht "
"Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!" "fischen!",
); "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!");
if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) { if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) {
msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage(); msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage();
} }
if (*textId == TEXT_FISHING_POND_START_MET) { if (*textId == TEXT_FISHING_POND_START_MET) {
msg = CustomMessage( msg = CustomMessage("Hey, mister! I remember you!&It's been a long time!^",
"Hey, mister! I remember you!&It's been a long time!^", "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!",
"Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!") +
"Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!" msg;
) + msg;
} }
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
@ -273,7 +276,7 @@ void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
*loadFromMessageTable = false; *loadFromMessageTable = false;
} }
void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { void BuildBigPoesHintMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT);
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
@ -340,9 +343,10 @@ void RegisterStaticHints() {
// Altar // Altar
COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage);
COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage);
//Skulltula // Skulltula
COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage);
COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT),
Build100SkullsHintMessage);
// Dampe's Diary // Dampe's Diary
COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage); COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage);
// Chest Game // Chest Game
@ -352,9 +356,12 @@ void RegisterStaticHints() {
// Warp // Warp
COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildSerenadeWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildRequiemWarpMessage); BuildSerenadeWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildNocturneWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
BuildRequiemWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS),
BuildNocturneWarpMessage);
COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage);
// Frogs // Frogs
COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage);
@ -365,10 +372,13 @@ void RegisterStaticHints() {
COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT),
BuildLoachHintMessage);
// Fishing Pole // Fishing Pole
COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE),
COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); BuildFishingPoleHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE),
BuildFishingPoleHintMessage);
// Saria // Saria
COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
@ -386,29 +396,41 @@ void RegisterStaticHints() {
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage);
// Biggoron // Biggoron
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT),
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT),
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT),
BuildBiggoronHintMessage);
// Big Poes // Big Poes
COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT),
BuildBigPoesHintMessage);
// Anju // Anju
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT),
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT),
BuildChickensHintMessage);
// Malon // Malon
COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage);
COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT),
BuildMalonHintMessage);
// Horseback Archery // Horseback Archery
COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT),
BuildHorsebackArcheryMessage);
COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage);
// Mask Shop Sign // Mask Shop Sign
COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage);

View file

@ -3971,8 +3971,8 @@ void RandomizerSettingsWindow::UpdateElement() {
} }
} }
class ExtendedVanillaTableInvalidItemIdException: public std::exception { class ExtendedVanillaTableInvalidItemIdException : public std::exception {
private: private:
s16 itemID; s16 itemID;
public: public:

View file

@ -26,7 +26,7 @@ class Randomizer {
public: public:
Randomizer(); Randomizer();
~Randomizer(); ~Randomizer();
static Sprite* GetSeedTexture(uint8_t index); static Sprite* GetSeedTexture(uint8_t index);
bool SpoilerFileExists(const char* spoilerFileName); bool SpoilerFileExists(const char* spoilerFileName);
bool IsTrialRequired(s32 trialFlag); bool IsTrialRequired(s32 trialFlag);