diff --git a/soh/soh/Enhancements/custom_message/CustomMessage.cpp b/soh/soh/Enhancements/custom_message/CustomMessage.cpp index 20170a7baff..7f26fb616f1 100644 --- a/soh/soh/Enhancements/custom_message/CustomMessage.cpp +++ b/soh/soh/Enhancements/custom_message/CustomMessage.cpp @@ -100,29 +100,27 @@ bool CustomMessage::CreateMessage(std::string tableID, uint16_t textID, CustomMe return InsertCustomMessage(tableID, textID, messages); } -std::string CustomMessage::RetrieveMessage(GlobalContext* globalCtx, std::string tableID, uint16_t textID) { +CustomMessageEntry CustomMessage::RetrieveMessage(std::string tableID, uint16_t textID) { std::unordered_map::const_iterator result = messageTables.find(tableID); if (result == messageTables.end()) { - return ""; + return NULL_CUSTOM_MESSAGE; } CustomMessageTable messageTable = result->second; std::unordered_map::const_iterator message_pair = messageTable.find(textID); if (message_pair == messageTable.end()) { - return ""; + return NULL_CUSTOM_MESSAGE; } - CustomMessageEntry messages = message_pair->second; - MessageContext* msgCtx = &globalCtx->msgCtx; - Font* font = &msgCtx->font; - font->charTexBuf[0] = (messages.textBoxType << 4) | messages.textBoxPos; - switch (gSaveContext.language) { - case LANGUAGE_FRA: - return messages.french; - case LANGUAGE_GER: - return messages.german; - case LANGUAGE_ENG: - default: - return messages.english; + CustomMessageEntry message = message_pair->second; + return message; +} + +bool CustomMessage::ClearMessageTable(std::string tableID) { + auto result = messageTables.find(tableID); + if (result == messageTables.end()) { + return false; } + auto& messageTable = result->second; + messageTable.clear(); } bool CustomMessage::AddCustomMessageTable(std::string tableID) { diff --git a/soh/soh/Enhancements/custom_message/CustomMessage.h b/soh/soh/Enhancements/custom_message/CustomMessage.h index 513cdaf6058..465d1fafcfa 100644 --- a/soh/soh/Enhancements/custom_message/CustomMessage.h +++ b/soh/soh/Enhancements/custom_message/CustomMessage.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include "z64.h" #include #undef MESSAGE_END @@ -23,6 +22,9 @@ typedef struct { std::string french; } CustomMessageEntry; +#define NULL_CUSTOM_MESSAGE \ + { (TextBoxType)(-1), (TextBoxPosition)(-1), "", "", "" } + typedef std::unordered_map CustomMessageTable; class CustomMessage { @@ -52,6 +54,7 @@ class CustomMessage { bool CreateGetItemMessage(std::string tableID, GetItemID giid, ItemID iid, CustomMessageEntry messages); bool CreateMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages); - std::string RetrieveMessage(GlobalContext* globalCtx, std::string tableID, uint16_t textID); + CustomMessageEntry RetrieveMessage(std::string tableID, uint16_t textID); + bool ClearMessageTable(std::string tableID); bool AddCustomMessageTable(std::string tableID); }; \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2e47c7c80cd..77e426bafa8 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -14,6 +14,7 @@ #include "3drando/rando_main.hpp" #include #include "Lib/ImGui/imgui_internal.h" +#include using json = nlohmann::json; @@ -21,7 +22,8 @@ std::unordered_map gSeedTextures; u8 generated; -const std::string Randomizer::customMessageTableID = "Randomizer"; +const std::string Randomizer::getItemMessageTableID = "Randomizer"; +const std::string Randomizer::hintMessageTableID = "RandomizerHints"; Randomizer::Randomizer() { Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 }; @@ -1479,6 +1481,22 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) { ParseHintLocationsFile(spoilerFileName); } + CustomMessage::Instance->ClearMessageTable(Randomizer::hintMessageTableID); + CustomMessage::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); + + CustomMessage::Instance->CreateMessage( + Randomizer::hintMessageTableID, 0x7040, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.childAltarText, "", "" }); + CustomMessage::Instance->CreateMessage( + Randomizer::hintMessageTableID, 0x7088, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.adultAltarText, "", "" }); + CustomMessage::Instance->CreateMessage( + Randomizer::hintMessageTableID, 0x70CC, + { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonHintText, "", "" }); + CustomMessage::Instance->CreateMessage( + Randomizer::hintMessageTableID, 0x70CD, + { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonText, "", "" }); + this->childAltarText = gSaveContext.childAltarText; this->adultAltarText = gSaveContext.adultAltarText; this->ganonHintText = gSaveContext.ganonHintText; @@ -1487,6 +1505,8 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) { for (auto hintLocation : gSaveContext.hintLocations) { if(hintLocation.check == RC_LINKS_POCKET) break; this->hintLocations[hintLocation.check] = hintLocation.hintText; + CustomMessage::Instance->CreateMessage( + Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, "", "" }); } } @@ -2409,9 +2429,9 @@ std::string Randomizer::GetGanonHintText() const { return ganonHintText; } -std::string Randomizer::GetHintFromCheck(RandomizerCheck check) { - return this->hintLocations[check]; -} +//CustomMessageEntry Randomizer::GetHintFromCheck(RandomizerCheck check) { +// return CustomMessage::Instance->RetrieveMessage(hintMessageTableID, check); +//} u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { return this->randoSettings[randoSettingKey]; @@ -4748,6 +4768,46 @@ void DrawRandoEditor(bool& open) { }*/ +void Randomizer::CreateCustomMessages() { + CustomMessage* customMessage = CustomMessage::Instance; + customMessage->AddCustomMessageTable(Randomizer::getItemMessageTableID); + customMessage->CreateGetItemMessage(Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", "", + "" }); + customMessage->CreateGetItemMessage(Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!", "", + "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", "", "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_FISH, ITEM_FISH, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", "", "" }); + customMessage->CreateGetItemMessage(Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_BUGS, ITEM_BUG, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!", "", + "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_FAIRY, ITEM_FAIRY, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "You got a %rFairy in a Bottle%w!&Use it wisely!", "", "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!", "", "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!", "", "" }); + customMessage->CreateGetItemMessage( + Randomizer::getItemMessageTableID, GI_BOTTLE_WITH_POE, ITEM_POE, + { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, + "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...", "", "" }); + } + void InitRando() { SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor); Randomizer::CreateCustomMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 5f9f1f1bc03..ec27d684d67 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -26,7 +26,8 @@ class Randomizer { Randomizer(); ~Randomizer(); - static const std::string customMessageTableID; + static const std::string getItemMessageTableID; + static const std::string hintMessageTableID; static Sprite* GetSeedTexture(uint8_t index); s16 GetItemModelFromId(s16 itemId); @@ -41,7 +42,7 @@ class Randomizer { std::string GetAdultAltarText() const; std::string GetGanonText() const; std::string GetGanonHintText() const; - std::string GetHintFromCheck(RandomizerCheck check); + //CustomMessageEntry GetHintFromCheck(RandomizerCheck check); GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); //std::string GetCustomGetItemMessage(GlobalContext* globalCtx, GetItemID giid); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c048d3358ee..f570c3b10d8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -36,15 +36,14 @@ #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugconsole.h" #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" #include "variables.h" #include "macros.h" #include +#include #ifdef __APPLE__ #include @@ -1490,11 +1489,11 @@ extern "C" int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSiz return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize); } -extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) { +extern "C" CustomMessageEntry Randomizer_CopyHintFromCheck(RandomizerCheck check) { // we don't want to make a copy of the std::string returned from GetHintFromCheck // so we're just going to let RVO take care of it - const std::string& hintText = OTRGlobals::Instance->gRandomizer->GetHintFromCheck(check); - return CopyStringToCharBuffer(hintText, buffer, maxBufferSize); + const CustomMessageEntry hintText = CustomMessage::Instance->RetrieveMessage(Randomizer::hintMessageTableID, check); + return hintText; } extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { @@ -1505,12 +1504,9 @@ extern "C" s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerChec return OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); } -extern "C" int Randomizer_GetCustomGetItemMessage(GlobalContext* globalCtx, GetItemID giid, char* buffer, const int maxBufferSize) { - const std::string& getItemText = CustomMessage::Instance->RetrieveMessage(globalCtx, Randomizer::customMessageTableID, giid); - if (getItemText == "") { - return false; - } - return CopyStringToCharBuffer(getItemText, buffer, maxBufferSize); +extern "C" CustomMessageEntry Randomizer_GetCustomGetItemMessage(GetItemID giid, char* buffer, const int maxBufferSize) { + const CustomMessageEntry getItemText = CustomMessage::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, giid); + return getItemText; } extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { @@ -1519,42 +1515,67 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { Font* font = &msgCtx->font; char* buffer = font->msgBuf; const int maxBufferSize = sizeof(font->msgBuf); + CustomMessageEntry messageEntry; if (gSaveContext.n64ddFlag) { if (textId == 0xF8) { - font->charTexBuf[0] = 0x23; - if (msgCtx->msgLength = font->msgLength = Randomizer_GetCustomGetItemMessage( - globalCtx, (GetItemID)GET_PLAYER(globalCtx)->getItemId, buffer, maxBufferSize)) { - return true; - } else { - switch (gSaveContext.language) { - case LANGUAGE_FRA: - return msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer( - "Il n'y a pas de message personnalisé pour cet élément.\x02", buffer, maxBufferSize); - case LANGUAGE_GER: - return msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer( - "Für diesen Artikel gibt es keine benutzerdefinierte Nachricht.\x02", buffer, - maxBufferSize); - case LANGUAGE_ENG: - default: - return msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer( - "There is no custom message for this item.\x02", buffer, maxBufferSize); + messageEntry = + Randomizer_GetCustomGetItemMessage((GetItemID)GET_PLAYER(globalCtx)->getItemId, buffer, maxBufferSize); + } + if (textId == 0x2053 && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 && + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 || + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 && + Player_GetMask(globalCtx) == PLAYER_MASK_TRUTH) || + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { + + s16 actorParams = msgCtx->talkActor->params; + + // if we're in a generic grotto + if (globalCtx->sceneNum == 62 && actorParams == 14360) { + // look for the chest in the actorlist to determine + // which grotto we're in + int numOfActorLists = + sizeof(globalCtx->actorCtx.actorLists) / sizeof(globalCtx->actorCtx.actorLists[0]); + for (int i = 0; i < numOfActorLists; i++) { + if (globalCtx->actorCtx.actorLists[i].length) { + if (globalCtx->actorCtx.actorLists[i].head->id == 10) { + // set the params for the hint check to be negative chest params + actorParams = 0 - globalCtx->actorCtx.actorLists[i].head->params; + } + } } } + + RandomizerCheck hintCheck = + Randomizer_GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams); + + messageEntry = Randomizer_CopyHintFromCheck(hintCheck); } } if (textId == 0x00B4 || textId == 0x00B5) { if (CVar_GetS32("gInjectSkulltulaCount", 0) != 0) { font->charTexBuf[0] = 0x03; - std::string message; if (CVar_GetS32("gSkulltulaFreeze", 0) != 0) { textId = 0x00B4; } else { textId = 0x00B5; } - message = CustomMessage::Instance->RetrieveMessage(globalCtx, "BaseGameOverrides", textId); - if (message != "") { - return msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(message, buffer, maxBufferSize); - } + messageEntry = CustomMessage::Instance->RetrieveMessage("BaseGameOverrides", textId); + } + } + if (messageEntry.textBoxType != -1) { + font->charTexBuf[0] = (messageEntry.textBoxType << 4) | messageEntry.textBoxPos; + switch (gSaveContext.language) { + case LANGUAGE_FRA: + return msgCtx->msgLength = font->msgLength = + CopyStringToCharBuffer(messageEntry.french, buffer, maxBufferSize); + case LANGUAGE_GER: + return msgCtx->msgLength = font->msgLength = + CopyStringToCharBuffer(messageEntry.german, buffer, maxBufferSize); + + case LANGUAGE_ENG: + default: + return msgCtx->msgLength = font->msgLength = + CopyStringToCharBuffer(messageEntry.english, buffer, maxBufferSize); } } return false; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 83618f994ed..4a924ed610a 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -9,6 +9,7 @@ #ifdef __cplusplus #include "Enhancements/savestates.h" #include "Enhancements/randomizer/randomizer.h" + class OTRGlobals { public: @@ -87,7 +88,6 @@ void Randomizer_LoadSettings(const char* spoilerFileName); u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum); int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize); -int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize); int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize); int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize); void Randomizer_LoadHintLocations(const char* spoilerFileName); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 503d3e14b24..c09286fadb4 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -1,7 +1,6 @@ #include "OTRGlobals.h" #include "ResourceMgr.h" #include "Scene.h" -#include "message_data_static.h" #include "Utils/StringHelper.h" #include "global.h" #include "vt.h" diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index e44e5f3257b..7a0aed9b2c8 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1675,39 +1675,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { //font->msgLength, __FILE__, __LINE__); } else { Message_FindMessage(globalCtx, textId); - // if we're rando'd and talking to a gossip stone - if (gSaveContext.n64ddFlag && - textId == 0x2053 && - Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 && - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 && - Player_GetMask(globalCtx) == PLAYER_MASK_TRUTH) || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && - CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { - - s16 actorParams = msgCtx->talkActor->params; - - // if we're in a generic grotto - if (globalCtx->sceneNum == 62 && actorParams == 14360) { - // look for the chest in the actorlist to determine - // which grotto we're in - int numOfActorLists = sizeof(globalCtx->actorCtx.actorLists)/sizeof(globalCtx->actorCtx.actorLists[0]); - for(int i = 0; i < numOfActorLists; i++) { - if(globalCtx->actorCtx.actorLists[i].length) { - if(globalCtx->actorCtx.actorLists[i].head->id == 10) { - // set the params for the hint check to be negative chest params - actorParams = 0 - globalCtx->actorCtx.actorLists[i].head->params; - } - } - } - } - - RandomizerCheck hintCheck = Randomizer_GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams); - - // Pass the sizeof the message buffer so we don't hardcode any sizes and can rely on globals. - // If no hint can be found, this just returns 0 size and doesn't modify the buffer, so no worries. - msgCtx->msgLength = font->msgLength = Randomizer_CopyHintFromCheck(hintCheck, font->msgBuf, sizeof(font->msgBuf)); - } else if (gSaveContext.n64ddFlag && (textId == 0x7040 || textId == 0x7088)) { + if (gSaveContext.n64ddFlag && (textId == 0x7040 || textId == 0x7088)) { // rando hints at altar msgCtx->msgLength = font->msgLength = Randomizer_CopyAltarMessage(font->msgBuf, sizeof(font->msgBuf)); } else if (gSaveContext.n64ddFlag && (textId == 0x10A2 || textId == 0x10DC || textId == 0x10DD)) {