Merge remote-tracking branch 'upstream/rando-next' into rando-navi-tips

This commit is contained in:
Sarge-117 2022-08-10 11:15:37 -07:00
commit 0f6e7ede48
45 changed files with 2160 additions and 742 deletions

View File

@ -15,9 +15,9 @@ namespace Ship {
std::map<ImGuiKey, std::string> BindingToggle;
static bool HelpCommand(const std::vector<std::string>&) {
INFO("SoH Commands:");
SohImGui::console->SendInfoMessage("SoH Commands:");
for (const auto& cmd : SohImGui::console->Commands) {
INFO("%s", (" - " + cmd.first).c_str());
SohImGui::console->SendInfoMessage(" - " + cmd.first);
}
return CMD_SUCCESS;
}
@ -45,7 +45,7 @@ namespace Ship {
std::ostringstream imploded;
std::copy(args.begin() + 2, args.end(), std::ostream_iterator<std::string>(imploded, delim));
Bindings[k] = imploded.str();
INFO("Binding '%s' to %s", args[1].c_str(), Bindings[k].c_str());
SohImGui::console->SendInfoMessage("Binding '%s' to %s", args[1].c_str(), Bindings[k].c_str());
break;
}
}
@ -61,7 +61,7 @@ namespace Ship {
if (toLowerCase(args[1]) == toLowerCase(key)) {
BindingToggle[k] = args[2];
INFO("Binding toggle '%s' to %s", args[1].c_str(), BindingToggle[k].c_str());
SohImGui::console->SendInfoMessage("Binding toggle '%s' to %s", args[1].c_str(), BindingToggle[k].c_str());
break;
}
}
@ -159,29 +159,39 @@ namespace Ship {
// Renders top bar filters
if (ImGui::Button("Clear")) this->Log[this->selected_channel].clear();
ImGui::SameLine();
ImGui::SetNextItemWidth(150);
if (ImGui::BeginCombo("##channel", this->selected_channel.c_str())) {
for (const auto& channel : log_channels) {
const bool is_selected = (channel == std::string(this->selected_channel));
if (ImGui::Selectable(channel.c_str(), is_selected))
this->selected_channel = channel;
if (is_selected) ImGui::SetItemDefaultFocus();
if (CVar_GetS32("gSinkEnabled", 0)) {
ImGui::SameLine();
ImGui::SetNextItemWidth(150);
if (ImGui::BeginCombo("##channel", this->selected_channel.c_str())) {
for (const auto& channel : log_channels) {
const bool is_selected = (channel == std::string(this->selected_channel));
if (ImGui::Selectable(channel.c_str(), is_selected))
this->selected_channel = channel;
if (is_selected) ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
ImGui::EndCombo();
} else {
this->selected_channel = "Console";
}
ImGui::SameLine();
ImGui::SetNextItemWidth(150);
if (ImGui::BeginCombo("##level", this->level_filter.c_str())) {
for (const auto& filter : priority_filters) {
const bool is_selected = (filter == std::string(this->level_filter));
if (ImGui::Selectable(filter.c_str(), is_selected))
{
this->level_filter = filter;
if (is_selected) ImGui::SetItemDefaultFocus();
if (this->selected_channel != "Console") {
if (ImGui::BeginCombo("##level", spdlog::level::to_string_view(this->level_filter).data())) {
for (const auto& priority_filter : priority_filters) {
const bool is_selected = priority_filter == this->level_filter;
if (ImGui::Selectable(spdlog::level::to_string_view(priority_filter).data(), is_selected))
{
this->level_filter = priority_filter;
if (is_selected) ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::EndCombo();
} else {
this->level_filter = spdlog::level::trace;
}
ImGui::SameLine();
ImGui::PushItemWidth(-1);
@ -203,7 +213,7 @@ namespace Ship {
for (int i = 0; i < static_cast<int>(channel.size()); i++) {
ConsoleLine line = channel[i];
if (!this->filter.empty() && line.text.find(this->filter) == std::string::npos) continue;
if (this->level_filter != NULLSTR && line.priority != (std::find(priority_filters.begin(), priority_filters.end(), this->level_filter) - priority_filters.begin()) - 1) continue;
if (this->level_filter > line.priority) continue;
std::string id = line.text + "##" + std::to_string(i);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
@ -226,54 +236,56 @@ namespace Ship {
ImGui::SetScrollHereY(1.0f);
ImGui::EndChild();
// Renders input textfield
constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit |
ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
ImGui::PushItemWidth(-53);
if (ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) {
input_focus = true;
if (this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ')
this->Dispatch(std::string(this->InputBuffer));
memset(this->InputBuffer, 0, MAX_BUFFER_SIZE);
}
if (this->CMDHint != NULLSTR) {
if (ImGui::IsItemFocused()) {
ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y));
ImGui::SameLine();
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(this->CMDHint.c_str());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
if (this->selected_channel == "Console") {
// Renders input textfield
constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit |
ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
ImGui::PushItemWidth(-53);
if (ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) {
input_focus = true;
if (this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ')
this->Dispatch(std::string(this->InputBuffer));
memset(this->InputBuffer, 0, MAX_BUFFER_SIZE);
}
}
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50);
if (ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') {
this->Dispatch(std::string(this->InputBuffer));
memset(this->InputBuffer, 0, MAX_BUFFER_SIZE);
}
if (this->CMDHint != NULLSTR) {
if (ImGui::IsItemFocused()) {
ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y));
ImGui::SameLine();
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(this->CMDHint.c_str());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
ImGui::SetItemDefaultFocus();
if (input_focus) ImGui::SetKeyboardFocusHere(-1);
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50);
if (ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') {
this->Dispatch(std::string(this->InputBuffer));
memset(this->InputBuffer, 0, MAX_BUFFER_SIZE);
}
ImGui::SetItemDefaultFocus();
if (input_focus) ImGui::SetKeyboardFocusHere(-1);
ImGui::PopItemWidth();
}
ImGui::End();
}
void Console::Dispatch(const std::string& line) {
this->CMDHint = NULLSTR;
this->History.push_back(line);
this->Log[this->selected_channel].push_back({ "> " + line });
SendInfoMessage("> " + line);
const std::vector<std::string> cmd_args = StringHelper::Split(line, " ");
if (this->Commands.contains(cmd_args[0])) {
const CommandEntry entry = this->Commands[cmd_args[0]];
if (!entry.handler(cmd_args) && !entry.arguments.empty())
this->Log[this->selected_channel].push_back({ "[SOH] Usage: " + cmd_args[0] + " " + BuildUsage(entry), ERROR_LVL });
SendErrorMessage("[SOH] Usage: " + cmd_args[0] + " " + BuildUsage(entry));
return;
}
this->Log[this->selected_channel].push_back({ "[SOH] Command not found", ERROR_LVL });
SendErrorMessage("[SOH] Command not found");
}
int Console::CallbackStub(ImGuiInputTextCallbackData* data) {
@ -325,13 +337,39 @@ namespace Ship {
return 0;
}
void Console::Append(const std::string& channel, Priority priority, const char* fmt, ...) {
char buf[1024];
va_list args;
va_start(args, fmt);
void Console::Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args) {
char buf[2048];
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
this->Log[channel].push_back({ std::string(buf), priority });
}
void Console::Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
Append(channel, priority, fmt, args);
va_end(args);
}
void Console::SendInfoMessage(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
Append("Console", spdlog::level::info, fmt, args);
va_end(args);
}
void Console::SendErrorMessage(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
Append("Console", spdlog::level::err, fmt, args);
va_end(args);
}
void Console::SendInfoMessage(const std::string& str) {
Append("Console", spdlog::level::info, str.c_str());
}
void Console::SendErrorMessage(const std::string& str) {
Append("Console", spdlog::level::err, str.c_str());
}
}

View File

@ -6,12 +6,11 @@
#include <functional>
#include "Lib/ImGui/imgui.h"
#define NOGDI
#define WIN32_LEAN_AND_MEAN
#include "spdlog/spdlog.h"
namespace Ship {
#define LOG(msg, ...) SohImGui::console->Append("Main", Ship::Priority::LOG_LVL, msg, ##__VA_ARGS__)
#define INFO(msg, ...) SohImGui::console->Append("Main", Ship::Priority::INFO_LVL, msg, ##__VA_ARGS__)
#define WARNING(msg, ...) SohImGui::console->Append("Main", Ship::Priority::WARNING_LVL, msg, ##__VA_ARGS__)
#define ERROR(msg, ...) SohImGui::console->Append("Main", Ship::Priority::ERROR_LVL, msg, ##__VA_ARGS__)
#define CMD_SUCCESS true
#define CMD_FAILED false
#define MAX_BUFFER_SIZE 255
@ -19,13 +18,6 @@ namespace Ship {
typedef std::function<bool(std::vector<std::string> args)> CommandHandler;
enum Priority {
INFO_LVL,
LOG_LVL,
WARNING_LVL,
ERROR_LVL
};
enum class ArgumentType {
TEXT, NUMBER, PLAYER_POS, PLAYER_ROT
};
@ -44,23 +36,29 @@ namespace Ship {
struct ConsoleLine {
std::string text;
Priority priority = Priority::INFO_LVL;
std::string channel = "Main";
spdlog::level::level_enum priority = spdlog::level::info;
std::string channel = "Console";
};
class Console {
int selectedId = -1;
std::vector<int> selectedEntries;
std::string filter;
std::string level_filter = NULLSTR;
std::vector<std::string> log_channels = { "Main", "SoH Logging" };
std::vector<std::string> priority_filters = { "None", "Info", "Log", "Warning", "Error" };
spdlog::level::level_enum level_filter = spdlog::level::trace;
std::vector<std::string> log_channels = { "Console", "Logs" };
std::vector<spdlog::level::level_enum> priority_filters = { spdlog::level::off, spdlog::level::critical, spdlog::level::err, spdlog::level::warn, spdlog::level::info, spdlog::level::debug, spdlog::level::trace };
std::vector<ImVec4> priority_colors = {
ImVec4(1.0f, 1.0f, 1.0f, 1.0f),
ImVec4(0.2f, 1.0f, 0.2f, 1.0f),
ImVec4(0.9f, 0.8f, 0.4f, 0.01f),
ImVec4(1.0f, 0.2f, 0.2f, 1.0f)
ImVec4(0.8f, 0.8f, 0.8f, 1.0f), // TRACE
ImVec4(0.9f, 0.9f, 0.9f, 1.0f), // DEBUG
ImVec4(1.0f, 1.0f, 1.0f, 1.0f), // INFO
ImVec4(1.0f, 0.875f, 0.125f, 1.0f), // WARN
ImVec4(0.65f, 0.18f, 0.25, 1.0f), // ERROR
ImVec4(0.95f, 0.11f, 0.25, 1.0f), // CRITICAL
ImVec4(0.0f, 0.0f, 0.0f, 0.0f) // OFF
};
protected:
void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args);
public:
std::map<std::string, std::vector<ConsoleLine>> Log;
std::map<std::string, CommandEntry> Commands;
@ -71,13 +69,17 @@ namespace Ship {
char* InputBuffer = nullptr;
bool OpenAutocomplete = false;
int HistoryIndex = -1;
std::string selected_channel = "Main";
std::string selected_channel = "Console";
bool opened = false;
void Init();
void Update();
void Draw();
void Append(const std::string& channel, Priority priority, const char* fmt, ...) IM_FMTARGS(4);
void Dispatch(const std::string& line);
static int CallbackStub(ImGuiInputTextCallbackData* data);
void SendInfoMessage(const char* fmt, ...);
void SendErrorMessage(const char* fmt, ...);
void SendInfoMessage(const std::string& str);
void SendErrorMessage(const std::string& str);
void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...);
};
}

View File

@ -1,4 +1,5 @@
#include "Cutscene.h"
#include "spdlog/spdlog.h"
enum class CutsceneCommands
{
@ -511,9 +512,7 @@ void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res)
return;
}
default:
#ifdef _DEBUG
printf("CutsceneV0: Unknown command %x\n", commandId);
#endif
SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId);
// error?
break;
}

View File

@ -4,7 +4,6 @@
#include "File.h"
#include "Archive.h"
#include "ResourceMgr.h"
#include "Console.h"
#include "ImGuiImpl.h"
#include "Lib/ImGui/imgui_internal.h"
#include "Utils/StringHelper.h"
@ -209,24 +208,25 @@ namespace Ship {
if (args[1] == "add") {
if (!overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f });
INFO("Added overlay: %s ", key);
SPDLOG_INFO("Added overlay: {} ", key);
SohImGui::console->SendInfoMessage("Added overlay: %s", key);
}
else {
ERROR("Overlay already exists: %s", key);
SPDLOG_ERROR("Overlay already exists: {}", key);
}
}
else if (args[1] == "remove") {
if (overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays.erase(key);
INFO("Removed overlay: %s ", key);
SPDLOG_INFO("Removed overlay: {} ", key);
}
else {
ERROR("Overlay not found: %s ", key);
SPDLOG_ERROR("Overlay not found: {}", key);
}
}
}
else {
ERROR("CVar %s does not exist", args[2].c_str());
SPDLOG_ERROR("CVar {} does not exist", args[2].c_str());
}
return CMD_SUCCESS;

View File

@ -90,12 +90,20 @@ namespace Ship {
// Setup Logging
spdlog::init_thread_pool(8192, 1);
auto SohConsoleSink = std::make_shared<spdlog::sinks::soh_sink_mt>();
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
SohConsoleSink->set_level(spdlog::level::trace);
#if defined(__linux__)
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
ConsoleSink->set_level(spdlog::level::trace);
#endif
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
FileSink->set_level(spdlog::level::trace);
std::vector<spdlog::sink_ptr> Sinks{ ConsoleSink, FileSink, SohConsoleSink };
std::vector<spdlog::sink_ptr> Sinks{
#if defined(__linux__)
ConsoleSink,
#endif
FileSink,
SohConsoleSink
};
Logger = std::make_shared<spdlog::async_logger>(GetName(), Sinks.begin(), Sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
GetLogger()->set_level(spdlog::level::trace);
GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v");

View File

@ -1530,7 +1530,7 @@ namespace SohImGui {
if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) {
for (int sId = 0; sId <= SwitchProfiles::POWERSAVINGM3; sId++) {
if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) {
INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]);
SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]);
CVar_SetS32("gSwitchPerfMode", sId);
Switch::ApplyOverclock();
needs_save = true;
@ -1752,6 +1752,14 @@ namespace SohImGui {
needs_save = true;
customWindows["Item Tracker"].enabled = CVar_GetS32("gItemTrackerEnabled", 0);
}
InsertPadding();
if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVar_GetS32("gItemTrackerSettingsEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gItemTrackerSettingsEnabled", 0);
CVar_SetS32("gItemTrackerSettingsEnabled", !currentValue);
needs_save = true;
customWindows["Item Tracker Settings"].enabled = CVar_GetS32("gItemTrackerSettingsEnabled", 0);
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);

View File

@ -31,47 +31,24 @@ public:
{}
protected:
void sink_it_(const details::log_msg &msg) override
{
const Ship::Priority priority = convert_to_soh(msg.level);
void sink_it_(const details::log_msg &msg) override {
memory_buf_t formatted;
if (use_raw_msg_)
{
if (use_raw_msg_) {
details::fmt_helper::append_string_view(msg.payload, formatted);
}
else
{
else {
base_sink<Mutex>::formatter_->format(msg, formatted);
}
formatted.push_back('\0');
const char *msg_output = formatted.data();
if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened)
SohImGui::console->Append("SoH Logging", priority, "%s", msg_output);
const char* msg_output = formatted.data();
if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened) {
SohImGui::console->Append("Logs", msg.level, "%s", msg_output);
}
}
void flush_() override {}
private:
static Ship::Priority convert_to_soh(spdlog::level::level_enum level)
{
switch (level) {
case spdlog::level::trace:
return Ship::Priority::INFO_LVL;
case spdlog::level::debug:
return Ship::Priority::LOG_LVL;
case spdlog::level::info:
return Ship::Priority::LOG_LVL;
case spdlog::level::warn:
return Ship::Priority::WARNING_LVL;
case spdlog::level::err:
return Ship::Priority::ERROR_LVL;
case spdlog::level::critical:
return Ship::Priority::ERROR_LVL;
default:
break;
}
return Ship::Priority::LOG_LVL;
}
std::string tag_;
bool use_raw_msg_;

View File

@ -1,6 +1,7 @@
#include "Resource.h"
#include "DisplayList.h"
#include "ResourceMgr.h"
#include "spdlog/spdlog.h"
#include "Utils/BinaryReader.h"
#include "Lib/tinyxml2/tinyxml2.h"
#include "Lib/Fast3D/U64/PR/ultra64/gbi.h"
@ -56,9 +57,7 @@ namespace Ship
patches.clear();
#if _DEBUG
if (file != nullptr)
printf("Deconstructor called on file %s\n", file->path.c_str());
#endif
SPDLOG_TRACE("Deconstructor called on file %s\n", file->path.c_str());
}
}

View File

@ -174,6 +174,7 @@ source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__s
set(Header_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer.h"
"soh/Enhancements/randomizer/randomizer_item_tracker.h"
"soh/Enhancements/randomizer/adult_trade_shuffle.h"
)
source_group("Header Files\\soh\\Enhancements\\randomizer" FILES ${Header_Files__soh__Enhancements__randomizer})
@ -266,6 +267,7 @@ source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__s
set(Source_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer.cpp"
"soh/Enhancements/randomizer/randomizer_item_tracker.cpp"
"soh/Enhancements/randomizer/adult_trade_shuffle.c"
)
source_group("Source Files\\soh\\Enhancements\\randomizer" FILES ${Source_Files__soh__Enhancements__randomizer})

View File

@ -253,6 +253,41 @@ typedef enum {
/* 0xA2 */ ITEM_BOTTLE_WITH_BUGS,
/* 0xA3 */ ITEM_BOTTLE_WITH_POE,
/* 0xA4 */ ITEM_BOTTLE_WITH_BIG_POE,
/* 0xA5 */ ITEM_GERUDO_FORTRESS_SMALL_KEY,
/* 0xA6 */ ITEM_FOREST_TEMPLE_SMALL_KEY,
/* 0xA7 */ ITEM_FIRE_TEMPLE_SMALL_KEY,
/* 0xA8 */ ITEM_WATER_TEMPLE_SMALL_KEY,
/* 0xA9 */ ITEM_SPIRIT_TEMPLE_SMALL_KEY,
/* 0xAA */ ITEM_SHADOW_TEMPLE_SMALL_KEY,
/* 0xAB */ ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY,
/* 0xAC */ ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY,
/* 0xAD */ ITEM_GANONS_CASTLE_SMALL_KEY,
/* 0xAE */ ITEM_FOREST_TEMPLE_BOSS_KEY,
/* 0xAF */ ITEM_FIRE_TEMPLE_BOSS_KEY,
/* 0xB0 */ ITEM_WATER_TEMPLE_BOSS_KEY,
/* 0xB1 */ ITEM_SPIRIT_TEMPLE_BOSS_KEY,
/* 0xB2 */ ITEM_SHADOW_TEMPLE_BOSS_KEY,
/* 0xB3 */ ITEM_GANONS_CASTLE_BOSS_KEY,
/* 0xB4 */ ITEM_DEKU_TREE_MAP,
/* 0xB5 */ ITEM_DODONGOS_CAVERN_MAP,
/* 0xB6 */ ITEM_JABU_JABUS_BELLY_MAP,
/* 0xB7 */ ITEM_FOREST_TEMPLE_MAP,
/* 0xB8 */ ITEM_FIRE_TEMPLE_MAP,
/* 0xB9 */ ITEM_WATER_TEMPLE_MAP,
/* 0xBA */ ITEM_SPIRIT_TEMPLE_MAP,
/* 0xBB */ ITEM_SHADOW_TEMPLE_MAP,
/* 0xBC */ ITEM_BOTTOM_OF_THE_WELL_MAP,
/* 0xBD */ ITEM_ICE_CAVERN_MAP,
/* 0xBE */ ITEM_DEKU_TREE_COMPASS,
/* 0xBF */ ITEM_DODONGOS_CAVERN_COMPASS,
/* 0xC0 */ ITEM_JABU_JABUS_BELLY_COMPASS,
/* 0xC1 */ ITEM_FOREST_TEMPLE_COMPASS,
/* 0xC2 */ ITEM_FIRE_TEMPLE_COMPASS,
/* 0xC3 */ ITEM_WATER_TEMPLE_COMPASS,
/* 0xC4 */ ITEM_SPIRIT_TEMPLE_COMPASS,
/* 0xC5 */ ITEM_SHADOW_TEMPLE_COMPASS,
/* 0xC6 */ ITEM_BOTTOM_OF_THE_WELL_COMPASS,
/* 0xC7 */ ITEM_ICE_CAVERN_COMPASS,
/* 0xFC */ ITEM_LAST_USED = 0xFC,
/* 0xFE */ ITEM_NONE_FE = 0xFE,
/* 0xFF */ ITEM_NONE = 0xFF
@ -397,39 +432,78 @@ typedef enum {
/* 0x82 */ GI_MEDALLION_SHADOW,
/* 0x83 */ GI_MEDALLION_SPIRIT,
/* 0x81 */ GI_STONE_KOKIRI,
/* 0x82 */ GI_STONE_GORON,
/* 0x83 */ GI_STONE_ZORA,
/* 0x84 */ GI_STONE_KOKIRI,
/* 0x85 */ GI_STONE_GORON,
/* 0x86 */ GI_STONE_ZORA,
/* 0x81 */ GI_ZELDAS_LULLABY,
/* 0x82 */ GI_SUNS_SONG,
/* 0x83 */ GI_EPONAS_SONG,
/* 0x81 */ GI_SONG_OF_STORMS,
/* 0x82 */ GI_SONG_OF_TIME,
/* 0x83 */ GI_SARIAS_SONG,
/* 0x87 */ GI_ZELDAS_LULLABY,
/* 0x88 */ GI_SUNS_SONG,
/* 0x89 */ GI_EPONAS_SONG,
/* 0x8A */ GI_SONG_OF_STORMS,
/* 0x8B */ GI_SONG_OF_TIME,
/* 0x8C */ GI_SARIAS_SONG,
/* 0x81 */ GI_MINUET_OF_FOREST,
/* 0x82 */ GI_BOLERO_OF_FIRE,
/* 0x83 */ GI_SERENADE_OF_WATER,
/* 0x81 */ GI_NOCTURNE_OF_SHADOW,
/* 0x82 */ GI_REQUIEM_OF_SPIRIT,
/* 0x83 */ GI_PRELUDE_OF_LIGHT,
/* 0x8D */ GI_MINUET_OF_FOREST,
/* 0x8E */ GI_BOLERO_OF_FIRE,
/* 0x8F */ GI_SERENADE_OF_WATER,
/* 0x90 */ GI_NOCTURNE_OF_SHADOW,
/* 0x91 */ GI_REQUIEM_OF_SPIRIT,
/* 0x92 */ GI_PRELUDE_OF_LIGHT,
GI_SINGLE_MAGIC,
GI_DOUBLE_MAGIC,
GI_DOUBLE_DEFENSE,
/* 0x93 */ GI_SINGLE_MAGIC,
/* 0x94 */ GI_DOUBLE_MAGIC,
/* 0x95 */ GI_DOUBLE_DEFENSE,
GI_BOTTLE_WITH_RED_POTION,
GI_BOTTLE_WITH_GREEN_POTION,
GI_BOTTLE_WITH_BLUE_POTION,
GI_BOTTLE_WITH_FAIRY,
GI_BOTTLE_WITH_FISH,
GI_BOTTLE_WITH_BLUE_FIRE,
GI_BOTTLE_WITH_BUGS,
GI_BOTTLE_WITH_POE,
GI_BOTTLE_WITH_BIG_POE,
/* 0x96 */ GI_BOTTLE_WITH_RED_POTION,
/* 0x97 */ GI_BOTTLE_WITH_GREEN_POTION,
/* 0x98 */ GI_BOTTLE_WITH_BLUE_POTION,
/* 0x99 */ GI_BOTTLE_WITH_FAIRY,
/* 0x9A */ GI_BOTTLE_WITH_FISH,
/* 0x9B */ GI_BOTTLE_WITH_BLUE_FIRE,
/* 0x9C */ GI_BOTTLE_WITH_BUGS,
/* 0x9D */ GI_BOTTLE_WITH_POE,
/* 0x9E */ GI_BOTTLE_WITH_BIG_POE,
/* 0x84 */ GI_MAX
/* 0x9F */ GI_GERUDO_FORTRESS_SMALL_KEY,
/* 0xA0 */ GI_FOREST_TEMPLE_SMALL_KEY,
/* 0xA1 */ GI_FIRE_TEMPLE_SMALL_KEY,
/* 0xA2 */ GI_WATER_TEMPLE_SMALL_KEY,
/* 0xA3 */ GI_SPIRIT_TEMPLE_SMALL_KEY,
/* 0xA4 */ GI_SHADOW_TEMPLE_SMALL_KEY,
/* 0xA5 */ GI_BOTTOM_OF_THE_WELL_SMALL_KEY,
/* 0xA6 */ GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY,
/* 0xA7 */ GI_GANONS_CASTLE_SMALL_KEY,
/* 0xA8 */ GI_FOREST_TEMPLE_BOSS_KEY,
/* 0xA9 */ GI_FIRE_TEMPLE_BOSS_KEY,
/* 0xAA */ GI_WATER_TEMPLE_BOSS_KEY,
/* 0xAB */ GI_SPIRIT_TEMPLE_BOSS_KEY,
/* 0xAC */ GI_SHADOW_TEMPLE_BOSS_KEY,
/* 0xAD */ GI_GANONS_CASTLE_BOSS_KEY,
/* 0xAE */ GI_DEKU_TREE_MAP,
/* 0xAF */ GI_DODONGOS_CAVERN_MAP,
/* 0xB0 */ GI_JABU_JABUS_BELLY_MAP,
/* 0xB1 */ GI_FOREST_TEMPLE_MAP,
/* 0xB2 */ GI_FIRE_TEMPLE_MAP,
/* 0xB3 */ GI_WATER_TEMPLE_MAP,
/* 0xB4 */ GI_SPIRIT_TEMPLE_MAP,
/* 0xB5 */ GI_SHADOW_TEMPLE_MAP,
/* 0xB6 */ GI_BOTTOM_OF_THE_WELL_MAP,
/* 0xB7 */ GI_ICE_CAVERN_MAP,
/* 0xB8 */ GI_DEKU_TREE_COMPASS,
/* 0xB9 */ GI_DODONGOS_CAVERN_COMPASS,
/* 0xBA */ GI_JABU_JABUS_BELLY_COMPASS,
/* 0xBB */ GI_FOREST_TEMPLE_COMPASS,
/* 0xBC */ GI_FIRE_TEMPLE_COMPASS,
/* 0xBD */ GI_WATER_TEMPLE_COMPASS,
/* 0xBE */ GI_SPIRIT_TEMPLE_COMPASS,
/* 0xBF */ GI_SHADOW_TEMPLE_COMPASS,
/* 0xC0 */ GI_BOTTOM_OF_THE_WELL_COMPASS,
/* 0xC1 */ GI_ICE_CAVERN_COMPASS,
/* 0xAE */ GI_MAX
} GetItemID;
typedef enum {

View File

@ -13,7 +13,7 @@ typedef struct {
/* 0x04 */ u16 objectId;
} GetItemEntry; // size = 0x06
extern GetItemEntry sGetItemTable[160];
extern GetItemEntry sGetItemTable[195];
typedef enum {
/* 0 */ PLAYER_SWORD_NONE,

View File

@ -175,7 +175,7 @@ typedef struct {
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator;
RandoSetting randoSettings[300];
ItemLocationRando itemLocations[500];
ItemLocationRando itemLocations[RC_MAX];
HintLocationRando hintLocations[50];
char childAltarText[250];
char adultAltarText[750];
@ -186,6 +186,7 @@ typedef struct {
u8 trialsDone[6];
u8 cowsMilked[10];
u8 temporaryWeapon;
u16 adultTradeItems;
} SaveContext; // size = 0x1428
typedef enum {

View File

@ -118,6 +118,7 @@ bool CustomMessageManager::ClearMessageTable(std::string tableID) {
}
auto& messageTable = foundMessageTable->second;
messageTable.clear();
return true;
}
bool CustomMessageManager::AddCustomMessageTable(std::string tableID) {

View File

@ -34,12 +34,12 @@ extern GlobalContext* gGlobalCtx;
static bool ActorSpawnHandler(const std::vector<std::string>& args) {
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
ERROR("Not enough arguments passed to actorspawn");
SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn");
return CMD_FAILED;
}
if (gGlobalCtx == nullptr) {
ERROR("GlobalCtx == nullptr");
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED;
}
@ -75,7 +75,7 @@ static bool ActorSpawnHandler(const std::vector<std::string>& args) {
if (Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z,
spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) {
ERROR("Failed to spawn actor. Actor_Spawn returned NULL");
SohImGui::console->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL");
return CMD_FAILED;
}
return CMD_SUCCESS;
@ -84,14 +84,13 @@ static bool ActorSpawnHandler(const std::vector<std::string>& args) {
static bool KillPlayerHandler([[maybe_unused]] const std::vector<std::string>&) {
gSaveContext.health = 0;
INFO("[SOH] You've met with a terrible fate, haven't you?");
SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?");
return CMD_SUCCESS;
}
static bool SetPlayerHealthHandler(const std::vector<std::string>& args) {
if (args.size() != 2) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -100,18 +99,18 @@ static bool SetPlayerHealthHandler(const std::vector<std::string>& args) {
try {
health = std::stoi(args[1]);
} catch (std::invalid_argument const& ex) {
ERROR("[SOH] Health value must be an integer.");
SohImGui::console->SendErrorMessage("[SOH] Health value must be an integer.");
return CMD_FAILED;
}
if (health < 0) {
ERROR("[SOH] Health value must be a positive integer");
SohImGui::console->SendErrorMessage("[SOH] Health value must be a positive integer");
return CMD_SUCCESS;
}
gSaveContext.health = health * 0x10;
INFO("[SOH] Player health updated to %d", health);
SohImGui::console->SendInfoMessage("[SOH] Player health updated to %d", health);
return CMD_SUCCESS;
}
@ -133,31 +132,32 @@ static bool RuppeHandler(const std::vector<std::string>& args) {
rupeeAmount = std::stoi(args[1]);
}
catch (std::invalid_argument const& ex) {
ERROR("[SOH] Rupee count must be an integer.");
SohImGui::console->SendErrorMessage("[SOH] Rupee count must be an integer.");
return CMD_FAILED;
}
if (rupeeAmount < 0) {
ERROR("[SOH] Rupee count must be positive");
SohImGui::console->SendErrorMessage("[SOH] Rupee count must be positive");
return CMD_FAILED;
}
gSaveContext.rupees = rupeeAmount;
INFO("Set rupee count to %u", rupeeAmount);
SohImGui::console->SendInfoMessage("Set rupee count to %u", rupeeAmount);
return CMD_SUCCESS;
}
static bool SetPosHandler(const std::vector<std::string> args) {
if (gGlobalCtx == nullptr) {
ERROR("GlobalCtx == nullptr");
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED;
}
Player* player = GET_PLAYER(gGlobalCtx);
if (args.size() == 1) {
INFO("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y,
SohImGui::console->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x,
player->actor.world.pos.y,
player->actor.world.pos.z);
return CMD_SUCCESS;
}
@ -168,14 +168,15 @@ static bool SetPosHandler(const std::vector<std::string> args) {
player->actor.world.pos.y = std::stof(args[2]);
player->actor.world.pos.z = std::stof(args[3]);
INFO("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y,
SohImGui::console->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x,
player->actor.world.pos.y,
player->actor.world.pos.z);
return CMD_SUCCESS;
}
static bool ResetHandler(std::vector<std::string> args) {
if (gGlobalCtx == nullptr) {
ERROR("GlobalCtx == nullptr");
SohImGui::console->SendErrorMessage("GlobalCtx == nullptr");
return CMD_FAILED;
}
@ -196,7 +197,7 @@ const static std::map<std::string, uint16_t> ammoItems{
static bool AmmoHandler(const std::vector<std::string>& args) {
if (args.size() != 3) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -205,19 +206,19 @@ static bool AmmoHandler(const std::vector<std::string>& args) {
try {
count = std::stoi(args[2]);
} catch (std::invalid_argument const& ex) {
ERROR("Ammo count must be an integer");
SohImGui::console->SendErrorMessage("Ammo count must be an integer");
return CMD_FAILED;
}
if (count < 0) {
ERROR("Ammo count must be positive");
SohImGui::console->SendErrorMessage("Ammo count must be positive");
return CMD_FAILED;
}
const auto& it = ammoItems.find(args[1]);
if (it == ammoItems.end()) {
ERROR("Invalid item passed");
SohImGui::console->SendErrorMessage("Invalid item passed");
return CMD_FAILED;
}
@ -239,7 +240,7 @@ const static std::map<std::string, uint16_t> bottleItems{
static bool BottleHandler(const std::vector<std::string>& args) {
if (args.size() != 3) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -247,19 +248,19 @@ static bool BottleHandler(const std::vector<std::string>& args) {
try {
slot = std::stoi(args[2]);
} catch (std::invalid_argument const& ex) {
ERROR("[SOH] Bottle slot must be an integer.");
SohImGui::console->SendErrorMessage("[SOH] Bottle slot must be an integer.");
return CMD_FAILED;
}
if ((slot < 1) || (slot > 4)) {
ERROR("Invalid slot passed");
SohImGui::console->SendErrorMessage("Invalid slot passed");
return CMD_FAILED;
}
const auto& it = bottleItems.find(args[1]);
if (it == bottleItems.end()) {
ERROR("Invalid item passed");
SohImGui::console->SendErrorMessage("Invalid item passed");
return CMD_FAILED;
}
@ -271,7 +272,7 @@ static bool BottleHandler(const std::vector<std::string>& args) {
static bool BHandler(const std::vector<std::string>& args) {
if (args.size() != 2) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -281,7 +282,7 @@ static bool BHandler(const std::vector<std::string>& args) {
static bool ItemHandler(const std::vector<std::string>& args) {
if (args.size() != 3) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -292,7 +293,7 @@ static bool ItemHandler(const std::vector<std::string>& args) {
static bool EntranceHandler(const std::vector<std::string>& args) {
if (args.size() != 2) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
@ -301,11 +302,11 @@ static bool EntranceHandler(const std::vector<std::string>& args) {
try {
entrance = std::stoi(args[1], nullptr, 16);
} catch (std::invalid_argument const& ex) {
ERROR("[SOH] Entrance value must be a Hex number.");
SohImGui::console->SendErrorMessage("[SOH] Entrance value must be a Hex number.");
return CMD_FAILED;
}
gGlobalCtx->nextEntranceIndex = entrance;
gGlobalCtx->nextEntranceIndex = entrance;
gGlobalCtx->sceneLoadFlag = 0x14;
gGlobalCtx->fadeTransition = 11;
gSaveContext.nextTransition = 11;
@ -317,10 +318,10 @@ static bool SaveStateHandler(const std::vector<std::string>& args) {
switch (rtn) {
case SaveStateReturn::SUCCESS:
INFO("[SOH] Saved state to slot %u", slot);
SohImGui::console->SendInfoMessage("[SOH] Saved state to slot %u", slot);
return CMD_SUCCESS;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
ERROR("[SOH] Can not save a state outside of \"GamePlay\"");
SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\"");
return CMD_FAILED;
}
@ -332,16 +333,16 @@ static bool LoadStateHandler(const std::vector<std::string>& args) {
switch (rtn) {
case SaveStateReturn::SUCCESS:
INFO("[SOH] Loaded state from slot %u", slot);
SohImGui::console->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot);
return CMD_SUCCESS;
case SaveStateReturn::FAIL_INVALID_SLOT:
ERROR("[SOH] Invalid State Slot Number (%u)", slot);
SohImGui::console->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot);
return CMD_FAILED;
case SaveStateReturn::FAIL_STATE_EMPTY:
ERROR("[SOH] State Slot (%u) is empty", slot);
SohImGui::console->SendErrorMessage("[SOH] State Slot (%u) is empty", slot);
return CMD_FAILED;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
ERROR("[SOH] Can not load a state outside of \"GamePlay\"");
SohImGui::console->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\"");
return CMD_FAILED;
}
@ -349,7 +350,7 @@ static bool LoadStateHandler(const std::vector<std::string>& args) {
static bool StateSlotSelectHandler(const std::vector<std::string>& args) {
if (args.size() != 2) {
ERROR("[SOH] Unexpected arguments passed");
SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
int slot;
@ -357,17 +358,18 @@ static bool StateSlotSelectHandler(const std::vector<std::string>& args) {
try {
slot = std::stoi(args[1], nullptr, 10);
} catch (std::invalid_argument const& ex) {
ERROR("[SOH] SaveState slot value must be a number.");
SohImGui::console->SendErrorMessage("[SOH] SaveState slot value must be a number.");
return CMD_FAILED;
}
if (slot < 0) {
ERROR("[SOH] Invalid slot passed. Slot must be between 0 and 2");
SohImGui::console->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2");
return CMD_FAILED;
}
OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot);
INFO("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
SohImGui::console->SendInfoMessage("[SOH] Slot %u selected",
OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
return CMD_SUCCESS;
}
@ -427,7 +429,7 @@ static bool SetCVarHandler(const std::vector<std::string>& args) {
CVar_Save();
//INFO("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z);
//SohImGui::console->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z);
return CMD_SUCCESS;
}
@ -441,17 +443,17 @@ static bool GetCVarHandler(const std::vector<std::string>& args) {
if (cvar != nullptr)
{
if (cvar->type == CVarType::S32)
INFO("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32);
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32);
else if (cvar->type == CVarType::Float)
INFO("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat);
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat);
else if (cvar->type == CVarType::String)
INFO("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr);
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr);
else if (cvar->type == CVarType::RGBA)
INFO("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA);
SohImGui::console->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA);
}
else
{
INFO("[SOH] Could not find variable %s", args[1].c_str());
SohImGui::console->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str());
}

View File

@ -1,5 +1,6 @@
#include "debugSaveEditor.h"
#include "../../util.h"
#include "../../OTRGlobals.h"
#include "../libultraship/ImGuiImpl.h"
#include "ImGuiHelpers.h"
@ -14,6 +15,7 @@ extern "C" {
#include "variables.h"
#include "functions.h"
#include "macros.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
extern GlobalContext* gGlobalCtx;
#include "textures/icon_item_static/icon_item_static.h"
@ -525,6 +527,24 @@ void DrawInfoTab() {
ImGui::PopItemWidth();
}
void DrawBGSItemFlag(uint8_t itemID) {
const ItemMapEntry& slotEntry = itemMapping[itemID];
ImGui::Image(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1));
ImGui::SameLine();
int tradeIndex = itemID - ITEM_POCKET_EGG;
bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0;
ImGui::Checkbox(("##adultTradeFlag" + std::to_string(itemID)).c_str(), &hasItem);
if (hasItem) {
gSaveContext.adultTradeItems |= (1 << tradeIndex);
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_NONE) {
INV_CONTENT(ITEM_TRADE_ADULT) = ITEM_POCKET_EGG + tradeIndex;
}
} else {
gSaveContext.adultTradeItems &= ~(1 << tradeIndex);
Inventory_ReplaceItem(gGlobalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem());
}
}
void DrawInventoryTab() {
static bool restrictToValid = true;
@ -596,6 +616,17 @@ void DrawInventoryTab() {
if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f),
ImVec2(0, 0), ImVec2(1, 1), 0)) {
gSaveContext.inventory.items[selectedIndex] = slotEntry.id;
// Set adult trade item flag if you're playing adult trade shuffle in rando
if (gSaveContext.n64ddFlag &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
selectedIndex == SLOT_TRADE_ADULT) {
if (slotEntry.id == ITEM_NONE) {
gSaveContext.adultTradeItems = 0;
} else if (slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) {
uint32_t tradeID = slotEntry.id - ITEM_POCKET_EGG;
gSaveContext.adultTradeItems |= tradeID;
}
}
ImGui::CloseCurrentPopup();
}
SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id));
@ -632,6 +663,16 @@ void DrawInventoryTab() {
ImGui::PopID();
}
}
// Trade quest flags are only used when shuffling the trade sequence, so
// don't show this if it isn't needed.
if (gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE)
&& ImGui::TreeNode("Adult trade quest items")) {
for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) {
DrawBGSItemFlag(i);
}
ImGui::TreePop();
}
}
// Draw a flag bitfield as an grid of checkboxes

View File

@ -156,7 +156,7 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve
//Entrances shouldn't connect to their own scene, fail in this situation
if (entrance->GetParentRegion()->scene != "" && entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene) {
auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " + target->to_string() + ". Connection failed.\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
}
@ -168,7 +168,7 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve
//Change connections between an entrance and a target assumed entrance, in order to test the connections afterwards if necessary
static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) {
auto message = "Attempting to connect " + entrance->GetName() + " to " + targetEntrance->to_string() + "\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
entrance->Connect(targetEntrance->Disconnect());
entrance->SetReplacement(targetEntrance->GetReplacement());
if (entrance->GetReverse() != nullptr /*&& entrances aren't decoupled*/) {
@ -208,7 +208,7 @@ static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) {
static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<Entrance*>& alreadyChecked) {
if (entrance == nullptr) {
SPDLOG_INFO("Entrance is nullptr in EntranceUnreachableAs()");
SPDLOG_DEBUG("Entrance is nullptr in EntranceUnreachableAs()");
return true;
}
@ -247,7 +247,7 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<E
}
static bool ValidateWorld(Entrance* entrancePlaced) {
SPDLOG_INFO("Validating world\n");
SPDLOG_DEBUG("Validating world\n");
//check certain conditions when certain types of ER are enabled
EntranceType type = EntranceType::None;
@ -285,11 +285,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
if (ElementInContainer(replacementName, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) {
auto message = replacementName + " is replaced by an entrance with a potential child access\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
} else if (ElementInContainer(replacementName, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) {
auto message = replacementName + " is replaced by an entrance with a potential adult access\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
}
}
@ -299,11 +299,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
if (ElementInContainer(name, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) {
auto message = name + " is potentially accessible as child\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
} else if (ElementInContainer(name, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) {
auto message = name + " is potentially accessible as adult\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
}
}
@ -317,7 +317,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
auto impasHouseBackHintRegion = GetHintRegionHintKey(KAK_IMPAS_HOUSE_BACK);
if (impasHouseFrontHintRegion != NONE && impasHouseBackHintRegion != NONE && impasHouseBackHintRegion != LINKS_POCKET && impasHouseFrontHintRegion != LINKS_POCKET && impasHouseBackHintRegion != impasHouseFrontHintRegion) {
auto message = "Kak Impas House entrances are not in the same hint area\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
return false;
}
}
@ -328,23 +328,23 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
if (checkOtherEntranceAccess) {
// At least one valid starting region with all basic refills should be reachable without using any items at the beginning of the seed
if (!AreaTable(KOKIRI_FOREST)->HasAccess() && !AreaTable(KAKARIKO_VILLAGE)->HasAccess()) {
SPDLOG_INFO("Invalid starting area\n");
SPDLOG_DEBUG("Invalid starting area\n");
return false;
}
// Check that a region where time passes is always reachable as both ages without having collected any items
if (!Areas::HasTimePassAccess(AGE_CHILD) || !Areas::HasTimePassAccess(AGE_ADULT)) {
SPDLOG_INFO("Time passing is not guaranteed as both ages\n");
SPDLOG_DEBUG("Time passing is not guaranteed as both ages\n");
return false;
}
// The player should be able to get back to ToT after going through time, without having collected any items
// This is important to ensure that the player never loses access to the pedestal after going through time
if (Settings::ResolvedStartingAge == AGE_CHILD && !AreaTable(TEMPLE_OF_TIME)->Adult()) {
SPDLOG_INFO("Path to Temple of Time as adult is not guaranteed\n");
SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n");
return false;
} else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(TEMPLE_OF_TIME)->Child()) {
SPDLOG_INFO("Path to Temple of Time as child is not guaranteed\n");
SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n");
return false;
}
}
@ -353,11 +353,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
// This is important to ensure that players can never lock their only bottles by filling them with Big Poes they can't sell
if (checkPoeCollectorAccess) {
if (!AreaTable(MARKET_GUARD_HOUSE)->Adult()) {
SPDLOG_INFO("Big Poe Shop access is not guarenteed as adult\n");
SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n");
return false;
}
}
SPDLOG_INFO("All Locations NOT REACHABLE\n");
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
return false;
}
return true;
@ -476,7 +476,7 @@ static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vecto
}
if (retries <= 0) {
SPDLOG_INFO("Entrance placement attempt count exceeded. Restarting randomization completely");
SPDLOG_DEBUG("Entrance placement attempt count exceeded. Restarting randomization completely");
entranceShuffleFailure = true;
}
}
@ -840,7 +840,7 @@ void CreateEntranceOverrides() {
if (noRandomEntrances) {
return;
}
SPDLOG_INFO("\nCREATING ENTRANCE OVERRIDES\n");
SPDLOG_DEBUG("\nCREATING ENTRANCE OVERRIDES\n");
auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false);
for (Entrance* entrance : allShuffleableEntrances) {
@ -851,7 +851,7 @@ void CreateEntranceOverrides() {
}
auto message = "Setting " + entrance->to_string() + "\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
int16_t originalIndex = entrance->GetIndex();
int16_t destinationIndex = entrance->GetReverse()->GetIndex();
@ -868,9 +868,9 @@ void CreateEntranceOverrides() {
});
message = "\tOriginal: " + std::to_string(originalIndex) + "\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
message = "\tReplacement " + std::to_string(replacementIndex) + "\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
}
}

View File

@ -420,7 +420,7 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
if (!Location(loc)->IsAddedToPool()) {
allLocationsReachable = false;
auto message = "Location " + Location(loc)->GetName() + " not reachable\n";
SPDLOG_INFO(message);
SPDLOG_DEBUG(message);
#ifndef ENABLE_DEBUG
break;
#endif
@ -567,17 +567,17 @@ static void AssumedFill(const std::vector<uint32_t>& items, const std::vector<ui
if (items.size() > allowedLocations.size()) {
printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS");
SPDLOG_INFO("Items:\n");
SPDLOG_DEBUG("Items:\n");
for (const uint32_t item : items) {
SPDLOG_INFO("\t");
SPDLOG_INFO(ItemTable(item).GetName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\t");
SPDLOG_DEBUG(ItemTable(item).GetName().GetEnglish());
SPDLOG_DEBUG("\n");
}
SPDLOG_INFO("\nAllowed Locations:\n");
SPDLOG_DEBUG("\nAllowed Locations:\n");
for (const uint32_t loc : allowedLocations) {
SPDLOG_INFO("\t");
SPDLOG_INFO(Location(loc)->GetName());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\t");
SPDLOG_DEBUG(Location(loc)->GetName());
SPDLOG_DEBUG("\n");
}
placementFailure = true;
return;
@ -627,9 +627,9 @@ static void AssumedFill(const std::vector<uint32_t>& items, const std::vector<ui
// retry if there are no more locations to place items
if (accessibleLocations.empty()) {
SPDLOG_INFO("\nCANNOT PLACE ");
SPDLOG_INFO(ItemTable(item).GetName().GetEnglish());
SPDLOG_INFO(". TRYING AGAIN...\n");
SPDLOG_DEBUG("\nCANNOT PLACE ");
SPDLOG_DEBUG(ItemTable(item).GetName().GetEnglish());
SPDLOG_DEBUG(". TRYING AGAIN...\n");
#ifdef ENABLE_DEBUG
Areas::DumpWorldGraph(ItemTable(item).GetName().GetEnglish());
@ -666,7 +666,7 @@ static void AssumedFill(const std::vector<uint32_t>& items, const std::vector<ui
LogicReset();
GetAccessibleLocations(allLocations, SearchMode::CheckBeatable);
if (playthroughBeatable) {
SPDLOG_INFO("Game beatable, now placing items randomly. " + std::to_string(itemsToPlace.size()) +
SPDLOG_DEBUG("Game beatable, now placing items randomly. " + std::to_string(itemsToPlace.size()) +
" major items remaining.\n\n");
FastFill(itemsToPlace, GetEmptyLocations(allowedLocations), true);
return;
@ -1062,7 +1062,7 @@ int Fill() {
}
//Unsuccessful placement
if(retries < 4) {
SPDLOG_INFO("\nGOT STUCK. RETRYING...\n");
SPDLOG_DEBUG("\nGOT STUCK. RETRYING...\n");
Areas::ResetAllLocations();
LogicReset();
ClearProgress();

View File

@ -206,23 +206,23 @@ static void AddHint(Text hint, const uint32_t gossipStone, const std::vector<uin
static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocations) {
//return if there aren't any hintable locations or gossip stones available
if (possibleHintLocations.empty()) {
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
const std::vector<uint32_t> accessibleGossipStones = GetAccessibleGossipStones(hintedLocation);
SPDLOG_INFO("\tLocation: ");
SPDLOG_INFO(Location(hintedLocation)->GetName());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_INFO("\tItem: ");
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
if (accessibleGossipStones.empty()) {
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
@ -235,9 +235,9 @@ static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocation
Text prefix = Hint(PREFIX).GetText();
Text finalHint = prefix + locationHintText + " #"+itemHintText+"#.";
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(finalHint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED});
}
@ -258,24 +258,24 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
// If no more locations can be hinted at for woth, then just try to get another hint
if (possibleHintLocations.empty()) {
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
SPDLOG_INFO("\tLocation: ");
SPDLOG_INFO(Location(hintedLocation)->GetName());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_INFO("\tItem: ");
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
// get an accessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
@ -293,9 +293,9 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
locationText = GetHintRegion(parentRegion)->GetHint().GetText();
}
Text finalWothHint = Hint(PREFIX).GetText() + "#" + locationText + "#" + Hint(WAY_OF_THE_HERO).GetText();
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(finalWothHint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalWothHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalWothHint, gossipStone, { QM_LBLUE });
}
@ -312,18 +312,18 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector<u
uint32_t hintedLocation = RandomElement(barrenLocations, true);
SPDLOG_INFO("\tLocation: ");
SPDLOG_INFO(Location(hintedLocation)->GetName());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_INFO("\tItem: ");
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
// get an accessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
@ -341,9 +341,9 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector<u
}
Text finalBarrenHint =
Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "#" + locationText + "#" + Hint(FOOLISH).GetText();
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(finalBarrenHint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalBarrenHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalBarrenHint, gossipStone, { QM_PINK });
// get rid of all other locations in this same barren region
@ -359,23 +359,23 @@ static void CreateRandomLocationHint(const bool goodItem = false) {
});
//If no more locations can be hinted at, then just try to get another hint
if (possibleHintLocations.empty()) {
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
SPDLOG_INFO("\tLocation: ");
SPDLOG_INFO(Location(hintedLocation)->GetName());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_INFO("\tItem: ");
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
//get an acessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
@ -387,16 +387,16 @@ static void CreateRandomLocationHint(const bool goodItem = false) {
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
Text locationText = AreaTable(parentRegion)->GetHint().GetText();
Text finalHint = Hint(PREFIX).GetText()+"#"+locationText+"# "+Hint(HOARDS).GetText()+" #"+itemText+"#.";
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(finalHint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED});
} else {
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text finalHint = Hint(PREFIX).GetText()+"#"+itemText+"# "+Hint(CAN_BE_FOUND_AT).GetText()+" #"+locationText+"#.";
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(finalHint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalHint, gossipStone, {QM_RED, QM_GREEN});
}
}
@ -411,15 +411,15 @@ static void CreateJunkHint() {
LogicReset();
const std::vector<uint32_t> gossipStones = GetAccessibleLocations(gossipStoneLocations);
if (gossipStones.empty()) {
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
uint32_t gossipStone = RandomElement(gossipStones);
Text hint = junkHint.GetText();
SPDLOG_INFO("\tMessage: ");
SPDLOG_INFO(hint.english);
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(hint.english);
SPDLOG_DEBUG("\n\n");
AddHint(hint, gossipStone, {QM_PINK});
}
@ -711,7 +711,7 @@ void CreateAllHints() {
CreateGanonText();
CreateAltarText();
SPDLOG_INFO("\nNOW CREATING HINTS\n");
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
uint8_t remainingDungeonWothHints = hintSetting.dungeonsWothLimit;
@ -768,9 +768,9 @@ void CreateAllHints() {
barrenDungeons.push_back(barrenRegion);
}
}
SPDLOG_INFO("\nBarren Dungeons:\n");
SPDLOG_DEBUG("\nBarren Dungeons:\n");
for (std::string barrenDungeon : barrenDungeons) {
SPDLOG_INFO(barrenDungeon + "\n");
SPDLOG_DEBUG(barrenDungeon + "\n");
}
//Get list of all woth dungeons
@ -783,9 +783,9 @@ void CreateAllHints() {
wothDungeons.push_back(wothRegion);
}
}
SPDLOG_INFO("\nWoth Dungeons:\n");
SPDLOG_DEBUG("\nWoth Dungeons:\n");
for (std::string wothDungeon : wothDungeons) {
SPDLOG_INFO(wothDungeon + "\n");
SPDLOG_DEBUG(wothDungeon + "\n");
}
//Set DungeonInfo array for each dungeon
@ -827,9 +827,9 @@ void CreateAllHints() {
//get a random hint type from the remaining hints
HintType type = RandomElement(remainingHintTypes, true);
SPDLOG_INFO("Attempting to make hint of type: ");
SPDLOG_INFO(hintTypeNames[static_cast<int>(type)]);
SPDLOG_INFO("\n");
SPDLOG_DEBUG("Attempting to make hint of type: ");
SPDLOG_DEBUG(hintTypeNames[static_cast<int>(type)]);
SPDLOG_DEBUG("\n");
//create the appropriate hint for the type
if (type == HintType::Woth) {

View File

@ -103,11 +103,11 @@ public:
return false;
}
if ((type == ITEMTYPE_BOSSKEY && getItemId != 0x9A) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
return false;
}
//Ganons Castle Boss Key
if (getItemId == 0x9A && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
return false;
}

View File

@ -1470,11 +1470,11 @@ void GenerateLocationPool() {
void PlaceItemInLocation(uint32_t locKey, uint32_t item, bool applyEffectImmediately /*= false*/, bool setHidden /*= false*/) {
auto loc = Location(locKey);
SPDLOG_INFO("\n");
SPDLOG_INFO(ItemTable(item).GetName().GetEnglish());
SPDLOG_INFO(" placed at ");
SPDLOG_INFO(loc->GetName());
SPDLOG_INFO("\n\n");
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG(ItemTable(item).GetName().GetEnglish());
SPDLOG_DEBUG(" placed at ");
SPDLOG_DEBUG(loc->GetName());
SPDLOG_DEBUG("\n\n");
if (applyEffectImmediately || Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
ItemTable(item).ApplyEffect();
@ -1561,7 +1561,7 @@ void AddExcludedOptions() {
}
void CreateItemOverrides() {
SPDLOG_INFO("NOW CREATING OVERRIDES\n\n");
SPDLOG_DEBUG("NOW CREATING OVERRIDES\n\n");
for (uint32_t locKey : allLocations) {
auto loc = Location(locKey);
ItemOverride_Value val = ItemTable(loc->GetPlaceduint32_t()).Value();
@ -1573,18 +1573,18 @@ void CreateItemOverrides() {
.key = loc->Key(),
.value = val,
});
SPDLOG_INFO("\tScene: ");
SPDLOG_INFO(std::to_string(loc->Key().scene));
SPDLOG_INFO("\tType: ");
SPDLOG_INFO(std::to_string(loc->Key().type));
SPDLOG_INFO("\tFlag: ");
SPDLOG_INFO(std::to_string(loc->Key().flag));
SPDLOG_INFO("\t");
SPDLOG_INFO(loc->GetName());
SPDLOG_INFO(": ");
SPDLOG_INFO(loc->GetPlacedItemName().GetEnglish());
SPDLOG_INFO("\n");
SPDLOG_DEBUG("\tScene: ");
SPDLOG_DEBUG(std::to_string(loc->Key().scene));
SPDLOG_DEBUG("\tType: ");
SPDLOG_DEBUG(std::to_string(loc->Key().type));
SPDLOG_DEBUG("\tFlag: ");
SPDLOG_DEBUG(std::to_string(loc->Key().flag));
SPDLOG_DEBUG("\t");
SPDLOG_DEBUG(loc->GetName());
SPDLOG_DEBUG(": ");
SPDLOG_DEBUG(loc->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
}
SPDLOG_INFO("Overrides Created: ");
SPDLOG_INFO(std::to_string(overrides.size()));
SPDLOG_DEBUG("Overrides Created: ");
SPDLOG_DEBUG(std::to_string(overrides.size()));
}

View File

@ -1184,6 +1184,6 @@ void GenerateItemPool() {
}
void AddJunk() {
SPDLOG_INFO("HAD TO PLACE EXTRA JUNK ");
SPDLOG_DEBUG("HAD TO PLACE EXTRA JUNK ");
AddItemToMainPool(GetPendingJunkItem());
}

View File

@ -26,13 +26,13 @@ Menu* currentMenu;
} // namespace
void PrintTopScreen() {
SPDLOG_INFO("\x1b[2;11H%sOcarina of Time 3D Randomizer%s", CYAN, RESET);
SPDLOG_INFO("\x1b[3;18H%s%s-%s%s", CYAN, RANDOMIZER_VERSION, COMMIT_NUMBER, RESET);
SPDLOG_INFO("\x1b[4;10HA/B/D-pad: Navigate Menu\n");
SPDLOG_INFO(" Select: Exit to Homebrew Menu\n");
SPDLOG_INFO(" Y: New Random Seed\n");
SPDLOG_INFO(" X: Input Custom Seed\n");
SPDLOG_INFO("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str());
SPDLOG_DEBUG("\x1b[2;11H%sOcarina of Time 3D Randomizer%s", CYAN, RESET);
SPDLOG_DEBUG("\x1b[3;18H%s%s-%s%s", CYAN, RANDOMIZER_VERSION, COMMIT_NUMBER, RESET);
SPDLOG_DEBUG("\x1b[4;10HA/B/D-pad: Navigate Menu\n");
SPDLOG_DEBUG(" Select: Exit to Homebrew Menu\n");
SPDLOG_DEBUG(" Y: New Random Seed\n");
SPDLOG_DEBUG(" X: Input Custom Seed\n");
SPDLOG_DEBUG("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str());
}
void MenuInit() {
@ -526,7 +526,7 @@ std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t>
if (ret == -1) { // Failed to generate after 5 tries
printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be "
"successful.");
SPDLOG_INFO("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");
SPDLOG_DEBUG("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");
return "";
} else {
printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret);

View File

@ -2537,6 +2537,8 @@ namespace Settings {
ShuffleGerudoToken.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]);
ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]);
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);
@ -2544,14 +2546,7 @@ namespace Settings {
StartingDekuShield.SetSelectedIndex(cvarSettings[RSK_STARTING_DEKU_SHIELD]);
StartingKokiriSword.SetSelectedIndex(cvarSettings[RSK_STARTING_KOKIRI_SWORD]);
if(cvarSettings[RSK_STARTING_MAPS_COMPASSES]) {
// "Start With" is index 0
MapsAndCompasses.SetSelectedIndex(0);
} else {
// We don't support maps/compasses outside of their own dungeon yet
// "Own Dungeon" is index 2
MapsAndCompasses.SetSelectedIndex(2);
}
MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]);
StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]);
StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]);
@ -2563,6 +2558,9 @@ namespace Settings {
ItemPoolValue.SetSelectedIndex(cvarSettings[RSK_ITEM_POOL]);
IceTrapValue.SetSelectedIndex(cvarSettings[RSK_ICE_TRAPS]);
Keysanity.SetSelectedIndex(cvarSettings[RSK_KEYSANITY]);
GerudoKeys.SetSelectedIndex(cvarSettings[RSK_GERUDO_KEYS]);
BossKeysanity.SetSelectedIndex(cvarSettings[RSK_BOSS_KEYSANITY]);
GanonsBossKey.SetSelectedIndex(cvarSettings[RSK_GANONS_BOSS_KEY]);
NumRequiredCuccos.SetSelectedIndex(cvarSettings[RSK_CUCCO_COUNT]);
@ -2572,6 +2570,8 @@ namespace Settings {
SkipTowerEscape.SetSelectedIndex(cvarSettings[RSK_SKIP_TOWER_ESCAPE]);
CompleteMaskQuest.SetSelectedIndex(cvarSettings[RSK_COMPLETE_MASK_QUEST]);
NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]);
// RANDOTODO implement chest shuffle with keysanity

View File

@ -347,7 +347,8 @@ static void WriteSettings(const bool printAll = false) {
setting->GetName() == "Cuccos to return" ||
setting->GetName() == "Skip Epona Race" ||
setting->GetName() == "Skip Tower Escape" ||
setting->GetName() == "Skip Child Stealth") {
setting->GetName() == "Skip Child Stealth" ||
setting->GetName() == "Complete Mask Quest") {
std::string settingName = menu->name + ":" + setting->GetName();
jsonData["settings"][settingName] = setting->GetSelectedOptionText();
}

View File

@ -0,0 +1,33 @@
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#include "functions.h"
#include "variables.h"
#include "macros.h"
void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId) {
gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId);
Inventory_ReplaceItem(globalCtx, itemId, Randomizer_GetNextAdultTradeItem());
}
u8 Randomizer_GetNextAdultTradeItem() {
const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1;
u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG;
for (int i = 0; i < numTradeItems; i++) {
u8 tradeIndex = (currentTradeItemIndex + i + 1) % numTradeItems;
if (gSaveContext.adultTradeItems & (1 << tradeIndex)) {
return ITEM_POCKET_EGG + tradeIndex;
}
}
return ITEM_NONE;
}
u8 Randomizer_GetPrevAdultTradeItem() {
const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1;
u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG;
for (int i = 0; i < numTradeItems; i++) {
u8 tradeIndex = (currentTradeItemIndex - i - 1 + numTradeItems) % numTradeItems;
if (gSaveContext.adultTradeItems & (1 << tradeIndex)) {
return ITEM_POCKET_EGG + tradeIndex;
}
}
return ITEM_NONE;
}

View File

@ -0,0 +1,12 @@
#ifndef Z_ADULT_TRADE_SHUFFLE_H
#define Z_ADULT_TRADE_SHUFFLE_H
#include <z64.h>
#define ADULT_TRADE_FLAG(itemId) (1 << (itemId - ITEM_POCKET_EGG))
void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId);
u8 Randomizer_GetNextAdultTradeItem();
u8 Randomizer_GetPrevAdultTradeItem();
#endif

View File

@ -1005,6 +1005,41 @@ std::unordered_map<s16, s16> itemIdToModel = { { GI_NONE, GID_MAXIMUM },
{ GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT },
{ GI_SINGLE_MAGIC, GID_MAGIC_SMALL },
{ GI_DOUBLE_MAGIC, GID_MAGIC_LARGE },
{ GI_GERUDO_FORTRESS_SMALL_KEY, GID_KEY_SMALL },
{ GI_FOREST_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_FIRE_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_WATER_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_SPIRIT_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_SHADOW_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_BOTTOM_OF_THE_WELL_SMALL_KEY, GID_KEY_SMALL },
{ GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, GID_KEY_SMALL },
{ GI_GANONS_CASTLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_FOREST_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_FIRE_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_WATER_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_SPIRIT_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_SHADOW_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_GANONS_CASTLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_DEKU_TREE_MAP, GID_DUNGEON_MAP },
{ GI_DODONGOS_CAVERN_MAP, GID_DUNGEON_MAP },
{ GI_JABU_JABUS_BELLY_MAP, GID_DUNGEON_MAP },
{ GI_FOREST_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_FIRE_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_WATER_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_SPIRIT_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_SHADOW_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_BOTTOM_OF_THE_WELL_MAP, GID_DUNGEON_MAP },
{ GI_ICE_CAVERN_MAP, GID_DUNGEON_MAP },
{ GI_DEKU_TREE_COMPASS, GID_COMPASS },
{ GI_DODONGOS_CAVERN_COMPASS, GID_COMPASS },
{ GI_JABU_JABUS_BELLY_COMPASS, GID_COMPASS },
{ GI_FOREST_TEMPLE_COMPASS, GID_COMPASS },
{ GI_FIRE_TEMPLE_COMPASS, GID_COMPASS },
{ GI_WATER_TEMPLE_COMPASS, GID_COMPASS },
{ GI_SPIRIT_TEMPLE_COMPASS, GID_COMPASS },
{ GI_SHADOW_TEMPLE_COMPASS, GID_COMPASS },
{ GI_BOTTOM_OF_THE_WELL_COMPASS, GID_COMPASS },
{ GI_ICE_CAVERN_COMPASS, GID_COMPASS },
{ GI_ICE_TRAP, GID_RUPEE_GOLD },
{ GI_ICE_TRAP, GID_MAXIMUM },
{ GI_TEXT_0, GID_MAXIMUM } };
@ -1408,10 +1443,14 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT },
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
{ "Shuffle Dungeon Items:Start with Maps/Compasses", RSK_STARTING_MAPS_COMPASSES },
{ "Shuffle Dungeon Items:Small Keys", RSK_KEYSANITY },
{ "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS },
{ "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY },
{ "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY },
{ "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS },
{ "Misc Settings:Hint Clarity", RSK_HINT_CLARITY },
@ -1423,7 +1462,8 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT },
{ "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH },
{ "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE },
{ "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }
{ "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE },
{ "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST },
};
s32 Randomizer::GetItemIDFromGetItemID(s32 getItemId) {
@ -1639,7 +1679,11 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
gSaveContext.randoSettings[index].value = std::stoi(numericValueString);
break;
case RSK_SHUFFLE_COWS:
case RSK_SHUFFLE_ADULT_TRADE:
case RSK_RANDOM_TRIALS:
case RSK_STARTING_DEKU_SHIELD:
case RSK_STARTING_KOKIRI_SWORD:
case RSK_COMPLETE_MASK_QUEST:
if(it.value() == "Off") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "On") {
@ -1647,24 +1691,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
}
break;
case RSK_STARTING_MAPS_COMPASSES:
if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 0;
} else if (it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 1;
}
break;
case RSK_STARTING_DEKU_SHIELD:
if(it.value() == "Off") {
if(it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "On") {
gSaveContext.randoSettings[index].value = 1;
}
break;
case RSK_STARTING_KOKIRI_SWORD:
if(it.value() == "Off") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "On") {
} else if(it.value() == "Vanilla") {
gSaveContext.randoSettings[index].value = 1;
} else if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 2;
} else if(it.value() == "Any Dungeon") {
gSaveContext.randoSettings[index].value = 3;
} else if(it.value() == "Overworld") {
gSaveContext.randoSettings[index].value = 4;
} else if(it.value() == "Anywhere") {
gSaveContext.randoSettings[index].value = 5;
}
break;
case RSK_STARTING_OCARINA:
@ -1705,13 +1743,49 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
gSaveContext.randoSettings[index].value = 3;
}
break;
case RSK_GANONS_BOSS_KEY:
if(it.value() == "Start with") {
case RSK_KEYSANITY:
if(it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "Vanilla") {
gSaveContext.randoSettings[index].value = 1;
} else if(it.value() == "Own dungeon") {
} else if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 2;
} else if(it.value() == "Any Dungeon") {
gSaveContext.randoSettings[index].value = 3;
} else if(it.value() == "Overworld") {
gSaveContext.randoSettings[index].value = 4;
} else if(it.value() == "Anywhere") {
gSaveContext.randoSettings[index].value = 5;
}
break;
case RSK_BOSS_KEYSANITY:
if(it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "Vanilla") {
gSaveContext.randoSettings[index].value = 1;
} else if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 2;
} else if(it.value() == "Any Dungeon") {
gSaveContext.randoSettings[index].value = 3;
} else if(it.value() == "Overworld") {
gSaveContext.randoSettings[index].value = 4;
} else if(it.value() == "Anywhere") {
gSaveContext.randoSettings[index].value = 5;
}
break;
case RSK_GANONS_BOSS_KEY:
if(it.value() == "Vanilla") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "Own dungeon") {
gSaveContext.randoSettings[index].value = 1;
} else if(it.value() == "Start with") {
gSaveContext.randoSettings[index].value = 2;
} else if(it.value() == "Any Dungeon") {
gSaveContext.randoSettings[index].value = 3;
} else if(it.value() == "Overworld") {
gSaveContext.randoSettings[index].value = 4;
} else if(it.value() == "Anywhere") {
gSaveContext.randoSettings[index].value = 5;
}
break;
case RSK_SKIP_CHILD_ZELDA:
@ -2228,50 +2302,79 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_PRELUDE_OF_LIGHT:
return GI_PRELUDE_OF_LIGHT;
// todo implement dungeon-specific maps/compasses
case RG_DEKU_TREE_MAP:
return GI_DEKU_TREE_MAP;
case RG_DODONGOS_CAVERN_MAP:
return GI_DODONGOS_CAVERN_MAP;
case RG_JABU_JABUS_BELLY_MAP:
return GI_JABU_JABUS_BELLY_MAP;
case RG_FOREST_TEMPLE_MAP:
return GI_FOREST_TEMPLE_MAP;
case RG_FIRE_TEMPLE_MAP:
return GI_FIRE_TEMPLE_MAP;
case RG_WATER_TEMPLE_MAP:
return GI_WATER_TEMPLE_MAP;
case RG_SPIRIT_TEMPLE_MAP:
return GI_SPIRIT_TEMPLE_MAP;
case RG_SHADOW_TEMPLE_MAP:
return GI_SHADOW_TEMPLE_MAP;
case RG_BOTTOM_OF_THE_WELL_MAP:
return GI_BOTTOM_OF_THE_WELL_MAP;
case RG_ICE_CAVERN_MAP:
return GI_MAP;
return GI_ICE_CAVERN_MAP;
case RG_DEKU_TREE_COMPASS:
return GI_DEKU_TREE_COMPASS;
case RG_DODONGOS_CAVERN_COMPASS:
return GI_DODONGOS_CAVERN_COMPASS;
case RG_JABU_JABUS_BELLY_COMPASS:
return GI_JABU_JABUS_BELLY_COMPASS;
case RG_FOREST_TEMPLE_COMPASS:
return GI_FOREST_TEMPLE_COMPASS;
case RG_FIRE_TEMPLE_COMPASS:
return GI_FIRE_TEMPLE_COMPASS;
case RG_WATER_TEMPLE_COMPASS:
return GI_WATER_TEMPLE_COMPASS;
case RG_SPIRIT_TEMPLE_COMPASS:
return GI_SPIRIT_TEMPLE_COMPASS;
case RG_SHADOW_TEMPLE_COMPASS:
return GI_SHADOW_TEMPLE_COMPASS;
case RG_BOTTOM_OF_THE_WELL_COMPASS:
return GI_BOTTOM_OF_THE_WELL_COMPASS;
case RG_ICE_CAVERN_COMPASS:
return GI_COMPASS;
return GI_ICE_CAVERN_COMPASS;
// todo implement dungeon-specific keys/keyrings
case RG_FOREST_TEMPLE_BOSS_KEY:
return GI_FOREST_TEMPLE_BOSS_KEY;
case RG_FIRE_TEMPLE_BOSS_KEY:
return GI_FIRE_TEMPLE_BOSS_KEY;
case RG_WATER_TEMPLE_BOSS_KEY:
return GI_WATER_TEMPLE_BOSS_KEY;
case RG_SPIRIT_TEMPLE_BOSS_KEY:
return GI_SPIRIT_TEMPLE_BOSS_KEY;
case RG_SHADOW_TEMPLE_BOSS_KEY:
return GI_SHADOW_TEMPLE_BOSS_KEY;
case RG_GANONS_CASTLE_BOSS_KEY:
return GI_KEY_BOSS;
return GI_GANONS_CASTLE_BOSS_KEY;
case RG_FOREST_TEMPLE_SMALL_KEY:
return GI_FOREST_TEMPLE_SMALL_KEY;
case RG_FIRE_TEMPLE_SMALL_KEY:
return GI_FIRE_TEMPLE_SMALL_KEY;
case RG_WATER_TEMPLE_SMALL_KEY:
return GI_WATER_TEMPLE_SMALL_KEY;
case RG_SPIRIT_TEMPLE_SMALL_KEY:
return GI_SPIRIT_TEMPLE_SMALL_KEY;
case RG_SHADOW_TEMPLE_SMALL_KEY:
return GI_SHADOW_TEMPLE_SMALL_KEY;
case RG_BOTTOM_OF_THE_WELL_SMALL_KEY:
return GI_BOTTOM_OF_THE_WELL_SMALL_KEY;
case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
return GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY;
case RG_GERUDO_FORTRESS_SMALL_KEY:
return GI_GERUDO_FORTRESS_SMALL_KEY;
case RG_GANONS_CASTLE_SMALL_KEY:
return GI_KEY_SMALL;
return GI_GANONS_CASTLE_SMALL_KEY;
// todo test this with keys in own dungeon
case RG_TREASURE_GAME_SMALL_KEY:
@ -3430,11 +3533,12 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVar_GetS32("gRandomizeShuffleKokiriSword", 0) ||
CVar_GetS32("gRandomizeStartingKokiriSword", 0);
cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVar_GetS32("gRandomizeStartingDekuShield", 0);
cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 0);
cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 2);
cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0);
cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0);
cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0);
cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0);
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
// if we skip child zelda, we start with zelda's letter, and malon starts
@ -3449,7 +3553,10 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVar_GetS32("gRandomizeGossipStoneHints", 1);
cvarSettings[RSK_HINT_CLARITY] = CVar_GetS32("gRandomizeHintClarity", 2);
cvarSettings[RSK_HINT_DISTRIBUTION] = CVar_GetS32("gRandomizeHintDistribution", 1);
cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 0);
cvarSettings[RSK_KEYSANITY] = CVar_GetS32("gRandomizeKeysanity", 2);
cvarSettings[RSK_GERUDO_KEYS] = CVar_GetS32("gRandomizeGerudoKeys", 0);
cvarSettings[RSK_BOSS_KEYSANITY] = CVar_GetS32("gRandomizeBossKeysanity", 2);
cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 1);
cvarSettings[RSK_STARTING_CONSUMABLES] = CVar_GetS32("gRandomizeStartingConsumables", 0);
cvarSettings[RSK_FULL_WALLETS] = CVar_GetS32("gRandomizeFullWallets", 0);
@ -3474,6 +3581,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SKIP_EPONA_RACE] = CVar_GetS32("gRandomizeSkipEponaRace", 0);
cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVar_GetS32("gRandomizeSkipTowerEscape", 0);
cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVar_GetS32("gRandomizeCompleteMaskQuest", 0);
cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0);
@ -3540,17 +3648,11 @@ void DrawRandoEditor(bool& open) {
const char* randoShuffleAdultTrade[2] = { "Off", "On" };
// Shuffle Dungeon Items Settings
const char* randoShuffleMapsAndCompasses[6] = { "Own Dungeon", "Any Dungeon", "Overworld",
"Anywhere", "Start with", "Vanilla" };
const char* randoShuffleSmallKeys[6] = { "Own Dungeon", "Any Dungeon", "Overworld",
"Anywhere", "Start with", "Vanilla" };
const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleSmallKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleBossKeys[6] = { "Own Dungeon", "Any Dungeon", "Overworld",
"Anywhere", "Start with", "Vanilla" };
// const char* randoShuffleGanonsBossKey[12] = { "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere",
// "LACS Vanilla", "LACS Medallions", "LACS Stones", "LACS Rewards",
// "LACS Dungeons", "LACS Tokens", "Start with", "Vanilla" };
const char* randoShuffleGanonsBossKey[3] = {"Vanilla", "Own dungeon", "Start with"};
const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleGanonsBossKey[6] = { "Vanilla", "Own dungeon", "Start with", "Any Dungeon", "Overworld", "Anywhere" };
// Timesaver Settings
const char* randoSkipSongReplays[3] = { "Don't skip", "Skip (no SFX)", "Skip (Keep SFX)" };
@ -3963,6 +4065,20 @@ void DrawRandoEditor(bool& open) {
InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
PaddedSeparator();
// Shuffle Adult Trade Quest
SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), "gRandomizeShuffleAdultTrade");
InsertHelpHoverText(
"Adds all of the adult trade quest items into the pool, each of which "
"can be traded for a unique reward.\n"
"\n"
"You will be able to choose which of your owned adult trade items is visible "
"in the inventory by selecting the item with A and using the control stick or "
"D-pad.\n"
"\n"
"If disabled, only the Claim Check will be found in the pool."
);
PaddedSeparator();
if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) {
// Shuffle Kokiri Sword
SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword");
@ -4060,22 +4176,90 @@ void DrawRandoEditor(bool& open) {
SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0);
PaddedSeparator();
// RANDOTODO implement ganon's boss key outside of ganon's castle
// Keysanity
ImGui::Text(Settings::Keysanity.GetName().c_str());
InsertHelpHoverText(
"Start with - You will start with all Small Keys from all dungeons.\n"
"\n"
"Vanilla - Small Keys will appear in their vanilla locations.\n"
"\n"
"Own dungeon - Small Keys can only appear in their respective dungeon.\n"
"\n"
"Any dungeon - Small Keys can only appear inside of any dungon.\n"
"\n"
"Overworld - Small Keys can only appear outside of dungeons.\n"
"\n"
"Anywhere - Small Keys can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2);
PaddedSeparator();
// Gerudo Keys
ImGui::Text(Settings::GerudoKeys.GetName().c_str());
InsertHelpHoverText(
"Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n"
"\n"
"Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n"
"\n"
"Overworld - Thieve's Hideout Keys can only appear outside of dungeons.\n"
"\n"
"Anywhere - Thieve's Hideout Keys can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0);
PaddedSeparator();
// Boss Keysanity
ImGui::Text(Settings::BossKeysanity.GetName().c_str());
InsertHelpHoverText(
"Start with - You will start with Boss keys from all dungeons.\n"
"\n"
"Vanilla - Boss Keys will appear in their vanilla locations.\n"
"\n"
"Own dungeon - Boss Keys can only appear in their respective dungeon.\n"
"\n"
"Any dungeon - Boss Keys can only appear inside of any dungon.\n"
"\n"
"Overworld - Boss Keys can only appear outside of dungeons.\n"
"\n"
"Anywhere - Boss Keys can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2);
PaddedSeparator();
// Ganon's Boss Key
ImGui::Text(Settings::GanonsBossKey.GetName().c_str());
InsertHelpHoverText(
"Vanilla - Key will appear in the vanilla location.\n"
"Vanilla - Ganon's Boss Key will appear in the vanilla location.\n"
"\n"
"Own dungeon - Key can appear anywhere inside Ganon's Castle.\n"
"Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n"
"\n"
"Start with - Places Ganon's Boss Key in your starting inventory."
"\n"
"Any dungeon - Ganon's Boss Key Key can only appear inside of any dungon.\n"
"\n"
"Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n"
"\n"
"Anywhere - Ganon's Boss Key Key can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3,
0);
SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1);
PaddedSeparator();
// Start with Maps & Compasses
SohImGui::EnhancementCheckbox(Settings::MapsAndCompasses.GetName().c_str(), "gRandomizeStartingMapsCompasses");
ImGui::Text(Settings::MapsAndCompasses.GetName().c_str());
InsertHelpHoverText(
"Start with - You will start with Maps & Compasses from all dungeons.\n"
"\n"
"Vanilla - Maps & Compasses will appear in their vanilla locations.\n"
"\n"
"Own dungeon - Maps & Compasses can only appear in their respective dungeon.\n"
"\n"
"Any dungeon - Maps & Compasses can only appear inside of any dungon.\n"
"\n"
"Overworld - Maps & Compasses can only appear outside of dungeons.\n"
"\n"
"Anywhere - Maps & Compasses can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2);
ImGui::PopItemWidth();
ImGui::EndTable();
@ -4156,6 +4340,13 @@ void DrawRandoEditor(bool& open) {
InsertHelpHoverText(
"The tower escape sequence between Ganondorf and Ganon will be skipped."
);
PaddedSeparator();
// Complete mask quest
SohImGui::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), "gRandomizeCompleteMaskQuest");
InsertHelpHoverText(
"Once the happy mask shop is opened, all masks will be available to be borrowed."
);
// COLUMN 2 - HINT SETTINGS
ImGui::TableNextColumn();
@ -4457,6 +4648,45 @@ void Randomizer::CreateCustomMessages() {
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!"),
GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_POE, ITEM_POE,
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this..."),
GIMESSAGE_UNTRANSLATED(GI_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training Grounds &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!"),
GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!"),
GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!"),
GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!"),
GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the &Well %wCompass!"),
GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!"),
};
CreateGetItemMessages(getItemMessages);
CreateScrubMessages();

View File

@ -10,6 +10,7 @@ typedef struct {
} Sprite;
typedef enum {
RC_UNKNOWN_CHECK,
RC_LINKS_POCKET,
RC_QUEEN_GOHMA,
RC_KING_DODONGO,
@ -752,7 +753,7 @@ typedef enum {
RC_ZR_NEAR_DOMAIN_GOSSIP_STONE,
RC_ZR_NEAR_GROTTOS_GOSSIP_STONE,
RC_ZR_OPEN_GROTTO_GOSSIP_STONE,
RC_UNKNOWN_CHECK
RC_MAX
} RandomizerCheck;
// based on https://github.com/TestRunnerSRL/OoT-Randomizer/blob/e337d7f603b91a6bacb618fb32cc7fd70ed9ffca/ItemList.py
@ -971,7 +972,7 @@ typedef enum {
RSK_STARTING_DEKU_SHIELD,
RSK_STARTING_KOKIRI_SWORD,
RSK_SHUFFLE_KOKIRI_SWORD,
RSK_STARTING_MAPS_COMPASSES, //RANDOTODO more options for this, rn it's just start with or own dungeon
RSK_STARTING_MAPS_COMPASSES,
RSK_SHUFFLE_DUNGEON_REWARDS,
RSK_SHUFFLE_SONGS,
RSK_SHUFFLE_TOKENS,
@ -984,6 +985,9 @@ typedef enum {
RSK_GOSSIP_STONE_HINTS,
RSK_HINT_CLARITY,
RSK_HINT_DISTRIBUTION,
RSK_KEYSANITY,
RSK_GERUDO_KEYS,
RSK_BOSS_KEYSANITY,
RSK_GANONS_BOSS_KEY,
RSK_SKIP_CHILD_STEALTH,
RSK_SKIP_CHILD_ZELDA,
@ -1001,5 +1005,7 @@ typedef enum {
RSK_BIG_POE_COUNT,
RSK_SKIP_EPONA_RACE,
RSK_SKIP_TOWER_ESCAPE,
RSK_SKULLS_SUNS_SONG
RSK_COMPLETE_MASK_QUEST,
RSK_SKULLS_SUNS_SONG,
RSK_SHUFFLE_ADULT_TRADE
} RandomizerSettingKey;

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,8 @@ void SaveManager::LoadRandomizerVersion1() {
for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) {
SaveManager::Instance->LoadData("gt" + std::to_string(i), gSaveContext.ganonText[i]);
}
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
}
void SaveManager::SaveRandomizer() {
@ -130,6 +132,8 @@ void SaveManager::SaveRandomizer() {
for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) {
SaveManager::Instance->SaveData("gt" + std::to_string(i), gSaveContext.ganonText[i]);
}
SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems);
}
void SaveManager::Init() {

View File

@ -33,19 +33,21 @@ void GameOver_Update(GlobalContext* globalCtx) {
gSaveContext.eventInf[1] &= ~1;
// search inventory for spoiling items and revert if necessary
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) {
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
// search c buttons for the found spoiling item and revert if necessary
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
Interface_LoadItemIcon1(globalCtx, j);
// search c buttons for the found spoiling item and revert if necessary
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
Interface_LoadItemIcon1(globalCtx, j);
}
}
}
}
}
}
// restore "temporary B" to the B Button if not a sword item
if (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI &&

View File

@ -4,6 +4,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
typedef enum {
/* 0 */ LENS_FLARE_CIRCLE0,
@ -2048,6 +2049,21 @@ void Environment_PlaySceneSequence(GlobalContext* globalCtx) {
Audio_SetEnvReverb(globalCtx->roomCtx.curRoom.echo);
}
bool HatchPocketEgg(GlobalContext* globalCtx) {
if (!gSaveContext.n64ddFlag) {
return Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO);
}
if (!(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_POCKET_EGG))) {
return 0;
}
gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(ITEM_POCKET_EGG);
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(ITEM_POCKET_CUCCO);
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO);
return 1;
}
// updates bgm/sfx and other things as the day progresses
void func_80075B44(GlobalContext* globalCtx) {
switch (globalCtx->envCtx.unk_E0) {
@ -2101,7 +2117,7 @@ void func_80075B44(GlobalContext* globalCtx) {
gSaveContext.dogIsLost = true;
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) ||
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) &&
HatchPocketEgg(globalCtx)) &&
globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) {
Message_StartTextbox(globalCtx, 0x3066, NULL);
}

View File

@ -3,6 +3,7 @@
#include "textures/parameter_static/parameter_static.h"
#include "textures/do_action_static/do_action_static.h"
#include "textures/icon_item_static/icon_item_static.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#ifdef _MSC_VER
#include <stdlib.h>
@ -1750,29 +1751,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
}
return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) {
// Small key exceptions for rando.
if (gSaveContext.n64ddFlag) {
if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle
if (gSaveContext.inventory.dungeonKeys[13] < 0) {
gSaveContext.inventory.dungeonKeys[13] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[13]++;
return ITEM_NONE;
}
}
if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple.
if (gSaveContext.inventory.dungeonKeys[6] < 0) {
gSaveContext.inventory.dungeonKeys[6] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[6]++;
return ITEM_NONE;
}
}
}
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1;
return ITEM_NONE;
@ -1780,6 +1758,100 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++;
return ITEM_NONE;
}
} else if (
(item >= ITEM_GERUDO_FORTRESS_SMALL_KEY && item <= ITEM_GANONS_CASTLE_SMALL_KEY) ||
(item >= ITEM_FOREST_TEMPLE_BOSS_KEY && item <= ITEM_GANONS_CASTLE_BOSS_KEY) ||
(item >= ITEM_DEKU_TREE_MAP && item <= ITEM_ICE_CAVERN_MAP) ||
(item >= ITEM_DEKU_TREE_COMPASS && item <= ITEM_ICE_CAVERN_COMPASS)
) {
int mapIndex = gSaveContext.mapIndex;
switch (item) {
case ITEM_DEKU_TREE_MAP:
case ITEM_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case ITEM_DODONGOS_CAVERN_MAP:
case ITEM_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case ITEM_JABU_JABUS_BELLY_MAP:
case ITEM_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case ITEM_FOREST_TEMPLE_MAP:
case ITEM_FOREST_TEMPLE_COMPASS:
case ITEM_FOREST_TEMPLE_SMALL_KEY:
case ITEM_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case ITEM_FIRE_TEMPLE_MAP:
case ITEM_FIRE_TEMPLE_COMPASS:
case ITEM_FIRE_TEMPLE_SMALL_KEY:
case ITEM_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case ITEM_WATER_TEMPLE_MAP:
case ITEM_WATER_TEMPLE_COMPASS:
case ITEM_WATER_TEMPLE_SMALL_KEY:
case ITEM_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case ITEM_SPIRIT_TEMPLE_MAP:
case ITEM_SPIRIT_TEMPLE_COMPASS:
case ITEM_SPIRIT_TEMPLE_SMALL_KEY:
case ITEM_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case ITEM_SHADOW_TEMPLE_MAP:
case ITEM_SHADOW_TEMPLE_COMPASS:
case ITEM_SHADOW_TEMPLE_SMALL_KEY:
case ITEM_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case ITEM_BOTTOM_OF_THE_WELL_MAP:
case ITEM_BOTTOM_OF_THE_WELL_COMPASS:
case ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case ITEM_ICE_CAVERN_MAP:
case ITEM_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case ITEM_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
case ITEM_GERUDO_FORTRESS_SMALL_KEY:
mapIndex = SCENE_GERUDOWAY;
break;
case ITEM_GANONS_CASTLE_SMALL_KEY:
mapIndex = SCENE_GANONTIKA;
break;
}
if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
return ITEM_NONE;
}
} else {
int bitmask;
if ((item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP)) {
bitmask = gBitFlags[2];
} else if ((item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)) {
bitmask = gBitFlags[1];
} else {
bitmask = gBitFlags[0];
}
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
return ITEM_NONE;
}
} else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) {
if (CUR_UPG_VALUE(UPG_QUIVER) == 0) {
Inventory_ChangeUpgrade(UPG_QUIVER, 1);
@ -2164,6 +2236,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
if (item >= ITEM_POCKET_EGG) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item);
}
temp = INV_CONTENT(item);
INV_CONTENT(item) = item;
@ -2289,6 +2365,13 @@ u8 Item_CheckObtainability(u8 item) {
} else {
return ITEM_NONE;
}
} else if (
(item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) ||
(item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) ||
(item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) ||
(item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)
) {
return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) {

View File

@ -416,6 +416,95 @@ void GiveLinkDungeonReward(GetItemID getItemId) {
}
}
void GiveLinkDungeonItem(GetItemID getItemId) {
int mapIndex;
switch (getItemId) {
case GI_DEKU_TREE_MAP:
case GI_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case GI_DODONGOS_CAVERN_MAP:
case GI_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case GI_JABU_JABUS_BELLY_MAP:
case GI_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case GI_FOREST_TEMPLE_MAP:
case GI_FOREST_TEMPLE_COMPASS:
case GI_FOREST_TEMPLE_SMALL_KEY:
case GI_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case GI_FIRE_TEMPLE_MAP:
case GI_FIRE_TEMPLE_COMPASS:
case GI_FIRE_TEMPLE_SMALL_KEY:
case GI_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case GI_WATER_TEMPLE_MAP:
case GI_WATER_TEMPLE_COMPASS:
case GI_WATER_TEMPLE_SMALL_KEY:
case GI_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case GI_SPIRIT_TEMPLE_MAP:
case GI_SPIRIT_TEMPLE_COMPASS:
case GI_SPIRIT_TEMPLE_SMALL_KEY:
case GI_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case GI_SHADOW_TEMPLE_MAP:
case GI_SHADOW_TEMPLE_COMPASS:
case GI_SHADOW_TEMPLE_SMALL_KEY:
case GI_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case GI_BOTTOM_OF_THE_WELL_MAP:
case GI_BOTTOM_OF_THE_WELL_COMPASS:
case GI_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case GI_ICE_CAVERN_MAP:
case GI_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case GI_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
case GI_GERUDO_FORTRESS_SMALL_KEY:
mapIndex = SCENE_GERUDOWAY;
break;
case GI_GANONS_CASTLE_SMALL_KEY:
mapIndex = SCENE_GANONTIKA;
break;
}
if ((getItemId >= GI_GERUDO_FORTRESS_SMALL_KEY) && (getItemId <= GI_GANONS_CASTLE_SMALL_KEY)) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
}
} else {
int bitmask;
if ((getItemId >= GI_DEKU_TREE_MAP) && (getItemId <= GI_ICE_CAVERN_MAP)) {
bitmask = gBitFlags[2];
} else if ((getItemId >= GI_DEKU_TREE_COMPASS) && (getItemId <= GI_ICE_CAVERN_COMPASS)) {
bitmask = gBitFlags[1];
} else {
bitmask = gBitFlags[0];
}
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
}
}
void GiveLinksPocketMedallion() {
GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
@ -563,13 +652,15 @@ void Sram_OpenSave() {
gSaveContext.equips.equipment |= 2;
}
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) {
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
}
}
}
}
@ -687,11 +778,12 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
}
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) {
// "Start with" == 0 for Maps and Compasses
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == 0) {
uint32_t mapBitMask = 1 << 1;
uint32_t compassBitMask = 1 << 2;
uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
for(int scene = 0; scene <= 9; scene++) {
for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) {
gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask;
}
}
@ -788,6 +880,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkMagic(giid);
} else if (giid == GI_DOUBLE_DEFENSE) {
GiveLinkDoubleDefense();
} else if (
(giid >= GI_GERUDO_FORTRESS_SMALL_KEY && giid <= GI_GANONS_CASTLE_SMALL_KEY) ||
(giid >= GI_FOREST_TEMPLE_BOSS_KEY && giid <= GI_GANONS_CASTLE_BOSS_KEY) ||
(giid >= GI_DEKU_TREE_MAP && giid <= GI_ICE_CAVERN_MAP) ||
(giid >= GI_DEKU_TREE_COMPASS && giid <= GI_ICE_CAVERN_COMPASS)
) {
GiveLinkDungeonItem(giid);
} else {
s32 iid = Randomizer_GetItemIDFromGetItemID(giid);
if (iid != -1) INV_CONTENT(iid) = iid;
@ -814,9 +913,31 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkRupees(9001);
}
// For Ganon's boss key "Start With" is 0
if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) {
gSaveContext.inventory.dungeonItems[10] |= 1;
// "Start with" == 0 for Keysanity
if(Randomizer_GetSettingValue(RSK_KEYSANITY) == 0) {
// TODO: If master quest there are different key counts
gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = 5; // Forest
gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = 8; // Fire
gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = 6; // Water
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 5; // Spirit
gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = 5; // Shadow
gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = 2; // BotW
gSaveContext.inventory.dungeonKeys[SCENE_MEN] = 9; // GTG
gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = 2; // Ganon
}
// "Start with" == 0 for Boss Kesanity
if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == 0) {
gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest
gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire
gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water
gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit
gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow
}
// "Start with" == 2 for Ganon's Boss Key
if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 2) {
gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1;
}
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
@ -878,6 +999,21 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkGerudoCard();
}
}
// shuffle adult trade quest
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
gSaveContext.adultTradeItems = 0;
}
// complete mask quest
if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask
gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask
gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask
gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks
}
}
Save_SaveFile();

