#include "OTRGlobals.h" #include #include "soh/resource/type/Scene.h" #include #include "global.h" #include "vt.h" #include "soh/resource/type/Text.h" #include #include "Enhancements/custom-message/CustomMessageManager.h" #include "Enhancements/custom-message/CustomMessageTypes.h" extern "C" MessageTableEntry* sNesMessageEntryTablePtr; extern "C" MessageTableEntry* sGerMessageEntryTablePtr; extern "C" MessageTableEntry* sFraMessageEntryTablePtr; extern "C" MessageTableEntry* sStaffMessageEntryTablePtr; //extern "C" MessageTableEntry* _message_0xFFFC_nes; MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) { auto file = std::static_pointer_cast(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(filePath)); if (file == nullptr) return nullptr; // Allocate room for an additional message MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * (file->messages.size() + 1)); for (size_t i = 0; i < file->messages.size(); i++) { // Look for Owl Text if (file->messages[i].id == 0x2066) { // Create a new message based on the Owl Text uint32_t kaeporaMsgSize = file->messages[i].msg.size(); char* kaeporaOg = (char*)malloc(sizeof(char) * kaeporaMsgSize); char* kaeporaPatch = (char*)malloc(sizeof(char) * kaeporaMsgSize); file->messages[i].msg.copy(kaeporaOg, kaeporaMsgSize, 0); file->messages[i].msg.copy(kaeporaPatch, kaeporaMsgSize, 0); size_t colorPos = file->messages[i].msg.find(QM_GREEN); size_t newLinePos = colorPos + file->messages[i].msg.substr(colorPos + 1).find(CTRL_NEWLINE) + 1; size_t endColorPos = newLinePos + file->messages[i].msg.substr(newLinePos).find(CTRL_COLOR); size_t NoLength = newLinePos - (colorPos + 1); size_t YesLength = endColorPos - (newLinePos + 1); // Swap the order of yes and no in this new message size_t yes = 0; while (yes < YesLength) { kaeporaPatch[colorPos + yes + 1] = kaeporaOg[newLinePos + yes + 1]; yes++; } kaeporaPatch[colorPos + yes + 1] = CTRL_NEWLINE; size_t no = 0; while (no < NoLength) { kaeporaPatch[colorPos + yes + 2 + no] = kaeporaOg[colorPos + 1 + no]; no++; } // load data into message table[file->messages.size()].textId = 0x71B3; table[file->messages.size()].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos; table[file->messages.size()].segment = kaeporaPatch; table[file->messages.size()].msgSize = kaeporaMsgSize; } table[i].textId = file->messages[i].id; table[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos; table[i].segment = file->messages[i].msg.c_str(); table[i].msgSize = file->messages[i].msg.size(); if (isNES && file->messages[i].id == 0xFFFC) _message_0xFFFC_nes = (char*)file->messages[i].msg.c_str(); } return table; } extern "C" void OTRMessage_Init() { sNesMessageEntryTablePtr = OTRMessage_LoadTable("text/nes_message_data_static/nes_message_data_static", true); sGerMessageEntryTablePtr = OTRMessage_LoadTable("text/ger_message_data_static/ger_message_data_static", false); sFraMessageEntryTablePtr = OTRMessage_LoadTable("text/fra_message_data_static/fra_message_data_static", false); auto file2 = std::static_pointer_cast(OTRGlobals::Instance->context->GetResourceManager()->LoadResource("text/staff_message_data_static/staff_message_data_static")); sStaffMessageEntryTablePtr = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file2->messages.size()); for (size_t i = 0; i < file2->messages.size(); i++) { sStaffMessageEntryTablePtr[i].textId = file2->messages[i].id; sStaffMessageEntryTablePtr[i].typePos = (file2->messages[i].textboxType << 4) | file2->messages[i].textboxYPos; sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str(); sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size(); } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "You got a %rGold Skulltula Token%w!&You've collected %r{{gsCount}}%w tokens&in total!\x0E\x3C", "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r{{gsCount}}&%wGoldene Skulltula-Symbole&gesammelt!\x0E\x3C", "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r{{gsCount}}%w symboles en tout!\x0E\x3C" } ); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "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 Skulltula-Symbole&gesammelt!", "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r{{gsCount}}%w symboles en tout!" } ); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHU_10_DESC, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, "\x08%rBombchu (10 pieces) 99 Rupees&%wThis looks like a toy mouse, but&it's actually a self-propelled time&bomb!\x09\x0A", "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als Distanzwaffe&einsetzen kannst!\x09\x0A", "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est &destructrice!!!\x09\x0A", } ); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHU_10_PROMPT, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, "\x08" "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%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", } ); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_CONTAINER, ITEM_HEART_CONTAINER, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "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!", "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r{{heartContainerCount}}%w en tout!" } ); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "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&Herteile gesammelt!", "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r{{heartPieceCount}}%w en tout!" } ); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, "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", "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w", } ); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_RANDO_SAVE_VERSION_WARNING, { TEXTBOX_TYPE_NONE_BOTTOM, TEXTBOX_POS_BOTTOM, "This save was created on&a different version of SoH.&&Things may be broken.", "Dieser Spielstand wurde auf einer&anderen Version von SoH erstellt.&&Es könnten Fehler auftreten.", "Cette sauvegarde a été créée sur&une version différente de SoH.&Certaines fonctionnalités&peuvent être corrompues.", } ); }