Merge branch 'develop' of https://github.com/Xeokn/Shipwright into develop

This commit is contained in:
Xeokn 2025-01-30 00:45:13 +10:00
commit 8a46f8e491
74 changed files with 1188 additions and 1056 deletions

@ -1 +1 @@
Subproject commit d60e84754a7a1226d6b3c2a515e21f8990b7a5b4
Subproject commit 5341b017254a186da3ffe6d681d4e293769f23f4

View File

@ -65,7 +65,7 @@ std::vector<AltTrapType> getEnabledAddTraps () {
};
static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps());

View File

@ -4,7 +4,7 @@
#include "assets/textures/parameter_static/parameter_static.h"
#include "assets/soh_assets.h"
#include "soh/ImGuiUtils.h"
#include "soh/SohGui/ImGuiUtils.h"
extern "C" {
#include "macros.h"

View File

@ -10,7 +10,7 @@ extern "C" {
#include "variables.h"
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
static bool sEnteredBlueWarp = false;

View File

@ -11,7 +11,7 @@
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include <utils/StringHelper.h>
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "AudioCollection.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"

View File

@ -9,7 +9,7 @@
#include <spdlog/spdlog.h>
#include <cmath>
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
// Text colors
static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);

View File

@ -1,7 +1,7 @@
#include "SohInputEditorWindow.h"
#include <utils/StringHelper.h>
#include "soh/OTRGlobals.h"
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "z64.h"
#include "soh/cvar_prefixes.h"
#ifndef __WIIU__

View File

@ -10,7 +10,7 @@
#include <algorithm>
#include <libultraship/libultraship.h>
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/OTRGlobals.h"
#include "soh/ResourceManagerHelpers.h"

View File

@ -185,7 +185,7 @@ void OnZTitleUpdatePressButtonToSkip(void* gameState) {
if (CHECK_BTN_ANY(titleContext->state.input->press.button, BTN_A | BTN_B | BTN_START)) {
// Force the title state to start fading to black and to last roughly 5 frames based on current fade in/out
titleContext->visibleDuration = 0;
titleContext->addAlpha = (255 - titleContext->coverAlpha) / 5;
titleContext->addAlpha = std::max<int16_t>((255 - titleContext->coverAlpha) / 5, 1);
}
}

View File

@ -1,6 +1,6 @@
#include "MessageViewer.h"
#include <soh/UIWidgets.hpp>
#include <soh/SohGui/UIWidgets.hpp>
#include <textures/message_static/message_static.h>
#include "../custom-message/CustomMessageManager.h"

View File

@ -1,6 +1,6 @@
#include "actorViewer.h"
#include "../../util.h"
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/ActorDB.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/nametag.h"

View File

@ -1,6 +1,6 @@
#include "colViewer.h"
#include "../../frame_interpolation.h"
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <vector>
#include <string>

View File

@ -1,8 +1,8 @@
#include "debugSaveEditor.h"
#include "../../util.h"
#include "../../ImGuiUtils.h"
#include "../../OTRGlobals.h"
#include "../../UIWidgets.hpp"
#include "soh/util.h"
#include "soh/SohGui/ImGuiUtils.h"
#include "soh/OTRGlobals.h"
#include "soh/SohGui/UIWidgets.hpp"
#include <spdlog/fmt/fmt.h>
#include <array>

View File

@ -1,9 +1,9 @@
#include "actorViewer.h"
#include "../../util.h"
#include "../../UIWidgets.hpp"
#include "soh/util.h"
#include "soh/SohGui/UIWidgets.hpp"
#include "ResourceManager.h"
#include "DisplayList.h"
#include "../../OTRGlobals.h"
#include "soh/OTRGlobals.h"
#include <array>
#include <bit>

View File

@ -1,6 +1,6 @@
#include "hookDebugger.h"
#include "../game-interactor/GameInteractor.h"
#include "../../UIWidgets.hpp"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/SohGui/UIWidgets.hpp"
#include <string>
#include <version>

View File

@ -1,5 +1,5 @@
#include "valueViewer.h"
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/OTRGlobals.h"
extern "C" {

View File

@ -305,7 +305,7 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies();
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber];

View File

@ -5,7 +5,7 @@
#include "functions.h"
#include "macros.h"
#include "soh/cvar_prefixes.h"
#include "../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/util.h"
#include <vector>

View File

@ -125,8 +125,8 @@ namespace Rando {
std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0,
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {

View File

@ -535,7 +535,7 @@ void UpdateMirrorModeState(int32_t sceneNum) {
(sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed()
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}

View File

@ -3,7 +3,7 @@
#include <string>
#include <cstdint>
#include <libultraship/bridge.h>
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <libultraship/libultraship.h>
void clearCvars(std::vector<const char*> cvarsToClear) {
@ -75,7 +75,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
if (presetTypeId == PRESET_TYPE_RANDOMIZER){
Rando::Context::GetInstance()->GetSettings()->ReloadOptions();
Rando::Settings::GetInstance()->ReloadOptions();
}
}
ImGui::PopStyleVar(1);

View File

@ -238,10 +238,10 @@ static int GetMaxGSCount() {
int maxBridge = 0;
int maxLACS = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex();
maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get();
}
maxBridge = std::max(maxBridge, maxLACS);
//Get the max amount of GS which could be useful from token reward locations
@ -266,7 +266,7 @@ static int GetMaxGSCount() {
maxUseful = 10;
}
//Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory
return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex();
return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get();
}
std::string GetShopItemBaseName(std::string itemName) {

View File

@ -222,18 +222,18 @@ uint8_t StonesRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t stones = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex();
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 6;
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 6;
} else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 6;
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 6;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex() });
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 6 )});
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 6 )});
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6 )});
}
return stones;
}
@ -242,18 +242,18 @@ uint8_t MedallionsRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t medallions = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex();
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 3;
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 3;
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 3;
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex() });
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 3 )});
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 3 )});
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3 )});
}
return medallions;
}
@ -262,10 +262,10 @@ uint8_t TokensRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t tokens = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex() });
tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get() });
}
return tokens;
}
@ -273,7 +273,7 @@ uint8_t TokensRequiredBySettings() {
std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlwaysHints = {
std::make_pair(RC_MARKET_10_BIG_POES, []() {
auto ctx = Rando::Context::GetInstance();
return ctx->GetOption(RSK_BIG_POE_COUNT).GetContextOptionIndex() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
}), // Remember, the option's value being 3 means 4 are required
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() {
auto ctx = Rando::Context::GetInstance();
@ -483,7 +483,7 @@ static void CreateTrialHints(uint8_t copies) {
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_ZERO_TRIALS});
} else {
std::vector<TrialInfo*> trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment
if (ctx->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() >= 4) {//4 or 5 required trials, get skipped trials
if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) {//4 or 5 required trials, get skipped trials
trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();});
} else {//1 to 3 trials, get requried trials
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();});
@ -611,7 +611,7 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistribu
void CreateStoneHints() {
auto ctx = Rando::Context::GetInstance();
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).GetContextOptionIndex()];
const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Get()];
std::vector<HintDistributionSetting> distTable = hintSetting.distTable;
// Apply impa's song exclusions when zelda is skipped
@ -738,7 +738,7 @@ void CreateAdultAltarHint() {
void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(hint)->IsEnabled()){
Option option = ctx->GetOption(staticData.setting);
OptionValue& option = ctx->GetOption(staticData.setting);
if ((std::holds_alternative<bool>(staticData.condition) && option.Is(std::get<bool>(staticData.condition))) ||
(std::holds_alternative<uint8_t>(staticData.condition) && option.Is(std::get<uint8_t>(staticData.condition)))){

View File

@ -761,7 +761,7 @@ static void SetMinimalItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1);
ReplaceMaxItem(RG_PIECE_OF_HEART, 0);
// Need an extra heart container when starting with 1 heart to be able to reach 3 hearts
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() == 18)? 1 : 0);
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Get() == 18)? 1 : 0);
}
void GenerateItemPool() {
@ -827,7 +827,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE);
AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition
ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true);
} else {
@ -935,7 +935,7 @@ void GenerateItemPool() {
if (fsMode.IsNot(RO_FISHSANITY_OFF)) {
if (fsMode.Is(RO_FISHSANITY_POND) || fsMode.Is(RO_FISHSANITY_BOTH)) {
// 17 max child pond fish
uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetContextOptionIndex();
uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).Get();
for (uint8_t i = 0; i < pondCt; i++) {
AddItemToMainPool(GetJunkItem());
}
@ -1518,7 +1518,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).GetContextOptionIndex() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY);

View File

@ -44,12 +44,12 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
return false; // TODO: Not sure if this is correct but I don't think we support this functionality yet anyway.
}
ctx->GetSettings()->SetSeedString(seedInput);
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
ctx->GetSettings()->SetSeed(seedHash & 0xFFFFFFFF);
ctx->SetSeedString(seedInput);
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(seedHash & 0xFFFFFFFF);
ctx->ClearItemLocations();
int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
int ret = Playthrough::Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
if (ret < 0) {
if (ret == -1) { // Failed to generate after 5 tries
SPDLOG_ERROR("Failed to generate after 5 tries.");
@ -60,14 +60,6 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
}
}
// Restore settings that were set to a specific value for vanilla logic
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
for (Rando::Option* setting : ctx->GetSettings()->VanillaLogicDefaults) {
setting->RestoreDelayedOption();
}
ctx->GetOption(RSK_KEYSANITY).RestoreDelayedOption();
}
StopPerformanceTimer(PT_WHOLE_SEED);
SPDLOG_DEBUG("Full Seed Genration Time: {}ms", GetPerformanceTimer(PT_WHOLE_SEED).count());
SPDLOG_DEBUG("LogicReset time: {}ms", GetPerformanceTimer(PT_LOGIC_RESET).count());