View File

@ -6,6 +6,7 @@
#include "z_en_ds.h"
#include "objects/object_ds/object_ds.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@ -91,7 +92,12 @@ void EnDs_GiveOddPotion(EnDs* this, GlobalContext* globalCtx) {
this->actionFunc = EnDs_DisplayOddPotionText;
gSaveContext.timer2State = 0;
} else {
func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f);
u32 itemId = GI_ODD_POTION;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM);
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
}
@ -99,7 +105,12 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
Message_CloseTextbox(globalCtx);
this->actionFunc = EnDs_GiveOddPotion;
func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f);
u32 itemId = GI_ODD_POTION;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM);
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
}
@ -120,7 +131,7 @@ void EnDs_BrewOddPotion2(EnDs* this, GlobalContext* globalCtx) {
this->brewTimer -= 1;
} else {
this->actionFunc = EnDs_BrewOddPotion3;
this->brewTimer = 60;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60;
Flags_UnsetSwitch(globalCtx, 0x3F);
}
}
@ -130,7 +141,7 @@ void EnDs_BrewOddPotion1(EnDs* this, GlobalContext* globalCtx) {
this->brewTimer -= 1;
} else {
this->actionFunc = EnDs_BrewOddPotion2;
this->brewTimer = 20;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 20;
}
Math_StepToF(&this->unk_1E4, 1.0f, 0.01f);
@ -144,7 +155,7 @@ void EnDs_OfferOddPotion(EnDs* this, GlobalContext* globalCtx) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0: // yes
this->actionFunc = EnDs_BrewOddPotion1;
this->brewTimer = 60;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60;
Flags_SetSwitch(globalCtx, 0x3F);
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
player->exchangeItemId = EXCH_ITEM_NONE;

