From 4eaf70b85901c10e9f3728ea17195d72c3fb21cd Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sun, 17 Jul 2022 12:34:56 -0400 Subject: [PATCH] Refactors CustomMessages to not be rando specific. Pulls the Custom Message related code out into it's own class, which has an initialization phase where other enhancements / future features can create messages during an initialization phase to be stored and retrieved later. Along with this refactoring, the 4 bottle messages from the previous rando-specific system are now created and stored during intialization and retrieved by their getItemId. Now that it isn't rando specific, the goal is to move anything text changes that are hard-coded into z_message_PAL.c and refactor it so that future text additions/overrides can be done without modifying that file. --- soh/soh.vcxproj | 4 +- .../custom_message/CustomMessage.cpp | 108 ++++++++++++++++++ .../custom_message/CustomMessage.h | 39 +++++++ .../Enhancements/randomizer/randomizer.cpp | 1 + soh/soh/Enhancements/randomizer/randomizer.h | 2 + .../randomizer/randomizer_custom_messages.cpp | 67 ++++------- .../randomizer/randomizer_custom_messages.h | 19 --- soh/soh/OTRGlobals.cpp | 3 + soh/soh/OTRGlobals.h | 1 - .../actors/ovl_player_actor/z_player.c | 8 +- 10 files changed, 182 insertions(+), 70 deletions(-) create mode 100644 soh/soh/Enhancements/custom_message/CustomMessage.cpp create mode 100644 soh/soh/Enhancements/custom_message/CustomMessage.h delete mode 100644 soh/soh/Enhancements/randomizer/randomizer_custom_messages.h 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,