Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 90 additions & 73 deletions logic/Hints.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions logic/Hints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ enum struct HintType
LOCATION,
};

class Location;
struct Hint
{
// Message for this location (one for each language)
std::unordered_map<std::string, std::u16string> text = {};
Location* location;
HintType type = HintType::NONE;
};

Expand Down
36 changes: 18 additions & 18 deletions logic/SpoilerLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ static std::string getSpoilerFormatLocation(Location* location, const size_t& lo
return location->getName() + locWorldNumber + ":" + spaces + itemName;
}

static std::string getSpoilerFormatHint(Location* location)
static std::string getSpoilerFormatHint(const Hint& hint)
{
// Get rid of commands in the hint text and then convert to UTF-8
std::u16string hintText = location->hint.text["English"];
std::u16string hintText = hint.text.at("English");
for (const std::u16string& eraseText : {TEXT_COLOR_RED, TEXT_COLOR_BLUE, TEXT_COLOR_CYAN, TEXT_COLOR_DEFAULT, TEXT_COLOR_GREEN, TEXT_COLOR_GRAY, TEXT_COLOR_YELLOW})
{
auto pos = std::string::npos;
Expand Down Expand Up @@ -238,24 +238,24 @@ void generateSpoilerLog(WorldPool& worlds)
for (auto& world : worlds)
{
// Don't print "Hints" if there are none
if (world.hohoHints.empty() && world.korlHints.empty() && world.bigOctoFairyHintLocation == nullptr && world.kreebHints.empty() && world.korlHyruleHints.empty())
if (world.hohoHints.empty() && world.korlHints.empty() && world.bigOctoFairyHint.location == nullptr && world.kreebHints.empty() && world.korlHyruleHints.empty())
{
continue;
}

spoilerLog << std::endl << (worlds.size() == 1 ? "Hints:" : "Hints for world " + std::to_string(world.getWorldId()) + ":") << std::endl;
if (!world.hohoHints.empty())
{
for (auto& [hohoLocation, hintLocations] : world.hohoHints)
for (auto& [hohoLocation, hints] : world.hohoHints)
{
spoilerLog << " " << hohoLocation->getName() << ":" << std::endl;
for (auto location : hintLocations)
for (auto& hint : hints)
{
spoilerLog << " " << getSpoilerFormatHint(location);
spoilerLog << " " << getSpoilerFormatHint(hint);
// Show what item/location was being referred to with each path hint
if (location->hint.type == HintType::PATH)
if (hint.type == HintType::PATH)
{
spoilerLog << " (" << location->currentItem.getName() << " at " << location->getName() << ")";
spoilerLog << " (" << hint.location->currentItem.getName() << " at " << hint.location->getName() << ")";
}
spoilerLog << std::endl;
}
Expand All @@ -265,13 +265,13 @@ void generateSpoilerLog(WorldPool& worlds)
if (!world.korlHints.empty())
{
spoilerLog << " KoRL Hints:" << std::endl;
for (auto location : world.korlHints)
for (auto& hint : world.korlHints)
{
spoilerLog << " " << getSpoilerFormatHint(location);
spoilerLog << " " << getSpoilerFormatHint(hint);
// Show what item/location was being referred to with each path hint
if (location->hint.type == HintType::PATH)
if (hint.type == HintType::PATH && hint.location)
{
spoilerLog << " (" << location->currentItem.getName() << " at " << location->getName() << ")";
spoilerLog << " (" << hint.location->currentItem.getName() << " at " << hint.location->getName() << ")";
}
spoilerLog << std::endl;
}
Expand All @@ -280,17 +280,17 @@ void generateSpoilerLog(WorldPool& worlds)
if (!world.korlHyruleHints.empty())
{
spoilerLog << " KoRL Hyrule Hints:" << std::endl;
for (auto location : world.korlHyruleHints)
for (auto& hint : world.korlHyruleHints)
{
spoilerLog << " " << getSpoilerFormatHint(location);
spoilerLog << " " << getSpoilerFormatHint(hint);
spoilerLog << std::endl;
}
}

if (world.bigOctoFairyHintLocation != nullptr)
if (world.bigOctoFairyHint.location != nullptr)
{
spoilerLog << " Big Octo Great Fairy:" << std::endl;
std::u16string hintText = world.bigOctoFairyHintLocation->hint.text["English"];
std::u16string hintText = world.bigOctoFairyHint.text["English"];
for (const std::u16string& eraseText : {TEXT_COLOR_RED, TEXT_COLOR_BLUE, TEXT_COLOR_CYAN, TEXT_COLOR_DEFAULT, TEXT_COLOR_GREEN, TEXT_COLOR_GRAY, TEXT_COLOR_YELLOW})
{
auto pos = std::string::npos;
Expand All @@ -305,9 +305,9 @@ void generateSpoilerLog(WorldPool& worlds)
if (!world.kreebHints.empty())
{
spoilerLog << " Kreeb Hints:" << std::endl;
for (auto location : world.kreebHints)
for (auto& hint : world.kreebHints)
{
spoilerLog << " " << getSpoilerFormatHint(location);
spoilerLog << " " << getSpoilerFormatHint(hint);
spoilerLog << std::endl;
}
}
Expand Down
11 changes: 6 additions & 5 deletions logic/World.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <logic/ItemPool.hpp>
#include <logic/Dungeon.hpp>
#include <logic/Entrance.hpp>
#include <logic/Hints.hpp>
#include <logic/Plandomizer.hpp>
#include <logic/WorldPool.hpp>
#include <utility/text.hpp>
Expand Down Expand Up @@ -127,11 +128,11 @@ class World
LocationPool raceModeLocations = {};
std::list<Location*> goalLocations = {};
std::map<std::string, std::unordered_set<Location*>> barrenRegions = {};
std::list<Location*> korlHints = {};
std::list<Location*> korlHyruleHints = {};
std::list<Location*> kreebHints = {};
std::map<Location*, std::unordered_set<Location*>, PointerLess<Location>> hohoHints = {}; // map of Ho Ho Hint Location to hinted locations
Location* bigOctoFairyHintLocation = nullptr;
std::list<Hint> korlHints = {};
std::list<Hint> korlHyruleHints = {};
std::list<Hint> kreebHints = {};
std::map<Location*, std::list<Hint>> hohoHints = {}; // map of Ho Ho Hint Location to hints
Hint bigOctoFairyHint{};
std::list<std::list<Location*>> playthroughSpheres = {};
std::list<std::list<Entrance*>> entranceSpheres = {};
std::map<uint8_t, GameItem> chartMappings = {};
Expand Down
10 changes: 5 additions & 5 deletions text_replacements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ TextReplacements generate_text_replacements(World& world)
auto& beedle500 = world.locationTable["Rock Spire Isle - Beedle 500 Rupee Item"]->currentItem;
auto& beedle950 = world.locationTable["Rock Spire Isle - Beedle 950 Rupee Item"]->currentItem;
auto& beedle900 = world.locationTable["Rock Spire Isle - Beedle 900 Rupee Item"]->currentItem;
auto& octoFairyItem = world.bigOctoFairyHintLocation->currentItem;
auto& octoFairyRegion = world.bigOctoFairyHintLocation->hintRegions.front();
auto& octoFairyItem = world.bigOctoFairyHint.location->currentItem;
auto& octoFairyRegion = world.bigOctoFairyHint.location->hintRegions.front();

LOG_TO_DEBUG("Calculating text replacement articles/pronouns");
// Calculate articles for some replacements
Expand Down Expand Up @@ -133,9 +133,9 @@ TextReplacements generate_text_replacements(World& world)
auto savageFloor50SpanishImportance = savageFloor50Loc->generateImportanceText("Spanish");
auto savageFloor50FrenchImportance = savageFloor50Loc->generateImportanceText("French");

auto bigOctoFairyEnglishImportance = world.bigOctoFairyHintLocation->generateImportanceText("English");
auto bigOctoFairySpanishImportance = world.bigOctoFairyHintLocation->generateImportanceText("Spanish");
auto bigOctoFairyFrenchImportance = world.bigOctoFairyHintLocation->generateImportanceText("French");
auto bigOctoFairyEnglishImportance = world.bigOctoFairyHint.location->generateImportanceText("English");
auto bigOctoFairySpanishImportance = world.bigOctoFairyHint.location->generateImportanceText("Spanish");
auto bigOctoFairyFrenchImportance = world.bigOctoFairyHint.location->generateImportanceText("French");

// Format for text replacements:
// Message Label,
Expand Down
60 changes: 30 additions & 30 deletions tweaks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,11 +1194,11 @@ TweakError update_korl_dialog(World& world) {

std::vector<std::u16string> hintMessages = {u""};
size_t curLine = 0;
for (auto location : world.korlHints) {
std::u16string hint = location->hint.text[language];
hint = Text::word_wrap_string(hint, 42); // wrap shorter lines, some edge cases are still too wide with 43
hint = Text::pad_str_4_lines(hint);
const size_t numLines = std::count(hint.begin(), hint.end(), u'\n'); // 4 for most hints, 8+ for long hints with multiple textboxes
for (auto& hint : world.korlHints) {
std::u16string hintText = hint.text[language];
hintText = Text::word_wrap_string(hintText, 42); // wrap shorter lines, some edge cases are still too wide with 43
hintText = Text::pad_str_4_lines(hintText);
const size_t numLines = std::count(hintText.begin(), hintText.end(), u'\n'); // 4 for most hints, 8+ for long hints with multiple textboxes

// if we would have >10 textboxes
if(curLine + numLines > 40) {
Expand All @@ -1207,7 +1207,7 @@ TweakError update_korl_dialog(World& world) {
curLine = 0; // restart line counter
}

hintMessages.back() += hint; // add hint to back of current message
hintMessages.back() += hintText; // add hint to back of current message
curLine += numLines; // add hint lines to count
}

Expand Down Expand Up @@ -1253,13 +1253,13 @@ TweakError update_korl_dialog(World& world) {
for (const auto& language : Text::supported_languages) {
std::u16string hintLines = u"";
size_t i = 0; // counter to know when to add null terminator
for (auto location : world.korlHyruleHints) {
std::u16string hint = Text::word_wrap_string(location->hint.text[language], 43);
for (auto& hint : world.korlHyruleHints) {
std::u16string hintText = Text::word_wrap_string(hint.text[language], 43);
++i;
if (i == world.korlHyruleHints.size()) {
hint += u'\0'; // add null terminator on last hint before padding
hintText += u'\0'; // add null terminator on last hint before padding
}
hintLines += Text::pad_str_4_lines(hint);
hintLines += Text::pad_str_4_lines(hintText);
}

RandoSession::CacheEntry& entry = g_session.openGameFile("content/Common/Pack/permanent_2d_Us" + language + ".pack@SARC@message2_msbt.szs@YAZ0@SARC@message2.msbt@MSBT");
Expand Down Expand Up @@ -1288,22 +1288,22 @@ TweakError update_ho_ho_dialog(World& world) {
RandoSession::CacheEntry& entry = g_session.openGameFile("content/Common/Pack/permanent_2d_Us" + language + ".pack@SARC@message4_msbt.szs@YAZ0@SARC@message4.msbt@MSBT");

entry.addAction([=, &world](RandoSession* session, FileType* data) -> int {
for (auto& [hohoLocation, hintLocations] : world.hohoHints) {
for (auto& [hohoLocation, hints] : world.hohoHints) {
std::u16string hintLines = u"";
size_t i = 0; // counter to know when to add null terminator
for (auto location : hintLocations) {
std::u16string hint = u"";
for (auto& hint : hints) {
std::u16string hintText = u"";
if (i == 0) {
hint += SOUND(0x0103) u"Ho ho! "s;
hintText += SOUND(0x0103) u"Ho ho! "s;
}
i++;
hint += location->hint.text[language];
hint = Text::word_wrap_string(hint, 43);
if (i == hintLocations.size()) {
hint += u'\0'; // add null terminator on last hint before padding
hintText += hint.text[language];
hintText = Text::word_wrap_string(hintText, 43);
if (i == hints.size()) {
hintText += u'\0'; // add null terminator on last hint before padding
}
hint = Text::pad_str_4_lines(hint);
hintLines += hint;
hintText = Text::pad_str_4_lines(hintText);
hintLines += hintText;
}
CAST_ENTRY_TO_FILETYPE(msbt, FileTypes::MSBTFile, data)

Expand All @@ -1327,16 +1327,16 @@ TweakError update_kreeb_dialog(World& world) {
entry.addAction([=, &world](RandoSession* session, FileType* data) -> int {
std::u16string hintLines = u"";
size_t i = 0; // counter to know when to add null terminator
for (auto location : world.kreebHints) {
std::u16string hint = u"";
hint += location->hint.text[language];
hint = Text::word_wrap_string(hint, 43);
for (auto& hint : world.kreebHints) {
std::u16string hintText = u"";
hintText += hint.text[language];
hintText = Text::word_wrap_string(hintText, 43);
++i;
if (i == world.kreebHints.size()) {
hint += u'\0'; // add null terminator on last hint before padding
hintText += u'\0'; // add null terminator on last hint before padding
}
hint = Text::pad_str_4_lines(hint);
hintLines += hint;
hintText = Text::pad_str_4_lines(hintText);
hintLines += hintText;
}
CAST_ENTRY_TO_FILETYPE(msbt, FileTypes::MSBTFile, data)

Expand All @@ -1354,10 +1354,10 @@ TweakError rotate_ho_ho_to_face_hints(World& world) {
return TweakError::NONE;
}

for (auto& [hohoLocation, hintLocations] : world.hohoHints) {
for (auto& [hohoLocation, hints] : world.hohoHints) {
std::string island = "";
for (auto location : hintLocations) {
for (auto region : location->hintRegions) {
for (auto& hint : hints) {
for (auto region : hint.location->hintRegions) {
// If this region is a dungeon, use the dungeon's island instead
if (world.dungeons.contains(region)) {
region = world.dungeons[region].islands.front();
Expand Down