View File

@ -3,6 +3,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_oF1d_map/object_oF1d_map.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@ -961,9 +962,17 @@ void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) {
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
getItemId = GI_CLAIM_CHECK;
if (gSaveContext.n64ddFlag) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS);
}
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
getItemId = GI_PRESCRIPTION;
if (gSaveContext.n64ddFlag) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN);
}
}
}

View File

@ -3,6 +3,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_oF1d_map/object_oF1d_map.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@ -652,7 +653,12 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
if (Message_ShouldAdvance(globalCtx)) {
if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) {
if (globalCtx->msgCtx.choiceIndex == 0) {
EnGo2_GetItem(this, globalCtx, GI_PRESCRIPTION);
u32 getItemId = GI_PRESCRIPTION;
if (gSaveContext.n64ddFlag) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN);
}
EnGo2_GetItem(this, globalCtx, getItemId);
this->actionFunc = EnGo2_SetupGetItem;
return 2;
}
@ -1847,12 +1853,14 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) {
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.shape.rot.y += 0x5B0;
this->unk_26E = 1;
this->animTimer = this->skelAnime.endFrame + 60.0f + 60.0f; // eyeDrops animation timer
this->animTimer = gSaveContext.n64ddFlag ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer
this->eyeMouthTexState = 2;
this->unk_20C = 0;
this->goronState++;
func_800F483C(0x28, 5);
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
if (!gSaveContext.n64ddFlag) {
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
}
break;
case 1:
if (DECR(this->animTimer)) {
@ -1879,7 +1887,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) {
this->unk_26E = 2;
this->skelAnime.playSpeed = 0.0f;
this->skelAnime.curFrame = this->skelAnime.endFrame;
EnGo2_GetItem(this, globalCtx, GI_CLAIM_CHECK);
u32 getItemId = GI_CLAIM_CHECK;
if (gSaveContext.n64ddFlag) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS);
}
EnGo2_GetItem(this, globalCtx, getItemId);
this->actionFunc = EnGo2_SetupGetItem;
this->goronState = 0;
}