View File

@ -31,10 +31,12 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
Regions::AccessReset();
StopPerformanceTimer(PT_REGION_RESET);
ctx->GetSettings()->FinalizeSettings(excludedLocations, enabledTricks);
ctx->FinalizeSettings(excludedLocations, enabledTricks);
// once the settings have been finalized turn them into a string for hashing
std::string settingsStr;
for (const Rando::OptionGroup& optionGroup : ctx->GetSettings()->GetOptionGroups()) {
auto& optionGroups = Rando::Settings::GetInstance()->GetOptionGroups();
for (size_t i = 0; i < RSG_MAX; i++) {
auto& optionGroup = optionGroups[i];
// don't go through non-menus
if (optionGroup.GetContainsType() == Rando::OptionGroupType::SUBGROUP) {
continue;
@ -43,7 +45,15 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
for (Rando::Option* option : optionGroup.GetOptions()) {
if (option->IsCategory(Rando::OptionCategory::Setting)) {
if (option->GetOptionCount() > 0) {
settingsStr += option->GetSelectedOptionText();
if (i >= RSG_EXCLUDES_KOKIRI_FOREST && i <= RSG_EXCLUDES_GANONS_CASTLE) {
auto locationOption = static_cast<Rando::LocationOption*>(option);
settingsStr += option->GetOptionText(ctx->GetLocationOption(locationOption->GetKey()).Get());
} else if (i == RSG_TRICKS) {
auto trickOption = static_cast<Rando::TrickOption*>(option);
settingsStr += option->GetOptionText(ctx->GetTrickOption(trickOption->GetKey()).Get());
} else {
settingsStr += option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
}
}
}
}
@ -53,9 +63,9 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
settingsStr += (char*)gBuildVersion;
}
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSettings()->GetSeed()) + settingsStr);
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSeed()) + settingsStr);
Random_Init(finalHash);
ctx->GetSettings()->SetHash(std::to_string(finalHash));
ctx->SetHash(std::to_string(finalHash));
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
@ -94,12 +104,12 @@ int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<Ran
auto ctx = Rando::Context::GetInstance();
uint32_t repeatedSeed = 0;
for (int i = 0; i < count; i++) {
ctx->GetSettings()->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
ctx->GetSettings()->SetSeed(repeatedSeed % 0xFFFFFFFF);
ctx->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(repeatedSeed % 0xFFFFFFFF);
SPDLOG_DEBUG("testing seed: %d", repeatedSeed);
ClearProgress();
Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
SPDLOG_INFO("Seeds Generated: {}", i + 1);
}

View File

