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,7 +198,7 @@ static const char* englishRupeeNames[188] = {
"Zorkmids", "Zorkmids",
}; };
static const char* germanRupeeNames[113] = { "Baht", static const char* germanRupeeNames[] = { "Baht",
"Baklava", "Baklava",
"Bananen", "Bananen",
"Bitcoin", "Bitcoin",
@@ -321,7 +320,7 @@ static const char* germanRupeeNames[113] = { "Baht",
"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) {