mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-07-16 10:02:59 -07:00
708 lines
No EOL
27 KiB
C++
708 lines
No EOL
27 KiB
C++
#include "hint.h"
|
|
#include "map"
|
|
#include "string"
|
|
#include "context.h"
|
|
#include <spdlog/spdlog.h>
|
|
#include "static_data.h"
|
|
|
|
namespace Rando {
|
|
Hint::Hint() {
|
|
}
|
|
|
|
Hint::Hint(RandomizerHint ownKey_, HintType hintType_, std::string distribution_,
|
|
std::vector<RandomizerHintTextKey> hintKeys_, std::vector<RandomizerCheck> locations_,
|
|
std::vector<RandomizerArea> areas_, std::vector<TrialKey> trials_)
|
|
: ownKey(ownKey_), hintType(hintType_), distribution(std::move(distribution_)), hintKeys(hintKeys_),
|
|
locations(locations_), areas(areas_), trials(trials_) {
|
|
FillGapsInData();
|
|
SetLocationsAsHinted();
|
|
NamesChosen();
|
|
enabled = true;
|
|
}
|
|
|
|
Hint::Hint(RandomizerHint ownKey_, HintType hintType_, std::vector<RandomizerHintTextKey> hintKeys_,
|
|
std::vector<RandomizerCheck> locations_, std::vector<RandomizerArea> areas_, std::vector<TrialKey> trials_,
|
|
bool yourPocket_, int num_)
|
|
: ownKey(ownKey_), hintType(hintType_), hintKeys(hintKeys_), locations(locations_), areas(areas_), trials(trials_),
|
|
yourPocket(yourPocket_), num(num_) {
|
|
FillGapsInData();
|
|
SetLocationsAsHinted();
|
|
NamesChosen();
|
|
enabled = true;
|
|
}
|
|
|
|
Hint::Hint(RandomizerHint ownKey_, std::vector<CustomMessage> messages_) : ownKey(ownKey_), messages(messages_) {
|
|
hintType = HINT_TYPE_MESSAGE;
|
|
enabled = true;
|
|
}
|
|
|
|
Hint::Hint(RandomizerHint ownKey_, nlohmann::json json_) {
|
|
ownKey = ownKey_;
|
|
if (json_.contains("enabled") && !json_["enabled"].get<bool>()) {
|
|
return;
|
|
}
|
|
enabled = true;
|
|
|
|
if (json_.contains("type")) {
|
|
hintType = (HintType)StaticData::hintTypeNameToEnum[json_["type"].get<std::string>()];
|
|
}
|
|
|
|
if (hintType == HINT_TYPE_MESSAGE) {
|
|
if (json_.contains("messages")) {
|
|
for (auto message : json_["messages"]) {
|
|
messages.push_back(CustomMessage(message.get<std::string>()));
|
|
}
|
|
} else if (json_.contains("message")) {
|
|
messages.push_back(CustomMessage(json_["message"].get<std::string>()));
|
|
}
|
|
}
|
|
|
|
if (json_.contains("distribution")) {
|
|
distribution = json_["distribution"].get<std::string>();
|
|
}
|
|
|
|
if (json_.contains("locations")) {
|
|
for (auto loc : json_["locations"]) {
|
|
locations.push_back(StaticData::locationNameToEnum[loc.get<std::string>()]);
|
|
}
|
|
} else if (json_.contains("location")) {
|
|
locations.push_back(StaticData::locationNameToEnum[json_["location"].get<std::string>()]);
|
|
}
|
|
|
|
if (json_.contains("itemNamesChosen")) {
|
|
for (auto name : json_["itemNamesChosen"]) {
|
|
itemNamesChosen.push_back(name.get<uint8_t>());
|
|
}
|
|
} else if (json_.contains("itemNameChosen")) {
|
|
itemNamesChosen.push_back(json_["itemNameChosen"].get<uint8_t>());
|
|
}
|
|
|
|
if (json_.contains("areas")) {
|
|
for (auto area : json_["areas"]) {
|
|
areas.push_back((RandomizerArea)Rando::StaticData::areaNameToEnum[area]);
|
|
}
|
|
} else if (json_.contains("area")) {
|
|
areas.push_back((RandomizerArea)Rando::StaticData::areaNameToEnum[json_["area"]]);
|
|
}
|
|
|
|
if (json_.contains("areaNamesChosen")) {
|
|
for (auto name : json_["areaNamesChosen"]) {
|
|
areaNamesChosen.push_back(name.get<uint8_t>());
|
|
}
|
|
} else if (json_.contains("areaNameChosen")) {
|
|
areaNamesChosen.push_back(json_["areaNameChosen"].get<uint8_t>());
|
|
}
|
|
|
|
if (json_.contains("trials")) {
|
|
for (auto trial : json_["trials"]) {
|
|
trials.push_back((TrialKey)Rando::StaticData::trialNameToEnum[trial]);
|
|
}
|
|
} else if (json_.contains("trial")) {
|
|
trials.push_back((TrialKey)Rando::StaticData::trialNameToEnum[json_["trial"]]);
|
|
}
|
|
|
|
if (json_.contains("hintKeys")) {
|
|
for (auto hintKey : json_["hintKeys"]) {
|
|
hintKeys.push_back((RandomizerHintTextKey)hintKey.get<uint32_t>());
|
|
}
|
|
} else if (json_.contains("hintKey")) {
|
|
hintKeys.push_back((RandomizerHintTextKey)json_["hintKey"].get<uint32_t>());
|
|
}
|
|
|
|
if (json_.contains("hintTextsChosen")) {
|
|
for (auto name : json_["hintTextsChosen"]) {
|
|
hintTextsChosen.push_back(name.get<uint8_t>());
|
|
}
|
|
} else if (json_.contains("hintTextChosen")) {
|
|
hintTextsChosen.push_back(json_["hintTextChosen"].get<uint8_t>());
|
|
}
|
|
|
|
if (json_.contains("num")) {
|
|
num = json_["num"].get<int>();
|
|
}
|
|
|
|
FillGapsInData();
|
|
SetLocationsAsHinted();
|
|
}
|
|
|
|
void Hint::FillGapsInData() {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
if (locations.size() == 0 && StaticData::staticHintInfoMap.contains(ownKey)) {
|
|
locations = StaticData::staticHintInfoMap[ownKey].targetChecks;
|
|
}
|
|
bool fillAreas = true;
|
|
bool fillItems = true;
|
|
if (areas.size() > 0) {
|
|
fillAreas = false;
|
|
}
|
|
if (items.size() > 0) {
|
|
fillItems = false;
|
|
}
|
|
for (uint8_t c = 0; c < locations.size(); c++) {
|
|
// if area matters for the hint, it should be specified and not left to this
|
|
if (fillAreas) {
|
|
areas.push_back(ctx->GetItemLocation(locations[c])->GetFirstArea());
|
|
}
|
|
if (fillItems) {
|
|
items.push_back(ctx->GetItemLocation(locations[c])->GetPlacedRandomizerGet());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Hint::SetLocationsAsHinted() const {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
for (uint8_t count = 0; count < locations.size(); count++) {
|
|
ctx->GetItemLocation(locations[count])->AddHintedBy(ownKey);
|
|
}
|
|
}
|
|
|
|
uint8_t GetRandomHintTextEntry(const HintText hintText) {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
uint8_t size = 0;
|
|
if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) {
|
|
size = hintText.GetAmbiguousSize();
|
|
} else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) {
|
|
size = hintText.GetObscureSize();
|
|
}
|
|
if (size > 0) {
|
|
return Random(0, size);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Hint::NamesChosen() {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
std::vector<uint8_t> namesTemp = {};
|
|
bool saveNames = false;
|
|
uint8_t numMessages = GetNumberOfMessages();
|
|
for (uint8_t c = 0; c < numMessages; c++) {
|
|
uint8_t selection = GetRandomHintTextEntry(GetHintText(c));
|
|
if (selection > 0) {
|
|
saveNames = true;
|
|
}
|
|
namesTemp.push_back(selection);
|
|
}
|
|
if (saveNames) {
|
|
hintTextsChosen = namesTemp;
|
|
}
|
|
|
|
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_ITEM_AREA) {
|
|
for (uint8_t c = 0; c < locations.size(); c++) {
|
|
namesTemp = {};
|
|
saveNames = false;
|
|
uint8_t selection = GetRandomHintTextEntry(GetItemHintText(c));
|
|
if (selection > 0) {
|
|
saveNames = true;
|
|
}
|
|
namesTemp.push_back(selection);
|
|
}
|
|
if (saveNames) {
|
|
itemNamesChosen = namesTemp;
|
|
}
|
|
}
|
|
|
|
if (hintType == HINT_TYPE_FOOLISH || hintType == HINT_TYPE_ITEM_AREA || hintType == HINT_TYPE_WOTH ||
|
|
hintType == HINT_TYPE_ALTAR_CHILD || hintType == HINT_TYPE_ALTAR_ADULT) {
|
|
namesTemp = {};
|
|
saveNames = false;
|
|
for (uint8_t c = 0; c < areas.size(); c++) {
|
|
uint8_t selection = GetRandomHintTextEntry(GetAreaHintText(c));
|
|
if (selection > 0) {
|
|
saveNames = true;
|
|
}
|
|
namesTemp.push_back(selection);
|
|
}
|
|
if (saveNames) {
|
|
areaNamesChosen = namesTemp;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint8_t Hint::GetNumberOfMessages() const {
|
|
size_t numMessages = std::max(messages.size(), hintKeys.size());
|
|
if (StaticData::staticHintInfoMap.contains(ownKey)) {
|
|
numMessages = std::max(StaticData::staticHintInfoMap[ownKey].hintKeys.size(), numMessages);
|
|
}
|
|
if (numMessages == 0) {
|
|
numMessages = 1; // RANDOTODO make std::max actually fucking work for 3 arguments
|
|
}
|
|
// RANDOTODO will number of messages always be u8?
|
|
return static_cast<uint8_t>(numMessages);
|
|
}
|
|
|
|
const std::vector<std::string> Hint::GetAllMessageStrings(MessageFormat format) const {
|
|
std::vector<std::string> hintMessages = {};
|
|
uint8_t numMessages = GetNumberOfMessages();
|
|
for (int c = 0; c < numMessages; c++) {
|
|
hintMessages.push_back(GetHintMessage(format, c).GetForCurrentLanguage(format));
|
|
}
|
|
return hintMessages;
|
|
}
|
|
|
|
const HintText Hint::GetHintText(uint8_t id) const {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
if (hintKeys.size() > id) {
|
|
return StaticData::hintTextTable[hintKeys[id]];
|
|
}
|
|
// If a static hint, load default from staticHintInfoMap
|
|
if (StaticData::staticHintInfoMap.contains(ownKey) && StaticData::staticHintInfoMap[ownKey].hintKeys.size() > id) {
|
|
return StaticData::hintTextTable[StaticData::staticHintInfoMap[ownKey].hintKeys[id]];
|
|
}
|
|
|
|
switch (hintType) {
|
|
case HINT_TYPE_HINT_KEY:
|
|
return StaticData::hintTextTable[0];
|
|
break;
|
|
case HINT_TYPE_TRIAL:
|
|
if (ctx->GetTrial(trials[0])->IsRequired()) {
|
|
return StaticData::hintTextTable[RHT_TRIAL_ON];
|
|
} else {
|
|
return StaticData::hintTextTable[RHT_TRIAL_OFF];
|
|
}
|
|
case HINT_TYPE_WOTH:
|
|
return StaticData::hintTextTable[RHT_WAY_OF_THE_HERO];
|
|
case HINT_TYPE_FOOLISH:
|
|
return StaticData::hintTextTable[RHT_FOOLISH];
|
|
case HINT_TYPE_ITEM:
|
|
if (locations.size() > 0) {
|
|
return *StaticData::GetLocation(locations[0])->GetHint();
|
|
} else {
|
|
return HintText(CustomMessage("ERROR: ITEM HINT WITH NO LOCATIONS OR HINT KEY"));
|
|
}
|
|
case HINT_TYPE_ITEM_AREA:
|
|
if (locations.size() > 0) {
|
|
if (StaticData::GetLocation(locations[0])->IsDungeon()) {
|
|
return StaticData::hintTextTable[RHT_HOARDS];
|
|
} else {
|
|
return StaticData::hintTextTable[RHT_CAN_BE_FOUND_AT];
|
|
}
|
|
} else {
|
|
return HintText(
|
|
CustomMessage("ERROR: ITEM AREA HINT WITH NO LOCATION")); // RANDOTODO get isDungeon from area?
|
|
}
|
|
default:
|
|
return HintText(CustomMessage("ERROR: NO HINTKEY PROVIDED AND HINT TYPE HAS NO DEFAULT"));
|
|
}
|
|
}
|
|
|
|
const CustomMessage Hint::GetHintMessage(MessageFormat format, uint8_t id) const {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
CustomMessage hintText = CustomMessage("");
|
|
|
|
uint8_t chosenMessage = 0;
|
|
if (hintTextsChosen.size() > id) {
|
|
chosenMessage = id;
|
|
}
|
|
|
|
if (hintType == HINT_TYPE_MESSAGE) {
|
|
if (id < messages.size()) {
|
|
hintText = messages[id];
|
|
}
|
|
} else if (hintType == HINT_TYPE_ALTAR_CHILD) {
|
|
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
|
|
hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage();
|
|
}
|
|
if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) {
|
|
hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage());
|
|
} else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY)) {
|
|
hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY].GetHintMessage());
|
|
} else {
|
|
hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED].GetHintMessage());
|
|
}
|
|
} else if (hintType == HINT_TYPE_ALTAR_ADULT) {
|
|
if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) {
|
|
hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage();
|
|
}
|
|
hintText += GetBridgeReqsText() + GetGanonBossKeyText() +
|
|
StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage();
|
|
} else {
|
|
hintText = GetHintText(id).GetHintMessage(chosenMessage);
|
|
}
|
|
|
|
std::vector<CustomMessage> toInsert = {};
|
|
|
|
switch (hintType) {
|
|
case HINT_TYPE_ITEM: {
|
|
// if we write items
|
|
for (uint8_t b = 0; b < locations.size(); b++) {
|
|
toInsert.push_back(GetItemName(b));
|
|
}
|
|
break;
|
|
}
|
|
case HINT_TYPE_TRIAL: {
|
|
// If we write trials
|
|
for (uint8_t b = 0; b < trials.size(); b++) {
|
|
toInsert.push_back(ctx->GetTrial(trials[b])->GetName());
|
|
}
|
|
break;
|
|
}
|
|
case HINT_TYPE_ITEM_AREA: {
|
|
// If we write items and areas
|
|
for (uint8_t b = 0; b < items.size(); b++) {
|
|
toInsert.push_back(GetItemName(b));
|
|
toInsert.push_back(GetAreaName(b));
|
|
}
|
|
break;
|
|
}
|
|
case HINT_TYPE_ALTAR_CHILD:
|
|
case HINT_TYPE_ALTAR_ADULT:
|
|
case HINT_TYPE_AREA:
|
|
case HINT_TYPE_WOTH:
|
|
case HINT_TYPE_FOOLISH: {
|
|
// If we write areas
|
|
for (uint8_t b = 0; b < areas.size(); b++) {
|
|
toInsert.push_back(GetAreaName(b));
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
hintText.InsertNames(toInsert);
|
|
|
|
if (num != 0) {
|
|
hintText.InsertNumber(num);
|
|
}
|
|
|
|
if (format == MF_FORMATTED) {
|
|
hintText.Format();
|
|
} else if (format == MF_AUTO_FORMAT) {
|
|
hintText.AutoFormat();
|
|
} else if (format == MF_CLEAN) {
|
|
hintText.Clean();
|
|
}
|
|
|
|
return hintText;
|
|
}
|
|
|
|
oJson Hint::toJSON() {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
nlohmann::ordered_json log = {};
|
|
if (enabled) {
|
|
log["type"] = StaticData::hintTypeNames[hintType].GetForCurrentLanguage(MF_CLEAN);
|
|
|
|
std::vector<std::string> hintMessages = GetAllMessageStrings(MF_CLEAN);
|
|
if (hintMessages.size() == 1) {
|
|
log["message"] = hintMessages[0];
|
|
} else if (hintMessages.size() > 1) {
|
|
log["messages"] = hintMessages;
|
|
}
|
|
|
|
if (distribution != "") {
|
|
log["distribution"] = distribution;
|
|
}
|
|
|
|
if (hintType != HINT_TYPE_FOOLISH) {
|
|
if (!(StaticData::staticHintInfoMap.contains(ownKey) &&
|
|
StaticData::staticHintInfoMap[ownKey].targetChecks.size() > 0)) {
|
|
if (locations.size() == 1) {
|
|
log["location"] = StaticData::GetLocation(locations[0])
|
|
->GetName(); // RANDOTODO change to CustomMessage when VB is done;
|
|
} else if (locations.size() > 1) {
|
|
// If we have defaults, no need to write more
|
|
std::vector<std::string> locStrings = {};
|
|
for (size_t c = 0; c < locations.size(); c++) {
|
|
locStrings.push_back(StaticData::GetLocation(locations[c])
|
|
->GetName()); // RANDOTODO change to CustomMessage when VB is done
|
|
}
|
|
log["locations"] = locStrings;
|
|
}
|
|
}
|
|
|
|
if (!(StaticData::staticHintInfoMap.contains(ownKey) &&
|
|
StaticData::staticHintInfoMap[ownKey].targetItems.size() > 0)) {
|
|
if (items.size() == 1) {
|
|
log["item"] = StaticData::GetItemTable()[items[0]].GetName().GetForCurrentLanguage(
|
|
MF_RAW); // RANDOTODO change to CustomMessage;
|
|
} else if (items.size() > 1) {
|
|
std::vector<std::string> itemStrings = {};
|
|
for (size_t c = 0; c < items.size(); c++) {
|
|
itemStrings.push_back(StaticData::GetItemTable()[items[c]].GetName().GetForCurrentLanguage(
|
|
MF_RAW)); // RANDOTODO change to CustomMessage
|
|
}
|
|
log["items"] = itemStrings;
|
|
}
|
|
}
|
|
|
|
if (itemNamesChosen.size() == 1) {
|
|
log["itemNameChosen"] = itemNamesChosen[0];
|
|
} else if (itemNamesChosen.size() > 1) {
|
|
std::vector<uint8_t> nameNums = {};
|
|
for (size_t c = 0; c < itemNamesChosen.size(); c++) {
|
|
nameNums.push_back(itemNamesChosen[c]);
|
|
}
|
|
log["itemNamesChosen"] = nameNums;
|
|
}
|
|
}
|
|
if (areas.size() == 1) {
|
|
log["area"] =
|
|
StaticData::hintTextTable[StaticData::areaNames[areas[0]]].GetClear().GetForCurrentLanguage(MF_CLEAN);
|
|
} else if (areas.size() > 0 && !(StaticData::staticHintInfoMap.contains(ownKey) &&
|
|
StaticData::staticHintInfoMap[ownKey].targetChecks.size() > 0)) {
|
|
// If we got locations from defaults, areas are derived from them and don't need logging
|
|
std::vector<std::string> areaStrings = {};
|
|
for (size_t c = 0; c < areas.size(); c++) {
|
|
areaStrings.push_back(
|
|
StaticData::hintTextTable[StaticData::areaNames[areas[c]]].GetClear().GetForCurrentLanguage(
|
|
MF_CLEAN));
|
|
}
|
|
log["areas"] = areaStrings;
|
|
}
|
|
|
|
if (areaNamesChosen.size() == 1) {
|
|
log["areaNameChosen"] = areaNamesChosen[0];
|
|
} else if (areaNamesChosen.size() > 1) {
|
|
std::vector<uint8_t> nameNums = {};
|
|
for (size_t c = 0; c < areaNamesChosen.size(); c++) {
|
|
nameNums.push_back(areaNamesChosen[c]);
|
|
}
|
|
log["areaNamesChosen"] = nameNums;
|
|
}
|
|
|
|
if (trials.size() == 1) {
|
|
log["trial"] = ctx->GetTrial(trials[0])->GetName().GetForCurrentLanguage(MF_CLEAN);
|
|
} else if (trials.size() > 0) {
|
|
std::vector<std::string> trialStrings = {};
|
|
for (size_t c = 0; c < trials.size(); c++) {
|
|
trialStrings.push_back(ctx->GetTrial(trials[c])->GetName().GetForCurrentLanguage(MF_CLEAN));
|
|
}
|
|
log["trials"] = trialStrings;
|
|
}
|
|
|
|
if (hintKeys.size() == 1) {
|
|
log["hintKey"] = hintKeys[0];
|
|
} else if (hintKeys.size() > 1) {
|
|
std::vector<uint32_t> hintKeyNums = {};
|
|
for (size_t c = 0; c < hintKeys.size(); c++) {
|
|
hintKeyNums.push_back(hintKeys[c]);
|
|
}
|
|
log["hintKeys"] = hintKeyNums;
|
|
}
|
|
|
|
if (hintTextsChosen.size() == 1) {
|
|
log["hintTextChosen"] = hintTextsChosen[0];
|
|
} else if (hintTextsChosen.size() > 1) {
|
|
std::vector<uint8_t> nameNums = {};
|
|
for (size_t c = 0; c < hintTextsChosen.size(); c++) {
|
|
nameNums.push_back(hintTextsChosen[c]);
|
|
}
|
|
log["hintTextsChosen"] = nameNums;
|
|
}
|
|
|
|
if (num != 0) {
|
|
log["num"] = num;
|
|
}
|
|
}
|
|
return log;
|
|
}
|
|
|
|
void Hint::logHint(oJson& jsonData) {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
std::string logMap = "Static Hints";
|
|
bool staticHint = true;
|
|
if (ownKey < RH_GANONDORF_HINT) {
|
|
logMap = "Gossip Stone Hints";
|
|
staticHint = false;
|
|
}
|
|
if (enabled &&
|
|
(!(staticHint && (hintType == HINT_TYPE_ITEM) && ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_CLEAR)))) {
|
|
// skip if not enabled or if a static hint with no possible variance
|
|
jsonData[logMap][Rando::StaticData::hintNames[ownKey].GetForCurrentLanguage(MF_CLEAN)] = toJSON();
|
|
}
|
|
}
|
|
|
|
const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const {
|
|
// RANDOTODO make unreliant on locations, or make Hint accept ItemLocation
|
|
auto ctx = Rando::Context::GetInstance();
|
|
RandomizerCheck hintedCheck = locations[slot];
|
|
RandomizerGet targetRG = ctx->GetItemLocation(hintedCheck)->GetPlacedRandomizerGet();
|
|
if (mysterious) {
|
|
return StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM];
|
|
} else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) &&
|
|
targetRG == RG_ICE_TRAP) { // RANDOTODO store in item hint instead of item
|
|
return HintText(CustomMessage({ ctx->overrides[hintedCheck].GetTrickName() }));
|
|
} else {
|
|
return ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetHint();
|
|
}
|
|
}
|
|
|
|
const HintText Hint::GetAreaHintText(uint8_t slot) const {
|
|
CustomMessage areaText;
|
|
if (yourPocket && areas[slot] == RA_LINKS_POCKET) {
|
|
return StaticData::hintTextTable[RHT_YOUR_POCKET];
|
|
} else {
|
|
return StaticData::hintTextTable[Rando::StaticData::areaNames[areas[slot]]];
|
|
}
|
|
}
|
|
|
|
const CustomMessage Hint::GetItemName(uint8_t slot, bool mysterious) const {
|
|
uint8_t nameNum = 0;
|
|
if (itemNamesChosen.size() > slot) {
|
|
nameNum = itemNamesChosen[slot];
|
|
}
|
|
return GetItemHintText(slot, mysterious).GetHintMessage(nameNum);
|
|
}
|
|
|
|
const CustomMessage Hint::GetAreaName(uint8_t slot) const {
|
|
uint8_t nameNum = 0;
|
|
if (areaNamesChosen.size() > slot) {
|
|
nameNum = areaNamesChosen[slot];
|
|
}
|
|
return GetAreaHintText(slot).GetHintMessage(nameNum);
|
|
}
|
|
|
|
CustomMessage Hint::GetBridgeReqsText() {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
CustomMessage bridgeMessage;
|
|
|
|
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN)) {
|
|
return StaticData::hintTextTable[RHT_BRIDGE_OPEN_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA)) {
|
|
return StaticData::hintTextTable[RHT_BRIDGE_VANILLA_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
|
|
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_STONES_HINT].GetHintMessage();
|
|
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
|
|
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT].GetHintMessage();
|
|
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
|
|
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_REWARDS_HINT].GetHintMessage();
|
|
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) {
|
|
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_DUNGEONS_HINT].GetHintMessage();
|
|
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
|
|
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_TOKENS_HINT].GetHintMessage();
|
|
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) {
|
|
return StaticData::hintTextTable[RHT_BRIDGE_GREG_HINT].GetHintMessage();
|
|
}
|
|
return bridgeMessage;
|
|
}
|
|
|
|
CustomMessage Hint::GetGanonBossKeyText() {
|
|
auto ctx = Rando::Context::GetInstance();
|
|
CustomMessage ganonBossKeyMessage;
|
|
|
|
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();
|
|
}
|
|
|
|
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_START_WITH_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_VANILLA_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_OWN_DUNGEON_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_ANY_DUNGEON_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_OVERWORLD_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_ANYWHERE_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
|
|
return StaticData::hintTextTable[RHT_GANON_BK_SKULLTULA_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_VANILLA)) {
|
|
return StaticData::hintTextTable[RHT_LACS_VANILLA_HINT].GetHintMessage();
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
|
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_STONES_HINT].GetHintMessage();
|
|
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
|
|
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_MEDALLIONS_HINT].GetHintMessage();
|
|
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
|
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_REWARDS_HINT].GetHintMessage();
|
|
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
|
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_DUNGEONS_HINT].GetHintMessage();
|
|
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get());
|
|
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
|
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage();
|
|
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
|
|
}
|
|
return ganonBossKeyMessage;
|
|
}
|
|
|
|
void Hint::AddHintedLocation(RandomizerCheck location) {
|
|
locations.push_back(location);
|
|
}
|
|
|
|
std::vector<RandomizerCheck> Hint::GetHintedLocations() const {
|
|
return locations;
|
|
}
|
|
|
|
void Hint::SetHintType(HintType type) {
|
|
hintType = type;
|
|
}
|
|
|
|
HintType Hint::GetHintType() const {
|
|
return hintType;
|
|
}
|
|
|
|
void Hint::AddHintedArea(RandomizerArea area) {
|
|
areas.push_back(area);
|
|
}
|
|
|
|
std::vector<RandomizerArea> Hint::GetHintedAreas() const {
|
|
return areas;
|
|
}
|
|
|
|
void Hint::SetDistribution(std::string distributionName) {
|
|
distribution = distributionName;
|
|
}
|
|
|
|
const std::string& Hint::GetDistribution() const {
|
|
return distribution;
|
|
}
|
|
|
|
bool Hint::IsEnabled() const {
|
|
return enabled;
|
|
}
|
|
|
|
std::vector<RandomizerHintTextKey> Hint::GetHintTextKeys() const {
|
|
return hintKeys;
|
|
}
|
|
|
|
std::vector<RandomizerGet> Hint::GetHintedItems() const {
|
|
return items;
|
|
}
|
|
|
|
std::vector<uint8_t> Hint::GetItemNamesChosen() const {
|
|
return itemNamesChosen;
|
|
}
|
|
|
|
std::vector<uint8_t> Hint::GetHintTextsChosen() const {
|
|
return hintTextsChosen;
|
|
}
|
|
std::vector<uint8_t> Hint::GetAreaTextsChosen() const {
|
|
return areaNamesChosen;
|
|
}
|
|
|
|
std::vector<TrialKey> Hint::GetHintedTrials() const {
|
|
return trials;
|
|
}
|
|
|
|
int Hint::GetNum() {
|
|
return num;
|
|
}
|
|
|
|
void Hint::ResetVariables() {
|
|
ownKey = RH_NONE;
|
|
num = 0;
|
|
yourPocket = false;
|
|
messages = {};
|
|
hintKeys = {};
|
|
locations = {};
|
|
items = {};
|
|
trials = {};
|
|
hintType = HINT_TYPE_HINT_KEY;
|
|
areas = {};
|
|
distribution = "";
|
|
enabled = false;
|
|
itemNamesChosen = {};
|
|
hintTextsChosen = {};
|
|
areaNamesChosen = {};
|
|
}
|
|
|
|
} // namespace Rando
|