@ -156,7 +156,7 @@ int GetPriceFromMax(int max) {
uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSettings) {
auto ctx = Rando::Context::GetInstance();
switch (ctx->GetOption(priceSettings.main).GetContextOptionIndex()){
switch (ctx->GetOption(priceSettings.main).Get()){
case RO_PRICE_VANILLA:
return loc->GetVanillaPrice();
case RO_PRICE_CHEAP_BALANCED:
@ -172,19 +172,19 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet
return 150;
}
case RO_PRICE_FIXED:
return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).GetContextOptionIndex() * 5;
return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
case RO_PRICE_RANGE:{
uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).GetContextOptionIndex() * 5;
uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).GetContextOptionIndex() * 5;
uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).Get() * 5;
uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).Get() * 5;
return range1 < range2 ? Random(range1, range2+1) : Random(range2, range1+1);
}
case RO_PRICE_SET_BY_WALLET:{
bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).GetContextOptionIndex();
uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).GetContextOptionIndex();
uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).GetContextOptionIndex();
uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).GetContextOptionIndex();
uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).GetContextOptionIndex();
uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).GetContextOptionIndex() : 0;
bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).Get();
uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).Get();
uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).Get();
uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).Get();
uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).Get();
uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).Get() : 0;
uint16_t totalWeight = noWeight + childWeight + adultWeight + giantWeight + tycoonWeight;
if (totalWeight == 0){ //if no weight, return from sane range
return Random(0, 501);

View File

@ -2,7 +2,7 @@
#include "../dungeon.h"
#include "../static_data.h"
#include "../context.h"
#include "../settings.h"
#include "../entrance.h"
#include "random.hpp"
#include "../trial.h"
@ -46,7 +46,7 @@ std::string placementtxt;
void GenerateHash() {
auto ctx = Rando::Context::GetInstance();
std::string hash = ctx->GetSettings()->GetHash();
std::string hash = ctx->GetHash();
// adds leading 0s to the hash string if it has less than 10 digits.
while (hash.length() < 10) {
hash = "0" + hash;
@ -139,10 +139,10 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
// Writes the settings (without excluded locations, starting inventory and tricks) to the spoilerLog document.
static void WriteSettings() {
auto ctx = Rando::Context::GetInstance();
std::array<Rando::Option, RSK_MAX> options = ctx->GetSettings()->GetAllOptions();
std::array<Rando::Option, RSK_MAX> options = Rando::Settings::GetInstance()->GetAllOptions();
for (const Rando::Option& option : options) {
if (option.GetName() != ""){
jsonData["settings"][option.GetName()] = option.GetSelectedOptionText();
jsonData["settings"][option.GetName()] = option.GetOptionText(ctx->GetOption(option.GetKey()).Get());
}
}
}
@ -157,9 +157,9 @@ std::string RemoveLineBreaks(std::string s) {
static void WriteExcludedLocations() {
auto ctx = Rando::Context::GetInstance();
for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) {
for (const auto& location : ctx->GetSettings()->GetExcludeLocationsOptions()[i]) {
if (location->GetContextOptionIndex() == RO_LOCATION_INCLUDE) {
for (size_t i = 1; i < Rando::Settings::GetInstance()->GetExcludeLocationsOptions().size(); i++) {
for (const auto& location : Rando::Settings::GetInstance()->GetExcludeLocationsOptions()[i]) {
if (ctx->GetOption(location->GetKey()).Get() == RO_LOCATION_INCLUDE) {
continue;
}
@ -172,11 +172,11 @@ static void WriteExcludedLocations() {
// Writes the starting inventory to the spoiler log, if there is any.
static void WriteStartingInventory() {
auto ctx = Rando::Context::GetInstance();
const Rando::OptionGroup& optionGroup = ctx->GetSettings()->GetOptionGroup(RSG_STARTING_INVENTORY);
const Rando::OptionGroup& optionGroup = Rando::Settings::GetInstance()->GetOptionGroup(RSG_STARTING_INVENTORY);
for (const Rando::OptionGroup* subGroup : optionGroup.GetSubGroups()) {
if (subGroup->GetContainsType() == Rando::OptionGroupType::DEFAULT) {
for (Rando::Option* option : subGroup->GetOptions()) {
jsonData["settings"][option->GetName()] = option->GetSelectedOptionText();
jsonData["settings"][option->GetName()] = option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
}
}
}
@ -186,8 +186,8 @@ static void WriteStartingInventory() {
static void WriteEnabledTricks() {
auto ctx = Rando::Context::GetInstance();
for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
if (setting->GetContextOptionIndex() != RO_GENERIC_ON) {
for (const auto& setting : Rando::Settings::GetInstance()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
if (ctx->GetOption(setting->GetKey()).IsNot(RO_GENERIC_ON)) {
continue;
}
jsonData["enabledTricks"].push_back(RemoveLineBreaks(setting->GetName()).c_str());
@ -322,8 +322,8 @@ const char* SpoilerLog_Write() {
jsonData["version"] = (char*) gBuildVersion;
jsonData["git_branch"] = (char*) gGitBranch;
jsonData["git_commit"] = (char*) gGitCommitHash;
jsonData["seed"] = ctx->GetSettings()->GetSeedString();
jsonData["finalSeed"] = ctx->GetSettings()->GetSeed();
jsonData["seed"] = ctx->GetSeedString();
jsonData["finalSeed"] = ctx->GetSeed();
// Write Hash
int index = 0;

View File

@ -112,7 +112,7 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
// }
// AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).GetContextOptionIndex());
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Get());
AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0);
AddItemToInventory(RG_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG) ? 1 : 0);
AddItemToInventory(RG_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG) ? 1 : 0);
@ -153,21 +153,21 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
// AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
// AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get());
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() - 2;
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() - 2;
AdditionalHeartContainers = 0;
if (hearts < 0) {
AddItemToInventory(RG_PIECE_OF_HEART, 4);
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
if (ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 0 || ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 3) {
if (ctx->GetOption(RSK_ITEM_POOL).Get() == 0 || ctx->GetOption(RSK_ITEM_POOL).Get() == 3) {
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
AdditionalHeartContainers = 1 - hearts;
} else if (hearts > 0) {
// 16 containers in plentiful, 8 in balanced and 0 in the others
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex());
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Get());
if (hearts <= maxContainers) {
AddItemToInventory(RG_HEART_CONTAINER, hearts);

View File

@ -9,7 +9,7 @@ extern PlayState* gPlayState;
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
using SceneDoorParamsPair = std::pair<int, int>;
std::map<SceneDoorParamsPair, RandomizerInf> lookupTable = {

View File

@ -1,5 +1,5 @@
#include "Plandomizer.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/util.h"
#include <vector>
#include "soh/Notification/Notification.h"
@ -10,7 +10,7 @@
#include <filesystem>
#include "soh/OTRGlobals.h"
#include "soh/ImGuiUtils.h"
#include "soh/SohGui/ImGuiUtils.h"
#include "soh/Enhancements/randomizer/logic.h"
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
#include "soh/Enhancements/randomizer/rando_hash.h"

View File

@ -23,7 +23,7 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
Rando::Location* loc = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
uint8_t isDungeon = loc->IsDungeon();
uint8_t freestandingSetting =
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).GetContextOptionIndex();
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();

View File

@ -28,7 +28,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
// Don't pull randomized item if pot isn't randomized or is already checked
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
@ -87,7 +87,7 @@ void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
if (id == VB_LOCK_BOSS_DOOR) {
DoorShutter* doorActor = va_arg(args, DoorShutter*);
uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
*should = false;

View File

@ -28,8 +28,31 @@ Context::Context() {
mDungeons = std::make_shared<Dungeons>();
mLogic = std::make_shared<Logic>();
mTrials = std::make_shared<Trials>();
mSettings = std::make_shared<Settings>();
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_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) {
@ -94,7 +117,7 @@ void Context::PlaceItemInLocation(const RandomizerCheck locKey, const Randomizer
const auto loc = GetItemLocation(locKey);
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish() + " placed at " + StaticData::GetLocation(locKey)->GetName() + "\n");
if (applyEffectImmediately || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS) || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) {
StaticData::RetrieveItem(item).ApplyEffect();
}
@ -130,17 +153,17 @@ bool Context::IsQuestOfLocationActive(RandomizerCheck rc) {
void Context::GenerateLocationPool() {
allLocations.clear();
if (mSettings->GetOption(RSK_TRIFORCE_HUNT)) {
if (mOptions[RSK_TRIFORCE_HUNT]) {
AddLocation(RC_TRIFORCE_COMPLETED);
}
AddLocations(StaticData::GetOverworldLocations());
if (mSettings->GetOption(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) {
if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_OFF)) {
AddLocations(mFishsanity->GetFishsanityLocations().first);
}
if (mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD) ||
mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
if (mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD) ||
mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_ALL)) {
AddLocations(StaticData::GetOverworldPotLocations());
}
@ -153,7 +176,17 @@ void Context::AddExcludedOptions() {
AddLocations(dungeon->GetEveryLocation(), &everyPossibleLocation);
}
for (const RandomizerCheck rc : everyPossibleLocation) {
GetItemLocation(rc)->AddExcludeOption();
bool alreadyAdded = false;
Location* loc = StaticData::GetLocation(rc);
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());
}
}
}
@ -289,7 +322,7 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
nlohmann::json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
ParseHashIconIndexesJson(spoilerFileJson);
mSettings->ParseJson(spoilerFileJson);
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
ParseItemLocationsJson(spoilerFileJson);
ParseHintJson(spoilerFileJson);
mEntranceShuffler->ParseJson(spoilerFileJson);
@ -362,10 +395,6 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
CreateStaticHints();
}
std::shared_ptr<Settings> Context::GetSettings() {
return mSettings;
}
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
return mEntranceShuffler;
}
@ -405,12 +434,28 @@ Sprite* Context::GetSeedTexture(const uint8_t index) {
return &gSeedTextures[index];
}
Option& Context::GetOption(const RandomizerSettingKey key) const {
return mSettings->GetOption(key);
OptionValue& Context::GetOption(const RandomizerSettingKey key) {
return mOptions[key];
}
TrickOption& Context::GetTrickOption(const RandomizerTrick key) const {
return mSettings->GetTrickOption(key);
OptionValue& Context::GetOption(const RandomizerTrick key) {
return mTrickOptions[key];
}
OptionValue& Context::GetOption(const RandomizerCheck key) {
return itemLocationTable[key].GetExcludedOption();
}
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;
}
std::shared_ptr<Kaleido> Context::GetKaleido() {
@ -419,4 +464,28 @@ std::shared_ptr<Kaleido> Context::GetKaleido() {
}
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

View File

@ -25,7 +25,6 @@
namespace Rando {
class EntranceShuffler;
class Logic;
class Settings;
class Dungeons;
class DungeonInfo;
class TrialInfo;
@ -63,7 +62,24 @@ class Context {
void SetSeedGenerated(bool seedGenerated = true);
bool IsSpoilerLoaded() const;
void SetSpoilerLoaded(bool spoilerLoaded = true);
std::shared_ptr<Settings> GetSettings();
/**
* @brief Reset all RandomizerTrick keys.
*/
void ResetTrickOptions();
/**
* @brief Runs before seed generation to ensure all options are compatible with each
* other and resolve options that have been set to random (such as random trial count,
* or starting age).
*
* @param excludedLocations Set of locations that should be forced to have junk items.
* @param enabledTricks Set of tricks that should be considered logically possible. Tricks
* are things that are possible to do in gameplay but are difficult, not intuitive or that
* require more extensive game knowledge, i.e. opening invisible chests without the Lens of Truth.
*/
void FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations,
const std::set<RandomizerTrick>& enabledTricks);
std::shared_ptr<EntranceShuffler> GetEntranceShuffler();
std::shared_ptr<Dungeons> GetDungeons();
std::shared_ptr<Fishsanity> GetFishsanity();
@ -74,8 +90,19 @@ class Context {
TrialInfo* GetTrial(size_t key) const;
TrialInfo* GetTrial(TrialKey key) const;
static Sprite* GetSeedTexture(uint8_t index);
Option& GetOption(RandomizerSettingKey key) const;
TrickOption& GetTrickOption(RandomizerTrick key) const;
OptionValue& GetOption(RandomizerSettingKey key);
OptionValue& GetOption(RandomizerTrick key);
OptionValue& GetOption(RandomizerCheck key);
OptionValue& GetTrickOption(RandomizerTrick key);
OptionValue& GetLocationOption(RandomizerCheck key);
/**
* @brief Gets the resolved Light Arrow CutScene check condition.
* There is no direct option for this, it is inferred based on the value of a few other options.
*
* @return RandoOptionLACSCondition
*/
RandoOptionLACSCondition LACSCondition() const;
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
void ParseSpoiler(const char* spoilerFileName);
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
@ -87,16 +114,61 @@ class Context {
std::vector<RandomizerCheck> everyPossibleLocation = {};
std::vector<RandomizerGet> possibleIceTrapModels = {};
std::unordered_map<RandomizerCheck, RandomizerGet> iceTrapModels = {};
std::vector<OptionValue*> VanillaLogicDefaults = {};
std::array<uint8_t, 5> hashIconIndexes = {};
bool playthroughBeatable = false;
bool allLocationsReachable = false;
RandomizerArea GetAreaFromString(std::string str);
/**
* @brief Get the hash for the current seed.
*
* @return std::string
*/
std::string GetHash() const;
/**
* @brief Get the Seed String
*
* @return const std::string&
*/
const std::string& GetSeedString() const;
/**
* @brief Set the Seed String
*
* @param seedString
*/
void SetSeedString(std::string seedString);
/**
* @brief Get the Seed
*
* @return const uint32_t
*/
uint32_t GetSeed() const;
/**
* @brief Set the Seed
*
* @param seed
*/
void SetSeed(uint32_t seed);
/**
* @brief Set the Seed Hash for the current seed.
*
* @param hash
*/
void SetHash(std::string hash);
private:
static std::weak_ptr<Context> mContext;
std::array<Hint, RH_MAX> hintTable = {};
std::array<ItemLocation, RC_MAX> itemLocationTable = {};
std::shared_ptr<Settings> mSettings;
std::array<OptionValue, RSK_MAX> mOptions;
std::array<OptionValue, RT_MAX> mTrickOptions;
RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA;
std::shared_ptr<EntranceShuffler> mEntranceShuffler;
std::shared_ptr<Dungeons> mDungeons;
std::shared_ptr<Logic> mLogic;
@ -105,5 +177,8 @@ class Context {
std::shared_ptr<Kaleido> mKaleido;
bool mSeedGenerated = false;
bool mSpoilerLoaded = false;
std::string mHash;
std::string mSeedString;
uint32_t mFinalSeed = 0;
};
} // namespace Rando

View File

@ -148,8 +148,8 @@ void DungeonInfo::PlaceVanillaSmallKeys() const {
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
std::vector<RandomizerCheck> DungeonInfo::GetDungeonLocations() const {
auto locations = masterQuest ? mqLocations : vanillaLocations;
if (Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
if (Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
auto potLocations = masterQuest ? mqPots : vanillaPots;
AddElementsToPool(locations, potLocations);
}

View File

@ -1318,12 +1318,12 @@ int EntranceShuffler::ShuffleAllEntrances() {
(ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) +
(ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0);
if (totalMixedPools < 2) {
ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).Set(RO_GENERIC_OFF);
}
if (ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS)) {
std::set<EntranceType> poolsToMix = {};

View File

@ -17,7 +17,7 @@ extern PlayState* gPlayState;
#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
/**
* @brief Parallel list of pond fish checks for both ages

View File

@ -559,23 +559,23 @@ CustomMessage Hint::GetBridgeReqsText() {
}
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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();
@ -613,23 +613,23 @@ CustomMessage Hint::GetGanonBossKeyText() {
}
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
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).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();

View File

@ -12,7 +12,7 @@
#include "soh/Enhancements/randomizer/ShuffleFreestanding.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ImGuiUtils.h"
#include "soh/SohGui/ImGuiUtils.h"
#include "soh/Notification/Notification.h"
#include "soh/SaveManager.h"
#include "soh/Enhancements/randomizer/ShuffleFairies.h"
@ -69,7 +69,7 @@ extern void EnMk_Wait(EnMk* enMk, PlayState* play);
extern void func_80ABA778(EnNiwLady* enNiwLady, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
bool LocMatchesQuest(Rando::Location loc) {
if (loc.GetQuest() == RCQUEST_BOTH) {
@ -647,7 +647,7 @@ void RandomizerOnDialogMessageHandler() {
MessageContext *msgCtx = &gPlayState->msgCtx;
Actor *actor = msgCtx->talkActor;
auto ctx = Rando::Context::GetInstance();
bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF;
bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).Get() != RO_GENERIC_OFF;
bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) ||
ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL);
@ -716,7 +716,7 @@ void RandomizerOnDialogMessageHandler() {
}
break;
case TEXT_SCRUB_RANDOM:
if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF) {
if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).Get() != RO_GENERIC_OFF) {
EnDns* enDns = (EnDns*)actor;
reveal = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf);
}

View File

@ -383,7 +383,7 @@ bool Item::IsBottleItem() const {
bool Item::IsMajorItem() const {
const auto ctx = Context::GetInstance();
if (type == ITEMTYPE_TOKEN) {
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS;
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->LACSCondition() == RO_LACS_TOKENS;
}
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||

View File

@ -178,34 +178,15 @@ void ItemLocation::SetHidden(const bool hidden_) {
}
bool ItemLocation::IsExcluded() {
return excludedOption.GetContextOptionIndex();
return excludedOption.Is(RO_LOCATION_EXCLUDE);
}
Option* ItemLocation::GetExcludedOption() {
return &excludedOption;
OptionValue& ItemLocation::GetExcludedOption() {
return excludedOption;
}
void ItemLocation::AddExcludeOption() {
if (const std::string name = StaticData::GetLocation(rc)->GetName(); name.length() < 23) {
excludedOption = Option::Bool(name, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
} else {
const size_t lastSpace = name.rfind(' ', 23);
std::string settingText = name;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = Option::Bool(settingText, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
}
// RANDOTODO: this without string compares and loops
bool alreadyAdded = false;
const Location* loc = StaticData::GetLocation(rc);
for (Option* location : Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea())) {
if (location->GetName() == excludedOption.GetName()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea()).push_back(&excludedOption);
}
void ItemLocation::SetExcludedOption(uint8_t val) {
excludedOption.Set(val);
}
bool ItemLocation::IsVisible() const {

View File

@ -3,7 +3,7 @@
#include "randomizerTypes.h"
#include "3drando/text.hpp"
#include "static_data.h"
#include "settings.h"
#include "option.h"
namespace Rando {
class ItemLocation {
@ -46,8 +46,8 @@ class ItemLocation {
void AddHintedBy(RandomizerHint hintKey);
bool IsHidden() const;
bool IsExcluded();
void AddExcludeOption();
Option* GetExcludedOption();
OptionValue& GetExcludedOption();
void SetExcludedOption(uint8_t val);
void SetHidden(bool hidden_);
bool IsVisible() const;
void SetVisible(bool visibleInImGui_);
@ -65,7 +65,7 @@ class ItemLocation {
bool addedToPool = false;
RandomizerGet placedItem = RG_NONE;
RandomizerGet delayedItem = RG_NONE;
Option excludedOption = Option::Bool(StaticData::GetLocation(rc)->GetName(), {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
OptionValue excludedOption = OptionValue(RO_LOCATION_INCLUDE);
uint16_t price = 0;
RandomizerRegion parentRegion = RR_NONE;
std::set<RandomizerArea> areas = {};

View File

@ -2,6 +2,7 @@
#include "static_data.h"
#include <algorithm>
#include <assert.h>
#include "option.h"
RandomizerCheck Rando::Location::GetRandomizerCheck() const {
return rc;
@ -86,6 +87,10 @@ int16_t Rando::Location::GetVanillaPrice() const {
return vanillaPrice;
}
Rando::Option* Rando::Location::GetExcludedOption() {
return &excludedOption;
}
RandomizerCheckArea GetAreaFromScene(uint8_t scene) {
switch (scene) {
case SCENE_LINKS_HOUSE:

View File

@ -10,6 +10,7 @@
#include "z64actor_enum.h"
#include "z64scene.h"
#include "../../util.h"
#include "option.h"
namespace Rando {
class SpoilerCollectionCheck {
@ -59,7 +60,17 @@ class Location {
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_),
scene(scene_), actorParams(actorParams_), shortName(std::move(shortName_)),
spoilerName(std::move(spoilerName_)), hintKey(hintKey_), vanillaItem(vanillaItem_),
isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
if (spoilerName.length() < 23) {
excludedOption = LocationOption(rc, spoilerName);
} else {
const size_t lastSpace = spoilerName.rfind(' ', 23);
std::string settingText = spoilerName;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = LocationOption(rc, spoilerName);
}
}
Location(const RandomizerCheck rc_, const RandomizerCheckQuest quest_, const RandomizerCheckType checkType_, const RandomizerCheckArea area_, const ActorID actorId_,
const SceneID scene_, const int32_t actorParams_, std::string shortName_, const RandomizerHintTextKey hintKey_, const RandomizerGet vanillaItem_,
@ -67,7 +78,17 @@ class Location {
const int vanillaPrice_ = 0)
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_), scene(scene_), actorParams(actorParams_), shortName(shortName_),
spoilerName(SpoilerNameFromShortName(shortName_, area_)), hintKey(hintKey_), vanillaItem(vanillaItem_), isVanillaCompletion(isVanillaCompletion_),
collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
if (spoilerName.length() < 23) {
excludedOption = LocationOption(rc, spoilerName);
} else {
const size_t lastSpace = spoilerName.rfind(' ', 23);
std::string settingText = spoilerName;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = LocationOption(rc, spoilerName);
}
}
static std::string SpoilerNameFromShortName(std::string shortName, RandomizerCheckArea area) {
if (area < 0 || area >= RCAREA_INVALID) {
@ -96,10 +117,13 @@ class Location {
const HintText& GetHint() const;
RandomizerGet GetVanillaItem() const;
int16_t GetVanillaPrice() const;
Option* GetExcludedOption();
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
std::string&& shortName_, std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
ActorID actorId_, SceneID scene_, int32_t actorParams_, std::string&& shortName_,
std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
@ -205,5 +229,6 @@ class Location {
SpoilerCollectionCheck collectionCheck;
int16_t vanillaPrice;
bool isHintable = false;
Option excludedOption;
};
} // namespace Rando

View File

@ -267,7 +267,7 @@ void RegionTable_Init() {
}, {
//Locations
LOCATION(RC_LINKS_POCKET, true),
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1;),
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1;),
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
}, {
//Exits
@ -409,7 +409,7 @@ void ReplaceAllInString(std::string& s, std::string const& toReplace, std::strin
std::string CleanCheckConditionString(std::string condition) {
ReplaceAllInString(condition, "logic->", "");
ReplaceAllInString(condition, "ctx->", "");
ReplaceAllInString(condition, ".GetContextOptionIndex()", "");
ReplaceAllInString(condition, ".Get()", "");
ReplaceAllInString(condition, "GetSaveContext()->", "");
return condition;
}

View File

@ -40,7 +40,7 @@ void RegionTable_Init_Kakariko() {
Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_BAZAAR_KEY);}),
Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}),
Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->DrainWell || logic->CanUse(RG_IRON_BOOTS);}),
Entrance(RR_KAK_POTION_SHOP_FRONT, []{return logic->AtDay || logic->IsChild && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
Entrance(RR_KAK_POTION_SHOP_FRONT, []{return (logic->AtDay || logic->IsChild) && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}),
Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}),
Entrance(RR_KAK_WATCHTOWER, []{return logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer());}),

View File

@ -1075,7 +1075,7 @@ namespace Rando {
10 for OHKO.
This is the number of shifts to apply, not a real multiplier
*/
uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() : 10;
uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() : 10;
//(Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) is quarter hearts after DD
//>> Multiplier halves on normal and does nothing on half, meaning we're working with half hearts on normal damage
return ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) >> Multiplier) +
@ -1205,21 +1205,21 @@ namespace Rando {
bool Logic::CanBuildRainbowBridge(){
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION) && CanUse(RG_LIGHT_ARROWS)) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && HasItem(RG_GREG_RUPEE));
}
bool Logic::CanTriggerLACS(){
return (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex());
return (ctx->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
(ctx->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) {
@ -1431,6 +1431,18 @@ namespace Rando {
{ RG_GERUDO_MEMBERSHIP_CARD, QUEST_GERUDO_CARD },
};
std::map<uint32_t, uint32_t> BottleRandomizerGetToItemID = {
{ RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED },
{ RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN },
{ RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE },
{ RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY },
{ RG_BOTTLE_WITH_FISH, ITEM_FISH },
{ RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE },
{ RG_BOTTLE_WITH_BUGS, ITEM_BUG },
{ RG_BOTTLE_WITH_POE, ITEM_POE },
{ RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE },
};
uint32_t HookshotLookup[3] = { ITEM_NONE, ITEM_HOOKSHOT, ITEM_LONGSHOT };
uint32_t OcarinaLookup[3] = { ITEM_NONE, ITEM_OCARINA_FAIRY, ITEM_OCARINA_TIME };
@ -1675,7 +1687,11 @@ namespace Rando {
}
slot++;
}
mSaveContext->inventory.items[slot] = item.GetGIEntry()->itemId;
uint16_t itemId = item.GetGIEntry()->itemId;
if (BottleRandomizerGetToItemID.contains(randoGet)) {
itemId = BottleRandomizerGetToItemID[randoGet];
}
mSaveContext->inventory.items[slot] = itemId;
} break;
case RG_RUTOS_LETTER:
SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER, state);
@ -2201,7 +2217,7 @@ namespace Rando {
//Bottle Count
Bottles = 0;
NumBottles = 0;
CanEmptyBigPoes = true;
CanEmptyBigPoes = false;
//Drops and Bottle Contents Access
NutPot = false;
@ -2238,7 +2254,7 @@ namespace Rando {
//CanPlantBean = false;
BigPoeKill = false;
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() + 1;
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() + 1;
//Bridge Requirements
@ -2247,7 +2263,7 @@ namespace Rando {
//Other
AtDay = false;
AtNight = false;
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
//Events
ShowedMidoSwordAndShield = false;

View File

@ -2,42 +2,56 @@
#include "libultraship/bridge.h"
#include <Context.h>
#include <imgui.h>
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
namespace Rando {
Option Option::Bool(std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_) {
return {false, std::move(name_), std::move(options_), category_, std::move(cvarName_), std::move(description_),
widgetType_, defaultOption_, defaultHidden_, imFlags_};
Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
const OptionCategory category_, std::string cvarName_, std::string description_,
WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
return {static_cast<size_t>(key_), std::move(name_), std::move(options_), category_,
std::move(cvarName_), std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
Option Option::Bool(std::string name_, std::string cvarName_, std::string description_, const int imFlags_,
const WidgetType widgetType_, const bool defaultOption_) {
return Option(false, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_, std::string description_,
const int imFlags_, const WidgetType widgetType_, const bool defaultOption_) {
return Option(key_, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, false, imFlags_);
}
Option Option::U8(std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_) {
return {static_cast<uint8_t>(0), std::move(name_), std::move(options_), category_, std::move(cvarName_),
Option Option::U8(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
const OptionCategory category_, std::string cvarName_, std::string description_,
WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
return {static_cast<size_t>(key_), std::move(name_), std::move(options_), category_, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
Option Option::LogicTrick(std::string name_) {
return Option(false, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
Option Option::LogicTrick(RandomizerTrick rt_, std::string name_) {
return Option(rt_, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
"", WidgetType::Checkbox, 0, false, IMFLAG_NONE);
}
Option::operator bool() const {
return contextSelection != 0;
OptionValue::OptionValue(uint8_t val) : mVal(val) {}
uint8_t OptionValue::Get() {
return mVal;
}
void OptionValue::Set(uint8_t val) {
mVal = val;
}
OptionValue::operator bool() const {
return mVal != 0;
}
size_t Option::GetOptionCount() const {
return options.size();
}
const RandomizerSettingKey Option::GetKey() const {
return static_cast<RandomizerSettingKey>(key);
}
const std::string& Option::GetName() const {
return name;
}
@ -50,26 +64,14 @@ uint8_t Option::GetMenuOptionIndex() const {
return menuSelection;
}
uint8_t Option::GetContextOptionIndex() const {
return contextSelection;
}
const std::string& Option::GetSelectedOptionText() const {
return options[contextSelection];
const std::string& Option::GetOptionText(size_t index) const {
return options[index];
}
const std::string& Option::GetCVarName() const {
return cvarName;
}
void Option::SetVariable() {
if (std::holds_alternative<bool>(var)) {
var.emplace<bool>(menuSelection != 0);
} else {
var.emplace<uint8_t>(menuSelection);
}
}
void Option::SaveCVar() const {
if (!cvarName.empty()) {
CVarSetInteger(cvarName.c_str(), GetMenuOptionIndex());
@ -95,10 +97,10 @@ void Option::SetMenuIndex(size_t idx) {
if (menuSelection > options.size() - 1) {
menuSelection = options.size() - 1;
}
SetVariable();
}
void Option::SetContextIndex(size_t idx) {
// TODO: Set to Context's OptionValue array.
contextSelection = idx;
if (contextSelection > options.size() - 1) {
contextSelection = options.size() - 1;
@ -178,6 +180,16 @@ void Option::RemoveFlag(const int imFlag_) {
imFlags &= ~imFlag_;
}
uint8_t Option::GetValueFromText(const std::string text) {
if (optionsTextToVar.contains(text)) {
return optionsTextToVar[text];
} else {
SPDLOG_ERROR("Option {} does not have a var named {}.", name, text);
assert(false);
}
return defaultOption;
}
void Option::SetContextIndexFromText(const std::string text) {
if (optionsTextToVar.contains(text)){
SetContextIndex(optionsTextToVar[text]);
@ -187,21 +199,10 @@ void Option::SetContextIndexFromText(const std::string text) {
}
}
Option::Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
Option::Option(size_t key_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_)
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
menuSelection = contextSelection = defaultOption;
hidden = defaultHidden;
PopulateTextToNum();
SetFromCVar();
}
Option::Option(bool var_, std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_)
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
: key(key_), name(std::move(name_)), options(std::move(options_)), category(category_),
cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
menuSelection = contextSelection = defaultOption;
@ -350,13 +351,25 @@ void Option::PopulateTextToNum(){
}
}
TrickOption::TrickOption(const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) :
Option(false, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
LocationOption::LocationOption(RandomizerCheck key_, const std::string& name_) :
Option(key_, name_, {"Included", "Excluded"}, OptionCategory::Setting, "", "", WidgetType::Checkbox,
RO_LOCATION_INCLUDE, false, IMFLAG_NONE) {}
const RandomizerCheck LocationOption::GetKey() const {
return static_cast<RandomizerCheck>(key);
}
TrickOption::TrickOption(RandomizerTrick key_, const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) :
Option(key_, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
std::move(description_), WidgetType::Checkbox, 0, false, IMFLAG_NONE),
mQuest(quest_), mArea(area_), mTags(std::move(tags_)) {}
TrickOption TrickOption::LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) {
return {quest_, area_, std::move(tags_), name_, std::move(description_)};
TrickOption TrickOption::LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) {
return {key_, quest_, area_, std::move(tags_), name_, std::move(description_)};
}
const RandomizerTrick TrickOption::GetKey() const {
return static_cast<RandomizerTrick>(key);
}
RandomizerCheckQuest TrickOption::GetQuest() const {

View File

@ -1,6 +1,6 @@
#pragma once
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <cstdint>
#include <set>
@ -40,6 +40,59 @@ enum class WidgetType {
Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */
};
class OptionValue {
public:
OptionValue() = default;
OptionValue(uint8_t value_);
/**
* @brief Returns the value of the OptionValue's mVal
*
* @return uint8_t
*/
uint8_t Get();
/**
* @brief Set the OptionValue's mVal to the provided val.
*
* @param val
*/
void Set(uint8_t val);
/**
* @brief Determines if the value/selected index of this Option matches the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool Is(uint32_t other) const {
return mVal == other;
}
/**
* @brief Determines if the value/selected index of this Option does not match the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool IsNot(uint32_t other) const {
return !Is(other);
}
/**
* @brief Allows the option to be used as a boolean value directly.
*
* @return true
* @return false
*/
explicit operator bool() const;
private:
uint8_t mVal;
};
/**
* @brief A class describing the state of a single option/setting, such as its name,
* options, current value, whether or not it is interactable in the menu, or the CVar,
@ -68,7 +121,8 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
static Option Bool(std::string name_, std::vector<std::string> options_ = { "Off", "On" },
static Option Bool(RandomizerSettingKey key_, std::string name_,
std::vector<std::string> options_ = { "Off", "On" },
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Checkbox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@ -79,6 +133,7 @@ class Option {
* existing calls to the other overload of this function. The options vector will be { "Off", "On" }
* when using this overload. If you want your option to have different value names, use the other overload.
*
* @param key_ The RandomizerSettingKey of this option.
* @param name_ The name of the option. Appears in the spoiler/patch file.
* @param cvarName_ The name of the CVar this option should correspond with. Set as an empty string to not
* link to any CVar.
@ -90,13 +145,14 @@ class Option {
* @param defaultOption_ The defaulted selected index for this Option.
* @return Option
*/
static Option Bool(std::string name_, std::string cvarName_, std::string description_ = "",
int imFlags_ = IMFLAG_SEPARATOR_BOTTOM, WidgetType widgetType_ = WidgetType::Checkbox,
bool defaultOption_ = false);
static Option Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_,
std::string description_ = "", int imFlags_ = IMFLAG_SEPARATOR_BOTTOM,
WidgetType widgetType_ = WidgetType::Checkbox, bool defaultOption_ = false);
/**
* @brief Constructs a U8 Option.
*
* @param key_ The RandomizerSettingKey for this option.
* @param name_ The name of this Option. Appears in the spoiler/patch file.
* @param options_ A vector of value names for this Option. The name corresponding to the selected
* index for this option will be printed to the spoiler/patch file.
@ -114,7 +170,7 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
static Option U8(std::string name_, std::vector<std::string> options_,
static Option U8(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Combobox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@ -125,37 +181,7 @@ class Option {
* @param name_ The name of the trick. Appears in the spoiler/patch file.
* @return Option
*/
static Option LogicTrick(std::string name_);
/**
* @brief Determines if the value/selected index of this Option matches the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool Is(uint32_t other) const {
return contextSelection == other;
}
/**
* @brief Determines if the value/selected index of this Option does not match the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool IsNot(uint32_t other) const {
return !Is(other);
}
/**
* @brief Allows the option to be used as a boolean value directly.
*
* @return true
* @return false
*/
explicit operator bool() const;
static Option LogicTrick(RandomizerTrick rt_, std::string name_);
/**
* @brief Get the size of the options array.
@ -164,6 +190,13 @@ class Option {
*/
size_t GetOptionCount() const;
/**
* @brief Get the Key Option
*
* @return const RandomizerSettingKey
*/
const RandomizerSettingKey GetKey() const;
/**
* @brief Get the name of the Option.
*
@ -173,11 +206,12 @@ class Option {
const std::string& GetDescription() const;
/**
* @brief Get the value name corresponding to the selected index.
*
* @return const std::string&
* @brief Get the text of the Option value of the selected index.
*
* @param index
* @return const std::string&
*/
const std::string& GetSelectedOptionText() const;
const std::string& GetOptionText(size_t index) const;
/**
* @brief Get the CVar name for this Option.
@ -193,18 +227,6 @@ class Option {
*/
uint8_t GetMenuOptionIndex() const;
/**
* @brief Get the rando context index for this Option.
*
* @return uint8_t
*/
uint8_t GetContextOptionIndex() const;
/**
* @brief Sets the variable to the currently selected index for this Option.
*/
void SetVariable();
/**
* @brief Sets the CVar corresponding to the property `cvarName` equal to the value
* of the property `selectedValue`.
@ -306,15 +328,14 @@ class Option {
void SetFlag(int imFlag_);
void RemoveFlag(int imFlag_);
uint8_t GetValueFromText(std::string text);
void SetContextIndexFromText(std::string text);
protected:
Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_);
Option(bool var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
Option(size_t key_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_);
size_t key;
private:
bool RenderCheckbox();
@ -322,7 +343,6 @@ protected:
bool RenderCombobox();
bool RenderSlider();
void PopulateTextToNum();
std::variant<bool, uint8_t> var;
std::string name;
std::vector<std::string> options;
uint8_t menuSelection = 0;
@ -342,12 +362,20 @@ protected:
std::unordered_map<std::string, uint8_t> optionsTextToVar = {};
};
class LocationOption : public Option {
public:
LocationOption() = default;
LocationOption(RandomizerCheck key_, const std::string& name_);
const RandomizerCheck GetKey() const;
};
class TrickOption : public Option {
public:
TrickOption() = default;
/**
* @brief A convenience function for constructing the Option for a trick.
*
* @param key_ A RandomizerTrick key for this option.
* @param quest_ MQ, Vanilla, or Both.
* @param area_ The area the trick is relevant for.
* @param tags_ The set of RandomizerTrickTags for this trick.
@ -355,7 +383,9 @@ public:
* @param description_ A brief description of the trick.
* @return Option
*/
static TrickOption LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
static TrickOption LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
const RandomizerTrick GetKey() const;
/**
* @brief Retrieve the quest type this trick is relevant for.
@ -382,7 +412,7 @@ public:
const std::set<Tricks::Tag>& GetTags() const;
private:
TrickOption(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
TrickOption(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
RandomizerCheckQuest mQuest;
RandomizerArea mArea;
std::set<Tricks::Tag> mTags;

View File

@ -11,9 +11,9 @@
#include "3drando/rando_main.hpp"
#include "3drando/random.hpp"
#include "soh/ResourceManagerHelpers.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "3drando/custom_messages.hpp"
#include "../../UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <imgui.h>
#include <imgui_internal.h>
#include "../custom-message/CustomMessageTypes.h"
@ -475,7 +475,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
(CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE);
case RG_DEKU_STICK_1:
case RG_BUY_DEKU_STICK_1:
return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).GetContextOptionIndex()
return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_NUT_UPGRADE:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@ -485,7 +485,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_DEKU_NUTS_10:
case RG_BUY_DEKU_NUTS_5:
case RG_BUY_DEKU_NUTS_10:
return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).GetContextOptionIndex()
return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_BOMB_BAG:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@ -1837,7 +1837,7 @@ FishIdentity Randomizer::IdentifyFish(s32 sceneNum, s32 actorParams) {
}
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetContextOptionIndex();
return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get();
}
GetItemEntry Randomizer::GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability) {
@ -1871,7 +1871,8 @@ void GenerateRandomizerImgui(std::string seed = "") {
CVarSave();
auto ctx = Rando::Context::GetInstance();
//RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings
ctx->GetSettings()->SetAllFromCVar();
Rando::Settings::GetInstance()->SetAllFromCVar();
Rando::Settings::GetInstance()->SetAllToContext();
// todo: this efficently when we build out cvar array support
std::set<RandomizerCheck> excludedLocations;
@ -3787,10 +3788,10 @@ class ExtendedVanillaTableInvalidItemIdException: public std::exception {
};
void RandomizerSettingsWindow::InitElement() {
mSettings = Rando::Context::GetInstance()->GetSettings();
mSettings = Rando::Settings::GetInstance();
Randomizer::CreateCustomMessages();
seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char));
Rando::Context::GetInstance()->GetSettings()->UpdateOptionProperties();
mSettings->UpdateOptionProperties();
}
// Gameplay stat tracking: Update time the item was acquired

View File

@ -6,7 +6,7 @@
#include "soh/cvar_prefixes.h"
#include "soh/SaveManager.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "dungeon.h"
#include "location_access.h"
@ -490,7 +490,7 @@ void CheckTrackerLoadGame(int32_t fileNum) {
}
}
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
RandomizerCheckArea startingArea;
switch (startingAge) {
case RO_AGE_CHILD:

View File

@ -1,7 +1,7 @@
#include "randomizer_entrance_tracker.h"
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include <map>
#include <string>

View File

@ -4,7 +4,7 @@
#include "soh/cvar_prefixes.h"
#include "soh/SaveManager.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "randomizerTypes.h"
#include <map>

View File

@ -272,7 +272,7 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO);
}
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
switch (startingAge) {
case RO_AGE_ADULT: // Adult
gSaveContext.linkAge = LINK_AGE_ADULT;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#pragma once
#include "context.h"
#include "option.h"
#include "randomizerTypes.h"
#include "3drando/spoiler_log.hpp"
@ -49,11 +50,6 @@ class Settings {
*/
TrickOption& GetTrickOption(RandomizerTrick key);
/**
* @brief Reset all RandomizerTrick keys.
*/
void ResetTrickOptions();
/**
* @brief Returns a reference to the entire array of options.
*
@ -77,56 +73,6 @@ class Settings {
*/
const std::vector<std::vector<Option*>>& GetExcludeLocationsOptions() const;
/**
* @brief Gets the resolved Light Arrow CutScene check condition.
* There is no direct option for this, it is inferred based on the value of a few other options.
*
* @return RandoOptionLACSCondition
*/
RandoOptionLACSCondition LACSCondition() const;
/**
* @brief Get the hash for the current seed.
*
* @return std::string
*/
std::string GetHash() const;
/**
* @brief Get the Seed String
*
* @return const std::string&
*/
const std::string& GetSeedString() const;
/**
* @brief Set the Seed String
*
* @param seedString
*/
void SetSeedString(std::string seedString);
/**
* @brief Get the Seed
*
* @return const uint32_t
*/
uint32_t GetSeed() const;
/**
* @brief Set the Seed
*
* @param seed
*/
void SetSeed(uint32_t seed);
/**
* @brief Set the Seed Hash for the current seed.
*
* @param hash
*/
void SetHash(std::string hash);
/**
* @brief Get the list of `OptionGroup`s.
*
@ -160,42 +106,43 @@ class Settings {
*/
void UpdateOptionProperties();
/**
* @brief Runs before seed generation to ensure all options are compatible with each
* other and resolve options that have been set to random (such as random trial count,
* or starting age).
*
* @param excludedLocations Set of locations that should be forced to have junk items.
* @param enabledTricks Set of tricks that should be considered logically possible. Tricks
* are things that are possible to do in gameplay but are difficult, not intuitive or that
* require more extensive game knowledge, i.e. opening invisible chests without the Lens of Truth.
*/
void FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations, const std::set<RandomizerTrick>& enabledTricks);
/**
* @brief Parse Options from a JSON file.
*
* @param spoilerFileJson
*/
void ParseJson(nlohmann::json spoilerFileJson);
std::vector<Option*> VanillaLogicDefaults = {};
std::map<RandomizerArea, std::vector<RandomizerTrick>> mTricksByArea = {};
void ReloadOptions();
/**
* @brief Assigns a Rando::Context instance to this settings instance
* with which to later instantiate and access OptionValues.
*
* @param ctx
*/
void AssignContext(std::shared_ptr<Context> ctx);
void ClearContext();
/**
* @brief Sets all the currently selected MenuIndexes to the currently assigned Rando::Context.
*/
void SetAllToContext();
static std::shared_ptr<Settings> GetInstance();
private:
/**
* @brief Create the list of description strings for `Option`s.
*/
void CreateOptionDescriptions();
static std::shared_ptr<Settings> mInstance;
std::shared_ptr<Context> mContext = nullptr;
std::array<Option, RSK_MAX> mOptions = {};
std::array<std::string, RSK_MAX> mOptionDescriptions = {};
std::array<OptionGroup, RSG_MAX> mOptionGroups = {};
std::array<TrickOption, RT_MAX> mTrickOptions = {};
std::vector<std::vector<Option*>> mExcludeLocationsOptionsAreas = {};
RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA;
std::string mHash;
std::string mSeedString;
uint32_t mFinalSeed = 0;
std::unordered_map<std::string, RandomizerTrick> mTrickNameToEnum;
};
} // namespace Rando

View File

@ -2,7 +2,7 @@
#include <imgui.h>
#include <libultraship/libultraship.h>
#include <soh/UIWidgets.hpp>
#include "soh/SohGui/UIWidgets.hpp"
#include <graphic/Fast3D/gfx_pc.h>
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"

View File

@ -44,7 +44,7 @@ extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play);
extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) {

View File

@ -1,5 +1,5 @@
#include "TimeSplits.h"
#include "soh/UIWidgets.hpp"
#include "soh/SohGui/UIWidgets.hpp"
#include "soh/Enhancements/gameplaystats.h"
#include "soh/SaveManager.h"
#include "soh/util.h"

View File

@ -42,7 +42,6 @@
#include "Fonts.h"
#include <utils/StringHelper.h>
#include "Enhancements/custom-message/CustomMessageManager.h"
#include "ImGuiUtils.h"
#include "Enhancements/presets.h"
#include "util.h"
#include <boost_custom/container_hash/hash_32.hpp>
@ -70,7 +69,8 @@
#include "Enhancements/custom-message/CustomMessageTypes.h"
#include <functions.h>
#include "Enhancements/item-tables/ItemTableManager.h"
#include "SohGui.hpp"
#include "soh/SohGui/SohGui.hpp"
#include "soh/SohGui/ImGuiUtils.h"
#include "ActorDB.h"
#include "SaveManager.h"
@ -391,9 +391,10 @@ OTRGlobals::OTRGlobals() {
gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext->InitStaticData();
gRandoContext = Rando::Context::CreateInstance();
Rando::Settings::GetInstance()->AssignContext(gRandoContext);
Rando::StaticData::InitItemTable();//RANDOTODO make this not rely on context's logic so it can be initialised in InitStaticData
gRandoContext->AddExcludedOptions();
gRandoContext->GetSettings()->CreateOptions();
Rando::Settings::GetInstance()->CreateOptions();
gRandomizer = std::make_shared<Randomizer>();
hasMasterQuest = hasOriginal = false;
@ -1930,7 +1931,7 @@ extern "C" u32 SpoilerFileExists(const char* spoilerFileName) {
}
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) {
return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).GetContextOptionIndex();
return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).Get();
}
extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) {
@ -2439,9 +2440,8 @@ void SoH_ProcessDroppedFiles(std::string filePath) {
}
}
auto randoCtx = Rando::Context::GetInstance();
randoCtx->GetSettings()->UpdateOptionProperties();
randoCtx->GetSettings()->SetAllFromCVar();
Rando::Settings::GetInstance()->UpdateOptionProperties();
Rando::Settings::GetInstance()->SetAllFromCVar();
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGuiWindow("Console")->Hide();

View File

@ -28,7 +28,7 @@ struct ExtensionEntry {
};
extern std::unordered_map<std::string, ExtensionEntry> ExtensionCache;
#include "Enhancements/randomizer/context.h"
#include "Enhancements/randomizer/settings.h"
const std::string customMessageTableID = "BaseGameOverrides";
const std::string appShortName = "soh";

View File

@ -15,7 +15,7 @@
#include "macros.h"
#include <variables.h>
#include <libultraship/libultraship.h>
#include "SohGui.hpp"
#include "soh/SohGui/SohGui.hpp"
#define NOGDI // avoid various windows defines that conflict with things in z64.h
#include <spdlog/spdlog.h>
@ -180,7 +180,7 @@ void SaveManager::LoadRandomizerVersion1() {
int key, value;
SaveManager::Instance->LoadData("sk" + std::to_string(i), key);
SaveManager::Instance->LoadData("sv" + std::to_string(i), value);
randoContext->GetOption(RandomizerSettingKey(key)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(key)).Set(value);
}
for (int i = 0; i < 50; i++) {
@ -277,16 +277,16 @@ void SaveManager::LoadRandomizerVersion2() {
std::string inputSeed;
SaveManager::Instance->LoadData("inputSeed", inputSeed);
randoContext->GetSettings()->SetSeedString(inputSeed);
randoContext->SetSeedString(inputSeed);
uint32_t finalSeed;
SaveManager::Instance->LoadData("finalSeed", finalSeed);
randoContext->GetSettings()->SetSeed(finalSeed);
randoContext->SetSeed(finalSeed);
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
int value = 0;
SaveManager::Instance->LoadData("", value);
randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(i)).Set(value);
});
SaveManager::Instance->LoadArray("hintLocations", RH_ZR_OPEN_GROTTO_GOSSIP_STONE + 1, [&](size_t i) {
@ -426,16 +426,16 @@ void SaveManager::LoadRandomizerVersion3() {
std::string inputSeed;
SaveManager::Instance->LoadData("inputSeed", inputSeed);
randoContext->GetSettings()->SetSeedString(inputSeed);
randoContext->SetSeedString(inputSeed);
uint32_t finalSeed;
SaveManager::Instance->LoadData("finalSeed", finalSeed);
randoContext->GetSettings()->SetSeed(finalSeed);
randoContext->SetSeed(finalSeed);
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
int value = 0;
SaveManager::Instance->LoadData("", value);
randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(i)).Set(value);
});
SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) {
@ -464,7 +464,7 @@ void SaveManager::LoadRandomizerVersion3() {
});
randoContext->GetTrials()->SkipAll();
SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() + 1, [&](size_t i) {
SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).Get() + 1, [&](size_t i) {
size_t trialId;
SaveManager::Instance->LoadData("", trialId);
randoContext->GetTrial(trialId)->SetAsRequired();
@ -508,12 +508,12 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
SaveManager::Instance->SaveData("", randoContext->hashIconIndexes[i]);
});
SaveManager::Instance->SaveData("inputSeed", randoContext->GetSettings()->GetSeedString());
SaveManager::Instance->SaveData("inputSeed", randoContext->GetSeedString());
SaveManager::Instance->SaveData("finalSeed", randoContext->GetSettings()->GetSeed());
SaveManager::Instance->SaveData("finalSeed", randoContext->GetSeed());
SaveManager::Instance->SaveArray("randoSettings", RSK_MAX, [&](size_t i) {
SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).GetContextOptionIndex());
SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).Get());
});
SaveManager::Instance->SaveArray("hintLocations", RH_MAX, [&](size_t i) {
@ -662,8 +662,6 @@ void SaveManager::Init() {
OTRGlobals::Instance->gRandoContext->ClearItemLocations();
}
}
auto ctx = Rando::Context::GetInstance();
ctx->GetSettings()->CreateOptions();
}
void SaveManager::InitMeta(int fileNum) {
@ -2846,14 +2844,11 @@ extern "C" void Save_SaveGlobal(void) {
extern "C" void Save_LoadFile(void) {
// Handle vanilla context reset
OTRGlobals::Instance->gRandoContext->GetLogic()->SetContext(nullptr);
Rando::Settings::GetInstance()->ClearContext();
OTRGlobals::Instance->gRandoContext.reset();
OTRGlobals::Instance->gRandoContext = Rando::Context::CreateInstance();
OTRGlobals::Instance->gRandoContext->GetLogic()->SetSaveContext(&gSaveContext);
if (SaveManager::Instance->fileMetaInfo[gSaveContext.fileNum].randoSave) {
OTRGlobals::Instance->gRandoContext->AddExcludedOptions();
OTRGlobals::Instance->gRandoContext->GetSettings()->CreateOptions();
}
Rando::Settings::GetInstance()->AssignContext(OTRGlobals::Instance->gRandoContext);
SaveManager::Instance->LoadFile(gSaveContext.fileNum);
}

View File

@ -1,50 +0,0 @@
//
// SohGui.hpp
// soh
//
// Created by David Chavez on 24.08.22.
//
#ifndef SohGui_hpp
#define SohGui_hpp
#include <stdio.h>
#include "SohMenuBar.h"
#include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/InputViewer.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h"
#include "Enhancements/debugger/debugSaveEditor.h"
#include "Enhancements/debugger/hookDebugger.h"
#include "Enhancements/debugger/dlViewer.h"
#include "Enhancements/debugger/valueViewer.h"
#include "Enhancements/gameplaystatswindow.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/randomizer/randomizer_settings_window.h"
#include "Enhancements/timesplits/TimeSplits.h"
#include "Enhancements/randomizer/Plandomizer.h"
#include "AboutWindow.h"
#include "SohModals.h"
#ifdef __cplusplus
extern "C" {
#endif
void enableBetaQuest();
void disableBetaQuest();
#ifdef __cplusplus
}
#endif
namespace SohGui {
void SetupHooks();
void SetupGuiElements();
void Draw();
void Destroy();
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
void ShowRandomizerSettingsMenu();
}
#endif /* SohGui_hpp */

View File

@ -7,7 +7,7 @@
#include <array>
#include <map>
#include <string>
#include "Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "variables.h" //only for gItemIcons
extern "C" {

View File

@ -25,15 +25,15 @@
#include "include/global.h"
#include "include/z64audio.h"
#include "soh/SaveManager.h"
#include "OTRGlobals.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/presets.h"
#include "soh/resource/type/Skeleton.h"
#include "libultraship/libultraship.h"
#include "Enhancements/game-interactor/GameInteractor.h"
#include "Enhancements/cosmetics/authenticGfxPatches.h"
#include "Enhancements/resolution-editor/ResolutionEditor.h"
#include "Enhancements/debugger/MessageViewer.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include "soh/Enhancements/resolution-editor/ResolutionEditor.h"
#include "soh/Enhancements/debugger/MessageViewer.h"
#include "soh/Notification/Notification.h"
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"

50
soh/soh/SohGui/SohGui.hpp Normal file
View File

@ -0,0 +1,50 @@
//
// SohGui.hpp
// soh
//
// Created by David Chavez on 24.08.22.
//
#ifndef SohGui_hpp
#define SohGui_hpp
#include <stdio.h>
#include "SohMenuBar.h"
#include "soh/Enhancements/audio/AudioEditor.h"
#include "soh/Enhancements/controls/InputViewer.h"
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
#include "soh/Enhancements/debugger/actorViewer.h"
#include "soh/Enhancements/debugger/colViewer.h"
#include "soh/Enhancements/debugger/debugSaveEditor.h"
#include "soh/Enhancements/debugger/hookDebugger.h"
#include "soh/Enhancements/debugger/dlViewer.h"
#include "soh/Enhancements/debugger/valueViewer.h"
#include "soh/Enhancements/gameplaystatswindow.h"
#include "soh/Enhancements/randomizer/randomizer_check_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_item_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_settings_window.h"
#include "soh/Enhancements/timesplits/TimeSplits.h"
#include "soh/Enhancements/randomizer/Plandomizer.h"
#include "soh/AboutWindow.h"
#include "SohModals.h"
#ifdef __cplusplus
extern "C" {
#endif
void enableBetaQuest();
void disableBetaQuest();
#ifdef __cplusplus
}
#endif
namespace SohGui {
void SetupHooks();
void SetupGuiElements();
void Draw();
void Destroy();
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
void ShowRandomizerSettingsMenu();
}
#endif /* SohGui_hpp */

View File

@ -6,45 +6,45 @@
#include "UIWidgets.hpp"
#include "include/z64audio.h"
#include "graphic/Fast3D/gfx_rendering_api.h"
#include "OTRGlobals.h"
#include "SaveManager.h"
#include "soh/OTRGlobals.h"
#include "soh/SaveManager.h"
#include "z64.h"
#include "cvar_prefixes.h"
#include "soh/cvar_prefixes.h"
#include "macros.h"
#include "functions.h"
#include "variables.h"
#include "Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/presets.h"
#include "soh/Enhancements/mods.h"
#include "soh/Notification/Notification.h"
#include "Enhancements/cosmetics/authenticGfxPatches.h"
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#ifdef ENABLE_REMOTE_CONTROL
#include "soh/Network/CrowdControl/CrowdControl.h"
#include "soh/Network/Sail/Sail.h"
#endif
#include "Enhancements/audio/AudioEditor.h"
#include "Enhancements/controls/InputViewer.h"
#include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugger/actorViewer.h"
#include "Enhancements/debugger/colViewer.h"
#include "Enhancements/debugger/debugSaveEditor.h"
#include "Enhancements/debugger/hookDebugger.h"
#include "Enhancements/debugger/dlViewer.h"
#include "Enhancements/debugger/valueViewer.h"
#include "Enhancements/gameplaystatswindow.h"
#include "Enhancements/debugger/MessageViewer.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/randomizer/randomizer_settings_window.h"
#include "Enhancements/resolution-editor/ResolutionEditor.h"
#include "Enhancements/enemyrandomizer.h"
#include "Enhancements/timesplits/TimeSplits.h"
#include "Enhancements/randomizer/Plandomizer.h"
#include "Enhancements/TimeDisplay/TimeDisplay.h"
#include "AboutWindow.h"
#include "soh/Enhancements/audio/AudioEditor.h"
#include "soh/Enhancements/controls/InputViewer.h"
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
#include "soh/Enhancements/debugger/actorViewer.h"
#include "soh/Enhancements/debugger/colViewer.h"
#include "soh/Enhancements/debugger/debugSaveEditor.h"
#include "soh/Enhancements/debugger/hookDebugger.h"
#include "soh/Enhancements/debugger/dlViewer.h"
#include "soh/Enhancements/debugger/valueViewer.h"
#include "soh/Enhancements/gameplaystatswindow.h"
#include "soh/Enhancements/debugger/MessageViewer.h"
#include "soh/Enhancements/randomizer/randomizer_check_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_item_tracker.h"
#include "soh/Enhancements/randomizer/randomizer_settings_window.h"
#include "soh/Enhancements/resolution-editor/ResolutionEditor.h"
#include "soh/Enhancements/enemyrandomizer.h"
#include "soh/Enhancements/timesplits/TimeSplits.h"
#include "soh/Enhancements/randomizer/Plandomizer.h"
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"
#include "soh/AboutWindow.h"
// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
// they don't work how I expect them to so I added that because it looked good when I eyeballed it

View File

@ -5,7 +5,7 @@
#include <libultraship/bridge.h>
#include <libultraship/libultraship.h>
#include "UIWidgets.hpp"
#include "OTRGlobals.h"
#include "soh/OTRGlobals.h"
#include "z64.h"
extern "C" PlayState* gPlayState;