diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 037539b2a..43054c711 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -179,6 +179,7 @@ + @@ -942,9 +943,9 @@ - + @@ -985,7 +986,6 @@ - diff --git a/soh/soh/Enhancements/custom_message/CustomMessage.cpp b/soh/soh/Enhancements/custom_message/CustomMessage.cpp new file mode 100644 index 000000000..1985a2bbc --- /dev/null +++ b/soh/soh/Enhancements/custom_message/CustomMessage.cpp @@ -0,0 +1,108 @@ +#include "CustomMessage.h" +#include + +using namespace std::literals::string_literals; + +CustomMessage::CustomMessage() { + this->textBoxSpecialCharacters = { { "À", 0x80 }, { "î", 0x81 }, { "Â", 0x82 }, { "Ä", 0x83 }, { "Ç", 0x84 }, + { "È", 0x85 }, { "É", 0x86 }, { "Ê", 0x87 }, { "Ë", 0x88 }, { "Ï", 0x89 }, + { "Ô", 0x8A }, { "Ö", 0x8B }, { "Ù", 0x8C }, { "Û", 0x8D }, { "Ü", 0x8E }, + { "ß", 0x8F }, { "à", 0x90 }, { "á", 0x91 }, { "â", 0x92 }, { "ä", 0x93 }, + { "ç", 0x94 }, { "è", 0x95 }, { "é", 0x96 }, { "ê", 0x97 }, { "ë", 0x98 }, + { "ï", 0x99 }, { "ô", 0x9A }, { "ö", 0x9B }, { "ù", 0x9C }, { "û", 0x9D }, + { "ü", 0x9E } }; + this->colors = { { "w", QM_WHITE }, { "r", QM_RED }, { "g", QM_GREEN }, { "b", QM_BLUE }, + { "c", QM_LBLUE }, { "p", QM_PINK }, { "y", QM_YELLOW }, { "B", QM_BLACK } }; +} + +CustomMessage::~CustomMessage() { + this->textBoxSpecialCharacters.clear(); +} + +void CustomMessage::ReplaceSpecialCharacters(std::string& string) { + // add special characters + for (auto specialCharacterPair : textBoxSpecialCharacters) { + size_t start_pos = 0; + std::string textBoxSpecialCharacterString = ""; + textBoxSpecialCharacterString += specialCharacterPair.second; + while ((start_pos = string.find(specialCharacterPair.first, start_pos)) != std::string::npos) { + string.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString); + start_pos += textBoxSpecialCharacterString.length(); + } + } +} + +void CustomMessage::ReplaceColors(std::string& string) { + for (auto colorPair : colors) { + std::string textToReplace = "%"; + textToReplace += colorPair.first; + size_t start_pos = 0; + while ((start_pos = string.find(textToReplace)) != std::string::npos) { + string.replace(start_pos, textToReplace.length(), COLOR(colorPair.second)); + start_pos += textToReplace.length(); + } + } +} + +void CustomMessage::CreateGetItemMessage(GetItemID giid, ItemID iid, std::string messages[LANGUAGE_MAX]) { + for (int i = 0; i < LANGUAGE_MAX; i++) { + if (!(messages[i].empty())) { + std::string message = messages[i]; + std::string formattedMessage = ITEM_OBTAINED(iid) + message; + size_t start_pos = 0; + std::replace(formattedMessage.begin(), formattedMessage.end(), '&', NEWLINE()[0]); + while ((start_pos = formattedMessage.find('^', start_pos)) != std::string::npos) { + formattedMessage.replace(start_pos, 1, WAIT_FOR_INPUT() + ITEM_OBTAINED(iid)); + start_pos += 3; + } + std::replace(formattedMessage.begin(), formattedMessage.end(), '@', PLAYER_NAME()[0]); + ReplaceSpecialCharacters(formattedMessage); + ReplaceColors(formattedMessage); + formattedMessage += MESSAGE_END(); + this->getItemMessageTable[i].emplace(giid, formattedMessage); + } else { + this->getItemMessageTable[i].emplace(giid, MESSAGE_END()); + } + } +} + +std::string CustomMessage::RetrieveGetItemMessage(GetItemID giid) { + std::unordered_map::const_iterator result = + getItemMessageTable[gSaveContext.language].find(giid); + if (result == getItemMessageTable[gSaveContext.language].end()) { + switch (gSaveContext.language) { + case LANGUAGE_FRA: + return "Il n'y a pas de message personnalisé pour cet élément."; + case LANGUAGE_GER: + return "Für diesen Artikel gibt es keine benutzerdefinierte Nachricht."; + case LANGUAGE_ENG: + default: + return "There is no custom message for this item."; + } + } + return result->second; +} + +std::string CustomMessage::MESSAGE_END() { + return "\x02"s; +} + +std::string CustomMessage::ITEM_OBTAINED(uint8_t x) { + return "\x13"s + char(x); +} + +std::string CustomMessage::NEWLINE() { + return "\x01"s; +} + +std::string CustomMessage::COLOR(uint8_t x) { + return "\x05"s + char(x); +} + +std::string CustomMessage::WAIT_FOR_INPUT() { + return "\x04"s; +} + +std::string CustomMessage::PLAYER_NAME() { + return "\x0F"s; +} \ No newline at end of file diff --git a/soh/soh/Enhancements/custom_message/CustomMessage.h b/soh/soh/Enhancements/custom_message/CustomMessage.h new file mode 100644 index 000000000..d8cfd8e0d --- /dev/null +++ b/soh/soh/Enhancements/custom_message/CustomMessage.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include "variables.h" + +#define QM_WHITE 0x00 +#define QM_RED 0x41 +#define QM_GREEN 0x42 +#define QM_BLUE 0x43 +#define QM_LBLUE 0x44 +#define QM_PINK 0x45 +#define QM_YELLOW 0x46 +#define QM_BLACK 0x47 + +class CustomMessage { + private: + std::unordered_map textBoxSpecialCharacters; + std::unordered_map colors; + std::unordered_map getItemMessageTable[LANGUAGE_MAX]; + + void ReplaceSpecialCharacters(std::string &string); + void ReplaceColors(std::string& string); + + std::string MESSAGE_END(); + std::string ITEM_OBTAINED(uint8_t x); + std::string NEWLINE(); + std::string COLOR(uint8_t x); + std::string WAIT_FOR_INPUT(); + std::string PLAYER_NAME(); + + public: + static CustomMessage* Instance; + + CustomMessage(); + ~CustomMessage(); + + void CreateGetItemMessage(GetItemID giid, ItemID iid, std::string messages[LANGUAGE_MAX]); + std::string RetrieveGetItemMessage(GetItemID giid); +}; \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 09704e867..4c589ea48 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4748,6 +4748,7 @@ void DrawRandoEditor(bool& open) { void InitRando() { SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor); + Randomizer::CreateCustomMessages(); } extern "C" { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 180d91691..6f928bd66 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -5,6 +5,7 @@ #include "../../../include/ultra64.h" #include "../../../include/z64item.h" #include +#include class Randomizer { private: @@ -42,6 +43,7 @@ class Randomizer { GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); std::string GetCustomGetItemMessage(GetItemID giid); + static void CreateCustomMessages(); }; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/randomizer/randomizer_custom_messages.cpp b/soh/soh/Enhancements/randomizer/randomizer_custom_messages.cpp index 659e68fe8..a31edcbee 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_custom_messages.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_custom_messages.cpp @@ -1,54 +1,33 @@ -#include "randomizer_custom_messages.h" #include "randomizer.h" -#include +#include "soh/Enhancements/custom_message/CustomMessage.h" using namespace std::literals::string_literals; +#define MESSAGES(eng, ger, fra) (new std::string[]{eng, ger, fra}) + +void Randomizer::CreateCustomMessages() { + CustomMessage* customMessage = CustomMessage::Instance; + customMessage->CreateGetItemMessage( + GI_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, + MESSAGES("You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", "", "")); + customMessage->CreateGetItemMessage( + GI_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE, + MESSAGES("You got a %rBig Poe in a bottle%w!&Sell it to the Ghost Shop!", "", "")); + customMessage->CreateGetItemMessage( + GI_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, + MESSAGES("You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", "", "")); + customMessage->CreateGetItemMessage( + GI_BOTTLE_WITH_FISH, ITEM_FISH, + MESSAGES("You got a %rFish in a bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", "", + "")); + + +} + std::string Randomizer::GetCustomGetItemMessage(GetItemID giid) { if (!gSaveContext.n64ddFlag) { return "Not Randomized."; } - switch (giid) { - case GI_BOTTLE_WITH_BLUE_FIRE: - switch (gSaveContext.language) { - case LANGUAGE_FRA: - case LANGUAGE_GER: - case LANGUAGE_ENG: - default: - return ITEM_OBTAINED(ITEM_BLUE_FIRE) + "You got a " + COLOR(QM_RED) + "Bottle with Blue " + - NEWLINE() + "Fire" + COLOR(QM_WHITE) + "! Use it to melt Red Ice!" + - MESSAGE_END(); - } - default: - switch (gSaveContext.language) { - case LANGUAGE_FRA: - return "Il n'y a pas de message personnalisé pour cet élément."; - case LANGUAGE_GER: - return "Für diesen Artikel gibt es keine benutzerdefinierte Nachricht."; - case LANGUAGE_ENG: - default: - return "There is no custom message for this item."; - } - } -} - -std::string MESSAGE_END() { - return "\x02"s; -} - -std::string ITEM_OBTAINED(uint8_t x) { - return "\x13"s + char(x); -} - -std::string NEWLINE() { - return "\x01"s; -} - -std::string COLOR(uint8_t x) { - return "\x05"s + char(x); -} - -std::string WAIT_FOR_INPUT() { - return "\x04"s; + return CustomMessage::Instance->RetrieveGetItemMessage(giid); } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer_custom_messages.h b/soh/soh/Enhancements/randomizer/randomizer_custom_messages.h deleted file mode 100644 index cae3c65b5..000000000 --- a/soh/soh/Enhancements/randomizer/randomizer_custom_messages.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "../../../include/z64item.h" - -#define QM_WHITE 0x00 -#define QM_RED 0x41 -#define QM_GREEN 0x42 -#define QM_BLUE 0x43 -#define QM_LBLUE 0x44 -#define QM_PINK 0x45 -#define QM_YELLOW 0x46 -#define QM_BLACK 0x47 - -std::string MESSAGE_END(); -std::string ITEM_OBTAINED(uint8_t x); -std::string NEWLINE(); -std::string COLOR(uint8_t x); -std::string WAIT_FOR_INPUT(); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 5ec051af0..6691127be 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -38,6 +38,7 @@ #include "Enhancements/debugger/debugger.h" #include "Enhancements/randomizer/randomizer.h" #include +#include #include "Enhancements/n64_weird_frame_data.inc" #include "soh/frame_interpolation.h" #include "Utils/BitConverter.h" @@ -55,6 +56,7 @@ OTRGlobals* OTRGlobals::Instance; SaveManager* SaveManager::Instance; +CustomMessage* CustomMessage::Instance; OTRGlobals::OTRGlobals() { context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian"); @@ -106,6 +108,7 @@ extern "C" void OTRExtScanner() { extern "C" void InitOTR() { OTRGlobals::Instance = new OTRGlobals(); SaveManager::Instance = new SaveManager(); + CustomMessage::Instance = new CustomMessage(); auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version"); if (!t->bHasLoadError) diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 1cb90fc91..d999f1bda 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -9,7 +9,6 @@ #ifdef __cplusplus #include "Enhancements/savestates.h" #include "Enhancements/randomizer/randomizer.h" - class OTRGlobals { public: diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index c27b78ee8..15ff2e7d8 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -654,13 +654,13 @@ static GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG), - GET_ITEM(ITEM_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0xF8, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG), - GET_ITEM(ITEM_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, 0xF8, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0xF8, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG), - GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG), - GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, 0xF9, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, 0xF8, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, 0xF8, 0x80, CHEST_ANIM_LONG), GET_ITEM_NONE, GET_ITEM_NONE,