mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-10 21:48:17 -05:00
Merge pull request #831 from leggettc18/custom-messages
System for Creating and Storing Custom Messages
This commit is contained in:
commit
fa090c51f6
@ -215,6 +215,13 @@ set(Header_Files__soh__Enhancements__randomizer__3drando
|
||||
)
|
||||
source_group("Header Files\\soh\\Enhancements\\randomizer\\3drando" FILES ${Header_Files__soh__Enhancements__randomizer__3drando})
|
||||
|
||||
set(Header_Files__soh__Enhancements__custom_message
|
||||
"soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
"soh/Enhancements/custom-message/CustomMessageManager.h"
|
||||
)
|
||||
|
||||
source_group("Header Files\\soh\\Enhancements\\custom-message" FILES ${Header_Files__soh__Enhancements__custom_message})
|
||||
|
||||
set(Source_Files__soh
|
||||
"soh/GbiWrap.cpp"
|
||||
"soh/OTRAudio.h"
|
||||
@ -326,6 +333,12 @@ set(Source_Files__soh__Enhancements__randomizer__3drando__location_access
|
||||
)
|
||||
source_group("Source Files\\soh\\Enhancements\\randomizer\\3drando\\location_access" FILES ${Source_Files__soh__Enhancements__randomizer__3drando__location_access})
|
||||
|
||||
set(Source_Files__soh__Enhancements__custom_message
|
||||
"soh/Enhancements/custom-message/CustomMessageManager.cpp"
|
||||
)
|
||||
|
||||
source_group("Source Files\\soh\\Enhancements\\custom-message" FILES ${Source_Files__soh__Enhancements__custom_message})
|
||||
|
||||
set(Source_Files__src__boot
|
||||
"src/boot/assert.c"
|
||||
"src/boot/boot_main.c"
|
||||
@ -1534,6 +1547,7 @@ set(ALL_FILES
|
||||
${Header_Files__soh__Enhancements__debugger}
|
||||
${Header_Files__soh__Enhancements__randomizer}
|
||||
${Header_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Header_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__soh}
|
||||
${Source_Files__soh__Enhancements}
|
||||
${Source_Files__soh__Enhancements__cosmetics}
|
||||
@ -1542,6 +1556,7 @@ set(ALL_FILES
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__hint_list}
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
|
||||
${Source_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__src__boot}
|
||||
${Source_Files__src__buffers}
|
||||
${Source_Files__src__code}
|
||||
|
150
soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
Normal file
150
soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "CustomMessageManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
CustomMessageManager::CustomMessageManager() {
|
||||
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 } };
|
||||
}
|
||||
|
||||
CustomMessageManager::~CustomMessageManager() {
|
||||
this->textBoxSpecialCharacters.clear();
|
||||
this->colors.clear();
|
||||
this->messageTables.clear();
|
||||
}
|
||||
|
||||
void CustomMessageManager::ReplaceSpecialCharacters(std::string& string) {
|
||||
// add special characters
|
||||
for (auto specialCharacterPair : this->textBoxSpecialCharacters) {
|
||||
size_t start_pos = 0;
|
||||
std::string textBoxSpecialCharacterString = ""s;
|
||||
textBoxSpecialCharacterString += specialCharacterPair.second;
|
||||
while ((start_pos = string.find(specialCharacterPair.first, 0)) != std::string::npos) {
|
||||
string.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString);
|
||||
start_pos += textBoxSpecialCharacterString.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomMessageManager::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 CustomMessageManager::FormatCustomMessage(std::string& message, ItemID iid) {
|
||||
message.insert(0, ITEM_OBTAINED(iid));
|
||||
size_t start_pos = 0;
|
||||
std::replace(message.begin(), message.end(), '&', NEWLINE()[0]);
|
||||
while ((start_pos = message.find('^', start_pos)) != std::string::npos) {
|
||||
message.replace(start_pos, 1, WAIT_FOR_INPUT() + ITEM_OBTAINED(iid));
|
||||
start_pos += 3;
|
||||
}
|
||||
std::replace(message.begin(), message.end(), '@', PLAYER_NAME()[0]);
|
||||
ReplaceSpecialCharacters(message);
|
||||
ReplaceColors(message);
|
||||
message += MESSAGE_END();
|
||||
}
|
||||
|
||||
void CustomMessageManager::FormatCustomMessage(std::string& message) {
|
||||
size_t start_pos = 0;
|
||||
std::replace(message.begin(), message.end(), '&', NEWLINE()[0]);
|
||||
std::replace(message.begin(), message.end(), '^', WAIT_FOR_INPUT()[0]);
|
||||
std::replace(message.begin(), message.end(), '@', PLAYER_NAME()[0]);
|
||||
ReplaceSpecialCharacters(message);
|
||||
ReplaceColors(message);
|
||||
message += MESSAGE_END();
|
||||
}
|
||||
|
||||
bool CustomMessageManager::InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages) {
|
||||
auto foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return false;
|
||||
}
|
||||
auto& messageTable = foundMessageTable->second;
|
||||
auto messageInsertResult = messageTable.emplace(textID, messages);
|
||||
return messageInsertResult.second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CustomMessageManager::CreateGetItemMessage(std::string tableID, GetItemID giid, ItemID iid, CustomMessageEntry messageEntry) {
|
||||
FormatCustomMessage(messageEntry.english, iid);
|
||||
FormatCustomMessage(messageEntry.german, iid);
|
||||
FormatCustomMessage(messageEntry.french, iid);
|
||||
const uint16_t textID = giid;
|
||||
return InsertCustomMessage(tableID, textID, messageEntry);
|
||||
}
|
||||
|
||||
bool CustomMessageManager::CreateMessage(std::string tableID, uint16_t textID, CustomMessageEntry messageEntry) {
|
||||
FormatCustomMessage(messageEntry.english);
|
||||
FormatCustomMessage(messageEntry.german);
|
||||
FormatCustomMessage(messageEntry.french);
|
||||
return InsertCustomMessage(tableID, textID, messageEntry);
|
||||
}
|
||||
|
||||
CustomMessageEntry CustomMessageManager::RetrieveMessage(std::string tableID, uint16_t textID) {
|
||||
std::unordered_map<std::string, CustomMessageTable>::const_iterator foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return NULL_CUSTOM_MESSAGE;
|
||||
}
|
||||
CustomMessageTable messageTable = foundMessageTable->second;
|
||||
std::unordered_map<uint16_t, CustomMessageEntry>::const_iterator foundMessage = messageTable.find(textID);
|
||||
if (foundMessage == messageTable.end()) {
|
||||
return NULL_CUSTOM_MESSAGE;
|
||||
}
|
||||
CustomMessageEntry message = foundMessage->second;
|
||||
return message;
|
||||
}
|
||||
|
||||
bool CustomMessageManager::ClearMessageTable(std::string tableID) {
|
||||
auto foundMessageTable = messageTables.find(tableID);
|
||||
if (foundMessageTable == messageTables.end()) {
|
||||
return false;
|
||||
}
|
||||
auto& messageTable = foundMessageTable->second;
|
||||
messageTable.clear();
|
||||
}
|
||||
|
||||
bool CustomMessageManager::AddCustomMessageTable(std::string tableID) {
|
||||
CustomMessageTable newMessageTable;
|
||||
return messageTables.emplace(tableID, newMessageTable).second;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::MESSAGE_END() {
|
||||
return "\x02"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::ITEM_OBTAINED(uint8_t x) {
|
||||
return "\x13"s + char(x);
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::NEWLINE() {
|
||||
return "\x01"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::COLOR(uint8_t x) {
|
||||
return "\x05"s + char(x);
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::WAIT_FOR_INPUT() {
|
||||
return "\x04"s;
|
||||
}
|
||||
|
||||
std::string CustomMessageManager::PLAYER_NAME() {
|
||||
return "\x0F"s;
|
||||
}
|
133
soh/soh/Enhancements/custom-message/CustomMessageManager.h
Normal file
133
soh/soh/Enhancements/custom-message/CustomMessageManager.h
Normal file
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "../../../include/z64item.h"
|
||||
|
||||
#undef MESSAGE_END
|
||||
|
||||
#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
|
||||
|
||||
#ifndef MESSAGE_DATA_STATIC_H
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_TYPE_BLACK,
|
||||
/* 1 */ TEXTBOX_TYPE_WOODEN,
|
||||
/* 2 */ TEXTBOX_TYPE_BLUE,
|
||||
/* 3 */ TEXTBOX_TYPE_OCARINA,
|
||||
/* 4 */ TEXTBOX_TYPE_NONE_BOTTOM,
|
||||
/* 5 */ TEXTBOX_TYPE_NONE_NO_SHADOW,
|
||||
/* 11 */ TEXTBOX_TYPE_CREDITS = 11
|
||||
} TextBoxType;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_BG_CROSS
|
||||
} TextBoxBackground;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TEXTBOX_POS_VARIABLE,
|
||||
/* 1 */ TEXTBOX_POS_TOP,
|
||||
/* 2 */ TEXTBOX_POS_MIDDLE,
|
||||
/* 3 */ TEXTBOX_POS_BOTTOM
|
||||
} TextBoxPosition;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TextBoxType textBoxType;
|
||||
TextBoxPosition textBoxPos;
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} CustomMessageEntry;
|
||||
|
||||
// Message Entry without the text type and position, useful for when
|
||||
// you need an array of these to loop over for registration
|
||||
// that will all have the same textbox type and position.
|
||||
typedef struct {
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} CustomMessageMinimal;
|
||||
|
||||
#define NULL_CUSTOM_MESSAGE \
|
||||
{ (TextBoxType)(-1), (TextBoxPosition)(-1), "", "", "" }
|
||||
|
||||
typedef std::unordered_map<uint16_t, CustomMessageEntry> CustomMessageTable;
|
||||
|
||||
class CustomMessageManager {
|
||||
private:
|
||||
std::unordered_map<std::string, char> textBoxSpecialCharacters;
|
||||
std::unordered_map<std::string, char> colors;
|
||||
std::unordered_map<std::string, CustomMessageTable> messageTables;
|
||||
|
||||
void ReplaceSpecialCharacters(std::string &string);
|
||||
void ReplaceColors(std::string& string);
|
||||
bool InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages);
|
||||
|
||||
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 CustomMessageManager* Instance;
|
||||
|
||||
CustomMessageManager();
|
||||
~CustomMessageManager();
|
||||
|
||||
/*
|
||||
Formats the provided Custom Message Entry and inserts it into the table with the provided tableID,
|
||||
with the provided giid (getItemID) as its key. This function also inserts the icon corresponding to
|
||||
the provided iid (itemID) at the beginning of each page of the textbox.
|
||||
*/
|
||||
bool CreateGetItemMessage(std::string tableID, GetItemID giid, ItemID iid, CustomMessageEntry messages);
|
||||
|
||||
/*
|
||||
Formats the provided Custom Message Entry and inserts it into the table with the provided tableID,
|
||||
with the provided textID as its key.
|
||||
*/
|
||||
bool CreateMessage(std::string tableID, uint16_t textID, CustomMessageEntry messages);
|
||||
|
||||
/*
|
||||
Retrieves a message from the table with id tableID with the provided textID.
|
||||
Returns a NULL_CUSTOM_MESSAGE if the message or table does not exist.
|
||||
*/
|
||||
CustomMessageEntry RetrieveMessage(std::string tableID, uint16_t textID);
|
||||
|
||||
/*
|
||||
Empties out the message table identified by tableID.
|
||||
Returns true if successful and false if not (for instance
|
||||
if a table with the provided tableID does not exist).
|
||||
*/
|
||||
bool ClearMessageTable(std::string tableID);
|
||||
|
||||
/*
|
||||
Creates an empty CustomMessageTable accessible at the provided
|
||||
tableID, returns true if creation was successful and false
|
||||
if not.
|
||||
*/
|
||||
bool AddCustomMessageTable(std::string tableID);
|
||||
|
||||
/*
|
||||
Replaces special characters and certain symbols with control codes
|
||||
& for newline, ^ for wait-for-input, and @ for the player name,
|
||||
as well as %<letter> for colors (i.e. %r for red and %w for white).
|
||||
*/
|
||||
void FormatCustomMessage(std::string& message, ItemID iid);
|
||||
|
||||
/*
|
||||
Replaces special characters and certain symbols with control codes
|
||||
& for newline, ^ for wait-for-input, and @ for the player name,
|
||||
as well as %<letter> for colors (i.e. %r for red and %w for white).
|
||||
*/
|
||||
void FormatCustomMessage(std::string& message);
|
||||
};
|
33
soh/soh/Enhancements/custom-message/CustomMessageTypes.h
Normal file
33
soh/soh/Enhancements/custom-message/CustomMessageTypes.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TEXT_GS_NO_FREEZE = 0xB4,
|
||||
TEXT_GS_FREEZE = 0xB5,
|
||||
TEXT_RANDOMIZER_CUSTOM_ITEM = 0xF8,
|
||||
TEXT_SCRUB_POH = 0x10A2,
|
||||
TEXT_SCRUB_STICK_UPGRADE = 0x10DC,
|
||||
TEXT_SCRUB_NUT_UPGRADE = 0x10DD,
|
||||
TEXT_RANDOMIZER_GOSSIP_STONE_HINTS = 0x2053,
|
||||
TEXT_ALTAR_CHILD = 0x7040,
|
||||
TEXT_ALTAR_ADULT = 0x7088,
|
||||
TEXT_GANONDORF = 0x70CC,
|
||||
TEXT_GANONDORF_NOHINT = 0x70CD
|
||||
} TextIDs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
typedef struct {
|
||||
GetItemID giid;
|
||||
ItemID iid;
|
||||
std::string english;
|
||||
std::string german;
|
||||
std::string french;
|
||||
} GetItemMessage;
|
||||
|
||||
#define GIMESSAGE(giid, iid, english, german, french) \
|
||||
{ giid, iid, english, german, french }
|
||||
|
||||
#define GIMESSAGE_UNTRANSLATED(giid, iid, message) \
|
||||
{ giid, iid, message, message, message }
|
||||
|
||||
#endif
|
@ -13,13 +13,20 @@
|
||||
#include "3drando/rando_main.hpp"
|
||||
#include <soh/Enhancements/debugger/ImGuiHelpers.h>
|
||||
#include "Lib/ImGui/imgui_internal.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
using json = nlohmann::json;
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
std::unordered_map<uint8_t, Sprite> gSeedTextures;
|
||||
|
||||
u8 generated;
|
||||
|
||||
const std::string Randomizer::getItemMessageTableID = "Randomizer";
|
||||
const std::string Randomizer::hintMessageTableID = "RandomizerHints";
|
||||
const std::string Randomizer::scrubMessageTableID = "RandomizerScrubs";
|
||||
|
||||
Randomizer::Randomizer() {
|
||||
Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 };
|
||||
gSeedTextures[0] = bowSprite;
|
||||
@ -1476,6 +1483,26 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
ParseHintLocationsFile(spoilerFileName);
|
||||
}
|
||||
|
||||
CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID);
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID);
|
||||
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.childAltarText,
|
||||
gSaveContext.childAltarText, gSaveContext.childAltarText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, gSaveContext.adultAltarText,
|
||||
gSaveContext.adultAltarText, gSaveContext.adultAltarText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_GANONDORF,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonHintText,
|
||||
gSaveContext.ganonHintText, gSaveContext.ganonHintText });
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, gSaveContext.ganonText,
|
||||
gSaveContext.ganonText, gSaveContext.ganonText });
|
||||
|
||||
this->childAltarText = gSaveContext.childAltarText;
|
||||
this->adultAltarText = gSaveContext.adultAltarText;
|
||||
this->ganonHintText = gSaveContext.ganonHintText;
|
||||
@ -1484,6 +1511,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;
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, hintLocation.hintText, hintLocation.hintText });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1795,57 +1824,8 @@ std::string AltarIconString(char iconChar) {
|
||||
|
||||
std::string FormatJsonHintText(std::string jsonHint) {
|
||||
std::string formattedHintMessage = jsonHint;
|
||||
char newLine = 0x01;
|
||||
char playerName = 0x0F;
|
||||
char nextBox = 0x04;
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '&', newLine);
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '^', nextBox);
|
||||
std::replace(formattedHintMessage.begin(), formattedHintMessage.end(), '@', playerName);
|
||||
|
||||
std::unordered_map<std::string, char> 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 }
|
||||
};
|
||||
|
||||
// add special characters
|
||||
for (auto specialCharacterPair : textBoxSpecialCharacters) {
|
||||
size_t start_pos = 0;
|
||||
std::string textBoxSpecialCharacterString = "";
|
||||
textBoxSpecialCharacterString += specialCharacterPair.second;
|
||||
while((start_pos = formattedHintMessage.find(specialCharacterPair.first, start_pos)) != std::string::npos) {
|
||||
formattedHintMessage.replace(start_pos, specialCharacterPair.first.length(), textBoxSpecialCharacterString);
|
||||
start_pos += textBoxSpecialCharacterString.length();
|
||||
}
|
||||
}
|
||||
CustomMessageManager::Instance->FormatCustomMessage(formattedHintMessage);
|
||||
|
||||
// add icons to altar text
|
||||
for (char iconChar : {'0', '1', '2', '3', '4', '5', '6', '7', '8', 'o', 'c', 'i', 'l', 'b', 'L', 'k'}) {
|
||||
@ -2406,10 +2386,6 @@ std::string Randomizer::GetGanonHintText() const {
|
||||
return ganonHintText;
|
||||
}
|
||||
|
||||
std::string Randomizer::GetHintFromCheck(RandomizerCheck check) {
|
||||
return this->hintLocations[check];
|
||||
}
|
||||
|
||||
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||
return this->randoSettings[randoSettingKey];
|
||||
}
|
||||
@ -4726,9 +4702,64 @@ void DrawRandoEditor(bool& open) {
|
||||
ImGui::End();
|
||||
}*/
|
||||
|
||||
void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
|
||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||
customMessageManager->AddCustomMessageTable(Randomizer::getItemMessageTableID);
|
||||
for (GetItemMessage messageEntry : messageEntries) {
|
||||
customMessageManager->CreateGetItemMessage(Randomizer::getItemMessageTableID, messageEntry.giid, messageEntry.iid,
|
||||
{ TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
|
||||
messageEntry.english, messageEntry.german,
|
||||
messageEntry.french });
|
||||
}
|
||||
}
|
||||
|
||||
void CreateScrubMessages() {
|
||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
|
||||
const std::vector<u8> prices = { 10, 40 };
|
||||
for (u8 price : prices) {
|
||||
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
|
||||
// RANDTODO: Translate the below string to German.
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
|
||||
"\x12\x38\x82J'abandonne! Tu veux bien m'acheter&un %gobjet mystérieux%w?&Ça fera %r" +
|
||||
std::to_string(price) + " Rubis%w!\x07\x10\xA3"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Randomizer::CreateCustomMessages() {
|
||||
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
|
||||
// with GIMESSAGE(getItemID, itemID, english, german, french).
|
||||
const std::vector<GetItemMessage> getItemMessages = {
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE,
|
||||
"You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE,
|
||||
"You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE,
|
||||
"You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_FISH, ITEM_FISH,
|
||||
"You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_BUGS, ITEM_BUG,
|
||||
"You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_FAIRY, ITEM_FAIRY, "You got a %rFairy in a Bottle%w!&Use it wisely!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED,
|
||||
"You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN,
|
||||
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!"),
|
||||
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_POE, ITEM_POE,
|
||||
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this..."),
|
||||
};
|
||||
CreateGetItemMessages(getItemMessages);
|
||||
CreateScrubMessages();
|
||||
}
|
||||
|
||||
void InitRando() {
|
||||
SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor);
|
||||
Randomizer::CreateCustomMessages();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include <string>
|
||||
#include "../../../include/ultra64.h"
|
||||
#include "../../../include/z64item.h"
|
||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||
#include <memory>
|
||||
#include <soh/Enhancements/randomizer/randomizerTypes.h>
|
||||
|
||||
class Randomizer {
|
||||
private:
|
||||
@ -25,6 +26,10 @@ class Randomizer {
|
||||
Randomizer();
|
||||
~Randomizer();
|
||||
|
||||
static const std::string getItemMessageTableID;
|
||||
static const std::string hintMessageTableID;
|
||||
static const std::string scrubMessageTableID;
|
||||
|
||||
static Sprite* GetSeedTexture(uint8_t index);
|
||||
s16 GetItemModelFromId(s16 itemId);
|
||||
s32 GetItemIDFromGetItemID(s32 getItemId);
|
||||
@ -38,9 +43,9 @@ class Randomizer {
|
||||
std::string GetAdultAltarText() const;
|
||||
std::string GetGanonText() const;
|
||||
std::string GetGanonHintText() const;
|
||||
std::string GetHintFromCheck(RandomizerCheck check);
|
||||
GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
static void CreateCustomMessages();
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,7 +32,6 @@
|
||||
#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 "Enhancements/n64_weird_frame_data.inc"
|
||||
#include "soh/frame_interpolation.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "macros.h"
|
||||
#include <Utils/StringHelper.h>
|
||||
#include "Hooks.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <SDL_scancode.h>
|
||||
@ -52,9 +52,12 @@
|
||||
#endif
|
||||
|
||||
#include <Audio.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
#include <functions.h>
|
||||
|
||||
OTRGlobals* OTRGlobals::Instance;
|
||||
SaveManager* SaveManager::Instance;
|
||||
CustomMessageManager* CustomMessageManager::Instance;
|
||||
|
||||
OTRGlobals::OTRGlobals() {
|
||||
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
|
||||
@ -171,6 +174,7 @@ extern "C" void InitOTR() {
|
||||
#endif
|
||||
OTRGlobals::Instance = new OTRGlobals();
|
||||
SaveManager::Instance = new SaveManager();
|
||||
CustomMessageManager::Instance = new CustomMessageManager();
|
||||
auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version");
|
||||
|
||||
if (!t->bHasLoadError)
|
||||
@ -1431,99 +1435,39 @@ extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorI
|
||||
return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams);
|
||||
}
|
||||
|
||||
extern "C" int CopyScrubMessage(u16 scrubTextId, char* buffer, const int maxBufferSize) {
|
||||
std::string scrubText("");
|
||||
int language = CVar_GetS32("gLanguages", 0);
|
||||
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(u16 scrubTextId) {
|
||||
int price = 0;
|
||||
switch (scrubTextId) {
|
||||
case 0x10A2:
|
||||
case TEXT_SCRUB_POH:
|
||||
price = 10;
|
||||
break;
|
||||
case 0x10DC:
|
||||
case 0x10DD:
|
||||
case TEXT_SCRUB_STICK_UPGRADE:
|
||||
case TEXT_SCRUB_NUT_UPGRADE:
|
||||
price = 40;
|
||||
break;
|
||||
}
|
||||
switch (language) {
|
||||
case 0: default:
|
||||
scrubText += 0x12; // add the sound
|
||||
scrubText += 0x38; // sound id
|
||||
scrubText += 0x82; // sound id
|
||||
scrubText += "All right! You win! In return for";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "sparing me, I will sell you a";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x42; // green
|
||||
scrubText += "mysterious item";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "!";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x41; // red
|
||||
scrubText += std::to_string(price);
|
||||
scrubText += price > 1 ? " Rupees" : " Rupee";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += " it is!";
|
||||
scrubText += 0x07; // go to a new message
|
||||
scrubText += 0x10; // message id
|
||||
scrubText += 0xA3; // message id
|
||||
break;
|
||||
case 2:
|
||||
scrubText += 0x12; // add the sound
|
||||
scrubText += 0x38; // sound id
|
||||
scrubText += 0x82; // sound id
|
||||
scrubText += "J'abandonne! Tu veux bien m'acheter";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "un ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x42; // green
|
||||
scrubText += "objet myst\x96rieux";
|
||||
//scrubText += ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "?";
|
||||
scrubText += 0x01; // newline
|
||||
scrubText += "\x84";
|
||||
scrubText += "a fera ";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x41; // red
|
||||
scrubText += std::to_string(price) + " Rubis";
|
||||
scrubText += 0x05; // change the color
|
||||
scrubText += 0x40; // white
|
||||
scrubText += "!";
|
||||
scrubText += 0x07; // go to a new message
|
||||
scrubText += 0x10; // message id
|
||||
scrubText += 0xA3; // message id
|
||||
break;
|
||||
}
|
||||
|
||||
return CopyStringToCharBuffer(scrubText, buffer, maxBufferSize);
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, price);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize) {
|
||||
const std::string& altarText = (LINK_IS_ADULT) ? OTRGlobals::Instance->gRandomizer->GetAdultAltarText()
|
||||
: OTRGlobals::Instance->gRandomizer->GetChildAltarText();
|
||||
return CopyStringToCharBuffer(altarText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetAltarMessage() {
|
||||
return (LINK_IS_ADULT)
|
||||
? CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_ADULT)
|
||||
: CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_ALTAR_CHILD);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize) {
|
||||
const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonText();
|
||||
return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetGanonText() {
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF_NOHINT);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize) {
|
||||
const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonHintText();
|
||||
return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize);
|
||||
extern "C" CustomMessageEntry Randomizer_GetGanonHintText() {
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF);
|
||||
}
|
||||
|
||||
extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) {
|
||||
// we don't want to make a copy of the std::string returned from GetHintFromCheck
|
||||
extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(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 = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, check);
|
||||
return hintText;
|
||||
}
|
||||
|
||||
extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) {
|
||||
@ -1542,3 +1486,89 @@ extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomize
|
||||
extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) {
|
||||
return gSaveContext.n64ddFlag && Randomizer_GetItemIdFromKnownCheck(randomizerCheck, ogId) == GI_ICE_TRAP;
|
||||
}
|
||||
|
||||
extern "C" CustomMessageEntry Randomizer_GetCustomGetItemMessage(GetItemID giid, char* buffer, const int maxBufferSize) {
|
||||
const CustomMessageEntry getItemText = CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, giid);
|
||||
return getItemText;
|
||||
}
|
||||
|
||||
extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
|
||||
MessageContext* msgCtx = &globalCtx->msgCtx;
|
||||
uint16_t textId = msgCtx->textId;
|
||||
Font* font = &msgCtx->font;
|
||||
char* buffer = font->msgBuf;
|
||||
const int maxBufferSize = sizeof(font->msgBuf);
|
||||
CustomMessageEntry messageEntry;
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) {
|
||||
messageEntry =
|
||||
Randomizer_GetCustomGetItemMessage((GetItemID)GET_PLAYER(globalCtx)->getItemId, buffer, maxBufferSize);
|
||||
} else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && 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_GetHintFromCheck(hintCheck);
|
||||
} else if (textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) {
|
||||
// rando hints at altar
|
||||
messageEntry = Randomizer_GetAltarMessage();
|
||||
} else if (textId == TEXT_GANONDORF) {
|
||||
if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) {
|
||||
messageEntry = Randomizer_GetGanonText();
|
||||
} else {
|
||||
messageEntry = Randomizer_GetGanonHintText();
|
||||
}
|
||||
} else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) {
|
||||
messageEntry = Randomizer_GetScrubMessage(textId);
|
||||
}
|
||||
}
|
||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||
if (CVar_GetS32("gInjectSkulltulaCount", 0) != 0) {
|
||||
if (CVar_GetS32("gSkulltulaFreeze", 0) != 0) {
|
||||
textId = TEXT_GS_NO_FREEZE;
|
||||
} else {
|
||||
textId = TEXT_GS_FREEZE;
|
||||
}
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, 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;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "Enhancements/savestates.h"
|
||||
#include "Enhancements/randomizer/randomizer.h"
|
||||
|
||||
const std::string customMessageTableID = "BaseGameOverrides";
|
||||
|
||||
class OTRGlobals
|
||||
{
|
||||
public:
|
||||
@ -91,10 +93,6 @@ Sprite* GetSeedTexture(uint8_t index);
|
||||
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);
|
||||
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||
s16 Randomizer_GetItemModelFromId(s16 itemId);
|
||||
@ -103,6 +101,7 @@ s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams,
|
||||
s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor);
|
||||
bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,13 @@
|
||||
#include "OTRGlobals.h"
|
||||
#include "ResourceMgr.h"
|
||||
#include "Scene.h"
|
||||
#include "message_data_static.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "global.h"
|
||||
#include "vt.h"
|
||||
#include <Text.h>
|
||||
#include <message_data_static.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
|
||||
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
|
||||
@ -92,4 +94,22 @@ extern "C" void OTRMessage_Init()
|
||||
sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str();
|
||||
sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size();
|
||||
}
|
||||
}
|
||||
|
||||
CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID);
|
||||
CustomMessageManager::Instance->CreateGetItemMessage(
|
||||
customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN,
|
||||
{
|
||||
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
|
||||
"You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!\x0E\x3C",
|
||||
"Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!\x0E\x3C",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!\x0E\x3C"
|
||||
}
|
||||
);
|
||||
CustomMessageManager::Instance->CreateGetItemMessage(
|
||||
customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN,
|
||||
{
|
||||
TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM,
|
||||
"You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!",
|
||||
"Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!",
|
||||
"Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" });
|
||||
}
|
||||
|
@ -1663,7 +1663,9 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) {
|
||||
gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0;
|
||||
}
|
||||
|
||||
if (sTextIsCredits) {
|
||||
if (CustomMessage_RetrieveIfExists(globalCtx)) {
|
||||
osSyncPrintf("Found custom message");
|
||||
} else if (sTextIsCredits) {
|
||||
Message_FindCreditsMessage(globalCtx, textId);
|
||||
msgCtx->msgLength = font->msgLength;
|
||||
char* src = (uintptr_t)font->msgOffset;
|
||||
@ -1674,73 +1676,9 @@ 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)) {
|
||||
// rando hints at altar
|
||||
msgCtx->msgLength = font->msgLength = Randomizer_CopyAltarMessage(font->msgBuf, sizeof(font->msgBuf));
|
||||
} else if (textId == 0x00b4 && CVar_GetS32("gInjectSkulltulaCount", 0) != 0) {
|
||||
switch (gSaveContext.language) {
|
||||
case LANGUAGE_FRA:
|
||||
strcpy(font->msgBuf, "\x08\x13\x71Vous obtenez un \x05\x41Symbole de\x01Skulltula d'or\x05\x40! "
|
||||
"Vous avez\x01\collect\x96 "
|
||||
"\x05\x41\x19\x05\x40 symboles en tout!\x02");
|
||||
break;
|
||||
case LANGUAGE_GER:
|
||||
strcpy(font->msgBuf, "\x08\x13\x71\Du erh\x93lst ein \x05\x41Goldene\x01Skulltula-Symbol\x05\x40\! "
|
||||
"Du hast\x01insgesamt "
|
||||
"\x05\x41\x19\x05\x40 symbol gesammelt!\x02");
|
||||
break;
|
||||
case LANGUAGE_ENG: default:
|
||||
strcpy(font->msgBuf,
|
||||
"\x08\x13\x71You got a \x05\x41Gold Skulltula Token\x05\x40!\x01You've collected "
|
||||
"\x05\x41\x19\x05\x40 tokens\x01in total!\x02");
|
||||
break;
|
||||
}
|
||||
msgCtx->msgLength = font->msgLength = strlen(font->msgBuf);
|
||||
} else if (gSaveContext.n64ddFlag && (textId == 0x10A2 || textId == 0x10DC || textId == 0x10DD)) {
|
||||
msgCtx->msgLength = font->msgLength = CopyScrubMessage(textId, font->msgBuf, sizeof(font->msgBuf));
|
||||
} else if (gSaveContext.n64ddFlag && textId == 0x70CC) {
|
||||
if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) {
|
||||
msgCtx->msgLength = font->msgLength = Randomizer_CopyGanonText(font->msgBuf, sizeof(font->msgBuf));
|
||||
} else {
|
||||
msgCtx->msgLength = font->msgLength = Randomizer_CopyGanonHintText(font->msgBuf, sizeof(font->msgBuf));
|
||||
}
|
||||
} else {
|
||||
msgCtx->msgLength = font->msgLength;
|
||||
char* src = (uintptr_t)font->msgOffset;
|
||||
memcpy(font->msgBuf, src, font->msgLength);
|
||||
}
|
||||
msgCtx->msgLength = font->msgLength;
|
||||
char* src = (uintptr_t)font->msgOffset;
|
||||
memcpy(font->msgBuf, src, font->msgLength);
|
||||
}
|
||||
|
||||
msgCtx->textBoxProperties = font->charTexBuf[0];
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
#include "objects/object_link_child/object_link_child.h"
|
||||
#include "textures/icon_item_24_static/icon_item_24_static.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 itemId;
|
||||
@ -653,15 +654,15 @@ static GetItemEntry sGetItemTable[] = {
|
||||
GET_ITEM(ITEM_DOUBLE_MAGIC, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG),
|
||||
|
||||
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_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_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 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_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
|
||||
|
||||
GET_ITEM_NONE,
|
||||
GET_ITEM_NONE,
|
||||
|
Loading…
Reference in New Issue
Block a user