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.
This commit is contained in:
Christopher Leggett 2022-07-21 13:05:15 -04:00
parent c5f66373c3
commit b5dc097587
No known key found for this signature in database
GPG Key ID: 7093AE5FF7037D79
8 changed files with 141 additions and 91 deletions

View File

@ -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<std::string, CustomMessageTable>::const_iterator result = messageTables.find(tableID);
if (result == messageTables.end()) {
return "";
return NULL_CUSTOM_MESSAGE;
}
CustomMessageTable messageTable = result->second;
std::unordered_map<uint16_t, CustomMessageEntry>::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) {

View File

@ -1,7 +1,6 @@
#pragma once
#include <string>
#include <unordered_map>
#include "z64.h"
#include <message_data_static.h>
#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<uint16_t, CustomMessageEntry> 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);
};

View File

@ -14,6 +14,7 @@
#include "3drando/rando_main.hpp"
#include <soh/Enhancements/debugger/ImGuiHelpers.h>
#include "Lib/ImGui/imgui_internal.h"
#include <soh/Enhancements/custom_message/CustomMessage.h>
using json = nlohmann::json;
@ -21,7 +22,8 @@ std::unordered_map<uint8_t, Sprite> 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();

View File

@ -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);

View File

@ -36,15 +36,14 @@
#include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugconsole.h"
#include "Enhancements/debugger/debugger.h"
#include "Enhancements/randomizer/randomizer.h"
#include <soh/Enhancements/randomizer/randomizer_item_tracker.h>
#include <soh/Enhancements/custom_message/CustomMessage.h>
#include "Enhancements/n64_weird_frame_data.inc"
#include "soh/frame_interpolation.h"
#include "Utils/BitConverter.h"
#include "variables.h"
#include "macros.h"
#include <Utils/StringHelper.h>
#include <soh/Enhancements/custom_message/CustomMessage.h>
#ifdef __APPLE__
#include <SDL_scancode.h>
@ -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;

View File

@ -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);

View File

@ -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"

View File

@ -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)) {