From b5dc097587dfe3f75362af9cbe6720991f3524d0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 21 Jul 2022 13:05:15 -0400 Subject: [PATCH] Cleanup and move most hint logic to CustomMessage. Haven't removed where rando stores the hints for itself and the ganon and altar hints are still pulled from the randomizer class' local storage, but gossip stone hints are pulled from the custom message table now. --- .../custom_message/CustomMessage.cpp | 28 +++--- .../custom_message/CustomMessage.h | 7 +- .../Enhancements/randomizer/randomizer.cpp | 68 ++++++++++++++- soh/soh/Enhancements/randomizer/randomizer.h | 5 +- soh/soh/OTRGlobals.cpp | 87 ++++++++++++------- soh/soh/OTRGlobals.h | 2 +- soh/soh/z_message_OTR.cpp | 1 - soh/src/code/z_message_PAL.c | 34 +------- 8 files changed, 141 insertions(+), 91 deletions(-) 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)) {