872 lines
37 KiB
C++
872 lines
37 KiB
C++
#include "context.h"
|
|
#include "static_data.h"
|
|
#include "soh/OTRGlobals.h"
|
|
#include "soh/Enhancements/item-tables/ItemTableManager.h"
|
|
#include "3drando/shops.hpp"
|
|
#include "dungeon.h"
|
|
#include "logic.h"
|
|
#include "entrance.h"
|
|
#include "settings.h"
|
|
#include "rando_hash.h"
|
|
#include "fishsanity.h"
|
|
#include "macros.h"
|
|
#include "3drando/hints.hpp"
|
|
#include "soh/util.h"
|
|
#include "../kaleido.h"
|
|
#include "soh/Network/Archipelago/Archipelago.h"
|
|
#include "soh/Network/Archipelago/ArchipelagoConsoleWindow.h"
|
|
|
|
#include <fstream>
|
|
#include <spdlog/spdlog.h>
|
|
|
|
namespace Rando {
|
|
std::weak_ptr<Context> Context::mContext;
|
|
|
|
Context::Context() {
|
|
|
|
for (int i = 0; i < RC_MAX; i++) {
|
|
itemLocationTable[i] = ItemLocation(static_cast<RandomizerCheck>(i));
|
|
}
|
|
mEntranceShuffler = std::make_shared<EntranceShuffler>();
|
|
mDungeons = std::make_shared<Dungeons>();
|
|
mLogic = std::make_shared<Logic>();
|
|
mTrials = std::make_shared<Trials>();
|
|
mFishsanity = std::make_shared<Fishsanity>();
|
|
VanillaLogicDefaults = {
|
|
// RANDOTODO check what this does
|
|
&mOptions[RSK_LINKS_POCKET],
|
|
&mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
|
|
&mOptions[RSK_SHUFFLE_SONGS],
|
|
&mOptions[RSK_SHOPSANITY],
|
|
&mOptions[RSK_SHOPSANITY_COUNT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_FISHSANITY],
|
|
&mOptions[RSK_FISHSANITY_POND_COUNT],
|
|
&mOptions[RSK_FISHSANITY_AGE_SPLIT],
|
|
&mOptions[RSK_SHUFFLE_SCRUBS],
|
|
&mOptions[RSK_SHUFFLE_BEEHIVES],
|
|
&mOptions[RSK_SHUFFLE_COWS],
|
|
&mOptions[RSK_SHUFFLE_POTS],
|
|
&mOptions[RSK_SHUFFLE_CRATES],
|
|
&mOptions[RSK_SHUFFLE_FREESTANDING],
|
|
&mOptions[RSK_SHUFFLE_MERCHANTS],
|
|
&mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
|
|
&mOptions[RSK_SHUFFLE_ADULT_TRADE],
|
|
&mOptions[RSK_SHUFFLE_100_GS_REWARD],
|
|
&mOptions[RSK_SHUFFLE_FAIRIES],
|
|
&mOptions[RSK_GOSSIP_STONE_HINTS],
|
|
};
|
|
}
|
|
|
|
RandomizerArea Context::GetAreaFromString(std::string str) {
|
|
return (RandomizerArea)StaticData::areaNameToEnum[str];
|
|
}
|
|
|
|
void Context::InitStaticData() {
|
|
StaticData::HintTable_Init();
|
|
StaticData::trialNameToEnum = StaticData::PopulateTranslationMap(StaticData::trialData);
|
|
StaticData::hintNameToEnum = StaticData::PopulateTranslationMap(StaticData::hintNames);
|
|
StaticData::hintTypeNameToEnum = StaticData::PopulateTranslationMap(StaticData::hintTypeNames);
|
|
StaticData::areaNameToEnum = StaticData::PopulateTranslationMap(StaticData::areaNames);
|
|
StaticData::InitLocationTable();
|
|
}
|
|
|
|
std::shared_ptr<Context> Context::CreateInstance() {
|
|
if (mContext.expired()) {
|
|
auto instance = std::make_shared<Context>();
|
|
mContext = instance;
|
|
GetInstance()->GetLogic()->SetContext(GetInstance());
|
|
return instance;
|
|
}
|
|
return GetInstance();
|
|
}
|
|
|
|
std::shared_ptr<Context> Context::GetInstance() {
|
|
return mContext.lock();
|
|
}
|
|
|
|
Hint* Context::GetHint(const RandomizerHint hintKey) {
|
|
return &hintTable[hintKey];
|
|
}
|
|
|
|
void Context::AddHint(const RandomizerHint hintId, const Hint hint) {
|
|
hintTable[hintId] = hint; // RANDOTODO this should probably be an rvalue
|
|
}
|
|
|
|
ItemLocation* Context::GetItemLocation(const RandomizerCheck locKey) {
|
|
return &itemLocationTable[locKey];
|
|
}
|
|
|
|
ItemLocation* Context::GetItemLocation(size_t locKey) {
|
|
return &itemLocationTable[static_cast<RandomizerCheck>(locKey)];
|
|
}
|
|
|
|
bool Context::IsLocationShuffled(const RandomizerCheck locKey) {
|
|
return itemLocationTable[locKey].GetPlacedRandomizerGet() != RG_NONE;
|
|
}
|
|
|
|
ItemOverride& Context::GetItemOverride(RandomizerCheck locKey) {
|
|
if (!overrides.contains(locKey)) {
|
|
overrides.emplace(locKey, ItemOverride());
|
|
}
|
|
return overrides.at(locKey);
|
|
}
|
|
|
|
ItemOverride& Context::GetItemOverride(size_t locKey) {
|
|
if (!overrides.contains(static_cast<RandomizerCheck>(locKey))) {
|
|
overrides.emplace(static_cast<RandomizerCheck>(locKey), ItemOverride());
|
|
}
|
|
return overrides.at(static_cast<RandomizerCheck>(locKey));
|
|
}
|
|
|
|
void Context::PlaceItemInLocation(const RandomizerCheck locKey, const RandomizerGet item,
|
|
const bool applyEffectImmediately, const bool setHidden) {
|
|
const auto loc = GetItemLocation(locKey);
|
|
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish() + " placed at " +
|
|
StaticData::GetLocation(locKey)->GetName() + "\n");
|
|
|
|
if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) ||
|
|
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) {
|
|
StaticData::RetrieveItem(item).ApplyEffect();
|
|
}
|
|
|
|
// TODO? Show Progress
|
|
|
|
loc->SetPlacedItem(item);
|
|
if (setHidden) {
|
|
loc->SetHidden(true);
|
|
}
|
|
}
|
|
|
|
void Context::AddLocation(const RandomizerCheck loc, std::vector<RandomizerCheck>* destination) {
|
|
if (destination == nullptr) {
|
|
destination = &allLocations;
|
|
}
|
|
destination->push_back(loc);
|
|
}
|
|
|
|
template <typename Container>
|
|
void Context::AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination) {
|
|
if (destination == nullptr) {
|
|
destination = &allLocations;
|
|
}
|
|
destination->insert(destination->end(), std::cbegin(locations), std::cend(locations));
|
|
}
|
|
|
|
bool Context::IsQuestOfLocationActive(RandomizerCheck rc) {
|
|
const auto loc = Rando::StaticData::GetLocation(rc);
|
|
return loc->GetQuest() == RCQUEST_BOTH ||
|
|
loc->GetQuest() == RCQUEST_MQ && mDungeons->GetDungeonFromScene(loc->GetScene())->IsMQ() ||
|
|
loc->GetQuest() == RCQUEST_VANILLA && mDungeons->GetDungeonFromScene(loc->GetScene())->IsVanilla();
|
|
}
|
|
|
|
void Context::GenerateLocationPool() {
|
|
allLocations.clear();
|
|
for (Location& location : StaticData::GetLocationTable()) {
|
|
// skip RCs that shouldn't be in the pool for any reason (i.e. settings, unsupported check type, etc.)
|
|
// TODO: Exclude checks for some of the older shuffles from the pool too i.e. Frog Songs, Scrubs, etc.)
|
|
if (location.GetRandomizerCheck() == RC_UNKNOWN_CHECK ||
|
|
location.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED || // already in pool
|
|
(location.GetRandomizerCheck() == RC_MASTER_SWORD_PEDESTAL &&
|
|
mOptions[RSK_SHUFFLE_MASTER_SWORD].Is(RO_GENERIC_OFF)) ||
|
|
(location.GetRandomizerCheck() == RC_KAK_100_GOLD_SKULLTULA_REWARD &&
|
|
mOptions[RSK_SHUFFLE_100_GS_REWARD].Is(RO_GENERIC_OFF)) ||
|
|
location.GetRCType() == RCTYPE_CHEST_GAME || // not supported yet
|
|
location.GetRCType() == RCTYPE_STATIC_HINT || // can't have items
|
|
location.GetRCType() == RCTYPE_GOSSIP_STONE || // can't have items
|
|
(location.GetRCType() == RCTYPE_FROG_SONG && mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES].Is(RO_GENERIC_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_SCRUB && mOptions[RSK_SHUFFLE_SCRUBS].Is(RO_SCRUBS_ONE_TIME_ONLY) &&
|
|
!(location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_GROTTO_FRONT ||
|
|
location.GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE ||
|
|
location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO)) ||
|
|
(location.GetRCType() == RCTYPE_ADULT_TRADE && mOptions[RSK_SHUFFLE_ADULT_TRADE].Is(RO_GENERIC_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_SONG_LOCATION && mOptions[RSK_SHUFFLE_SONGS].Is(RO_SONG_SHUFFLE_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_COW && mOptions[RSK_SHUFFLE_COWS].Is(RO_GENERIC_OFF)) ||
|
|
(location.GetRandomizerCheck() == RC_LH_HYRULE_LOACH &&
|
|
mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) ||
|
|
(location.GetRCType() == RCTYPE_FISH && !mFishsanity->GetFishLocationIncluded(&location)) ||
|
|
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_NLCRATE && (mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF) ||
|
|
!mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC))) ||
|
|
(location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_FAIRY && !mOptions[RSK_SHUFFLE_FAIRIES]) ||
|
|
(location.GetRCType() == RCTYPE_FREESTANDING &&
|
|
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) ||
|
|
(location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES])) {
|
|
continue;
|
|
}
|
|
if (location.IsOverworld()) {
|
|
// Skip stuff that is shuffled to dungeon only, i.e. tokens, pots, etc., or other checks that
|
|
// should not have a shuffled item.
|
|
if ((location.GetRCType() == RCTYPE_FREESTANDING &&
|
|
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_DUNGEONS)) ||
|
|
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_DUNGEONS)) ||
|
|
(location.GetRCType() == RCTYPE_GRASS && mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_DUNGEONS)) ||
|
|
(location.GetRCType() == RCTYPE_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) ||
|
|
(location.GetRCType() == RCTYPE_NLCRATE &&
|
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) &&
|
|
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) ||
|
|
(location.GetRCType() == RCTYPE_SMALL_CRATE &&
|
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS))) {
|
|
continue;
|
|
}
|
|
// If we've gotten past all the conditions where an overworld location should not be
|
|
// shuffled, add it to the pool.
|
|
AddLocation(location.GetRandomizerCheck(), &overworldLocations);
|
|
AddLocation(location.GetRandomizerCheck());
|
|
} else { // is a dungeon check
|
|
auto* dungeon = GetDungeon(location.GetArea() - RCAREA_DEKU_TREE);
|
|
if (location.GetQuest() == RCQUEST_BOTH || (location.GetQuest() == RCQUEST_MQ) == dungeon->IsMQ()) {
|
|
if ((location.GetRCType() == RCTYPE_FREESTANDING &&
|
|
mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OVERWORLD)) ||
|
|
(location.GetRCType() == RCTYPE_POT && mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD)) ||
|
|
(location.GetRCType() == RCTYPE_GRASS &&
|
|
mOptions[RSK_SHUFFLE_GRASS].Is(RO_SHUFFLE_GRASS_OVERWORLD)) ||
|
|
(location.GetRCType() == RCTYPE_CRATE &&
|
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD)) ||
|
|
(location.GetRCType() == RCTYPE_NLCRATE &&
|
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD) &&
|
|
mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) ||
|
|
(location.GetRCType() == RCTYPE_SMALL_CRATE &&
|
|
mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD))) {
|
|
continue;
|
|
}
|
|
// also add to that dungeon's location list.
|
|
AddLocation(location.GetRandomizerCheck(), &dungeon->locations);
|
|
AddLocation(location.GetRandomizerCheck());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Context::AddExcludedOptions() {
|
|
for (auto& loc : StaticData::GetLocationTable()) {
|
|
// Checks of these types don't have items, skip them.
|
|
if (loc.GetRandomizerCheck() == RC_UNKNOWN_CHECK || loc.GetRandomizerCheck() == RC_TRIFORCE_COMPLETED ||
|
|
loc.GetRCType() == RCTYPE_CHEST_GAME || loc.GetRCType() == RCTYPE_STATIC_HINT ||
|
|
loc.GetRCType() == RCTYPE_GOSSIP_STONE) {
|
|
continue;
|
|
}
|
|
AddLocation(loc.GetRandomizerCheck(), &everyPossibleLocation);
|
|
bool alreadyAdded = false;
|
|
for (Option* location : Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc.GetArea())) {
|
|
if (location->GetName() == loc.GetExcludedOption()->GetName()) {
|
|
alreadyAdded = true;
|
|
}
|
|
}
|
|
if (!alreadyAdded) {
|
|
Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc.GetArea()).push_back(loc.GetExcludedOption());
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<RandomizerCheck> Context::GetLocations(const std::vector<RandomizerCheck>& locationPool,
|
|
const RandomizerCheckType checkType) {
|
|
std::vector<RandomizerCheck> locationsOfType;
|
|
for (RandomizerCheck locKey : locationPool) {
|
|
if (StaticData::GetLocation(locKey)->GetRCType() == checkType) {
|
|
locationsOfType.push_back(locKey);
|
|
}
|
|
}
|
|
return locationsOfType;
|
|
}
|
|
|
|
void Context::ClearItemLocations() {
|
|
for (size_t i = 0; i < itemLocationTable.size(); i++) {
|
|
GetItemLocation(static_cast<RandomizerCheck>(i))->ResetVariables();
|
|
}
|
|
}
|
|
|
|
void Context::ItemReset() {
|
|
for (const RandomizerCheck il : allLocations) {
|
|
GetItemLocation(il)->ResetVariables();
|
|
}
|
|
|
|
for (const RandomizerCheck il : StaticData::dungeonRewardLocations) {
|
|
GetItemLocation(il)->ResetVariables();
|
|
}
|
|
|
|
GetItemLocation(RC_GIFT_FROM_RAURU)->ResetVariables();
|
|
GetItemLocation(RC_LINKS_POCKET)->ResetVariables();
|
|
}
|
|
|
|
void Context::LocationReset() {
|
|
for (auto& il : itemLocationTable) {
|
|
il.RemoveFromPool();
|
|
}
|
|
}
|
|
|
|
void Context::HintReset() {
|
|
for (const RandomizerCheck il : StaticData::GetGossipStoneLocations()) {
|
|
GetItemLocation(il)->ResetVariables();
|
|
}
|
|
for (Hint& hint : hintTable) {
|
|
hint.ResetVariables();
|
|
}
|
|
}
|
|
|
|
void Context::CreateItemOverrides() {
|
|
SPDLOG_DEBUG("NOW CREATING OVERRIDES\n\n");
|
|
for (RandomizerCheck locKey : allLocations) {
|
|
const auto loc = StaticData::GetLocation(locKey);
|
|
// If this is an ice trap, store the disguise model in iceTrapModels
|
|
const auto itemLoc = GetItemLocation(locKey);
|
|
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
|
|
ItemOverride val(locKey, RandomElement(possibleIceTrapModels));
|
|
iceTrapModels[locKey] = val.LooksLike();
|
|
val.SetTrickName(GetIceTrapName(val.LooksLike()));
|
|
// If this is ice trap is in a shop, change the name based on what the model will look like
|
|
overrides[locKey] = val;
|
|
}
|
|
SPDLOG_DEBUG(loc->GetName());
|
|
SPDLOG_DEBUG(": ");
|
|
SPDLOG_DEBUG(itemLoc->GetPlacedItemName().GetEnglish());
|
|
SPDLOG_DEBUG("\n");
|
|
}
|
|
SPDLOG_DEBUG("Overrides Created: ");
|
|
SPDLOG_DEBUG(std::to_string(overrides.size()));
|
|
}
|
|
|
|
bool Context::IsSeedGenerated() const {
|
|
return mSeedGenerated;
|
|
}
|
|
|
|
void Context::SetSeedGenerated(const bool seedGenerated) {
|
|
mSeedGenerated = seedGenerated;
|
|
}
|
|
|
|
bool Context::IsSpoilerLoaded() const {
|
|
return mSpoilerLoaded;
|
|
}
|
|
|
|
void Context::SetSpoilerLoaded(const bool spoilerLoaded) {
|
|
mSpoilerLoaded = spoilerLoaded;
|
|
}
|
|
|
|
void Context::AddReceivedArchipelagoItem(const RandomizerGet item) {
|
|
mAPreceiveQueue.emplace(item);
|
|
std::string logMessage = "[LOG] Item Pushed: " + std::to_string(item);
|
|
ArchipelagoConsole_SendMessage(logMessage.c_str(), true);
|
|
}
|
|
|
|
GetItemEntry Context::GetArchipelagoGIEntry() {
|
|
ArchipelagoConsole_SendMessage("[LOG] Trying to get Item Entry", true);
|
|
if (mAPreceiveQueue.empty()) {
|
|
// something must have gone wrong here, just give a rupee
|
|
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_HEART);
|
|
}
|
|
|
|
// get the first item from the archipelago queue
|
|
RandomizerGet item_id = mAPreceiveQueue.front();
|
|
assert(item_id != RG_NONE);
|
|
|
|
Item& item = StaticData::RetrieveItem(item_id);
|
|
SPDLOG_TRACE("Found item! {}, {}", item.GetName().GetEnglish(), (int)item_id);
|
|
GetItemEntry item_entry = item.GetGIEntry_Copy();
|
|
mAPreceiveQueue.pop();
|
|
return item_entry; // todo: add custom text maybe?
|
|
}
|
|
|
|
GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability,
|
|
const GetItemID ogItemId) {
|
|
const auto itemLoc = GetItemLocation(rc);
|
|
if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) {
|
|
if (ogItemId != GI_NONE) {
|
|
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, ogItemId);
|
|
}
|
|
return ItemTableManager::Instance->RetrieveItemEntry(
|
|
MOD_NONE, StaticData::RetrieveItem(StaticData::GetLocation(rc)->GetVanillaItem()).GetItemID());
|
|
}
|
|
if (checkObtainability && OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerGet(
|
|
itemLoc->GetPlacedRandomizerGet()) != CAN_OBTAIN) {
|
|
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_RUPEE_BLUE);
|
|
}
|
|
GetItemEntry giEntry = itemLoc->GetPlacedItem().GetGIEntry_Copy();
|
|
if (overrides.contains(rc)) {
|
|
const auto fakeGiEntry = StaticData::RetrieveItem(overrides[rc].LooksLike()).GetGIEntry();
|
|
giEntry.gid = fakeGiEntry->gid;
|
|
giEntry.gi = fakeGiEntry->gi;
|
|
giEntry.drawItemId = fakeGiEntry->drawItemId;
|
|
giEntry.drawModIndex = fakeGiEntry->drawModIndex;
|
|
giEntry.drawFunc = fakeGiEntry->drawFunc;
|
|
}
|
|
return giEntry;
|
|
}
|
|
|
|
void Context::ParseSpoiler(const char* spoilerFileName) {
|
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
|
if (!spoilerFileStream) {
|
|
return;
|
|
}
|
|
mSeedGenerated = false;
|
|
mSpoilerLoaded = false;
|
|
try {
|
|
nlohmann::json spoilerFileJson;
|
|
spoilerFileStream >> spoilerFileJson;
|
|
spoilerFileStream.close();
|
|
ParseHashIconIndexesJson(spoilerFileJson);
|
|
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
|
|
ParseItemLocationsJson(spoilerFileJson);
|
|
ParseTricksJson(spoilerFileJson);
|
|
mEntranceShuffler->ParseJson(spoilerFileJson);
|
|
ParseHintJson(spoilerFileJson);
|
|
mDungeons->ParseJson(spoilerFileJson);
|
|
mTrials->ParseJson(spoilerFileJson);
|
|
mSpoilerLoaded = true;
|
|
mSeedGenerated = false;
|
|
} catch (...) { LUSLOG_ERROR("Failed to load Spoiler File: %s", spoilerFileName); }
|
|
}
|
|
|
|
void Context::ParseArchipelago() {
|
|
mSeedGenerated = false;
|
|
mSpoilerLoaded = false;
|
|
|
|
ArchipelagoClient& ap_client = ArchipelagoClient::GetInstance();
|
|
ParseArchipelagoItemsLocations(ap_client.GetScoutedItems());
|
|
ParseArchipelagoOptions(ap_client.GetSlotData());
|
|
mEntranceShuffler->UnshuffleAllEntrances();
|
|
mDungeons->ResetAllDungeons();
|
|
mTrials->RemoveAllTrials();
|
|
|
|
mSpoilerLoaded = true;
|
|
mSeedGenerated = false;
|
|
}
|
|
|
|
void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) {
|
|
nlohmann::json hashJson = spoilerFileJson["file_hash"];
|
|
int index = 0;
|
|
for (auto it = hashJson.begin(); it != hashJson.end(); ++it) {
|
|
hashIconIndexes[index] = gSeedTextures[it.value()].id;
|
|
index++;
|
|
}
|
|
}
|
|
|
|
void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) {
|
|
// first fill all the items with their vanilla location
|
|
nlohmann::json locationsJson = spoilerFileJson["locations"];
|
|
for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) {
|
|
RandomizerCheck rc = StaticData::locationNameToEnum[it.key()];
|
|
if (it->is_structured()) {
|
|
nlohmann::json itemJson = *it;
|
|
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
|
|
if (itemit.key() == "item") {
|
|
itemLocationTable[rc].SetPlacedItem(StaticData::itemNameToEnum[itemit.value().get<std::string>()]);
|
|
} else if (itemit.key() == "price") {
|
|
itemLocationTable[rc].SetCustomPrice(itemit.value().get<uint16_t>());
|
|
} else if (itemit.key() == "model") {
|
|
overrides[rc] = ItemOverride(rc, StaticData::itemNameToEnum[itemit.value().get<std::string>()]);
|
|
} else if (itemit.key() == "trickName") {
|
|
overrides[rc].SetTrickName(Text(itemit.value().get<std::string>()));
|
|
}
|
|
}
|
|
} else {
|
|
itemLocationTable[rc].SetPlacedItem(StaticData::itemNameToEnum[it.value().get<std::string>()]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Context::ParseArchipelagoOptions(const std::map<std::string, int>& slot_data) {
|
|
// Set options to what Archipelago expects. Need to slowly convert these to options in apworld and
|
|
// load those in instead.
|
|
|
|
nlohmann::json slotData = ArchipelagoClient::GetInstance().GetSlotData();
|
|
mOptions[RSK_FOREST].Set(RO_CLOSED_FOREST_OFF);
|
|
mOptions[RSK_KAK_GATE].Set(RO_KAK_GATE_OPEN);
|
|
mOptions[RSK_DOOR_OF_TIME].Set(RO_DOOROFTIME_OPEN);
|
|
mOptions[RSK_ZORAS_FOUNTAIN].Set(RO_ZF_CLOSED);
|
|
mOptions[RSK_SLEEPING_WATERFALL].Set(RO_WATERFALL_CLOSED);
|
|
mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD);
|
|
mOptions[RSK_SELECTED_STARTING_AGE].Set(0);
|
|
mOptions[RSK_GERUDO_FORTRESS].Set(RO_GF_CARPENTERS_NORMAL);
|
|
mOptions[RSK_RAINBOW_BRIDGE].Set(RO_BRIDGE_GREG);
|
|
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Set(0);
|
|
mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Set(0);
|
|
mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Set(0);
|
|
mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Set(0);
|
|
mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Set(0);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Set(0);
|
|
mOptions[RSK_GANONS_TRIALS].Set(RO_GANONS_TRIALS_SKIP);
|
|
mOptions[RSK_TRIAL_COUNT].Set(0);
|
|
mOptions[RSK_STARTING_OCARINA].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_OCARINA].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SHUFFLE_OCARINA_BUTTONS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_SWIM].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_DEKU_SHIELD].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_KOKIRI_SWORD].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_MASTER_SWORD].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_ZELDAS_LULLABY].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_EPONAS_SONG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_SARIAS_SONG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_SUNS_SONG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_SONG_OF_TIME].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_SONG_OF_STORMS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_MINUET_OF_FOREST].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_BOLERO_OF_FIRE].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_SERENADE_OF_WATER].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_PRELUDE_OF_LIGHT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_KOKIRI_SWORD].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SHUFFLE_MASTER_SWORD].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_CHILD_WALLET].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_INCLUDE_TYCOON_WALLET].Set(RO_GENERIC_YES);
|
|
if (slotData["shuffle_dungeon_rewards"] == 0) {
|
|
mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Set(RO_DUNGEON_REWARDS_VANILLA);
|
|
} else if (slotData["shuffle_dungeon_rewards"] == 1) {
|
|
mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Set(RO_DUNGEON_REWARDS_ANYWHERE);
|
|
}
|
|
mOptions[RSK_SHUFFLE_SONGS].Set(RO_SONG_SHUFFLE_ANYWHERE);
|
|
mOptions[RSK_SHUFFLE_TOKENS].Set(slotData["shuffle_tokens"]);
|
|
mOptions[RSK_SHOPSANITY].Set(slotData["shuffle_shops"]);
|
|
mOptions[RSK_SHOPSANITY_COUNT].Set(4);
|
|
mOptions[RSK_SHOPSANITY_PRICES].Set(RO_PRICE_FIXED);
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Set(1);
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Set(0);
|
|
if (slotData["shuffle_scrubs"] == 1) {
|
|
mOptions[RSK_SHUFFLE_SCRUBS].Set(RO_SCRUBS_ALL);
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_SCRUBS].Set(RO_SCRUBS_OFF);
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES].Set(RO_PRICE_FIXED);
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Set(1);
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Set(0);
|
|
mOptions[RSK_SHUFFLE_BEEHIVES].Set(slotData["shuffle_beehives"]);
|
|
mOptions[RSK_SHUFFLE_COWS].Set(slotData["shuffle_cows"]);
|
|
mOptions[RSK_SHUFFLE_WEIRD_EGG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SHUFFLE_POTS].Set(slotData["shuffle_pots"]);
|
|
mOptions[RSK_SHUFFLE_CRATES].Set(slotData["shuffle_crates"]);
|
|
mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES].Set(slotData["shuffle_frogs"]);
|
|
mOptions[RSK_ITEM_POOL].Set(0);
|
|
mOptions[RSK_ICE_TRAPS].Set(0);
|
|
mOptions[RSK_GOSSIP_STONE_HINTS].Set(RO_GOSSIP_STONES_NONE);
|
|
mOptions[RSK_TOT_ALTAR_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_GANONDORF_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHEIK_LA_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_DAMPES_DIARY_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_GREG_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_LOACH_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SARIA_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_FROGS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_OOT_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_10_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_20_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_30_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_40_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_50_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_KAK_100_SKULLS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_MASK_SHOP_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_BIGGORON_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_BIG_POES_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_CHICKENS_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_MALON_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_HBA_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_WARP_SONG_HINTS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SCRUB_TEXT_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_MERCHANT_TEXT_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_FISHING_POLE_HINT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_HINT_CLARITY].Set(0);
|
|
mOptions[RSK_HINT_DISTRIBUTION].Set(0);
|
|
mOptions[RSK_SHUFFLE_MAPANDCOMPASS].Set(RO_DUNGEON_ITEM_LOC_ANYWHERE);
|
|
mOptions[RSK_KEYSANITY].Set(RO_DUNGEON_ITEM_LOC_ANYWHERE);
|
|
mOptions[RSK_GERUDO_KEYS].Set(RO_GERUDO_KEYS_ANYWHERE);
|
|
mOptions[RSK_BOSS_KEYSANITY].Set(RO_DUNGEON_ITEM_LOC_ANYWHERE);
|
|
if (slotData["gcbk_setting"] == 1) {
|
|
mOptions[RSK_GANONS_BOSS_KEY].Set(RO_GANON_BOSS_KEY_ANYWHERE);
|
|
} else if (slotData["gcbk_setting"] == 0) {
|
|
mOptions[RSK_GANONS_BOSS_KEY].Set(RO_GANON_BOSS_KEY_LACS_REWARDS);
|
|
}
|
|
mOptions[RSK_SKIP_CHILD_STEALTH].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SKIP_CHILD_ZELDA].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_STICKS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_STARTING_NUTS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_FULL_WALLETS].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SHUFFLE_CHEST_MINIGAME].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_BIG_POE_COUNT].Set(1);
|
|
mOptions[RSK_SKIP_EPONA_RACE].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_COMPLETE_MASK_QUEST].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SKIP_SCARECROWS_SONG].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SKULLS_SUNS_SONG].Set(0);
|
|
mOptions[RSK_SHUFFLE_ADULT_TRADE].Set(slotData["shuffle_trade_items"]);
|
|
if (slotData["shuffle_merchants"] == 1) {
|
|
mOptions[RSK_SHUFFLE_MERCHANTS].Set(RO_SHUFFLE_MERCHANTS_ALL);
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_MERCHANTS].Set(RO_SHUFFLE_MERCHANTS_OFF);
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Set(0);
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Set(0);
|
|
mOptions[RSK_BLUE_FIRE_ARROWS].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_SUNLIGHT_ARROWS].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_ENABLE_BOMBCHU_DROPS].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_BOMBCHU_BAG].Set(RO_GENERIC_YES);
|
|
mOptions[RSK_LINKS_POCKET].Set(RO_LINKS_POCKET_ANYTHING);
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(0);
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(0);
|
|
mOptions[RSK_MQ_DUNGEON_SET].Set(0);
|
|
mOptions[RSK_MQ_DEKU_TREE].Set(0);
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Set(0);
|
|
mOptions[RSK_MQ_JABU_JABU].Set(0);
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Set(0);
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Set(0);
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Set(0);
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Set(0);
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Set(0);
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Set(0);
|
|
mOptions[RSK_MQ_ICE_CAVERN].Set(0);
|
|
mOptions[RSK_MQ_GTG].Set(0);
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Set(0);
|
|
mOptions[RSK_LACS_STONE_COUNT].Set(0);
|
|
mOptions[RSK_LACS_MEDALLION_COUNT].Set(0);
|
|
mOptions[RSK_LACS_REWARD_COUNT].Set(slotData["gcbk_rewards_required"]);
|
|
mOptions[RSK_LACS_DUNGEON_COUNT].Set(0);
|
|
mOptions[RSK_LACS_TOKEN_COUNT].Set(0);
|
|
mOptions[RSK_LACS_OPTIONS].Set(0);
|
|
mOptions[RSK_KEYRINGS].Set(0);
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].Set(0);
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Set(0);
|
|
mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Set(0);
|
|
mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Set(0);
|
|
mOptions[RSK_KEYRINGS_WATER_TEMPLE].Set(0);
|
|
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Set(0);
|
|
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Set(0);
|
|
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Set(0);
|
|
mOptions[RSK_KEYRINGS_GTG].Set(0);
|
|
mOptions[RSK_KEYRINGS_GANONS_CASTLE].Set(0);
|
|
mOptions[RSK_SHUFFLE_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_OWL_DROPS].Set(0);
|
|
mOptions[RSK_SHUFFLE_WARP_SONGS].Set(0);
|
|
mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS].Set(0);
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].Set(0);
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Set(0);
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Set(0);
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Set(0);
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Set(0);
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(0);
|
|
mOptions[RSK_DECOUPLED_ENTRANCES].Set(0);
|
|
mOptions[RSK_STARTING_SKULLTULA_TOKEN].Set(0);
|
|
mOptions[RSK_STARTING_HEARTS].Set(2);
|
|
mOptions[RSK_DAMAGE_MULTIPLIER].Set(0);
|
|
mOptions[RSK_ALL_LOCATIONS_REACHABLE].Set(0);
|
|
mOptions[RSK_SHUFFLE_BOSS_ENTRANCES].Set(0);
|
|
mOptions[RSK_SHUFFLE_100_GS_REWARD].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_TRIFORCE_HUNT].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Set(0);
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Set(0);
|
|
mOptions[RSK_SHUFFLE_BOSS_SOULS].Set(RO_GENERIC_NO);
|
|
if (slotData["shuffle_fish"] == 0) {
|
|
mOptions[RSK_FISHSANITY].Set(RO_FISHSANITY_OFF);
|
|
} else if (slotData["shuffle_fish"] == 1) {
|
|
mOptions[RSK_FISHSANITY].Set(RO_FISHSANITY_POND);
|
|
} else if (slotData["shuffle_fish"] == 2) {
|
|
mOptions[RSK_FISHSANITY].Set(RO_FISHSANITY_OVERWORLD);
|
|
} else if (slotData["shuffle_fish"] == 3) {
|
|
mOptions[RSK_FISHSANITY].Set(RO_FISHSANITY_BOTH);
|
|
}
|
|
mOptions[RSK_FISHSANITY_POND_COUNT].Set(15);
|
|
mOptions[RSK_FISHSANITY_AGE_SPLIT].Set(15);
|
|
mOptions[RSK_SHUFFLE_FISHING_POLE].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_INFINITE_UPGRADES].Set(RO_INF_UPGRADES_OFF);
|
|
mOptions[RSK_SKELETON_KEY].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_DEKU_STICK_BAG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_DEKU_NUT_BAG].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_FREESTANDING].Set(slotData["shuffle_freestanding"]);
|
|
mOptions[RSK_SHUFFLE_FAIRIES].Set(slotData["shuffle_fairies"]);
|
|
mOptions[RSK_LOCK_OVERWORLD_DOORS].Set(RO_GENERIC_NO);
|
|
mOptions[RSK_SHUFFLE_GRASS].Set(slotData["shuffle_grass"]);
|
|
}
|
|
|
|
void Context::ParseArchipelagoItemsLocations(const std::vector<ArchipelagoClient::ApItem>& scouted_items) {
|
|
const std::string SlotName = ArchipelagoClient::GetInstance().GetSlotName();
|
|
|
|
// Zero out the location table first
|
|
for (int rc = 1; rc < RC_MAX; rc++) {
|
|
itemLocationTable[rc].SetPlacedItem(RG_NONE);
|
|
}
|
|
|
|
for (const ArchipelagoClient::ApItem& ap_item : scouted_items) {
|
|
// const RandomizerCheck rc = StaticData::APcheckToSoh.find(ap_item.locationName)->second;
|
|
const RandomizerCheck rc = StaticData::locationNameToEnum[ap_item.locationName];
|
|
|
|
itemLocationTable[rc].SetCustomPrice(10);
|
|
|
|
if (SlotName == ap_item.playerName) {
|
|
// our item
|
|
SPDLOG_TRACE("Populated item {} at location {}", ap_item.itemName, ap_item.locationName);
|
|
const RandomizerGet item = StaticData::itemNameToEnum[ap_item.itemName];
|
|
itemLocationTable[rc].SetPlacedItem(item);
|
|
} else {
|
|
// Other player item
|
|
// If progressive or trap bit flag is set, make item progressive.
|
|
if (ap_item.flags & (1 << 0) || ap_item.flags & (1 << 2)) {
|
|
itemLocationTable[rc].SetPlacedItem(RG_ARCHIPELAGO_ITEM_PROGRESSIVE);
|
|
// If useful bit flag is on, make item useful.
|
|
} else if (ap_item.flags & (1 << 1)) {
|
|
itemLocationTable[rc].SetPlacedItem(RG_ARCHIPELAGO_ITEM_USEFUL);
|
|
// None of these flags being present means it's junk.
|
|
} else {
|
|
itemLocationTable[rc].SetPlacedItem(RG_ARCHIPELAGO_ITEM_JUNK);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Context::WriteHintJson(nlohmann::ordered_json& spoilerFileJson) {
|
|
for (Hint hint : hintTable) {
|
|
hint.logHint(spoilerFileJson);
|
|
}
|
|
}
|
|
|
|
nlohmann::json getValueForMessage(std::unordered_map<std::string, nlohmann::json> map, CustomMessage message) {
|
|
std::vector<std::string> strings = message.GetAllMessages();
|
|
for (uint8_t language = 0; language < LANGUAGE_MAX; language++) {
|
|
if (map.contains(strings[language])) {
|
|
return strings[language];
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
|
|
for (auto hintData : spoilerFileJson["Gossip Stone Hints"].items()) {
|
|
RandomizerHint hint = (RandomizerHint)StaticData::hintNameToEnum[hintData.key()];
|
|
AddHint(hint, Hint(hint, hintData.value()));
|
|
}
|
|
for (auto hintData : spoilerFileJson["Static Hints"].items()) {
|
|
RandomizerHint hint = (RandomizerHint)StaticData::hintNameToEnum[hintData.key()];
|
|
AddHint(hint, Hint(hint, hintData.value()));
|
|
}
|
|
CreateStaticHints();
|
|
}
|
|
|
|
void Context::ParseTricksJson(nlohmann::json spoilerFileJson) {
|
|
nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"];
|
|
const auto& settings = Rando::Settings::GetInstance();
|
|
for (auto it : enabledTricksJson) {
|
|
int rt = settings->GetRandomizerTrickByName(it);
|
|
if (rt != -1) {
|
|
mTrickOptions[rt].Set(RO_GENERIC_ON);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
|
|
return mEntranceShuffler;
|
|
}
|
|
|
|
std::shared_ptr<Dungeons> Context::GetDungeons() {
|
|
return mDungeons;
|
|
}
|
|
|
|
std::shared_ptr<Fishsanity> Context::GetFishsanity() {
|
|
return mFishsanity;
|
|
}
|
|
|
|
DungeonInfo* Context::GetDungeon(size_t key) const {
|
|
return mDungeons->GetDungeon(static_cast<DungeonKey>(key));
|
|
}
|
|
|
|
std::shared_ptr<Logic> Context::GetLogic() {
|
|
if (mLogic.get() == nullptr) {
|
|
mLogic = std::make_shared<Logic>();
|
|
}
|
|
return mLogic;
|
|
}
|
|
|
|
std::shared_ptr<Trials> Context::GetTrials() {
|
|
return mTrials;
|
|
}
|
|
|
|
TrialInfo* Context::GetTrial(size_t key) const {
|
|
return mTrials->GetTrial(static_cast<TrialKey>(key));
|
|
}
|
|
|
|
TrialInfo* Context::GetTrial(TrialKey key) const {
|
|
return mTrials->GetTrial(key);
|
|
}
|
|
|
|
Sprite* Context::GetSeedTexture(const uint8_t index) {
|
|
return &gSeedTextures[index];
|
|
}
|
|
|
|
OptionValue& Context::GetOption(const RandomizerSettingKey key) {
|
|
return mOptions[key];
|
|
}
|
|
|
|
OptionValue& Context::GetTrickOption(const RandomizerTrick key) {
|
|
return mTrickOptions[key];
|
|
}
|
|
|
|
OptionValue& Context::GetLocationOption(const RandomizerCheck key) {
|
|
return itemLocationTable[key].GetExcludedOption();
|
|
}
|
|
|
|
RandoOptionLACSCondition Context::LACSCondition() const {
|
|
return mLACSCondition;
|
|
}
|
|
|
|
void Context::LACSCondition(RandoOptionLACSCondition lacsCondition) {
|
|
mLACSCondition = lacsCondition;
|
|
}
|
|
|
|
std::shared_ptr<Kaleido> Context::GetKaleido() {
|
|
if (mKaleido == nullptr) {
|
|
mKaleido = std::make_shared<Kaleido>();
|
|
}
|
|
return mKaleido;
|
|
}
|
|
|
|
std::string Context::GetHash() const {
|
|
return mHash;
|
|
}
|
|
|
|
void Context::SetHash(std::string hash) {
|
|
mHash = std::move(hash);
|
|
}
|
|
|
|
const std::string& Context::GetSeedString() const {
|
|
return mSeedString;
|
|
}
|
|
|
|
void Context::SetSeedString(std::string seedString) {
|
|
mSeedString = std::move(seedString);
|
|
}
|
|
|
|
uint32_t Context::GetSeed() const {
|
|
return mFinalSeed;
|
|
}
|
|
|
|
void Context::SetSeed(const uint32_t seed) {
|
|
mFinalSeed = seed;
|
|
}
|
|
} // namespace Rando
|