Misc fixes mostly related to custom text refactor (#6174)

fix goron messages in rando
also always include "IS_RANDO" in rando shipinit dependencies
don't use rando RNG, trying std::array
avoid sprintf, std::array not necessary
fix random rupee name crash
roll random traps: don't reuse rando rng
fix better bombchu typo
This commit is contained in:
Philip Dubé
2026-01-20 20:55:24 +00:00
committed by GitHub
parent 9991a95ab1
commit c9414b4d45
15 changed files with 196 additions and 211 deletions

View File

@@ -1,8 +1,7 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
#include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Enhancements/randomizer/SeedContext.h"
#include "soh/Notification/Notification.h" #include "soh/Notification/Notification.h"
#include "soh/OTRGlobals.h"
extern "C" { extern "C" {
#include "variables.h" #include "variables.h"
@@ -59,12 +58,13 @@ std::vector<AltTrapType> getEnabledAddTraps() {
return enabledAddTraps; return enabledAddTraps;
}; };
static void RollRandomTrap(uint32_t seed) { static void RollRandomTrap(uint64_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() uint64_t finalSeed = seed + (IS_RANDO ? static_cast<uint64_t>(Rando::Context::GetInstance()->GetSeed())
: static_cast<uint32_t>(gSaveContext.ship.stats.fileCreatedAt)); : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed); uint64_t state;
ShipUtils::RandInit(finalSeed, &state);
roll = RandomElement(getEnabledAddTraps()); roll = ShipUtils::RandomElement(getEnabledAddTraps(), &state);
switch (roll) { switch (roll) {
case ADD_ICE_TRAP: case ADD_ICE_TRAP:
GameInteractor::RawAction::FreezePlayer(); GameInteractor::RawAction::FreezePlayer();

View File

@@ -20,9 +20,9 @@ void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) {
} }
void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage("\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", CustomMessage msg = CustomMessage("\010Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w",
"\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\010Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w",
"\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w"); "\010Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w");
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;

View File

@@ -7,6 +7,7 @@
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <variables.h> #include <variables.h>
#include <soh/Enhancements/gameconsole.h> #include <soh/Enhancements/gameconsole.h>
#include <soh/util.h>
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
@@ -266,36 +267,25 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const {
return !operator==(operand); return !operator==(operand);
} }
int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) {
if (!inputStr.empty()) {
// Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents
// negatives.
memset(buffer, 0, std::max<int>(0, maxBufferSize));
// 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());
memcpy(buffer, inputStr.c_str(), copiedCharLen);
return copiedCharLen;
}
return 0;
}
void CustomMessage::LoadIntoFont() { void CustomMessage::LoadIntoFont() {
MessageContext* msgCtx = &gPlayState->msgCtx; MessageContext* msgCtx = &gPlayState->msgCtx;
Font* font = &msgCtx->font; Font* font = &msgCtx->font;
char* buffer = font->msgBuf; char* buffer = font->msgBuf;
const int maxBufferSize = sizeof(font->msgBuf); const size_t maxBufferSize = sizeof(font->msgBuf);
font->charTexBuf[0] = (type << 4) | position; font->charTexBuf[0] = (type << 4) | position;
switch (gSaveContext.language) { switch (gSaveContext.language) {
case LANGUAGE_FRA: case LANGUAGE_FRA:
msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetFrench(MF_RAW), buffer, maxBufferSize); msgCtx->msgLength = font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, GetFrench(MF_RAW), maxBufferSize);
break; break;
case LANGUAGE_GER: case LANGUAGE_GER:
msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetGerman(MF_RAW), buffer, maxBufferSize); msgCtx->msgLength = font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, GetGerman(MF_RAW), maxBufferSize);
break; break;
case LANGUAGE_ENG: case LANGUAGE_ENG:
default: default:
msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetEnglish(MF_RAW), buffer, maxBufferSize); msgCtx->msgLength = font->msgLength =
SohUtils::CopyStringToCharBuffer(buffer, GetEnglish(MF_RAW), maxBufferSize);
break; break;
} }
} }
@@ -545,7 +535,7 @@ void CustomMessage::AutoFormatString(std::string& str) const {
const bool hasIcon = str.find('\x13') != std::string::npos; const bool hasIcon = str.find('\x13') != std::string::npos;
size_t lineLength = NextLineLength(&str, lastNewline, hasIcon); size_t lineLength = NextLineLength(&str, lastNewline, hasIcon);
size_t lineCount = 1; size_t lineCount = 1;
size_t yesNo = str.find("\x1B"s[0], lastNewline); size_t yesNo = str.find('\x1B', lastNewline);
while (lastNewline + lineLength < str.length() || yesNo != std::string::npos) { while (lastNewline + lineLength < str.length() || yesNo != std::string::npos) {
const size_t carrot = str.find('^', lastNewline); const size_t carrot = str.find('^', lastNewline);
const size_t ampersand = str.find('&', lastNewline); const size_t ampersand = str.find('&', lastNewline);
@@ -581,11 +571,10 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lineCount = 0; lineCount = 0;
// some lines need to be split but don't have spaces, look for periods instead // some lines need to be split but don't have spaces, look for periods instead
} else { } else {
const size_t lastBreak = const size_t lastBreak = str.find_last_of(".,!?- ", lastNewline + lineLength);
str.find_last_of(static_cast<std::string>(".,!?- "), lastNewline + lineLength);
// if none exist or we go backwards, we look forward for a something and allow the overflow // if none exist or we go backwards, we look forward for a something and allow the overflow
if (lastBreak == std::string::npos || lastBreak < lastNewline) { if (lastBreak == std::string::npos || lastBreak < lastNewline) {
const size_t nextBreak = str.find_first_of(static_cast<std::string>(".,!?- &^"), lastNewline); const size_t nextBreak = str.find_first_of(".,!?- &^", lastNewline);
if (str[nextBreak] == '^') { if (str[nextBreak] == '^') {
lastNewline = nextBreak + 1; lastNewline = nextBreak + 1;
lineCount = 0; // increments to 1 at the end lineCount = 0; // increments to 1 at the end
@@ -617,11 +606,10 @@ void CustomMessage::AutoFormatString(std::string& str) const {
lastNewline = carrot + 1; lastNewline = carrot + 1;
// some lines need to be split but don't have spaces, look for punctuation instead // some lines need to be split but don't have spaces, look for punctuation instead
} else { } else {
const size_t lastBreak = const size_t lastBreak = str.find_last_of(".,!?- &", lastNewline + lineLength);
str.find_last_of(static_cast<std::string>(".,!?- &"), lastNewline + lineLength);
// if none exist or we go backwards, we look forward for a something and allow the overflow // if none exist or we go backwards, we look forward for a something and allow the overflow
if (lastBreak == std::string::npos || lastBreak < lastNewline) { if (lastBreak == std::string::npos || lastBreak < lastNewline) {
const size_t nextBreak = str.find_first_of(static_cast<std::string>(".,!?- &^"), lastNewline); const size_t nextBreak = str.find_first_of(".,!?- &^", lastNewline);
if (str[nextBreak] == '^') { if (str[nextBreak] == '^') {
lastNewline = nextBreak + 1; lastNewline = nextBreak + 1;
} else { } else {
@@ -637,14 +625,14 @@ void CustomMessage::AutoFormatString(std::string& str) const {
} }
lineLength = NextLineLength(&str, lastNewline, hasIcon); lineLength = NextLineLength(&str, lastNewline, hasIcon);
} }
yesNo = str.find("\x1B"s[0], lastNewline); yesNo = str.find('\x1B', lastNewline);
} }
ReplaceSpecialCharacters(str); ReplaceSpecialCharacters(str);
ReplaceAltarIcons(str); ReplaceAltarIcons(str);
std::replace(str.begin(), str.end(), '&', NEWLINE()[0]); std::replace(str.begin(), str.end(), '&', NEWLINE()[0]);
std::replace(str.begin(), str.end(), '^', WAIT_FOR_INPUT()[0]); std::replace(str.begin(), str.end(), '^', WAIT_FOR_INPUT()[0]);
std::replace(str.begin(), str.end(), '@', PLAYER_NAME()[0]); std::replace(str.begin(), str.end(), '@', PLAYER_NAME()[0]);
std::replace(str.begin(), str.end(), '_', " "[0]); std::replace(str.begin(), str.end(), '_', ' ');
str += MESSAGE_END(); str += MESSAGE_END();
} }
@@ -666,7 +654,7 @@ void CustomMessage::InsertNumber(uint8_t num) {
} }
} }
// remove the remaining bar // remove the remaining bar
this->Replace("|", ""); Replace("|", "");
Replace("[[d]]", std::to_string(num)); Replace("[[d]]", std::to_string(num));
} }
@@ -689,8 +677,8 @@ void CustomMessage::SetSingularPlural() {
} }
} }
// remove the remaining bar // remove the remaining bar
this->Replace("|", ""); Replace("|", "");
this->Replace("", ""); Replace("", "");
} }
void CustomMessage::Capitalize() { void CustomMessage::Capitalize() {
@@ -773,7 +761,7 @@ void CustomMessage::ReplaceAltarIcons(std::string& str) const {
void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert) { void CustomMessage::InsertNames(std::vector<CustomMessage> toInsert) {
for (uint8_t a = 0; a < toInsert.size(); a++) { for (uint8_t a = 0; a < toInsert.size(); a++) {
CustomMessage temp = toInsert[a]; CustomMessage temp = toInsert[a];
if ((capital.size() > a) && (capital[a] = true)) { if (capital.size() > a && capital[a]) {
temp.Capitalize(); temp.Capitalize();
} }
Replace("[[" + std::to_string(a + 1) + "]]", temp); Replace("[[" + std::to_string(a + 1) + "]]", temp);

View File

@@ -328,7 +328,7 @@ class MessageNotFoundException : public std::exception {
} }
virtual const char* what() const noexcept { virtual const char* what() const noexcept {
static char message[500]; static char message[500];
sprintf(message, "Message from table %s with textId %u was not found", messageTableId.c_str(), textId); snprintf(message, 500, "Message from table %s with textId %u was not found", messageTableId.c_str(), textId);
return message; return message;
} }
}; };

View File

@@ -430,7 +430,7 @@ void DrawInfoTab() {
gSaveContext.highScores[i] |= fishSize & 0x7F; gSaveContext.highScores[i] |= fishSize & 0x7F;
} }
char fishMsg[64]; char fishMsg[64];
std::sprintf(fishMsg, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5)); std::snprintf(fishMsg, 64, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5));
Tooltip(fishMsg); Tooltip(fishMsg);
PopStyleInput(); PopStyleInput();
bool FishBool = gSaveContext.highScores[i] & 0x80; bool FishBool = gSaveContext.highScores[i] & 0x80;
@@ -445,7 +445,7 @@ void DrawInfoTab() {
gSaveContext.highScores[i] &= ~0x7F000000; gSaveContext.highScores[i] &= ~0x7F000000;
gSaveContext.highScores[i] |= (fishSize & 0x7F) << 0x18; gSaveContext.highScores[i] |= (fishSize & 0x7F) << 0x18;
} }
std::sprintf(fishMsg, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5)); std::snprintf(fishMsg, 64, "Weight: %2.0f lbs", ((SQ(fishSize) * .0036) + .5));
Tooltip(fishMsg); Tooltip(fishMsg);
PopStyleInput(); PopStyleInput();
FishBool = gSaveContext.highScores[i] & 0x80000000; FishBool = gSaveContext.highScores[i] & 0x80000000;