View File

@ -7,6 +7,7 @@
#include "z_en_hs.h"
#include "vt.h"
#include "objects/object_hs/object_hs.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@ -78,7 +79,14 @@ void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) {
// "chicken shop (adult era)"
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST);
func_80A6E3A0(this, func_80A6E9AC);
if (gSaveContext.itemGetInf[3] & 1) {
bool shouldDespawn;
bool tradedMushroom = gSaveContext.itemGetInf[3] & 1;
if (gSaveContext.n64ddFlag) {
shouldDespawn = tradedMushroom && !(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_COJIRO));
} else {
shouldDespawn = tradedMushroom;
}
if (shouldDespawn) {
// "chicken shop closed"
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST);
Actor_Kill(&this->actor);
@ -127,7 +135,9 @@ void func_80A6E5EC(EnHs* this, GlobalContext* globalCtx) {
void func_80A6E630(EnHs* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
func_80088AA0(180);
if (!gSaveContext.n64ddFlag) {
func_80088AA0(180);
}
func_80A6E3A0(this, func_80A6E6B0);
gSaveContext.eventInf[1] &= ~1;
}
@ -156,7 +166,12 @@ void func_80A6E740(EnHs* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
func_80A6E3A0(this, func_80A6E630);
} else {
func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
s32 itemId = GI_ODD_MUSHROOM;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO);
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
this->unk_2A8 |= 1;
@ -167,7 +182,12 @@ void func_80A6E7BC(EnHs* this, GlobalContext* globalCtx) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0:
func_80A6E3A0(this, func_80A6E740);
func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
s32 itemId = GI_ODD_MUSHROOM;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO);
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
break;
case 1:
Message_ContinueTextbox(globalCtx, 0x10B4);