View File

@@ -8,8 +8,7 @@ extern "C" {
#include <variables.h> #include <variables.h>
} }
#define NUM_GORON_MESSAGES 9 static CustomMessage FireTempleGoronMessages[] = {
static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = {
{ {
"Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?",
"Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du "
@@ -84,8 +83,7 @@ static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = {
}; };
void BuildGoronMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildGoronMessage(uint16_t* textId, bool* loadFromMessageTable) {
uint16_t choice = Random(0, NUM_GORON_MESSAGES); CustomMessage msg = ShipUtils::RandomElement(FireTempleGoronMessages);
CustomMessage msg = FireTempleGoronMessages[choice];
msg.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); msg.Replace("[[days]]", std::to_string(gSaveContext.totalDays));
msg.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A])); msg.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A]));
msg.AutoFormat(); msg.AutoFormat();
@@ -106,3 +104,5 @@ void RegisterGoronMessages() {
COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, IS_RANDO, BuildGoronMessage); COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, IS_RANDO, BuildGoronMessage);
COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET, IS_RANDO, BuildGoronMessage); COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET, IS_RANDO, BuildGoronMessage);
} }
static RegisterShipInitFunc initFunc(RegisterGoronMessages, { "IS_RANDO" });

View File

@@ -26,8 +26,7 @@ void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) {
if (Rando::StaticData::stoneParamsToHint.contains(hintParams)) { if (Rando::StaticData::stoneParamsToHint.contains(hintParams)) {
stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; stoneHint = Rando::StaticData::stoneParamsToHint[hintParams];
} else if (hintParams == 0x18) { } else if (hintParams == 0x18) {
int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]); for (size_t i = 0; i < ACTORCAT_MAX; i++) {
for (int i = 0; i < numOfActorLists; i++) {
if (gPlayState->actorCtx.actorLists[i].length) { if (gPlayState->actorCtx.actorLists[i].length) {
if (gPlayState->actorCtx.actorLists[i].head->id == 10 && if (gPlayState->actorCtx.actorLists[i].head->id == 10 &&
Rando::StaticData::grottoChestParamsToHint.contains( Rando::StaticData::grottoChestParamsToHint.contains(

View File

@@ -17,7 +17,7 @@ extern "C" {
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
static const char* const englishIceTrapMessages[169] = { static const char* const englishIceTrapMessages[] = {
"You are a #FOOL#!", "You are a #FOOL#!",
"You are a #FOWL#!", "You are a #FOWL#!",
"#FOOL#!", "#FOOL#!",
@@ -193,7 +193,7 @@ static const char* const englishIceTrapMessages[169] = {
"#Titanic's revenge#.", "#Titanic's revenge#.",
}; };
static const char* const germanIceTrapMessages[23] = { static const char* const germanIceTrapMessages[] = {
"Du bist ein #DUMMKOPF#!", "Du bist ein #DUMMKOPF#!",
"Du bist eine #Frostbeule#!", "Du bist eine #Frostbeule#!",
"#DUMMKOPF#!", "#DUMMKOPF#!",
@@ -219,7 +219,7 @@ static const char* const germanIceTrapMessages[23] = {
"Kalt. Kalt. Kälter. #EISKALT#!", "Kalt. Kalt. Kälter. #EISKALT#!",
}; };
static const char* const frenchIceTrapMessages[83] = { static const char* const frenchIceTrapMessages[] = {
"#Pauvre fou#...", "#Pauvre fou#...",
"Tu es un #glaçon#, Harry!", "Tu es un #glaçon#, Harry!",
"#Sot# que tu es.", "#Sot# que tu es.",
@@ -319,8 +319,9 @@ void BuildIceTrapMessage(CustomMessage& msg) {
/*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!", { QM_BLUE }); /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", { QM_BLUE });
} else { } else {
msg = CustomMessage(RandomElement(englishIceTrapMessages), RandomElement(germanIceTrapMessages), msg = CustomMessage(ShipUtils::RandomElement(englishIceTrapMessages),
RandomElement(frenchIceTrapMessages), { QM_BLUE, QM_BLUE, QM_BLUE }); ShipUtils::RandomElement(germanIceTrapMessages),
ShipUtils::RandomElement(frenchIceTrapMessages), { QM_BLUE, QM_BLUE, QM_BLUE });
} }
msg.AutoFormat(); msg.AutoFormat();

View File

@@ -8,8 +8,7 @@ extern "C" {
#include <variables.h> #include <variables.h>
} }
#define NUM_NAVI_MESSAGES 18 static CustomMessage NaviMessages[] = {
CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = {
{ "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!",
"%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!",
@@ -113,7 +112,7 @@ CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = {
}; };
void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = NaviMessages[Random(0, NUM_NAVI_MESSAGES)]; CustomMessage msg = ShipUtils::RandomElement(NaviMessages);
msg.AutoFormat(); msg.AutoFormat();
msg.LoadIntoFont(); msg.LoadIntoFont();
*loadFromMessageTable = false; *loadFromMessageTable = false;
@@ -178,4 +177,5 @@ void RegisterNaviMessages() {
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); 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"), "IS_RANDO" });

View File

@@ -1,6 +1,5 @@
/** /**
* This file is for handling the Randomize Rupee Names * This file is for handling the Randomize Rupee Names enhancement
* enhancement
*/ */
#include <soh/OTRGlobals.h> #include <soh/OTRGlobals.h>
@@ -8,7 +7,7 @@ extern "C" {
#include "variables.h" #include "variables.h"
} }
static const char* englishRupeeNames[188] = { static const char* englishRupeeNames[] = {
"[P]", "[P]",
"Bad RNG Rolls", "Bad RNG Rolls",
"Baht", "Baht",
@@ -199,129 +198,129 @@ static const char* englishRupeeNames[188] = {
"Zorkmids", "Zorkmids",
}; };
static const char* germanRupeeNames[113] = { "Baht", static const char* germanRupeeNames[] = { "Baht",
"Baklava", "Baklava",
"Bananen", "Bananen",
"Bitcoin", "Bitcoin",
"Bonbons", "Bonbons",
"Bonschen", "Bonschen",
"Brause UFOs", "Brause UFOs",
"Bucks", "Bucks",
"Burek", "Burek",
"Cent", "Cent",
"Chickenwing", "Chickenwing",
"Diamanten", "Diamanten",
"Dinar", "Dinar",
"Diridari", "Diridari",
"Dollar", "Dollar",
"Draken", "Draken",
"ECU", "ECU",
"Eis", "Eis",
"Elexit", "Elexit",
"Erz", "Erz",
"Erzbrocken", "Erzbrocken",
"Ethereum", "Ethereum",
"Euro", "Euro",
"EXP", "EXP",
"Fartcoin", "Fartcoin",
"Forint", "Forint",
"Franken", "Franken",
"Freunde", "Freunde",
"Geister", "Geister",
"Gil", "Gil",
"Gold", "Gold",
"Groschen", "Groschen",
"Gulden", "Gulden",
"Haribo", "Haribo",
"Heller", "Heller",
"Juwelen", "Juwelen",
"Kapseln", "Kapseln",
"Karolin", "Karolin",
"Kartoffeln", "Kartoffeln",
"Keks", "Keks",
"Kies", "Kies",
"Knete", "Knete",
"Knochen", "Knochen",
"Knuspertaler", "Knuspertaler",
"Kohle", "Kohle",
"Kraniche", "Kraniche",
"Kreuzer", "Kreuzer",
"Kronen", "Kronen",
"Kronkorken", "Kronkorken",
"Lauchcoins", "Lauchcoins",
"Lira", "Lira",
"Mana", "Mana",
"Mark", "Mark",
"Monde", "Monde",
"Moos", "Moos",
"Naira", "Naira",
"Nugget", "Nugget",
"Penunze", "Penunze",
"Pesa", "Pesa",
"Peso", "Peso",
"Pfandflaschen", "Pfandflaschen",
"Pfennig", "Pfennig",
"Pfund", "Pfund",
"Pillen", "Pillen",
"Pilze", "Pilze",
"Plastiks", "Plastiks",
"Pok\x96" "Pok\x96"
"dollar", "dollar",
"Poster", "Poster",
"Puzzle", "Puzzle",
"Radieschen", "Radieschen",
"Rand", "Rand",
"Rappen", "Rappen",
"Real", "Real",
"Rial", "Rial",
"Riesennugget", "Riesennugget",
"Riyal", "Riyal",
"Rubine", "Rubine",
"Rupien", "Rupien",
"Saphire", "Saphire",
"Schilling", "Schilling",
"Schokobon", "Schokobon",
"Seelen", "Seelen",
"Septime", "Septime",
"Shitcoin", "Shitcoin",
"Smaragde", "Smaragde",
"Solana", "Solana",
"Sosis", "Sosis",
"Steine", "Steine",
"Sterne", "Sterne",
"Sternis", "Sternis",
"Tael", "Tael",
"Taler", "Taler",
"Tokens", "Tokens",
"Wagenchips", "Wagenchips",
"Won", "Won",
"Wumpas", "Wumpas",
"Yen", "Yen",
"Yuan", "Yuan",
"Zenny", "Zenny",
"M\x93use", "M\x93use",
"M\x9Enzen", "M\x9Enzen",
"Kr\x9Bten", "Kr\x9Bten",
"D\x9Bner", "D\x9Bner",
"W\x9Erstchen", "W\x9Erstchen",
"Kn\x9B" "Kn\x9B"
"del", "del",
"R\x9Bsti", "R\x9Bsti",
"H\x9Brnli", "H\x9Brnli",
"R\x9E" "R\x9E"
"ebli", "ebli",
"K\x9B" "K\x9B"
"fte", "fte",
"Bratw\x9E" "Bratw\x9E"
"rste", "rste",
"Br\x98" "Br\x98"
"tchen", "tchen",
"Gummib\x93" "Gummib\x93"
"ren", "ren",
"Moorh\x9E" "Moorh\x9E"
"hner" }; "hner" };
static const char* frenchRupeeNames[39] = { static const char* frenchRupeeNames[] = {
"Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules", "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules",
"Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dollars", "Émeraudes", "Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dollars", "Émeraudes",
"Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", "Grouses", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", "Grouses",
@@ -330,32 +329,33 @@ static const char* frenchRupeeNames[39] = {
}; };
void BuildRupeeMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildRupeeMessage(uint16_t* textId, bool* loadFromMessageTable) {
CustomMessage msg = CustomMessage( CustomMessage msg =
"You found [[color]][[amount]] [[rupee]]\x05\x00!", "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", CustomMessage("You found [[color]][[amount]] [[rupee]]%w!", "Du hast [[color]][[amount]] [[rupee]]%w gefunden!",
"Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM); "Vous obtenez [[color]][[amount]] [[rupee]]%w!");
std::string color; std::string color;
std::string amount; std::string amount;
CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), RandomElement(germanRupeeNames), CustomMessage rupee =
RandomElement(frenchRupeeNames)); CustomMessage(ShipUtils::RandomElement(englishRupeeNames), ShipUtils::RandomElement(germanRupeeNames),
ShipUtils::RandomElement(frenchRupeeNames));
switch (*textId) { switch (*textId) {
case TEXT_BLUE_RUPEE: case TEXT_BLUE_RUPEE:
color = "\x05\x03"; color = "%b";
amount = "5"; amount = "5";
break; break;
case TEXT_RED_RUPEE: case TEXT_RED_RUPEE:
color = "\x05\x01"; color = "%r";
amount = "20"; amount = "20";
break; break;
case TEXT_PURPLE_RUPEE: case TEXT_PURPLE_RUPEE:
color = "\x05\x05"; color = "%p";
amount = "50"; amount = "50";
break; break;
case TEXT_HUGE_RUPEE: case TEXT_HUGE_RUPEE:
color = "\x05\x06"; color = "%y";
amount = "200"; amount = "200";
break; break;
default: default:
assert(!"This should not be reachable"); assert(false);
return; return;
} }
msg.Replace("[[color]]", color); msg.Replace("[[color]]", color);
@@ -377,4 +377,5 @@ void RegisterRandomRupeeNames() {
IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); 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"), "IS_RANDO" });

View File

@@ -2,8 +2,6 @@
#include <soh/GameVersions.h> #include <soh/GameVersions.h>
#include <cstdio> // std::sprintf
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <soh/OTRGlobals.h> #include <soh/OTRGlobals.h>

View File

@@ -8,13 +8,11 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <spdlog/fmt/fmt.h> #include <spdlog/fmt/fmt.h>
#include "soh/OTRGlobals.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
#include "message_data_static.h" #include "message_data_static.h"
#include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "overlays/gamestates/ovl_file_choose/file_choose.h"
#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/Enhancements/FileSelectEnhancements.h" #include "soh/Enhancements/FileSelectEnhancements.h"
#include "soh/resource/type/SohResourceType.h"
extern "C" { extern "C" {
extern MapData* gMapData; extern MapData* gMapData;
@@ -862,16 +860,16 @@ void RegisterOnUpdateMainMenuSelection() {
if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0)) if (!CVarGetInteger(CVAR_SETTING("A11yTTS"), 0))
return; return;
char charVal[2]; char charVal[2] = {};
std::string translation; std::string translation;
if (charCode < 10) { // Digits if (charCode < 10) { // Digits
sprintf(charVal, "%c", charCode + 0x30); charVal[0] = charCode + 0x30;
} else if (charCode >= 10 && charCode < 36) { // Uppercase letters } else if (charCode >= 10 && charCode < 36) { // Uppercase letters
sprintf(charVal, "%c", charCode + 0x37); charVal[0] = charCode + 0x37;
translation = GetParameritizedText("capital_letter", TEXT_BANK_FILECHOOSE, charVal); translation = GetParameritizedText("capital_letter", TEXT_BANK_FILECHOOSE, charVal);
} else if (charCode >= 36 && charCode < 62) { // Lowercase letters } else if (charCode >= 36 && charCode < 62) { // Lowercase letters
sprintf(charVal, "%c", charCode + 0x3D); charVal[0] = charCode + 0x3D;
} else if (charCode == 62) { // Space } else if (charCode == 62) { // Space
translation = GetParameritizedText("space", TEXT_BANK_FILECHOOSE, nullptr); translation = GetParameritizedText("space", TEXT_BANK_FILECHOOSE, nullptr);
} else if (charCode == 63) { // - } else if (charCode == 63) { // -
@@ -883,7 +881,7 @@ void RegisterOnUpdateMainMenuSelection() {
} else if (charCode == 0xF0 + FS_KBD_BTN_END) { } else if (charCode == 0xF0 + FS_KBD_BTN_END) {
translation = GetParameritizedText("end", TEXT_BANK_FILECHOOSE, nullptr); translation = GetParameritizedText("end", TEXT_BANK_FILECHOOSE, nullptr);
} else { } else {
sprintf(charVal, "%c", charCode); charVal[0] = charCode;
} }
if (translation.empty()) { if (translation.empty()) {

View File

@@ -2,7 +2,6 @@
#define SHIP_UTILS_H #define SHIP_UTILS_H
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
//#include "PR/ultratypes.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -9,6 +9,8 @@
#include "Enhancements/randomizer/randomizerTypes.h" #include "Enhancements/randomizer/randomizerTypes.h"
#include <variables.h> #include <variables.h>
std::string invalidString = "";
std::vector<std::string> sceneNames = { std::vector<std::string> sceneNames = {
"Inside the Deku Tree", "Inside the Deku Tree",
"Dodongo's Cavern", "Dodongo's Cavern",
@@ -683,7 +685,7 @@ const std::string& SohUtils::GetSceneName(int32_t scene) {
if (scene > sceneNames.size()) { if (scene > sceneNames.size()) {
SPDLOG_WARN("Passed invalid scene id to SohUtils::GetSceneName: ({})", scene); SPDLOG_WARN("Passed invalid scene id to SohUtils::GetSceneName: ({})", scene);
assert(false); assert(false);
return ""; return invalidString;
} }
return sceneNames[scene]; return sceneNames[scene];
@@ -708,7 +710,7 @@ const std::string& SohUtils::GetItemName(int32_t item) {
if (item >= currentItemNames->size()) { if (item >= currentItemNames->size()) {
SPDLOG_WARN("Passed invalid item id to SohUtils::GetItemName: ({})", item); SPDLOG_WARN("Passed invalid item id to SohUtils::GetItemName: ({})", item);
assert(false); assert(false);
return ""; return invalidString;
} }
return (*currentItemNames)[item]; return (*currentItemNames)[item];
@@ -732,7 +734,7 @@ const std::string& SohUtils::GetQuestItemName(int32_t item) {
if (item > questItemNamesEng.size()) { if (item > questItemNamesEng.size()) {
SPDLOG_WARN("Passed invalid quest item id to SohUtils::GetQuestItemName: ({})", item); SPDLOG_WARN("Passed invalid quest item id to SohUtils::GetQuestItemName: ({})", item);
assert(false); assert(false);
return ""; return invalidString;
} }
return (*currentQuestItemNames)[item]; return (*currentQuestItemNames)[item];
@@ -742,7 +744,7 @@ const std::string& SohUtils::GetRandomizerCheckAreaPrefix(int32_t rcarea) {
if (rcarea > rcareaPrefixes.size()) { if (rcarea > rcareaPrefixes.size()) {
SPDLOG_WARN("Passed invalid rcarea to SohUtils::GetRandomizerCheckAreaPrefix: ({})", rcarea); SPDLOG_WARN("Passed invalid rcarea to SohUtils::GetRandomizerCheckAreaPrefix: ({})", rcarea);
assert(false); assert(false);
return ""; return invalidString;
} }
return rcareaPrefixes[rcarea]; return rcareaPrefixes[rcarea];

View File

@@ -2785,7 +2785,6 @@ void Message_OpenText(PlayState* play, u16 textId) {
gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0; gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0;
} }
// RANDOTODO: Use this for ice trap messages
if (!loadFromMessageTable) { if (!loadFromMessageTable) {
osSyncPrintf("Found custom message"); osSyncPrintf("Found custom message");
if (gSaveContext.language == LANGUAGE_JPN) { if (gSaveContext.language == LANGUAGE_JPN) {