View File

@ -10,6 +10,7 @@
#include "objects/object_km1/object_km1.h"
#include "objects/object_kw1/object_kw1.h"
#include "vt.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@ -1216,7 +1217,12 @@ void func_80A99504(EnKo* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
this->actionFunc = func_80A99560;
} else {
func_8002F434(&this->actor, globalCtx, GI_SAW, 120.0f, 10.0f);
s32 itemId = GI_SAW;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_POTION);
}
func_8002F434(&this->actor, globalCtx, itemId, 120.0f, 10.0f);
}
}

View File

@ -6,6 +6,7 @@
#include "z_en_kz.h"
#include "objects/object_kz/object_kz.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@ -465,6 +466,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) {
if (this->isTrading) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_PRESCRIPTION);
Flags_SetTreasure(globalCtx, 0x1F);
} else {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA);
@ -480,7 +482,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) {
void EnKz_StartTimer(EnKz* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !gSaveContext.n64ddFlag) {
func_80088AA0(180); // start timer2 with 3 minutes
gSaveContext.eventInf[1] &= ~1;
}

View File

@ -6,6 +6,7 @@
#include "z_en_mk.h"
#include "objects/object_mk/object_mk.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@ -93,17 +94,29 @@ void func_80AACA94(EnMk* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx) != 0) {
this->actor.parent = NULL;
this->actionFunc = func_80AACA40;
func_80088AA0(240);
gSaveContext.eventInf[1] &= ~1;
if (!gSaveContext.n64ddFlag) {
func_80088AA0(240);
gSaveContext.eventInf[1] &= ~1;
}
} else {
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
s32 getItemID = GI_EYEDROPS;
if (gSaveContext.n64ddFlag) {
getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG);
}
func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f);
}
}
void func_80AACB14(EnMk* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
this->actionFunc = func_80AACA94;
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
s32 getItemID = GI_EYEDROPS;
if (gSaveContext.n64ddFlag) {
getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG);
}
func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f);
}
}
@ -129,7 +142,7 @@ void func_80AACC04(EnMk* this, GlobalContext* globalCtx) {
if (this->timer > 0) {
this->timer--;
} else {
this->timer = 16;
this->timer = gSaveContext.n64ddFlag ? 0 : 16;
this->actionFunc = func_80AACBAC;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
@ -142,7 +155,7 @@ void func_80AACCA0(EnMk* this, GlobalContext* globalCtx) {
this->timer--;
this->actor.shape.rot.y += 0x800;
} else {
this->timer = 120;
this->timer = gSaveContext.n64ddFlag ? 0 : 120;
this->actionFunc = func_80AACC04;
Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f);
@ -158,7 +171,7 @@ void func_80AACD48(EnMk* this, GlobalContext* globalCtx) {
this->actionFunc = func_80AACCA0;
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
player->exchangeItemId = EXCH_ITEM_NONE;
this->timer = 16;
this->timer = gSaveContext.n64ddFlag ? 0 : 16;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;

View File

@ -3,6 +3,7 @@
#include "objects/object_os_anime/object_os_anime.h"
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
#include "vt.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@ -454,8 +455,13 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) {
if (LINK_IS_ADULT) {
getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO;
if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG);
if (gSaveContext.n64ddFlag) {
if (getItemId == GI_POCKET_EGG) {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG);
} else {
getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_POCKET_CUCCO);
}
}
}
func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f);

View File

@ -6,6 +6,7 @@
#include "z_en_toryo.h"
#include "objects/object_toryo/object_toryo.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@ -313,7 +314,12 @@ void func_80B20768(EnToryo* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
this->unk_1E4 = 5;
} else {
func_8002F434(&this->actor, globalCtx, GI_SWORD_BROKEN, 100.0f, 10.0f);
s32 itemId = GI_SWORD_BROKEN;
if (gSaveContext.n64ddFlag) {
itemId = Randomizer_GetItemIdFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SAW);
}
func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 10.0f);
}
return;
}

View File

@ -656,6 +656,45 @@ GetItemEntry sGetItemTable[] = {
GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT),
GET_ITEM(ITEM_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG),
GET_ITEM_NONE,
GET_ITEM_NONE,
};

View File

@ -1,5 +1,7 @@
#include "z_kaleido_scope.h"
#include "textures/parameter_static/parameter_static.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
u8 gAmmoItems[] = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
@ -10,6 +12,7 @@ static s16 sEquipState = 0;
static s16 sEquipAnimTimer = 0;
static s16 sEquipMoveTimer = 10;
bool gSelectingMask;
bool gSelectingAdultTrade;
static s16 sAmmoVtxOffset[] = {
0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12,
@ -109,7 +112,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
pauseCtx->nameColorSet = 0;
if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) {
moveCursorResult = 0 || gSelectingMask;
moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade;
oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM];
cursorItem = pauseCtx->cursorItem[PAUSE_ITEM];
@ -283,7 +286,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
if (pauseCtx->cursorSpecialPos == 0) {
if (cursorItem != PAUSE_ITEM_NONE) {
if ((ABS(pauseCtx->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) {
moveCursorResult = 0 || gSelectingMask;
moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade;
cursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM];
cursorY = pauseCtx->cursorY[PAUSE_ITEM];
@ -385,6 +388,24 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
}
gSelectingMask = cursorSlot == SLOT_TRADE_CHILD;
}
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
cursorSlot == SLOT_TRADE_ADULT && CHECK_BTN_ALL(input->press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSelectingAdultTrade = !gSelectingAdultTrade;
}
if (gSelectingAdultTrade) {
pauseCtx->cursorColorSet = 8;
if (((pauseCtx->stickRelX > 30 || pauseCtx->stickRelY > 30) ||
dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT | BTN_DUP))) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem());
} else if (((pauseCtx->stickRelX < -30 || pauseCtx->stickRelY < -30) ||
dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DDOWN))) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetPrevAdultTradeItem());
}
gSelectingAdultTrade = cursorSlot == SLOT_TRADE_ADULT;
}
u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT;
if (CVar_GetS32("gDpadEquips", 0) && (!CVar_GetS32("gDpadPauseName", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
@ -510,6 +531,7 @@ void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s
Input* input = &globalCtx->state.input[0];
PauseContext* pauseCtx = &globalCtx->pauseCtx;
gSelectingMask = false;
gSelectingAdultTrade = false;
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
pauseCtx->equipTargetCBtn = 0;