Merge branch 'rando-next' of https://github.com/HarbourMasters/Shipwright into shopsanity

This commit is contained in:
Garrett Cox 2022-08-26 21:41:21 -05:00
commit 67a890ed1e
124 changed files with 4722 additions and 3791 deletions

View File

@ -60,7 +60,7 @@ To build you'll need to follow the instructions from the building section.
_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._ _Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
_Experimental: You can also use another build system entirely rathen than MSVC like [Ninja](https://ninja-build.org/) for possibly better performance._ _Experimental: You can also use another build system entirely rather than MSVC like [Ninja](https://ninja-build.org/) for possibly better performance._
### Generating the distributable ### Generating the distributable

View File

@ -195,6 +195,11 @@ install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
PERMISSIONS ${PROGRAM_PERMISSIONS_EXECUTE} PERMISSIONS ${PROGRAM_PERMISSIONS_EXECUTE}
) )
install(CODE "
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/soh-macos\" \"\" \"${dirs}\")
")
endif() endif()
if(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS") if(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")

View File

@ -31,10 +31,10 @@ Congratulations, you are now sailing with the Ship of Harkinian! Have fun!
The Ship of Harkinian uses a proprietary versioning system consisting of a sci-fi film character followed by a phonetic alphabet code word. The film character represents a major release version which increments with the addition of many new features and bug fixes. The code word represents a minor release version which increments with small updates mainly comprised of bug fixes. For example, `DECKARD ALFA`. The Ship of Harkinian uses a proprietary versioning system consisting of a sci-fi film character followed by a phonetic alphabet code word. The film character represents a major release version which increments with the addition of many new features and bug fixes. The code word represents a minor release version which increments with small updates mainly comprised of bug fixes. For example, `DECKARD ALFA`.
### The Extraction Tool ### Windows Rom Extraction
* Open a rom to initiate generating the `oot.otr` archive file. * Open OTRGui.exe, and select one of the supported roms listed above, to generate the `oot.otr` archive file.
* If a second button exists then `oot.otr` already exists. To prevent overwriting the old `oot.otr` use this button to choose a new game directory. The new directory must not already contain an `oot.otr` to prevent an error. * If a second button already exits then `oot.otr` already exists. To prevent overwriting the old `oot.otr` use this button to choose a new game directory. The new directory must not already contain an `oot.otr` to prevent an error.
* When the process completes, place `oot.otr` beside `soh.exe` if it is not already. * When the process completes, place `oot.otr` beside `soh.exe` if it is not already.
This packaging process can take up to **5 minutes**. This packaging process can take up to **5 minutes**.
@ -42,6 +42,37 @@ This packaging process can take up to **5 minutes**.
Close the OTRGui when the `Done!` message appears. Close the OTRGui when the `Done!` message appears.
If you get another message, then you might have selected the wrong rom. Make sure to use a rom consistent with the above checksum. If you get another message, then you might have selected the wrong rom. Make sure to use a rom consistent with the above checksum.
### Linux Rom Extraction
* Place one of the supported roms in the same folder as the appimage.
* When you run the soh appimage, it should begin generating the `oot.otr` archive file.
* When the process completes, place `oot.otr` in the same folder as the appimage, if it is not already, then run the appimage.
The packaging process can take up to **5 minutes**.
If you get any errors, then you might have selected the wrong rom. Make sure to use a rom consistent with the above checksum.
### MacOS Rom Extraction
* Run `soh.app`, and when prompted, select one of the supported roms listed above.
* You should see a notification saying `Processing OTR`, then, once the process is complete, you should get a notification saying `OTR Successfully Generated`, then the game should start.
The packing process can take up to **5 minutes**.
If you get an error saying `Incompatible ROM hash`, you have selected the wrong rom, make sure the checksum matches one of the ones listed above.
### Nintendo Switch Rom Extraction
* Download the latest PC release of the Ship of Harkinian, and follow the instructions above for generating the `oot.otr` archive on that platform.
* Place the `.nro` and the `oot.otr` archive into a folder called `soh` in your Switch folder on your Switch
### Nintendo Wii U Rom Extraction
* Download the latest PC release of the Ship of Harkinian, and follow the instructions above for generating the `oot.otr` archive on that platform.
* Copy the `.rpx` and the `oot.otr` archive to `wiiu/apps/soh`
---
If you still cannot get the tool to work, join our [Discord Server](https://discord.com/invite/BtBmd55HVH) and ask for help in the `#support` text channel. Keep-in-mind that we do not condone piracy in any way. If you still cannot get the tool to work, join our [Discord Server](https://discord.com/invite/BtBmd55HVH) and ask for help in the `#support` text channel. Keep-in-mind that we do not condone piracy in any way.
### Running The Ship of Harkinian ### Running The Ship of Harkinian

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <cstdint>
struct Vec3f struct Vec3f
{ {
float x, y, z; float x, y, z;

View File

@ -10,7 +10,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "Resource.h" #include "Resource.h"
//#include "Lib/StrHash64.h"
#include "StormLib.h" #include "StormLib.h"

View File

@ -87,6 +87,7 @@ set(Source_Files__Controller
"KeyboardController.cpp" "KeyboardController.cpp"
"KeyboardController.h" "KeyboardController.h"
"UltraController.h" "UltraController.h"
"DummyController.cpp"
"DummyController.h" "DummyController.h"
) )
@ -133,8 +134,6 @@ source_group("Source Files\\CustomImpl\\Utils" FILES ${Source_Files__CustomImpl_
set(Source_Files__Globals set(Source_Files__Globals
"Cvar.cpp" "Cvar.cpp"
"Cvar.h" "Cvar.h"
"GlobalCtx2.cpp"
"GlobalCtx2.h"
"LUSMacros.h" "LUSMacros.h"
"Window.cpp" "Window.cpp"
"Window.h" "Window.h"
@ -569,6 +568,10 @@ target_include_directories(${PROJECT_NAME} PRIVATE
if(MSVC) if(MSVC)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_options(${PROJECT_NAME} PRIVATE target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/Od;
/Oi-
>
$<$<CONFIG:Release>: $<$<CONFIG:Release>:
/std:c++latest; /std:c++latest;
/Oi; /Oi;

View File

@ -1,12 +1,12 @@
#include "Console.h" #include "Console.h"
#include "Cvar.h" #include "Cvar.h"
#include "GlobalCtx2.h"
#include "ImGuiImpl.h" #include "ImGuiImpl.h"
#include "Lib/ImGui/imgui.h" #include "Lib/ImGui/imgui.h"
#include "Utils/StringHelper.h" #include "Utils/StringHelper.h"
#include "Lib/ImGui/imgui_internal.h" #include "Lib/ImGui/imgui_internal.h"
#include "Utils.h" #include "Utils.h"
#include <sstream>
namespace Ship { namespace Ship {
std::string BuildUsage(const CommandEntry& entry) { std::string BuildUsage(const CommandEntry& entry) {
@ -389,4 +389,20 @@ namespace Ship {
Commands[command] = entry; Commands[command] = entry;
} }
} }
std::string Console::GetCurrentChannel() {
return currentChannel;
}
bool Console::IsOpened() {
return opened;
}
void Console::Close() {
opened = false;
}
void Console::Open() {
opened = true;
}
} }

View File

@ -6,8 +6,6 @@
#include <functional> #include <functional>
#include "Lib/ImGui/imgui.h" #include "Lib/ImGui/imgui.h"
#define NOGDI
#define WIN32_LEAN_AND_MEAN
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
namespace Ship { namespace Ship {
@ -95,10 +93,9 @@ namespace Ship {
void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...); void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...);
bool HasCommand(const std::string& command); bool HasCommand(const std::string& command);
void AddCommand(const std::string& command, CommandEntry entry); void AddCommand(const std::string& command, CommandEntry entry);
std::string GetCurrentChannel();
std::string GetCurrentChannel() { return currentChannel; } bool IsOpened();
bool IsOpened() { return opened; } void Close();
void Close() { opened = false; } void Open();
void Open() { opened = true; }
}; };
} }

View File

@ -96,7 +96,7 @@ namespace Ship {
#define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), virtualSlot, __VA_ARGS__) #define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), virtualSlot, __VA_ARGS__)
void ControlDeck::LoadControllerSettings() { void ControlDeck::LoadControllerSettings() {
std::shared_ptr<Mercury> Config = GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<Mercury> Config = Window::GetInstance()->GetConfig();
for (auto const& val : Config->rjson["Controllers"]["Deck"].items()) { for (auto const& val : Config->rjson["Controllers"]["Deck"].items()) {
int32_t slot = std::stoi(val.key().substr(5)); int32_t slot = std::stoi(val.key().substr(5));
@ -182,7 +182,7 @@ namespace Ship {
} }
void ControlDeck::SaveControllerSettings() { void ControlDeck::SaveControllerSettings() {
std::shared_ptr<Mercury> Config = GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<Mercury> Config = Window::GetInstance()->GetConfig();
for (size_t i = 0; i < virtualDevices.size(); i++) { for (size_t i = 0; i < virtualDevices.size(); i++) {
std::shared_ptr<Controller> backend = physicalDevices[virtualDevices[i]]; std::shared_ptr<Controller> backend = physicalDevices[virtualDevices[i]];

View File

@ -21,7 +21,7 @@ namespace Ship {
size_t GetNumVirtualDevices(); size_t GetNumVirtualDevices();
uint8_t* GetControllerBits(); uint8_t* GetControllerBits();
private: private:
std::vector<int> virtualDevices = {}; std::vector<int32_t> virtualDevices = {};
std::vector<std::shared_ptr<Controller>> physicalDevices = {}; std::vector<std::shared_ptr<Controller>> physicalDevices = {};
uint8_t* controllerBits = nullptr; uint8_t* controllerBits = nullptr;
}; };

View File

@ -112,4 +112,16 @@ namespace Ship {
std::shared_ptr<DeviceProfile> Controller::getProfile(int32_t virtualSlot) { std::shared_ptr<DeviceProfile> Controller::getProfile(int32_t virtualSlot) {
return profiles[virtualSlot]; return profiles[virtualSlot];
} }
std::shared_ptr<ControllerAttachment> Controller::GetAttachment() {
return Attachment;
}
bool Controller::IsRumbling() {
return isRumbling;
}
std::string Controller::GetGuid() {
return GUID;
}
} }

View File

@ -40,7 +40,6 @@ namespace Ship {
public: public:
virtual ~Controller() = default; virtual ~Controller() = default;
Controller(); Controller();
void Read(OSContPad* pad, int32_t virtualSlot);
virtual void ReadFromSource(int32_t virtualSlot) = 0; virtual void ReadFromSource(int32_t virtualSlot) = 0;
virtual void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) = 0; virtual void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) = 0;
virtual bool Connected() const = 0; virtual bool Connected() const = 0;
@ -49,8 +48,12 @@ namespace Ship {
virtual void CreateDefaultBinding(int32_t virtualSlot) = 0; virtual void CreateDefaultBinding(int32_t virtualSlot) = 0;
virtual void ClearRawPress() = 0; virtual void ClearRawPress() = 0;
virtual int32_t ReadRawPress() = 0; virtual int32_t ReadRawPress() = 0;
virtual const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) = 0;
virtual const std::string GetControllerName() = 0;
void Read(OSContPad* pad, int32_t virtualSlot);
void SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t dwScancode); void SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t dwScancode);
std::shared_ptr<ControllerAttachment> GetAttachment() { return Attachment; } std::shared_ptr<ControllerAttachment> GetAttachment();
std::shared_ptr<DeviceProfile> getProfile(int32_t virtualSlot);
int8_t& getLeftStickX(int32_t virtualSlot); int8_t& getLeftStickX(int32_t virtualSlot);
int8_t& getLeftStickY(int32_t virtualSlot); int8_t& getLeftStickY(int32_t virtualSlot);
int8_t& getRightStickX(int32_t virtualSlot); int8_t& getRightStickX(int32_t virtualSlot);
@ -58,11 +61,8 @@ namespace Ship {
int32_t& getPressedButtons(int32_t virtualSlot); int32_t& getPressedButtons(int32_t virtualSlot);
float& getGyroX(int32_t virtualSlot); float& getGyroX(int32_t virtualSlot);
float& getGyroY(int32_t virtualSlot); float& getGyroY(int32_t virtualSlot);
std::shared_ptr<DeviceProfile> getProfile(int32_t virtualSlot); bool IsRumbling();
bool IsRumbling() { return isRumbling; } std::string GetGuid();
std::string GetGuid() { return GUID; }
virtual const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) = 0;
virtual const std::string GetControllerName() = 0;
protected: protected:
std::shared_ptr<ControllerAttachment> Attachment; std::shared_ptr<ControllerAttachment> Attachment;

View File

@ -5,7 +5,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <Utils/File.h> #include <Utils/File.h>
#include "GlobalCtx2.h" #include "Window.h"
std::map<std::string, std::unique_ptr<CVar>, std::less<>> cvars; std::map<std::string, std::unique_ptr<CVar>, std::less<>> cvars;
@ -144,7 +144,7 @@ template <typename Numeric> bool is_number(const std::string& s) {
} }
void CVar_LoadLegacy() { void CVar_LoadLegacy() {
auto cvarsConfig = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("cvars.cfg"); auto cvarsConfig = Ship::Window::GetPathRelativeToAppDirectory("cvars.cfg");
if (File::Exists(cvarsConfig)) { if (File::Exists(cvarsConfig)) {
const auto lines = File::ReadAllLines(cvarsConfig); const auto lines = File::ReadAllLines(cvarsConfig);
@ -191,7 +191,7 @@ void CVar_LoadLegacy() {
extern "C" void CVar_Load() { extern "C" void CVar_Load() {
std::shared_ptr<Mercury> pConf = Ship::GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<Mercury> pConf = Ship::Window::GetInstance()->GetConfig();
pConf->reload(); pConf->reload();
for (const auto& item : pConf->rjson["CVars"].items()) { for (const auto& item : pConf->rjson["CVars"].items()) {
@ -235,7 +235,7 @@ extern "C" void CVar_Load() {
extern "C" void CVar_Save() extern "C" void CVar_Save()
{ {
std::shared_ptr<Mercury> pConf = Ship::GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<Mercury> pConf = Ship::Window::GetInstance()->GetConfig();
for (const auto& cvar : cvars) { for (const auto& cvar : cvars) {
const std::string key = StringHelper::Sprintf("CVars.%s", cvar.first.c_str()); const std::string key = StringHelper::Sprintf("CVars.%s", cvar.first.c_str());
@ -251,9 +251,9 @@ extern "C" void CVar_Save()
auto keyStr = key.c_str(); auto keyStr = key.c_str();
Color_RGBA8 clr = cvar.second->value.valueRGBA; Color_RGBA8 clr = cvar.second->value.valueRGBA;
pConf->setUInt(StringHelper::Sprintf("%s.R", keyStr), clr.r); pConf->setUInt(StringHelper::Sprintf("%s.R", keyStr), clr.r);
pConf->setUInt(StringHelper::Sprintf("%s.G", keyStr), clr.r); pConf->setUInt(StringHelper::Sprintf("%s.G", keyStr), clr.g);
pConf->setUInt(StringHelper::Sprintf("%s.B", keyStr), clr.r); pConf->setUInt(StringHelper::Sprintf("%s.B", keyStr), clr.b);
pConf->setUInt(StringHelper::Sprintf("%s.A", keyStr), clr.r); pConf->setUInt(StringHelper::Sprintf("%s.A", keyStr), clr.a);
pConf->setString(StringHelper::Sprintf("%s.Type", keyStr), mercuryRGBAObjectType); pConf->setString(StringHelper::Sprintf("%s.Type", keyStr), mercuryRGBAObjectType);
} }
} }

View File

@ -0,0 +1,61 @@
#include "DummyController.h"
namespace Ship {
DummyController::DummyController(const std::string& CUID, const std::string& KeyName, bool Connected) {
GUID = CUID;
isConnected = Connected;
ButtonName = KeyName;
}
void DummyController::ReadFromSource(int32_t virtualSlot) {
}
const std::string DummyController::GetControllerName() {
return GUID;
}
const std::string DummyController::GetButtonName(int32_t virtualSlot, int32_t n64Button) {
return ButtonName;
}
void DummyController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller){
}
bool DummyController::Connected() const {
return isConnected;
}
bool DummyController::CanRumble() const {
return false;
}
bool DummyController::CanGyro() const {
return false;
}
void DummyController::CreateDefaultBinding(int32_t slot) {
}
std::string DummyController::GetControllerType() {
return "Unk";
}
std::string DummyController::GetConfSection() {
return "Unk";
}
std::string DummyController::GetBindingConfSection() {
return "Unk";
}
void DummyController::ClearRawPress() {
}
int32_t DummyController::ReadRawPress() {
return -1;
}
}

View File

@ -7,31 +7,25 @@
namespace Ship { namespace Ship {
class DummyController final : public Controller { class DummyController final : public Controller {
public: public:
DummyController(const std::string& CUID, const std::string& KeyName, bool Connected) { DummyController(const std::string& CUID, const std::string& KeyName, bool Connected);
GUID = CUID;
isConnected = Connected;
ButtonName = KeyName;
}
std::map<std::vector<std::string>, int32_t> ReadButtonPress(); std::map<std::vector<std::string>, int32_t> ReadButtonPress();
void ReadFromSource(int32_t slot) override {} void ReadFromSource(int32_t virtualSlot) override;
const std::string GetControllerName() override { return GUID; } const std::string GetControllerName() override;
const std::string GetButtonName(int slot, int n64Button) override { return ButtonName; } const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override;
void WriteToSource(int32_t slot, ControllerCallback* controller) override { } void WriteToSource(int32_t slot, ControllerCallback* controller) override;
bool Connected() const override { return isConnected; } bool Connected() const override;
bool CanRumble() const override { return false; } bool CanRumble() const override;
bool CanGyro() const override { return false; } bool CanGyro() const override;
void ClearRawPress() override;
void ClearRawPress() override {} int32_t ReadRawPress() override;
int32_t ReadRawPress() override { return -1; } bool HasPadConf() const;
bool HasPadConf() const { return true; } std::optional<std::string> GetPadConfSection();
std::optional<std::string> GetPadConfSection() { return "Unk"; } void CreateDefaultBinding(int32_t virtualSlot) override;
void CreateDefaultBinding(int32_t slot) override {}
protected: protected:
std::string ButtonName; std::string ButtonName;
bool isConnected = false; bool isConnected = false;
std::string GetControllerType() { return "Unk"; } std::string GetControllerType();
std::string GetConfSection() { return "Unk"; } std::string GetConfSection();
std::string GetBindingConfSection() { return "Unk"; } std::string GetBindingConfSection();
}; };
} }

View File

@ -2,7 +2,8 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include "GlobalCtx2.h" #include <mutex>
#include <condition_variable>
namespace Ship { namespace Ship {
class Archive; class Archive;

View File

@ -45,7 +45,7 @@ namespace Ship {
void GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) { void GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
std::shared_ptr<Archive> base = GlobalCtx2::GetInstance()->GetResourceManager()->GetArchive(); std::shared_ptr<Archive> base = Window::GetInstance()->GetResourceManager()->GetArchive();
std::shared_ptr<File> font = std::make_shared<File>(); std::shared_ptr<File> font = std::make_shared<File>();
base->LoadFile(path, false, font); base->LoadFile(path, false, font);
if (font->bIsLoaded) { if (font->bIsLoaded) {

View File

@ -1,149 +0,0 @@
#include "GlobalCtx2.h"
#include <iostream>
#include <vector>
#include "ResourceMgr.h"
#include "Window.h"
#include "spdlog/async.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/sohconsole_sink.h"
#ifdef __APPLE__
#include "OSXFolderManager.h"
#elif defined(__SWITCH__)
#include "SwitchImpl.h"
#elif defined(__WIIU__)
#include "WiiUImpl.h"
#endif
namespace Ship {
std::weak_ptr<GlobalCtx2> GlobalCtx2::Context;
std::shared_ptr<GlobalCtx2> GlobalCtx2::GetInstance() {
return Context.lock();
}
std::shared_ptr<GlobalCtx2> GlobalCtx2::CreateInstance(const std::string& Name) {
if (Context.expired()) {
auto Shared = std::make_shared<GlobalCtx2>(Name);
Context = Shared;
Shared->InitWindow();
return Shared;
} else {
SPDLOG_DEBUG("Trying to create a context when it already exists.");
}
return GetInstance();
}
std::string GlobalCtx2::GetAppDirectoryPath() {
#ifdef __APPLE__
FolderManager folderManager;
std::string fpath = std::string(folderManager.pathForDirectory(NSApplicationSupportDirectory, NSUserDomainMask));
fpath.append("/com.shipofharkinian.soh");
return fpath;
#endif
return ".";
}
std::string GlobalCtx2::GetPathRelativeToAppDirectory(const char* path) {
return GlobalCtx2::GetAppDirectoryPath() + "/" + path;
}
GlobalCtx2::GlobalCtx2(std::string Name) : Name(std::move(Name)) {
}
GlobalCtx2::~GlobalCtx2() {
SPDLOG_INFO("destruct GlobalCtx2");
}
void GlobalCtx2::InitWindow() {
InitLogging();
Config = std::make_shared<Mercury>(GetPathRelativeToAppDirectory("shipofharkinian.json"));
MainPath = Config->getString("Game.Main Archive", GetPathRelativeToAppDirectory("oot.otr"));
PatchesPath = Config->getString("Game.Patches Archive", GetAppDirectoryPath() + "/mods");
ResMan = std::make_shared<ResourceMgr>(GetInstance(), MainPath, PatchesPath);
Win = std::make_shared<Window>(GetInstance());
if (!ResMan->DidLoadSuccessfully())
{
#ifdef _WIN32
MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK);
#elif defined(__SWITCH__)
printf("Main OTR file not found!\n");
#elif defined(__WIIU__)
Ship::WiiU::ThrowMissingOTR(MainPath.c_str());
#else
SPDLOG_ERROR("Main OTR file not found!");
#endif
exit(1);
}
#ifdef __SWITCH__
Ship::Switch::Init(PostInitPhase);
#endif
}
void GlobalCtx2::InitLogging() {
try {
// Setup Logging
spdlog::init_thread_pool(8192, 1);
std::vector<spdlog::sink_ptr> Sinks;
auto SohConsoleSink = std::make_shared<spdlog::sinks::soh_sink_mt>();
SohConsoleSink->set_level(spdlog::level::trace);
Sinks.push_back(SohConsoleSink);
#if (!defined(_WIN32) && !defined(__WIIU__)) || defined(_DEBUG)
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
ConsoleSink->set_level(spdlog::level::trace);
Sinks.push_back(ConsoleSink);
#endif
#ifndef __WIIU__
auto logPath = GetPathRelativeToAppDirectory(("logs/" + GetName() + ".log").c_str());
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
FileSink->set_level(spdlog::level::trace);
Sinks.push_back(FileSink);
#endif
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);
#ifndef __WIIU__
GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v");
#else
GetLogger()->set_pattern("[%s:%#] [%l] %v");
#endif
spdlog::register_logger(GetLogger());
spdlog::set_default_logger(GetLogger());
}
catch (const spdlog::spdlog_ex& ex) {
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
void GlobalCtx2::WriteSaveFile(const std::filesystem::path& savePath, const uintptr_t addr, void* dramAddr, const size_t size) {
std::ofstream saveFile = std::ofstream(savePath, std::fstream::in | std::fstream::out | std::fstream::binary);
saveFile.seekp(addr);
saveFile.write((char*)dramAddr, size);
saveFile.close();
}
void GlobalCtx2::ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size) {
std::ifstream saveFile = std::ifstream(savePath, std::fstream::in | std::fstream::out | std::fstream::binary);
// If the file doesn't exist, initialize DRAM
if (saveFile.good()) {
saveFile.seekg(addr);
saveFile.read((char*)dramAddr, size);
} else {
memset(dramAddr, 0, size);
}
saveFile.close();
}
}

View File

@ -1,54 +0,0 @@
#ifndef GLOBAL_CTX_2
#define GLOBAL_CTX_2
#pragma once
#ifdef __cplusplus
#include <filesystem>
#include <memory>
#include <fstream>
#include "spdlog/spdlog.h"
#include "Lib/Mercury/Mercury.h"
namespace Ship {
class ResourceMgr;
class Window;
class GlobalCtx2 {
public:
static std::shared_ptr<GlobalCtx2> GetInstance();
static std::shared_ptr<GlobalCtx2> CreateInstance(const std::string& Name);
std::string GetName() { return Name; }
std::shared_ptr<Window> GetWindow() { return Win; }
std::shared_ptr<ResourceMgr> GetResourceManager() { return ResMan; }
std::shared_ptr<spdlog::logger> GetLogger() { return Logger; }
std::shared_ptr<Mercury> GetConfig() { return Config; }
static std::string GetAppDirectoryPath();
static std::string GetPathRelativeToAppDirectory(const char* path);
void WriteSaveFile(const std::filesystem::path& savePath, uintptr_t addr, void* dramAddr, size_t size);
void ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size);
GlobalCtx2(std::string Name);
~GlobalCtx2();
protected:
void InitWindow();
void InitLogging();
private:
static std::weak_ptr <GlobalCtx2> Context;
std::shared_ptr<spdlog::logger> Logger;
std::shared_ptr<Window> Win;
std::shared_ptr<Mercury> Config; // Config needs to be after the Window because we call the Window during it's destructor.
std::shared_ptr<ResourceMgr> ResMan;
std::string Name;
std::string MainPath;
std::string PatchesPath;
};
}
#endif
#endif

View File

@ -0,0 +1,5 @@
#include "Hooks.h"
namespace Ship {
}

View File

@ -18,7 +18,6 @@
#include "Hooks.h" #include "Hooks.h"
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
#include "Lib/ImGui/imgui_internal.h" #include "Lib/ImGui/imgui_internal.h"
#include "GlobalCtx2.h"
#include "ResourceMgr.h" #include "ResourceMgr.h"
#include "Window.h" #include "Window.h"
#include "Cvar.h" #include "Cvar.h"
@ -42,8 +41,10 @@
#if __APPLE__ #if __APPLE__
#include <SDL_hints.h> #include <SDL_hints.h>
#include <SDL_video.h>
#else #else
#include <SDL2/SDL_hints.h> #include <SDL2/SDL_hints.h>
#include <SDL2/SDL_video.h>
#endif #endif
#ifdef __SWITCH__ #ifdef __SWITCH__
@ -164,8 +165,14 @@ namespace SohImGui {
} else { } else {
console->Close(); console->Close();
} }
SohImGui::controller->Opened = CVar_GetS32("gControllerConfigurationEnabled", 0);
UpdateAudio(); if (CVar_GetS32("gControllerConfigurationEnabled", 0)) {
controller->Open();
} else {
controller->Close();
}
UpdateAudio();
}); });
} }
@ -338,6 +345,8 @@ namespace SohImGui {
switch (impl.backend) { switch (impl.backend) {
case Backend::DX11: case Backend::DX11:
return true; return true;
case Backend::SDL:
return true;
default: default:
return false; return false;
} }
@ -345,27 +354,27 @@ namespace SohImGui {
void ShowCursor(bool hide, Dialogues d) { void ShowCursor(bool hide, Dialogues d) {
if (d == Dialogues::dLoadSettings) { if (d == Dialogues::dLoadSettings) {
GlobalCtx2::GetInstance()->GetWindow()->ShowCursor(hide); Window::GetInstance()->ShowCursor(hide);
return; return;
} }
if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) {
return; return;
} }
if (!GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) { if (!Window::GetInstance()->IsFullscreen()) {
oldCursorState = false; oldCursorState = false;
return; return;
} }
if (oldCursorState != hide) { if (oldCursorState != hide) {
oldCursorState = hide; oldCursorState = hide;
GlobalCtx2::GetInstance()->GetWindow()->ShowCursor(hide); Window::GetInstance()->ShowCursor(hide);
} }
} }
void LoadTexture(const std::string& name, const std::string& path) { void LoadTexture(const std::string& name, const std::string& path) {
GfxRenderingAPI* api = gfx_get_current_rendering_api(); GfxRenderingAPI* api = gfx_get_current_rendering_api();
const auto res = GlobalCtx2::GetInstance()->GetResourceManager()->LoadFile(path); const auto res = Window::GetInstance()->GetResourceManager()->LoadFile(path);
const auto asset = new GameAsset{ api->new_texture() }; const auto asset = new GameAsset{ api->new_texture() };
uint8_t* img_data = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(res->buffer.get()), res->dwBufferSize, &asset->width, &asset->height, nullptr, 4); uint8_t* img_data = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(res->buffer.get()), res->dwBufferSize, &asset->width, &asset->height, nullptr, 4);
@ -401,7 +410,7 @@ namespace SohImGui {
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) {
GfxRenderingAPI* api = gfx_get_current_rendering_api(); GfxRenderingAPI* api = gfx_get_current_rendering_api();
const auto res = static_cast<Ship::Texture*>(GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(path).get()); const auto res = static_cast<Ship::Texture*>(Window::GetInstance()->GetResourceManager()->LoadResource(path).get());
std::vector<uint8_t> texBuffer; std::vector<uint8_t> texBuffer;
texBuffer.reserve(res->width * res->height * 4); texBuffer.reserve(res->width * res->height * 4);
@ -452,6 +461,8 @@ namespace SohImGui {
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io->Fonts->AddFontDefault(); io->Fonts->AddFontDefault();
statsWindowOpen = CVar_GetS32("gStatsEnabled", 0); statsWindowOpen = CVar_GetS32("gStatsEnabled", 0);
CVar_RegisterS32("gRandomizeRupeeNames", 1);
CVar_RegisterS32("gRandoRelevantNavi", 1);
#ifdef __SWITCH__ #ifdef __SWITCH__
Ship::Switch::SetupFont(io->Fonts); Ship::Switch::SetupFont(io->Fonts);
#endif #endif
@ -466,7 +477,7 @@ namespace SohImGui {
io->DisplaySize.y = window_impl.gx2.height; io->DisplaySize.y = window_impl.gx2.height;
#endif #endif
lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig()); lastBackendID = GetBackendID(Window::GetInstance()->GetConfig());
if (CVar_GetS32("gOpenMenuBar", 0) != 1) { if (CVar_GetS32("gOpenMenuBar", 0) != 1) {
#if defined(__SWITCH__) || defined(__WIIU__) #if defined(__SWITCH__) || defined(__WIIU__)
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu"); SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
@ -475,8 +486,8 @@ namespace SohImGui {
#endif #endif
} }
auto imguiIniPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui.ini"); auto imguiIniPath = Ship::Window::GetPathRelativeToAppDirectory("imgui.ini");
auto imguiLogPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui_log.txt"); auto imguiLogPath = Ship::Window::GetPathRelativeToAppDirectory("imgui_log.txt");
io->IniFilename = strcpy(new char[imguiIniPath.length() + 1], imguiIniPath.c_str()); io->IniFilename = strcpy(new char[imguiIniPath.length() + 1], imguiIniPath.c_str());
io->LogFilename = strcpy(new char[imguiLogPath.length() + 1], imguiLogPath.c_str()); io->LogFilename = strcpy(new char[imguiLogPath.length() + 1], imguiLogPath.c_str());
@ -500,7 +511,7 @@ namespace SohImGui {
#endif #endif
Ship::RegisterHook<Ship::GfxInit>([] { Ship::RegisterHook<Ship::GfxInit>([] {
if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) if (Window::GetInstance()->IsFullscreen())
ShowCursor(CVar_GetS32("gOpenMenuBar", 0), Dialogues::dLoadSettings); ShowCursor(CVar_GetS32("gOpenMenuBar", 0), Dialogues::dLoadSettings);
LoadTexture("Game_Icon", "assets/ship_of_harkinian/icons/gSohIcon.png"); LoadTexture("Game_Icon", "assets/ship_of_harkinian/icons/gSohIcon.png");
@ -600,13 +611,101 @@ namespace SohImGui {
ImGui::Text("%s", text); ImGui::Text("%s", text);
} }
void EnhancementCheckbox(const char* text, const char* cvarName) void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz)
{ {
float thickness = ImMax(sz / 5.0f, 1.0f);
sz -= thickness * 0.5f;
pos += ImVec2(thickness * 0.25f, thickness * 0.25f);
draw_list->PathLineTo(ImVec2(pos.x, pos.y));
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y));
draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz));
draw_list->PathStroke(col, 0, thickness);
}
bool CustomCheckbox(const char* label, bool* v, bool disabled, ImGuiCheckboxGraphics disabledGraphic) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
const float square_sz = ImGui::GetFrameHeight();
const ImVec2 pos = window->DC.CursorPos;
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ImGui::ItemSize(total_bb, style.FramePadding.y);
if (!ImGui::ItemAdd(total_bb, id))
{
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false;
}
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held);
if (pressed)
{
*v = !(*v);
ImGui::MarkItemEdited(id);
}
const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
ImGui::RenderNavHighlight(total_bb, id);
ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark);
ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f));
bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value)
{
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
// This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox)
ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
}
else if ((!disabled && *v) || (disabled && disabledGraphic == ImGuiCheckboxGraphics::Checkmark))
{
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
}
else if (disabled && disabledGraphic == ImGuiCheckboxGraphics::Cross) {
const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f);
}
ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
if (g.LogEnabled)
ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
if (label_size.x > 0.0f)
ImGui::RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic)
{
if (disabled) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
bool val = (bool)CVar_GetS32(cvarName, 0); bool val = (bool)CVar_GetS32(cvarName, 0);
if (ImGui::Checkbox(text, &val)) { if (CustomCheckbox(text, &val, disabled, disabledGraphic)) {
CVar_SetS32(cvarName, val); CVar_SetS32(cvarName, val);
needs_save = true; needs_save = true;
} }
if (disabled) {
ImGui::PopStyleVar(1);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && disabledTooltipText != "") {
ImGui::SetTooltip("%s", disabledTooltipText);
}
ImGui::PopItemFlag();
}
} }
void EnhancementButton(const char* text, const char* cvarName) void EnhancementButton(const char* text, const char* cvarName)
@ -753,12 +852,7 @@ namespace SohImGui {
} }
void RandomizeColor(const char* cvarName, ImVec4* colors) { void RandomizeColor(const char* cvarName, ImVec4* colors) {
std::string Cvar_Red = cvarName; Color_RGBA8 NewColors = {0,0,0,255};
Cvar_Red += "R";
std::string Cvar_Green = cvarName;
Cvar_Green += "G";
std::string Cvar_Blue = cvarName;
Cvar_Blue += "B";
std::string Cvar_RBM = cvarName; std::string Cvar_RBM = cvarName;
Cvar_RBM += "RBM"; Cvar_RBM += "RBM";
std::string MakeInvisible = "##"; std::string MakeInvisible = "##";
@ -773,9 +867,10 @@ namespace SohImGui {
colors->x = (float)RND_R / 255; colors->x = (float)RND_R / 255;
colors->y = (float)RND_G / 255; colors->y = (float)RND_G / 255;
colors->z = (float)RND_B / 255; colors->z = (float)RND_B / 255;
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(colors->x * 255, 0, 255)); NewColors.r = ClampFloatToInt(colors->x * 255, 0, 255);
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(colors->y * 255, 0, 255)); NewColors.g = ClampFloatToInt(colors->y * 255, 0, 255);
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(colors->z * 255, 0, 255)); NewColors.b = ClampFloatToInt(colors->z * 255, 0, 255);
CVar_SetRGBA(cvarName, NewColors);
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
needs_save = true; needs_save = true;
} }
@ -802,16 +897,16 @@ namespace SohImGui {
MakeInvisible += cvarName; MakeInvisible += cvarName;
MakeInvisible += "Reset"; MakeInvisible += "Reset";
if (ImGui::Button(MakeInvisible.c_str())) { if (ImGui::Button(MakeInvisible.c_str())) {
colors->x = defaultcolors.x / 255; colors->x = defaultcolors.x;
colors->y = defaultcolors.y / 255; colors->y = defaultcolors.y;
colors->z = defaultcolors.z / 255; colors->z = defaultcolors.z;
if (has_alpha) { colors->w = defaultcolors.w / 255; }; if (has_alpha) { colors->w = defaultcolors.w; };
Color_RGBA8 colorsRGBA; Color_RGBA8 colorsRGBA;
colorsRGBA.r = defaultcolors.x / 255; colorsRGBA.r = defaultcolors.x;
colorsRGBA.g = defaultcolors.y / 255; colorsRGBA.g = defaultcolors.y;
colorsRGBA.b = defaultcolors.z / 255; colorsRGBA.b = defaultcolors.z;
if (has_alpha) { colorsRGBA.a = defaultcolors.w / 255; }; if (has_alpha) { colorsRGBA.a = defaultcolors.w; };
CVar_SetRGBA(cvarName, colorsRGBA); CVar_SetRGBA(cvarName, colorsRGBA);
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
@ -883,8 +978,8 @@ namespace SohImGui {
ImGuiWMNewFrame(); ImGuiWMNewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
const std::shared_ptr<Window> wnd = GlobalCtx2::GetInstance()->GetWindow(); const std::shared_ptr<Window> wnd = Window::GetInstance();
const std::shared_ptr<Mercury> pConf = GlobalCtx2::GetInstance()->GetConfig(); const std::shared_ptr<Mercury> pConf = Window::GetInstance()->GetConfig();
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove |
@ -921,9 +1016,9 @@ namespace SohImGui {
bool menu_bar = CVar_GetS32("gOpenMenuBar", 0); bool menu_bar = CVar_GetS32("gOpenMenuBar", 0);
CVar_SetS32("gOpenMenuBar", !menu_bar); CVar_SetS32("gOpenMenuBar", !menu_bar);
needs_save = true; needs_save = true;
GlobalCtx2::GetInstance()->GetWindow()->SetMenuBar(menu_bar); Window::GetInstance()->SetMenuBar(menu_bar);
ShowCursor(menu_bar, Dialogues::dMenubar); ShowCursor(menu_bar, Dialogues::dMenubar);
GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->SaveControllerSettings(); Window::GetInstance()->GetControlDeck()->SaveControllerSettings();
if (CVar_GetS32("gControlNav", 0) && CVar_GetS32("gOpenMenuBar", 0)) { if (CVar_GetS32("gControlNav", 0) && CVar_GetS32("gOpenMenuBar", 0)) {
io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard; io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard;
} else { } else {
@ -1009,7 +1104,11 @@ namespace SohImGui {
bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0); bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0);
CVar_SetS32("gControllerConfigurationEnabled", !currentValue); CVar_SetS32("gControllerConfigurationEnabled", !currentValue);
needs_save = true; needs_save = true;
controller->Opened = CVar_GetS32("gControllerConfigurationEnabled", 0); if (CVar_GetS32("gControllerConfigurationEnabled", 0)) {
controller->Open();
} else {
controller->Close();
}
} }
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);
@ -1214,6 +1313,8 @@ namespace SohImGui {
Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); Tooltip("The default response to Kaepora Gaebora is always that you understood what he said");
PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false);
Tooltip("Skip the part where the Ocarina playback is called when you play a song"); Tooltip("Skip the part where the Ocarina playback is called when you play a song");
PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false);
Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song.");
PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false);
Tooltip("Allow Link to put items away without having to wait around"); Tooltip("Allow Link to put items away without having to wait around");
PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false);
@ -1268,6 +1369,8 @@ namespace SohImGui {
); );
PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false);
Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses");
PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false);
Tooltip("Bombchus will sometimes drop in place of bombs");
PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false);
Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series");
PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false);
@ -1502,6 +1605,7 @@ namespace SohImGui {
Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64");
PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false);
Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC");
PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false);
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -1897,11 +2001,21 @@ namespace SohImGui {
if (ImGui::BeginMenu("Rando Enhancements")) if (ImGui::BeginMenu("Rando Enhancements"))
{ {
EnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares"); EnhancementCheckbox("Rando-Relevant Navi Hints", "gRandoRelevantNavi");
Tooltip( Tooltip(
"Play unique fanfares when obtaining quest items\n" "Replace Navi's overworld quest hints with rando-related gameplay hints."
"(medallions/stones/songs). Note that these fanfares\n" );
"are longer than usual." PaddedEnhancementCheckbox("Random Rupee Names", "gRandomizeRupeeNames", true, false);
Tooltip(
"When obtaining rupees, randomize what the rupee is called in the textbox."
);
PaddedEnhancementCheckbox("Key Colors Match Dungeon", "gRandoMatchKeyColors", true, false);
Tooltip(
"Matches the color of small keys and boss keys to the dungeon they belong to. This helps identify keys from afar and adds a little bit of flair.");
PaddedEnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares", true, false);
Tooltip(
"Play unique fanfares when obtaining quest items "
"(medallions/stones/songs). Note that these fanfares are longer than usual."
); );
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -2157,6 +2271,8 @@ namespace SohImGui {
CVar_SetS32("gNoRandomDrops", 0); CVar_SetS32("gNoRandomDrops", 0);
// No Heart Drops // No Heart Drops
CVar_SetS32("gNoHeartDrops", 0); CVar_SetS32("gNoHeartDrops", 0);
// Enable Bombchu Drops
CVar_SetS32("gBombchuDrops", 0);
// Always Win Goron Pot // Always Win Goron Pot
CVar_SetS32("gGoronPot", 0); CVar_SetS32("gGoronPot", 0);
@ -2288,6 +2404,7 @@ namespace SohImGui {
// Bombchus out of bounds // Bombchus out of bounds
CVar_SetS32("gBombchusOOB", 0); CVar_SetS32("gBombchusOOB", 0);
CVar_SetS32("gGsCutscene", 0);
// Autosave // Autosave
CVar_SetS32("gAutosave", 0); CVar_SetS32("gAutosave", 0);
} }
@ -2407,6 +2524,8 @@ namespace SohImGui {
CVar_SetS32("gVisualAgony", 1); CVar_SetS32("gVisualAgony", 1);
// Pull grave during the day // Pull grave during the day
CVar_SetS32("gDayGravePull", 1); CVar_SetS32("gDayGravePull", 1);
// Pull out Ocarina to Summon Scarecrow
CVar_SetS32("gSkipScarecrow", 0);
// Pause link animation (0 to 16) // Pause link animation (0 to 16)
CVar_SetS32("gPauseLiveLink", 16); CVar_SetS32("gPauseLiveLink", 16);
@ -2418,8 +2537,18 @@ namespace SohImGui {
ImGui::Render(); ImGui::Render();
ImGuiRenderDrawData(ImGui::GetDrawData()); ImGuiRenderDrawData(ImGui::GetDrawData());
if (UseViewports()) { if (UseViewports()) {
ImGui::UpdatePlatformWindows(); if (impl.backend == Backend::SDL) {
ImGui::RenderPlatformWindowsDefault(); SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
} else {
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
} }
} }
@ -2650,11 +2779,11 @@ namespace SohImGui {
} }
} }
void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom) { void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic) {
if (padTop) { if (padTop) {
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
} }
EnhancementCheckbox(text, cvarName); EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic);
if (padBottom) { if (padBottom) {
ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Dummy(ImVec2(0.0f, 0.0f));
} }

View File

@ -34,6 +34,14 @@ namespace SohImGui {
dLoadSettings, dLoadSettings,
}; };
// Enumeration for disabled checkbox graphics
enum class ImGuiCheckboxGraphics
{
Cross,
Checkmark,
None
};
typedef struct { typedef struct {
Backend backend; Backend backend;
union { union {
@ -86,7 +94,7 @@ namespace SohImGui {
void Tooltip(const char* text); void Tooltip(const char* text);
void EnhancementRadioButton(const char* text, const char* cvarName, int id); void EnhancementRadioButton(const char* text, const char* cvarName, int id);
void EnhancementCheckbox(const char* text, const char* cvarName); void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross);
void EnhancementButton(const char* text, const char* cvarName); void EnhancementButton(const char* text, const char* cvarName);
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false);
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false); void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false);
@ -123,7 +131,7 @@ namespace SohImGui {
void InsertPadding(float extraVerticalPadding = 0.0f); void InsertPadding(float extraVerticalPadding = 0.0f);
void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f);
void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true);
void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true); void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross);
void PaddedText(const char* text, bool padTop = true, bool padBottom = true); void PaddedText(const char* text, bool padTop = true, bool padBottom = true);
std::string GetWindowButtonText(const char* text, bool menuOpen); std::string GetWindowButtonText(const char* text, bool menuOpen);
} }

View File

@ -16,11 +16,11 @@ namespace Ship {
} }
std::shared_ptr<Controller> GetControllerPerSlot(int slot) { std::shared_ptr<Controller> GetControllerPerSlot(int slot) {
auto controlDeck = Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
return controlDeck->GetPhysicalDeviceFromVirtualSlot(slot); return controlDeck->GetPhysicalDeviceFromVirtualSlot(slot);
} }
void InputEditor::DrawButton(const char* label, int n64Btn) { void InputEditor::DrawButton(const char* label, int32_t n64Btn) {
const std::shared_ptr<Controller> backend = GetControllerPerSlot(CurrentPort); const std::shared_ptr<Controller> backend = GetControllerPerSlot(CurrentPort);
float size = 40; float size = 40;
@ -85,7 +85,7 @@ namespace Ship {
} }
void InputEditor::DrawControllerSchema() { void InputEditor::DrawControllerSchema() {
auto controlDeck = Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
auto Backend = controlDeck->GetPhysicalDeviceFromVirtualSlot(CurrentPort); auto Backend = controlDeck->GetPhysicalDeviceFromVirtualSlot(CurrentPort);
auto profile = Backend->getProfile(CurrentPort); auto profile = Backend->getProfile(CurrentPort);
bool IsKeyboard = Backend->GetGuid() == "Keyboard" || Backend->GetGuid() == "Auto" || !Backend->Connected(); bool IsKeyboard = Backend->GetGuid() == "Keyboard" || Backend->GetGuid() == "Auto" || !Backend->Connected();
@ -357,4 +357,16 @@ namespace Ship {
ImGui::End(); ImGui::End();
} }
bool InputEditor::IsOpened() {
return Opened;
}
void InputEditor::Open() {
Opened = true;
}
void InputEditor::Close() {
Opened = false;
}
} }

View File

@ -1,18 +1,22 @@
#pragma once #pragma once
#include "stdint.h"
#include "Lib/ImGui/imgui.h" #include "Lib/ImGui/imgui.h"
namespace Ship { namespace Ship {
class InputEditor { class InputEditor {
int CurrentPort = 0; int32_t CurrentPort = 0;
int BtnReading = -1; int32_t BtnReading = -1;
public:
bool Opened = false; bool Opened = false;
public:
void Init(); void Init();
void DrawButton(const char* label, int n64Btn); void DrawButton(const char* label, int32_t n64Btn);
void DrawVirtualStick(const char* label, ImVec2 stick); void DrawVirtualStick(const char* label, ImVec2 stick);
void DrawControllerSchema(); void DrawControllerSchema();
void DrawHud(); void DrawHud();
bool IsOpened();
void Open();
void Close();
}; };
} }

View File

@ -7,7 +7,7 @@
#endif #endif
#include "Hooks.h" #include "Hooks.h"
#include "GlobalCtx2.h"
#include "Window.h" #include "Window.h"
namespace Ship { namespace Ship {
@ -70,7 +70,7 @@ namespace Ship {
}); });
if (find == Mappings.end()) return "Unknown"; if (find == Mappings.end()) return "Unknown";
const char* name = GlobalCtx2::GetInstance()->GetWindow()->GetKeyName(find->first); const char* name = Window::GetInstance()->GetKeyName(find->first);
return strlen(name) == 0 ? "Unknown" : name; return strlen(name) == 0 ? "Unknown" : name;
} }
@ -100,4 +100,28 @@ namespace Ship {
const std::string KeyboardController::GetControllerName() { const std::string KeyboardController::GetControllerName() {
return "Keyboard"; return "Keyboard";
} }
bool KeyboardController::Connected() const {
return true;
}
bool KeyboardController::CanRumble() const {
return false;
}
bool KeyboardController::CanGyro() const {
return false;
}
void KeyboardController::ClearRawPress() {
lastKey = -1;
}
void KeyboardController::SetLastScancode(int32_t key) {
lastScancode = key;
}
int32_t KeyboardController::GetLastScancode() {
return lastScancode;
}
} }

View File

@ -9,26 +9,18 @@ namespace Ship {
void ReadFromSource(int32_t virtualSlot) override; void ReadFromSource(int32_t virtualSlot) override;
void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override;
bool Connected() const override { return true; }
bool CanRumble() const override { return false; }
bool CanGyro() const override { return false; }
const std::string GetControllerName() override; const std::string GetControllerName() override;
const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override; const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override;
bool PressButton(int32_t dwScancode); bool PressButton(int32_t dwScancode);
bool ReleaseButton(int32_t dwScancode); bool ReleaseButton(int32_t dwScancode);
bool Connected() const override;
void ClearRawPress() override { bool CanRumble() const override;
lastKey = -1; bool CanGyro() const override;
} void ClearRawPress() override;
int32_t ReadRawPress() override; int32_t ReadRawPress() override;
void ReleaseAllButtons(); void ReleaseAllButtons();
void SetLastScancode(int32_t key);
void SetLastScancode(int32_t key) { int32_t GetLastScancode();
lastScancode = key;
}
int32_t GetLastScancode() { return lastScancode; }
void CreateDefaultBinding(int32_t virtualSlot) override; void CreateDefaultBinding(int32_t virtualSlot) override;
protected: protected:

View File

@ -16,7 +16,6 @@
#include "gfx_cc.h" #include "gfx_cc.h"
#include "gfx_rendering_api.h" #include "gfx_rendering_api.h"
#include "../../GlobalCtx2.h"
#include "gfx_pc.h" #include "gfx_pc.h"
#include "gfx_wiiu.h" #include "gfx_wiiu.h"

View File

@ -44,7 +44,7 @@
#include "gfx_cc.h" #include "gfx_cc.h"
#include "gfx_rendering_api.h" #include "gfx_rendering_api.h"
#include "../../ImGuiImpl.h" #include "../../ImGuiImpl.h"
#include "../../GlobalCtx2.h" #include "../../Window.h"
#include "gfx_pc.h" #include "gfx_pc.h"
using namespace std; using namespace std;

View File

@ -15,6 +15,7 @@
#ifndef _LANGUAGE_C #ifndef _LANGUAGE_C
#define _LANGUAGE_C #define _LANGUAGE_C
#endif #endif
#include <PR/ultra64/types.h>
#include <PR/ultra64/gbi.h> #include <PR/ultra64/gbi.h>
#include <PR/ultra64/gs2dex.h> #include <PR/ultra64/gs2dex.h>
#include <string> #include <string>
@ -36,6 +37,7 @@
#include "../../ResourceMgr.h" #include "../../ResourceMgr.h"
#include "../../Utils.h" #include "../../Utils.h"
// OTRTODO: fix header files for these // OTRTODO: fix header files for these
extern "C" { extern "C" {
const char* ResourceMgr_GetNameByCRC(uint64_t crc); const char* ResourceMgr_GetNameByCRC(uint64_t crc);
@ -2171,7 +2173,7 @@ static void gfx_run_dl(Gfx* cmd) {
uintptr_t mtxAddr = cmd->words.w1; uintptr_t mtxAddr = cmd->words.w1;
// OTRTODO: Temp way of dealing with gMtxClear. Need something more elegant in the future... // OTRTODO: Temp way of dealing with gMtxClear. Need something more elegant in the future...
uint32_t gameVersion = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->GetGameVersion(); uint32_t gameVersion = Ship::Window::GetInstance()->GetResourceManager()->GetGameVersion();
if (gameVersion == OOT_PAL_GC) { if (gameVersion == OOT_PAL_GC) {
if (mtxAddr == SEG_ADDR(0, 0x0FBC20)) { if (mtxAddr == SEG_ADDR(0, 0x0FBC20)) {
mtxAddr = clearMtx; mtxAddr = clearMtx;

View File

@ -8,6 +8,7 @@
#include <list> #include <list>
#include <cstddef> #include <cstddef>
#include "U64/PR/ultra64/gbi.h"
#include "U64/PR/ultra64/types.h" #include "U64/PR/ultra64/types.h"
// TODO figure out why changing these to 640x480 makes the game only render in a quarter of the window // TODO figure out why changing these to 640x480 makes the game only render in a quarter of the window

View File

@ -189,6 +189,7 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen, uint32
} }
#endif #endif
SDL_GL_MakeCurrent(wnd, ctx);
SDL_GL_SetSwapInterval(1); SDL_GL_SetSwapInterval(1);
SohImGui::WindowImpl window_impl; SohImGui::WindowImpl window_impl;

View File

@ -1,4 +1,5 @@
#include "Resource.h" #include "Resource.h"
#include "StrHash.h"
namespace Ship namespace Ship
{ {

View File

@ -3,15 +3,14 @@
#include <stdint.h> #include <stdint.h>
#include "Utils/BinaryReader.h" #include "Utils/BinaryReader.h"
#include "Utils/BinaryWriter.h" #include "Utils/BinaryWriter.h"
#include "GlobalCtx2.h"
#include "StrHash.h"
#include "File.h" #include "File.h"
#include "Lib/tinyxml2/tinyxml2.h" #include "Lib/tinyxml2/tinyxml2.h"
#include "spdlog/spdlog.h"
namespace Ship namespace Ship {
{ class ResourceMgr;
enum class ResourceType
{ enum class ResourceType {
Archive = 0x4F415243, // OARC (UNUSED) Archive = 0x4F415243, // OARC (UNUSED)
Model = 0x4F4D444C, // OMDL (WIP) Model = 0x4F4D444C, // OMDL (WIP)
Texture = 0x4F544558, // OTEX Texture = 0x4F544558, // OTEX
@ -36,8 +35,7 @@ namespace Ship
AudioSequence = 0x4F534551, // OSEQ AudioSequence = 0x4F534551, // OSEQ
}; };
enum class DataType enum class DataType {
{
U8 = 0, U8 = 0,
S8 = 1, S8 = 1,
U16 = 2, U16 = 2,
@ -51,8 +49,7 @@ namespace Ship
F64 = 10 F64 = 10
}; };
enum class Version enum class Version {
{
// BR // BR
Deckard = 0, Deckard = 0,
Roy = 1, Roy = 1,
@ -61,15 +58,13 @@ namespace Ship
// ... // ...
}; };
struct Patch struct Patch {
{
uint64_t crc; uint64_t crc;
uint32_t index; uint32_t index;
uintptr_t origData; uintptr_t origData;
}; };
class Resource class Resource {
{
public: public:
ResourceMgr* resMgr; ResourceMgr* resMgr;
uint64_t id; // Unique Resource ID uint64_t id; // Unique Resource ID
@ -81,8 +76,7 @@ namespace Ship
virtual ~Resource(); virtual ~Resource();
}; };
class ResourceFile class ResourceFile {
{
public: public:
Endianness endianness; // 0x00 - Endianness of the file Endianness endianness; // 0x00 - Endianness of the file
uint32_t resourceType; // 0x01 - 4 byte MAGIC uint32_t resourceType; // 0x01 - 4 byte MAGIC

View File

@ -9,13 +9,14 @@
namespace Ship { namespace Ship {
ResourceMgr::ResourceMgr(std::shared_ptr<GlobalCtx2> Context, const std::string& MainPath, const std::string& PatchesPath) : Context(Context), bIsRunning(false), FileLoadThread(nullptr) { ResourceMgr::ResourceMgr(std::shared_ptr<Window> Context, const std::string& MainPath, const std::string& PatchesPath) : Context(Context), bIsRunning(false), FileLoadThread(nullptr) {
OTR = std::make_shared<Archive>(MainPath, PatchesPath, false); OTR = std::make_shared<Archive>(MainPath, PatchesPath, false);
gameVersion = OOT_UNKNOWN; gameVersion = OOT_UNKNOWN;
if (OTR->IsMainMPQValid()) if (OTR->IsMainMPQValid()) {
Start(); Start();
}
} }
ResourceMgr::~ResourceMgr() { ResourceMgr::~ResourceMgr() {
@ -87,10 +88,11 @@ namespace Ship {
OTR->LoadFile(ToLoad->path, true, ToLoad); OTR->LoadFile(ToLoad->path, true, ToLoad);
if (!ToLoad->bHasLoadError) if (!ToLoad->bHasLoadError) {
FileCache[ToLoad->path] = ToLoad->bIsLoaded && !ToLoad->bHasLoadError ? ToLoad : nullptr; FileCache[ToLoad->path] = ToLoad->bIsLoaded && !ToLoad->bHasLoadError ? ToLoad : nullptr;
}
SPDLOG_DEBUG("Loaded File {} on ResourceMgr thread", ToLoad->path); SPDLOG_TRACE("Loaded File {} on ResourceMgr thread", ToLoad->path);
ToLoad->FileLoadNotifier.notify_all(); ToLoad->FileLoadNotifier.notify_all();
} }
@ -123,12 +125,10 @@ namespace Ship {
} }
} }
if (!ToLoad->file->bHasLoadError) if (!ToLoad->file->bHasLoadError) {
{
auto UnmanagedRes = ResourceLoader::LoadResource(ToLoad->file); auto UnmanagedRes = ResourceLoader::LoadResource(ToLoad->file);
if (UnmanagedRes != nullptr) if (UnmanagedRes != nullptr) {
{
UnmanagedRes->resMgr = this; UnmanagedRes->resMgr = this;
auto Res = std::shared_ptr<Resource>(UnmanagedRes); auto Res = std::shared_ptr<Resource>(UnmanagedRes);
@ -142,17 +142,14 @@ namespace Ship {
SPDLOG_DEBUG("Loaded Resource {} on ResourceMgr thread", ToLoad->file->path); SPDLOG_DEBUG("Loaded Resource {} on ResourceMgr thread", ToLoad->file->path);
Res->file = nullptr; Res->file = nullptr;
} } else {
else {
ToLoad->bHasResourceLoaded = false; ToLoad->bHasResourceLoaded = false;
ToLoad->resource = nullptr; ToLoad->resource = nullptr;
SPDLOG_ERROR("Resource load FAILED {} on ResourceMgr thread", ToLoad->file->path); SPDLOG_ERROR("Resource load FAILED {} on ResourceMgr thread", ToLoad->file->path);
} }
} }
} } else {
else
{
ToLoad->bHasResourceLoaded = false; ToLoad->bHasResourceLoaded = false;
ToLoad->resource = nullptr; ToLoad->resource = nullptr;
} }
@ -163,13 +160,11 @@ namespace Ship {
SPDLOG_INFO("Resource Manager LoadResourceThread ended"); SPDLOG_INFO("Resource Manager LoadResourceThread ended");
} }
uint32_t ResourceMgr::GetGameVersion() uint32_t ResourceMgr::GetGameVersion() {
{
return gameVersion; return gameVersion;
} }
void ResourceMgr::SetGameVersion(uint32_t newGameVersion) void ResourceMgr::SetGameVersion(uint32_t newGameVersion) {
{
gameVersion = newGameVersion; gameVersion = newGameVersion;
} }
@ -206,24 +201,23 @@ namespace Ship {
auto resCacheFind = ResourceCache.find(FilePath); auto resCacheFind = ResourceCache.find(FilePath);
if (resCacheFind != ResourceCache.end() && if (resCacheFind != ResourceCache.end() &&
resCacheFind->second.use_count() > 0) resCacheFind->second.use_count() > 0) {
{
return resCacheFind->second; return resCacheFind->second;
} } else {
else
return nullptr; return nullptr;
}
} }
std::shared_ptr<Resource> ResourceMgr::LoadResource(const char* FilePath) { std::shared_ptr<Resource> ResourceMgr::LoadResource(const char* FilePath) {
auto Res = LoadResourceAsync(FilePath); auto Res = LoadResourceAsync(FilePath);
if (std::holds_alternative<std::shared_ptr<Resource>>(Res)) if (std::holds_alternative<std::shared_ptr<Resource>>(Res)) {
return std::get<std::shared_ptr<Resource>>(Res); return std::get<std::shared_ptr<Resource>>(Res);
}
auto& Promise = std::get<std::shared_ptr<ResourcePromise>>(Res); auto& Promise = std::get<std::shared_ptr<ResourcePromise>>(Res);
if (!Promise->bHasResourceLoaded) if (!Promise->bHasResourceLoaded) {
{
std::unique_lock<std::mutex> Lock(Promise->resourceLoadMutex); std::unique_lock<std::mutex> Lock(Promise->resourceLoadMutex);
while (!Promise->bHasResourceLoaded) { while (!Promise->bHasResourceLoaded) {
Promise->resourceLoadNotifier.wait(Lock); Promise->resourceLoadNotifier.wait(Lock);
@ -234,8 +228,9 @@ namespace Ship {
} }
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> ResourceMgr::LoadResourceAsync(const char* FilePath) { std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> ResourceMgr::LoadResourceAsync(const char* FilePath) {
if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_') if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_') {
FilePath += 7; FilePath += 7;
}
const std::lock_guard<std::mutex> ResLock(ResourceLoadMutex); const std::lock_guard<std::mutex> ResLock(ResourceLoadMutex);
auto resCacheFind = ResourceCache.find(FilePath); auto resCacheFind = ResourceCache.find(FilePath);
@ -248,21 +243,16 @@ namespace Ship {
std::shared_ptr<File> FileData = LoadFile(FilePath); std::shared_ptr<File> FileData = LoadFile(FilePath);
Promise->file = FileData; Promise->file = FileData;
if (Promise->file->bHasLoadError) if (Promise->file->bHasLoadError) {
{
Promise->bHasResourceLoaded = true; Promise->bHasResourceLoaded = true;
} } else {
else
{
Promise->bHasResourceLoaded = false; Promise->bHasResourceLoaded = false;
ResourceLoadQueue.push(Promise); ResourceLoadQueue.push(Promise);
ResourceLoadNotifier.notify_all(); ResourceLoadNotifier.notify_all();
} }
return Promise; return Promise;
} } else {
else
{
return resCacheFind->second; return resCacheFind->second;
} }
} }
@ -273,8 +263,7 @@ namespace Ship {
for (DWORD i = 0; i < fileList.size(); i++) { for (DWORD i = 0; i < fileList.size(); i++) {
auto resource = LoadResourceAsync(fileList.operator[](i).cFileName); auto resource = LoadResourceAsync(fileList.operator[](i).cFileName);
if (std::holds_alternative<std::shared_ptr<Resource>>(resource)) if (std::holds_alternative<std::shared_ptr<Resource>>(resource)) {
{
auto promise = std::make_shared<ResourcePromise>(); auto promise = std::make_shared<ResourcePromise>();
promise->bHasResourceLoaded = true; promise->bHasResourceLoaded = true;
promise->resource = std::get<std::shared_ptr<Resource>>(resource); promise->resource = std::get<std::shared_ptr<Resource>>(resource);
@ -304,8 +293,7 @@ namespace Ship {
return LoadedList; return LoadedList;
} }
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> ResourceMgr::DirtyDirectory(std::string SearchMask) std::shared_ptr<std::vector<std::shared_ptr<Resource>>> ResourceMgr::DirtyDirectory(const std::string& SearchMask) {
{
auto PromiseList = CacheDirectoryAsync(SearchMask); auto PromiseList = CacheDirectoryAsync(SearchMask);
auto LoadedList = std::make_shared<std::vector<std::shared_ptr<Resource>>>(); auto LoadedList = std::make_shared<std::vector<std::shared_ptr<Resource>>>();
@ -317,8 +305,9 @@ namespace Ship {
Promise->resourceLoadNotifier.wait(Lock); Promise->resourceLoadNotifier.wait(Lock);
} }
if (Promise->resource != nullptr) if (Promise->resource != nullptr) {
Promise->resource->isDirty = true; Promise->resource->isDirty = true;
}
LoadedList->push_back(Promise->resource); LoadedList->push_back(Promise->resource);
} }
@ -326,8 +315,7 @@ namespace Ship {
return LoadedList; return LoadedList;
} }
std::shared_ptr<std::vector<std::string>> ResourceMgr::ListFiles(std::string SearchMask) std::shared_ptr<std::vector<std::string>> ResourceMgr::ListFiles(std::string SearchMask) {
{
auto result = std::make_shared<std::vector<std::string>>(); auto result = std::make_shared<std::vector<std::string>>();
auto fileList = OTR->ListFiles(SearchMask); auto fileList = OTR->ListFiles(SearchMask);
@ -345,4 +333,17 @@ namespace Ship {
const std::string* ResourceMgr::HashToString(uint64_t Hash) const { const std::string* ResourceMgr::HashToString(uint64_t Hash) const {
return OTR->HashToString(Hash); return OTR->HashToString(Hash);
} }
std::shared_ptr<Archive> ResourceMgr::GetArchive() {
return OTR;
}
std::shared_ptr<Window> ResourceMgr::GetContext() {
return Context;
}
std::shared_ptr<Resource> ResourceMgr::LoadResource(const std::string& FilePath) {
return LoadResource(FilePath.c_str());
}
} }

View File

@ -5,42 +5,39 @@
#include <thread> #include <thread>
#include <queue> #include <queue>
#include <variant> #include <variant>
#include "Window.h"
#include "Resource.h" #include "Resource.h"
#include "GlobalCtx2.h" #include "Archive.h"
#include "File.h"
namespace Ship namespace Ship {
{ class Window;
class Archive;
class File;
// Resource manager caches any and all files it comes across into memory. This will be unoptimal in the future when modifications have gigabytes of assets. // Resource manager caches any and all files it comes across into memory. This will be unoptimal in the future when modifications have gigabytes of assets.
// It works with the original game's assets because the entire ROM is 64MB and fits into RAM of any semi-modern PC. // It works with the original game's assets because the entire ROM is 64MB and fits into RAM of any semi-modern PC.
class ResourceMgr { class ResourceMgr {
public: public:
ResourceMgr(std::shared_ptr<GlobalCtx2> Context, const std::string& MainPath, const std::string& PatchesPath); ResourceMgr(std::shared_ptr<Window> Context, const std::string& MainPath, const std::string& PatchesPath);
~ResourceMgr(); ~ResourceMgr();
bool IsRunning(); bool IsRunning();
bool DidLoadSuccessfully(); bool DidLoadSuccessfully();
std::shared_ptr<Archive> GetArchive() { return OTR; } std::shared_ptr<Archive> GetArchive();
std::shared_ptr<GlobalCtx2> GetContext() { return Context.lock(); } std::shared_ptr<Window> GetContext();
const std::string* HashToString(uint64_t Hash) const; const std::string* HashToString(uint64_t Hash) const;
void InvalidateResourceCache(); void InvalidateResourceCache();
uint32_t GetGameVersion(); uint32_t GetGameVersion();
void SetGameVersion(uint32_t newGameVersion); void SetGameVersion(uint32_t newGameVersion);
std::shared_ptr<File> LoadFileAsync(const std::string& FilePath); std::shared_ptr<File> LoadFileAsync(const std::string& FilePath);
std::shared_ptr<File> LoadFile(const std::string& FilePath); std::shared_ptr<File> LoadFile(const std::string& FilePath);
std::shared_ptr<Ship::Resource> GetCachedFile(const char* FilePath) const; std::shared_ptr<Resource> GetCachedFile(const char* FilePath) const;
std::shared_ptr<Resource> LoadResource(const char* FilePath); std::shared_ptr<Resource> LoadResource(const char* FilePath);
std::shared_ptr<Resource> LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); } std::shared_ptr<Resource> LoadResource(const std::string& FilePath);
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> LoadResourceAsync(const char* FilePath); std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> LoadResourceAsync(const char* FilePath);
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> CacheDirectory(const std::string& SearchMask); std::shared_ptr<std::vector<std::shared_ptr<Resource>>> CacheDirectory(const std::string& SearchMask);
std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> CacheDirectoryAsync(const std::string& SearchMask); std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> CacheDirectoryAsync(const std::string& SearchMask);
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> DirtyDirectory(std::string SearchMask); std::shared_ptr<std::vector<std::shared_ptr<Resource>>> DirtyDirectory(const std::string& SearchMask);
std::shared_ptr<std::vector<std::string>> ListFiles(std::string SearchMask); std::shared_ptr<std::vector<std::string>> ListFiles(std::string SearchMask);
protected: protected:
@ -50,7 +47,7 @@ namespace Ship
void LoadResourceThread(); void LoadResourceThread();
private: private:
std::weak_ptr<GlobalCtx2> Context; std::shared_ptr<Window> Context;
volatile bool bIsRunning; volatile bool bIsRunning;
std::unordered_map<std::string, std::shared_ptr<File>> FileCache; std::unordered_map<std::string, std::shared_ptr<File>> FileCache;
std::unordered_map<std::string, std::shared_ptr<Resource>> ResourceCache; std::unordered_map<std::string, std::shared_ptr<Resource>> ResourceCache;

View File

@ -1,5 +1,5 @@
#include "SDLController.h" #include "SDLController.h"
#include "GlobalCtx2.h"
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "Window.h" #include "Window.h"
#include <Utils/StringHelper.h> #include <Utils/StringHelper.h>
@ -12,6 +12,10 @@ extern "C" uint8_t __osMaxControllers;
namespace Ship { namespace Ship {
SDLController::SDLController(int32_t physicalSlot) : Controller(), Cont(nullptr), physicalSlot(physicalSlot) {
}
bool SDLController::Open() { bool SDLController::Open() {
const auto NewCont = SDL_GameControllerOpen(physicalSlot); const auto NewCont = SDL_GameControllerOpen(physicalSlot);
@ -450,4 +454,23 @@ namespace Ship {
profile->GyroData[DRIFT_Y] = 0.0f; profile->GyroData[DRIFT_Y] = 0.0f;
profile->GyroData[GYRO_SENSITIVITY] = 1.0f; profile->GyroData[GYRO_SENSITIVITY] = 1.0f;
} }
bool SDLController::Connected() const {
return Cont != nullptr;
}
bool SDLController::CanGyro() const {
return supportsGyro;
}
bool SDLController::CanRumble() const {
#if SDL_COMPILEDVERSION >= SDL_VERSIONNUM(2,0,18)
return SDL_GameControllerHasRumble(Cont);
#endif
return false;
}
void SDLController::ClearRawPress() {
}
} }

View File

@ -5,6 +5,19 @@
namespace Ship { namespace Ship {
class SDLController : public Controller { class SDLController : public Controller {
public: public:
SDLController(int32_t physicalSlot);
void ReadFromSource(int32_t virtualSlot) override;
const std::string GetControllerName() override;
const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override;
void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override;
bool Connected() const override;
bool CanGyro() const override;
bool CanRumble() const override;
bool Open();
void ClearRawPress() override;
int32_t ReadRawPress() override;
protected:
inline static const char* AxisNames[] = { inline static const char* AxisNames[] = {
"Left Stick X", "Left Stick X",
"Left Stick Y", "Left Stick Y",
@ -15,25 +28,6 @@ namespace Ship {
"Start Button" "Start Button"
}; };
SDLController(int32_t physicalSlot) : Controller(), Cont(nullptr), physicalSlot(physicalSlot) { }
void ReadFromSource(int32_t virtualSlot) override;
const std::string GetControllerName() override;
const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override;
void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override;
bool Connected() const override { return Cont != nullptr; }
bool CanGyro() const override { return supportsGyro; }
bool CanRumble() const override {
#if SDL_COMPILEDVERSION >= SDL_VERSIONNUM(2,0,18)
return SDL_GameControllerHasRumble(Cont);
#endif
return false;
}
bool Open();
void ClearRawPress() override {}
int32_t ReadRawPress() override;
protected:
void CreateDefaultBinding(int32_t virtualSlot) override; void CreateDefaultBinding(int32_t virtualSlot) override;
private: private:

View File

@ -1,6 +1,5 @@
#ifdef __WIIU__ #ifdef __WIIU__
#include "WiiUController.h" #include "WiiUController.h"
#include "GlobalCtx2.h"
#include "Window.h" #include "Window.h"
#include "ImGuiImpl.h" #include "ImGuiImpl.h"

View File

@ -1,6 +1,5 @@
#ifdef __WIIU__ #ifdef __WIIU__
#include "WiiUGamepad.h" #include "WiiUGamepad.h"
#include "GlobalCtx2.h"
#include "ImGuiImpl.h" #include "ImGuiImpl.h"
#include "WiiUImpl.h" #include "WiiUImpl.h"

View File

@ -114,7 +114,7 @@ void Update() {
// rescan devices if connection state changed // rescan devices if connection state changed
if (rescan) { if (rescan) {
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->ScanPhysicalDevices(); Window::GetInstance()->GetControlDeck()->ScanPhysicalDevices();
} }
} }

View File

@ -1,23 +1,18 @@
#include <string>
#include <chrono>
#include <fstream>
#include <iostream>
#include "Window.h" #include "Window.h"
#include "spdlog/spdlog.h"
#include "KeyboardController.h"
#include "GlobalCtx2.h"
#include "DisplayList.h"
#include "Vertex.h"
#include "Array.h"
#include "ResourceMgr.h" #include "ResourceMgr.h"
#include "KeyboardController.h"
#include "UltraController.h"
#include "DisplayList.h"
#include "Console.h"
#include "Array.h"
#include "Texture.h" #include "Texture.h"
#include "Blob.h" #include "Blob.h"
#include "Matrix.h" #include "Matrix.h"
#include "AudioPlayer.h"
#include "Hooks.h" #include "Hooks.h"
#include "UltraController.h"
#include <SDL2/SDL.h>
#include <string>
#include <chrono>
#include "Console.h"
#include "ImGuiImpl.h"
#include "PR/ultra64/gbi.h"
#include "Lib/Fast3D/gfx_pc.h" #include "Lib/Fast3D/gfx_pc.h"
#include "Lib/Fast3D/gfx_sdl.h" #include "Lib/Fast3D/gfx_sdl.h"
#include "Lib/Fast3D/gfx_dxgi.h" #include "Lib/Fast3D/gfx_dxgi.h"
@ -27,12 +22,25 @@
#include "Lib/Fast3D/gfx_direct3d12.h" #include "Lib/Fast3D/gfx_direct3d12.h"
#include "Lib/Fast3D/gfx_wiiu.h" #include "Lib/Fast3D/gfx_wiiu.h"
#include "Lib/Fast3D/gfx_gx2.h" #include "Lib/Fast3D/gfx_gx2.h"
#include "Lib/Fast3D/gfx_rendering_api.h"
#include "Lib/Fast3D/gfx_window_manager_api.h" #include "Lib/Fast3D/gfx_window_manager_api.h"
#include <string> #include <SDL2/SDL.h>
#include "ImGuiImpl.h"
#include "spdlog/async.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/sohconsole_sink.h"
#include "PR/ultra64/gbi.h"
#ifdef __APPLE__
#include "OSXFolderManager.h"
#elif defined(__SWITCH__)
#include "SwitchImpl.h"
#elif defined(__WIIU__)
#include "WiiUImpl.h"
#endif
#include <iostream>
#define LOAD_TEX(texPath) static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); #define LOAD_TEX(texPath) static_cast<Ship::Texture*>(Ship::Window::GetInstance()->GetResourceManager()->LoadResource(texPath).get());
extern "C" { extern "C" {
struct OSMesgQueue; struct OSMesgQueue;
@ -59,7 +67,7 @@ extern "C" {
#endif #endif
#endif #endif
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->Init(controllerBits); Ship::Window::GetInstance()->GetControlDeck()->Init(controllerBits);
return 0; return 0;
} }
@ -78,22 +86,22 @@ extern "C" {
pad->gyro_x = 0; pad->gyro_x = 0;
pad->gyro_y = 0; pad->gyro_y = 0;
if (SohImGui::controller->Opened) return; if (SohImGui::controller->IsOpened()) return;
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->WriteToPad(pad); Ship::Window::GetInstance()->GetControlDeck()->WriteToPad(pad);
Ship::ExecuteHooks<Ship::ControllerRead>(pad); Ship::ExecuteHooks<Ship::ControllerRead>(pad);
} }
const char* ResourceMgr_GetNameByCRC(uint64_t crc) { const char* ResourceMgr_GetNameByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(crc);
return hashStr != nullptr ? hashStr->c_str() : nullptr; return hashStr != nullptr ? hashStr->c_str() : nullptr;
} }
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) { Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != nullptr) { if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); auto res = std::static_pointer_cast<Ship::Array>(Ship::Window::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (Vtx*)res->vertices.data(); return (Vtx*)res->vertices.data();
} }
@ -101,10 +109,10 @@ extern "C" {
} }
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) { int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != nullptr) { if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); auto res = std::static_pointer_cast<Ship::Matrix>(Ship::Window::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (int32_t*)res->mtx.data(); return (int32_t*)res->mtx.data();
} }
@ -112,10 +120,10 @@ extern "C" {
} }
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) { Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != nullptr) { if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::Window::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (Gfx*)&res->instructions[0]; return (Gfx*)&res->instructions[0];
} else { } else {
return nullptr; return nullptr;
@ -123,7 +131,7 @@ extern "C" {
} }
char* ResourceMgr_LoadTexByCRC(uint64_t crc) { char* ResourceMgr_LoadTexByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != nullptr) { if (hashStr != nullptr) {
const auto res = LOAD_TEX(hashStr->c_str()); const auto res = LOAD_TEX(hashStr->c_str());
@ -137,11 +145,11 @@ extern "C" {
void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData) void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData)
{ {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash); const std::string* hashStr = Ship::Window::GetInstance()->GetResourceManager()->HashToString(hash);
if (hashStr != nullptr) if (hashStr != nullptr)
{ {
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get(); auto res = (Ship::Texture*)Ship::Window::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get();
Ship::Patch patch; Ship::Patch patch;
patch.crc = hash; patch.crc = hash;
@ -201,7 +209,7 @@ extern "C" {
} }
char* ResourceMgr_LoadBlobByName(char* blobPath) { char* ResourceMgr_LoadBlobByName(char* blobPath) {
auto res = (Ship::Blob*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(blobPath).get(); auto res = (Ship::Blob*)Ship::Window::GetInstance()->GetResourceManager()->LoadResource(blobPath).get();
return (char*)res->data.data(); return (char*)res->data.data();
} }
@ -217,7 +225,26 @@ extern "C" {
namespace Ship { namespace Ship {
Window::Window(std::shared_ptr<GlobalCtx2> Context) : Context(Context), APlayer(nullptr), ControllerApi(nullptr) { std::weak_ptr<Window> Window::Context;
std::shared_ptr<Window> Window::GetInstance() {
return Context.lock();
}
std::shared_ptr<Window> Window::CreateInstance(const std::string Name) {
if (Context.expired()) {
auto Shared = std::make_shared<Window>(Name);
Context = Shared;
Shared->Initialize();
return Shared;
}
SPDLOG_DEBUG("Trying to create a context when it already exists. Returning existing.");
return GetInstance();
}
Window::Window(std::string Name) : Name(std::move(Name)), APlayer(nullptr), ControllerApi(nullptr), ResMan(nullptr), Logger(nullptr), Config(nullptr) {
WmApi = nullptr; WmApi = nullptr;
RenderingApi = nullptr; RenderingApi = nullptr;
bIsFullscreen = false; bIsFullscreen = false;
@ -226,77 +253,91 @@ namespace Ship {
} }
Window::~Window() { Window::~Window() {
SPDLOG_INFO("destruct window"); SPDLOG_DEBUG("destruct window");
} }
void Window::CreateDefaults() { void Window::CreateDefaults() {
const std::shared_ptr<Mercury> pConf = GlobalCtx2::GetInstance()->GetConfig(); if (GetConfig()->isNewInstance) {
if (pConf->isNewInstance) { GetConfig()->setInt("Window.Width", 640);
pConf->setInt("Window.Width", 640); GetConfig()->setInt("Window.Height", 480);
pConf->setInt("Window.Height", 480); GetConfig()->setBool("Window.Options", false);
pConf->setBool("Window.Options", false); GetConfig()->setString("Window.GfxBackend", "");
pConf->setString("Window.GfxBackend", "");
pConf->setBool("Window.Fullscreen.Enabled", false); GetConfig()->setBool("Window.Fullscreen.Enabled", false);
pConf->setInt("Window.Fullscreen.Width", 1920); GetConfig()->setInt("Window.Fullscreen.Width", 1920);
pConf->setInt("Window.Fullscreen.Height", 1080); GetConfig()->setInt("Window.Fullscreen.Height", 1080);
pConf->setString("Game.SaveName", ""); GetConfig()->setString("Game.SaveName", "");
pConf->setString("Game.Main Archive", ""); GetConfig()->setString("Game.Main Archive", "");
pConf->setString("Game.Patches Archive", ""); GetConfig()->setString("Game.Patches Archive", "");
pConf->setInt("Shortcuts.Fullscreen", 0x044); GetConfig()->setInt("Shortcuts.Fullscreen", 0x044);
pConf->setInt("Shortcuts.Console", 0x029); GetConfig()->setInt("Shortcuts.Console", 0x029);
pConf->save(); GetConfig()->save();
} }
} }
void Window::Init() { void Window::Initialize() {
std::shared_ptr<Mercury> pConf = GlobalCtx2::GetInstance()->GetConfig(); InitializeLogging();
InitializeConfiguration();
InitializeResourceManager();
CreateDefaults(); CreateDefaults();
InitializeAudioPlayer(); InitializeAudioPlayer();
InitializeControlDeck(); InitializeControlDeck();
bIsFullscreen = pConf->getBool("Window.Fullscreen.Enabled", false); bIsFullscreen = GetConfig()->getBool("Window.Fullscreen.Enabled", false);
if (bIsFullscreen) { if (bIsFullscreen) {
dwWidth = pConf->getInt("Window.Fullscreen.Width", 1920); dwWidth = GetConfig()->getInt("Window.Fullscreen.Width", 1920);
dwHeight = pConf->getInt("Window.Fullscreen.Height", 1080); dwHeight = GetConfig()->getInt("Window.Fullscreen.Height", 1080);
} else { } else {
dwWidth = pConf->getInt("Window.Width", 640); dwWidth = GetConfig()->getInt("Window.Width", 640);
dwHeight = pConf->getInt("Window.Height", 480); dwHeight = GetConfig()->getInt("Window.Height", 480);
} }
dwMenubar = pConf->getBool("Window.Options", false); dwMenubar = GetConfig()->getBool("Window.Options", false);
gfxBackend = pConf->getString("Window.GfxBackend"); const std::string& gfx_backend = GetConfig()->getString("Window.GfxBackend");
InitializeWindowManager(); InitializeWindowManager();
gfx_init(WmApi, RenderingApi, GetContext()->GetName().c_str(), bIsFullscreen, dwWidth, dwHeight); gfx_init(WmApi, RenderingApi, GetName().c_str(), bIsFullscreen, dwWidth, dwHeight);
WmApi->set_fullscreen_changed_callback(OnFullscreenChanged); WmApi->set_fullscreen_changed_callback(OnFullscreenChanged);
WmApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp); WmApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp);
Ship::RegisterHook<Ship::ExitGame>([this]() { Ship::RegisterHook<ExitGame>([this]() {
ControllerApi->SaveControllerSettings(); ControllerApi->SaveControllerSettings();
}); });
} }
std::string Window::GetAppDirectoryPath() {
#ifdef __APPLE__
FolderManager folderManager;
std::string fpath = std::string(folderManager.pathForDirectory(NSApplicationSupportDirectory, NSUserDomainMask));
fpath.append("/com.shipofharkinian.soh");
return fpath;
#endif
#ifdef __linux__
char* fpath = std::getenv("SHIP_HOME");
if (fpath != NULL)
return std::string(fpath);
#endif
return ".";
}
std::string Window::GetPathRelativeToAppDirectory(const char* path) {
return GetAppDirectoryPath() + "/" + path;
}
void Window::StartFrame() { void Window::StartFrame() {
gfx_start_frame(); gfx_start_frame();
} }
void Window::RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements) { void Window::SetTargetFps(int32_t fps) {
for (const auto& m : mtx_replacements) {
gfx_run(Commands, m);
gfx_end_frame();
}
}
void Window::SetTargetFps(int fps) {
gfx_set_target_fps(fps); gfx_set_target_fps(fps);
} }
void Window::SetMaximumFrameLatency(int latency) { void Window::SetMaximumFrameLatency(int32_t latency) {
gfx_set_maximum_frame_latency(latency); gfx_set_maximum_frame_latency(latency);
} }
@ -329,17 +370,17 @@ namespace Ship {
void Window::MainLoop(void (*MainFunction)(void)) { void Window::MainLoop(void (*MainFunction)(void)) {
WmApi->main_loop(MainFunction); WmApi->main_loop(MainFunction);
} }
bool Window::KeyUp(int32_t dwScancode) {
std::shared_ptr<Mercury> pConf = GlobalCtx2::GetInstance()->GetConfig();
if (dwScancode == pConf->getInt("Shortcuts.Fullscreen", 0x044)) { bool Window::KeyUp(int32_t dwScancode) {
GlobalCtx2::GetInstance()->GetWindow()->ToggleFullscreen(); if (dwScancode == GetInstance()->GetConfig()->getInt("Shortcuts.Fullscreen", 0x044)) {
GetInstance()->ToggleFullscreen();
} }
GlobalCtx2::GetInstance()->GetWindow()->SetLastScancode(-1); GetInstance()->SetLastScancode(-1);
bool bIsProcessed = false; bool bIsProcessed = false;
auto controlDeck = GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = GetInstance()->GetControlDeck();
const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get());
if (pad != nullptr) { if (pad != nullptr) {
if (pad->ReleaseButton(dwScancode)) { if (pad->ReleaseButton(dwScancode)) {
@ -352,7 +393,7 @@ namespace Ship {
bool Window::KeyDown(int32_t dwScancode) { bool Window::KeyDown(int32_t dwScancode) {
bool bIsProcessed = false; bool bIsProcessed = false;
auto controlDeck = GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = GetInstance()->GetControlDeck();
const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get());
if (pad != nullptr) { if (pad != nullptr) {
if (pad->PressButton(dwScancode)) { if (pad->PressButton(dwScancode)) {
@ -360,14 +401,14 @@ namespace Ship {
} }
} }
GlobalCtx2::GetInstance()->GetWindow()->SetLastScancode(dwScancode); GetInstance()->SetLastScancode(dwScancode);
return bIsProcessed; return bIsProcessed;
} }
void Window::AllKeysUp(void) { void Window::AllKeysUp(void) {
auto controlDeck = GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = Window::GetInstance()->GetControlDeck();
const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); const auto pad = dynamic_cast<KeyboardController*>(controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get());
if (pad != nullptr) { if (pad != nullptr) {
pad->ReleaseAllButtons(); pad->ReleaseAllButtons();
@ -375,15 +416,13 @@ namespace Ship {
} }
void Window::OnFullscreenChanged(bool bIsFullscreen) { void Window::OnFullscreenChanged(bool bIsFullscreen) {
std::shared_ptr<Mercury> pConf = GlobalCtx2::GetInstance()->GetConfig(); std::shared_ptr<Mercury> pConf = Window::GetInstance()->GetConfig();
GlobalCtx2::GetInstance()->GetWindow()->bIsFullscreen = bIsFullscreen; Window::GetInstance()->bIsFullscreen = bIsFullscreen;
pConf->setBool("Window.Fullscreen.Enabled", bIsFullscreen); pConf->setBool("Window.Fullscreen.Enabled", bIsFullscreen);
GlobalCtx2::GetInstance()->GetWindow()->ShowCursor(!bIsFullscreen); Window::GetInstance()->ShowCursor(!bIsFullscreen);
} }
uint32_t Window::GetCurrentWidth() { uint32_t Window::GetCurrentWidth() {
WmApi->get_dimensions(&dwWidth, &dwHeight); WmApi->get_dimensions(&dwWidth, &dwHeight);
return dwWidth; return dwWidth;
@ -453,4 +492,141 @@ namespace Ship {
void Window::InitializeControlDeck() { void Window::InitializeControlDeck() {
ControllerApi = std::make_shared<ControlDeck>(); ControllerApi = std::make_shared<ControlDeck>();
} }
void Window::InitializeLogging() {
try {
// Setup Logging
spdlog::init_thread_pool(8192, 1);
std::vector<spdlog::sink_ptr> Sinks;
auto SohConsoleSink = std::make_shared<spdlog::sinks::soh_sink_mt>();
SohConsoleSink->set_level(spdlog::level::trace);
Sinks.push_back(SohConsoleSink);
#if (!defined(_WIN32) && !defined(__WIIU__)) || defined(_DEBUG)
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
ConsoleSink->set_level(spdlog::level::trace);
Sinks.push_back(ConsoleSink);
#endif
#ifndef __WIIU__
auto logPath = GetPathRelativeToAppDirectory(("logs/" + GetName() + ".log").c_str());
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
FileSink->set_level(spdlog::level::trace);
Sinks.push_back(FileSink);
#endif
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);
#ifndef __WIIU__
GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v");
#else
GetLogger()->set_pattern("[%s:%#] [%l] %v");
#endif
spdlog::register_logger(GetLogger());
spdlog::set_default_logger(GetLogger());
}
catch (const spdlog::spdlog_ex& ex) {
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
void Window::InitializeResourceManager() {
MainPath = Config->getString("Game.Main Archive", GetPathRelativeToAppDirectory("oot.otr"));
PatchesPath = Config->getString("Game.Patches Archive", GetAppDirectoryPath() + "/mods");
ResMan = std::make_shared<ResourceMgr>(GetInstance(), MainPath, PatchesPath);
if (!ResMan->DidLoadSuccessfully())
{
#ifdef _WIN32
MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK);
#elif defined(__SWITCH__)
printf("Main OTR file not found!\n");
#elif defined(__WIIU__)
Ship::WiiU::ThrowMissingOTR(MainPath.c_str());
#else
SPDLOG_ERROR("Main OTR file not found!");
#endif
exit(1);
}
#ifdef __SWITCH__
Ship::Switch::Init(PostInitPhase);
#endif
}
void Window::InitializeConfiguration() {
Config = std::make_shared<Mercury>(GetPathRelativeToAppDirectory("shipofharkinian.json"));
}
void Window::WriteSaveFile(const std::filesystem::path& savePath, const uintptr_t addr, void* dramAddr, const size_t size) {
std::ofstream saveFile = std::ofstream(savePath, std::fstream::in | std::fstream::out | std::fstream::binary);
saveFile.seekp(addr);
saveFile.write((char*)dramAddr, size);
saveFile.close();
}
void Window::ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size) {
std::ifstream saveFile = std::ifstream(savePath, std::fstream::in | std::fstream::out | std::fstream::binary);
// If the file doesn't exist, initialize DRAM
if (saveFile.good()) {
saveFile.seekg(addr);
saveFile.read((char*)dramAddr, size);
}
else {
memset(dramAddr, 0, size);
}
saveFile.close();
}
bool Window::IsFullscreen() {
return bIsFullscreen;
}
uint32_t Window::GetMenuBar() {
return dwMenubar;
}
void Window::SetMenuBar(uint32_t dwMenuBar) {
this->dwMenubar = dwMenuBar;
}
std::string Window::GetName() {
return Name;
}
std::shared_ptr<ControlDeck> Window::GetControlDeck() {
return ControllerApi;
}
std::shared_ptr<AudioPlayer> Window::GetAudioPlayer() {
return APlayer;
}
std::shared_ptr<ResourceMgr> Window::GetResourceManager() {
return ResMan;
}
std::shared_ptr<Mercury> Window::GetConfig() {
return Config;
}
std::shared_ptr<spdlog::logger> Window::GetLogger() {
return Logger;
}
const char* Window::GetKeyName(int32_t scancode) {
return WmApi->get_key_name(scancode);
}
int32_t Window::GetLastScancode() {
return lastScancode;
}
void Window::SetLastScancode(int32_t scanCode) {
lastScancode = scanCode;
}
} }

View File

@ -1,60 +1,79 @@
#pragma once #pragma once
#include <memory>
#include "PR/ultra64/gbi.h"
#include "Lib/Fast3D/gfx_pc.h"
#include "Controller.h"
#include "GlobalCtx2.h"
#include "ControlDeck.h"
#include <memory>
#include <filesystem>
#include "spdlog/spdlog.h"
#include "ControlDeck.h"
#include "AudioPlayer.h"
#include "Lib/Fast3D/gfx_window_manager_api.h" #include "Lib/Fast3D/gfx_window_manager_api.h"
#include "Lib/Mercury/Mercury.h"
struct GfxRenderingAPI;
struct GfxWindowManagerAPI;
namespace Ship { namespace Ship {
class AudioPlayer; class ResourceMgr;
class Window { class Window {
public: public:
Window(std::shared_ptr<GlobalCtx2> Context); static std::shared_ptr<Window> GetInstance();
static std::shared_ptr<Window> CreateInstance(const std::string Name);
static std::string GetAppDirectoryPath();
static std::string GetPathRelativeToAppDirectory(const char* path);
Window(std::string Name);
~Window(); ~Window();
void WriteSaveFile(const std::filesystem::path& savePath, uintptr_t addr, void* dramAddr, size_t size);
void ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size);
void CreateDefaults(); void CreateDefaults();
void MainLoop(void (*MainFunction)(void)); void MainLoop(void (*MainFunction)(void));
void Init(); void Initialize();
void StartFrame(); void StartFrame();
void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements); void SetTargetFps(int32_t fps);
void SetTargetFps(int fps); void SetMaximumFrameLatency(int32_t latency);
void SetMaximumFrameLatency(int latency);
void GetPixelDepthPrepare(float x, float y); void GetPixelDepthPrepare(float x, float y);
uint16_t GetPixelDepth(float x, float y); uint16_t GetPixelDepth(float x, float y);
void ToggleFullscreen(); void ToggleFullscreen();
void SetFullscreen(bool bIsFullscreen); void SetFullscreen(bool bIsFullscreen);
void ShowCursor(bool hide); void ShowCursor(bool hide);
bool IsFullscreen() { return bIsFullscreen; }
uint32_t GetCurrentWidth(); uint32_t GetCurrentWidth();
uint32_t GetCurrentHeight(); uint32_t GetCurrentHeight();
uint32_t GetMenuBar() { return dwMenubar; } bool IsFullscreen();
void SetMenuBar(uint32_t dwMenuBar) { this->dwMenubar = dwMenuBar; } uint32_t GetMenuBar();
std::shared_ptr<ControlDeck> GetControlDeck() { return ControllerApi; }; void SetMenuBar(uint32_t dwMenuBar);
std::shared_ptr<GlobalCtx2> GetContext() { return Context.lock(); } std::string GetName();
std::shared_ptr<AudioPlayer> GetAudioPlayer() { return APlayer; } std::shared_ptr<ControlDeck> GetControlDeck();
const char* GetKeyName(int scancode) { return WmApi->get_key_name(scancode); } std::shared_ptr<AudioPlayer> GetAudioPlayer();
int32_t GetLastScancode() { return lastScancode; }; std::shared_ptr<ResourceMgr> GetResourceManager();
void SetLastScancode(int32_t scanCode) { lastScancode = scanCode; }; std::shared_ptr<Mercury> GetConfig();
std::shared_ptr<spdlog::logger> GetLogger();
const char* GetKeyName(int32_t scancode);
int32_t GetLastScancode();
void SetLastScancode(int32_t scanCode);
protected: protected:
Window() = default;
private: private:
static bool KeyDown(int32_t dwScancode); static bool KeyDown(int32_t dwScancode);
static bool KeyUp(int32_t dwScancode); static bool KeyUp(int32_t dwScancode);
static void AllKeysUp(void); static void AllKeysUp(void);
static void OnFullscreenChanged(bool bIsNowFullscreen); static void OnFullscreenChanged(bool bIsNowFullscreen);
static std::weak_ptr<Window> Context;
void InitializeConfiguration();
void InitializeControlDeck(); void InitializeControlDeck();
void InitializeAudioPlayer(); void InitializeAudioPlayer();
void InitializeLogging();
void InitializeResourceManager();
void InitializeWindowManager(); void InitializeWindowManager();
std::weak_ptr<GlobalCtx2> Context; std::shared_ptr<spdlog::logger> Logger;
std::shared_ptr<Mercury> Config; // Config needs to be after the Window because we call the Window during it's destructor.
std::shared_ptr<ResourceMgr> ResMan;
std::shared_ptr<AudioPlayer> APlayer; std::shared_ptr<AudioPlayer> APlayer;
std::shared_ptr<ControlDeck> ControllerApi; std::shared_ptr<ControlDeck> ControllerApi;
std::string gfxBackend;
std::string gfxBackend;
GfxRenderingAPI* RenderingApi; GfxRenderingAPI* RenderingApi;
GfxWindowManagerAPI* WmApi; GfxWindowManagerAPI* WmApi;
bool bIsFullscreen; bool bIsFullscreen;
@ -62,5 +81,8 @@ namespace Ship {
uint32_t dwHeight; uint32_t dwHeight;
uint32_t dwMenubar; uint32_t dwMenubar;
int32_t lastScancode; int32_t lastScancode;
std::string Name;
std::string MainPath;
std::string PatchesPath;
}; };
} }

View File

@ -5,14 +5,18 @@ export PATH="$HERE"/bin:"$HERE"/usr/bin:"$PATH"
export LD_LIBRARY_PATH="$HERE"/usr/lib:"$LD_LIBRARY_PATH" export LD_LIBRARY_PATH="$HERE"/usr/lib:"$LD_LIBRARY_PATH"
export ZENITY=$(command -v zenity) export ZENITY=$(command -v zenity)
while [[ ! -e "$PWD"/oot.otr ]]; do if [ -z ${SHIP_HOME+x} ]; then
export SHIP_HOME=$PWD
fi
while [[ ! -e "$SHIP_HOME"/oot.otr ]]; do
export ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)" export ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
ln -s "$HERE"/usr/bin/{assets,soh.elf,OTRGui} "$ASSETDIR" ln -s "$HERE"/usr/bin/{assets,soh.elf,OTRGui} "$ASSETDIR"
export OLDPWD="$PWD" export OLDPWD="$PWD"
mkdir -p "$ASSETDIR"/tmp mkdir -p "$ASSETDIR"/tmp
mkdir -p "$ASSETDIR"/Extract/assets mkdir -p "$ASSETDIR"/Extract/assets
if [ -e "$PWD"/*.*64 ]; then if [ -e "$SHIP_HOME"/*.*64 ]; then
ln -s "$OLDPWD"/*.*64 "$ASSETDIR"/tmp/rom.z64 ln -s "$SHIP_HOME"/*.*64 "$ASSETDIR"/tmp/rom.z64
cp -r "$ASSETDIR"/assets/game/ship_of_harkinian "$ASSETDIR"/Extract/assets/ cp -r "$ASSETDIR"/assets/game/ship_of_harkinian "$ASSETDIR"/Extract/assets/
cd "$ASSETDIR" cd "$ASSETDIR"
ROMHASH=$(sha1sum -b "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }') ROMHASH=$(sha1sum -b "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')
@ -36,22 +40,19 @@ while [[ ! -e "$PWD"/oot.otr ]]; do
echo "Processing..." echo "Processing..."
fi fi
assets/extractor/ZAPD.out ed -eh -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR > /dev/null 2>&1 assets/extractor/ZAPD.out ed -eh -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR > /dev/null 2>&1
cp "$ASSETDIR"/oot.otr "$OLDPWD" cp "$ASSETDIR"/oot.otr "$SHIP_HOME"
echo "Restart $APPIMAGE to play!" echo "Restart $APPIMAGE to play!"
sleep 3 sleep 3
rm -r "$ASSETDIR" rm -r "$ASSETDIR"
break break
else else
if [ -n "$ZENITY" ]; then if [ -n "$ZENITY" ]; then
zenity --error --timeout=5 --text="Place ROM in $OWD" --title="Missing ROM file" --width=500 --width=200 zenity --error --timeout=5 --text="Place ROM in $SHIP_HOME" --title="Missing ROM file" --width=500 --width=200
else else
echo -e "\nPlace ROM in this folder\n" echo -e "\nPlace ROM in this folder\n"
fi fi
exit exit
fi fi
done done
cd "$OWD" (cd "$HERE/usr/bin"; ./soh.elf)
ln -s "$HERE"/usr/bin/gamecontrollerdb.txt "$PWD"
"$HERE"/usr/bin/soh.elf
unlink "$PWD"/gamecontrollerdb.txt
exit exit

View File

@ -110,6 +110,9 @@ set(Header_Files__include
"include/ichain.h" "include/ichain.h"
"include/macro.inc" "include/macro.inc"
"include/macros.h" "include/macros.h"
"include/message_data_fmt.h"
"include/message_data_static.h"
"include/message_data_textbox_types.h"
#"include/math_n64.h" #"include/math_n64.h"
"include/regs.h" "include/regs.h"
"include/segment_symbols.h" "include/segment_symbols.h"
@ -178,9 +181,11 @@ source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__s
set(Header_Files__soh__Enhancements__randomizer set(Header_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer.h" "soh/Enhancements/randomizer/randomizer.h"
"soh/Enhancements/randomizer/randomizer_inf.h"
"soh/Enhancements/randomizer/randomizer_item_tracker.h" "soh/Enhancements/randomizer/randomizer_item_tracker.h"
"soh/Enhancements/randomizer/adult_trade_shuffle.h" "soh/Enhancements/randomizer/adult_trade_shuffle.h"
"soh/Enhancements/randomizer/randomizer_check_objects.h" "soh/Enhancements/randomizer/randomizer_check_objects.h"
"soh/Enhancements/randomizer/draw.h"
) )
source_group("Header Files\\soh\\Enhancements\\randomizer" FILES ${Header_Files__soh__Enhancements__randomizer}) source_group("Header Files\\soh\\Enhancements\\randomizer" FILES ${Header_Files__soh__Enhancements__randomizer})
@ -288,6 +293,7 @@ set(Source_Files__soh__Enhancements__randomizer
"soh/Enhancements/randomizer/randomizer_item_tracker.cpp" "soh/Enhancements/randomizer/randomizer_item_tracker.cpp"
"soh/Enhancements/randomizer/adult_trade_shuffle.c" "soh/Enhancements/randomizer/adult_trade_shuffle.c"
"soh/Enhancements/randomizer/randomizer_check_objects.cpp" "soh/Enhancements/randomizer/randomizer_check_objects.cpp"
"soh/Enhancements/randomizer/draw.cpp"
) )
source_group("Source Files\\soh\\Enhancements\\randomizer" FILES ${Source_Files__soh__Enhancements__randomizer}) source_group("Source Files\\soh\\Enhancements\\randomizer" FILES ${Source_Files__soh__Enhancements__randomizer})
@ -1758,15 +1764,15 @@ if(MSVC)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_options(${PROJECT_NAME} PRIVATE target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>: $<$<CONFIG:Debug>:
/sdl-; /w;
/w /Od
> >
$<$<CONFIG:Release>: $<$<CONFIG:Release>:
/Oi; /Oi;
/sdl-;
/Gy; /Gy;
/W3 /W3
> >
/sdl-;
/permissive-; /permissive-;
/MP; /MP;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT}; ${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
@ -2003,14 +2009,6 @@ elseif(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "NintendoSwitch|CafeOS")
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship) INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
endif() endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
install(CODE "
include(InstallRequiredSystemLibraries)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/soh-macos\" \"\" \"${dirs}\")
")
endif()
if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS") if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
if (NOT TARGET pathconf) if (NOT TARGET pathconf)
add_library(pathconf OBJECT platform/pathconf.c) add_library(pathconf OBJECT platform/pathconf.c)

View File

@ -11,6 +11,7 @@ extern "C"
#include "../../libultraship/libultraship/luslog.h" #include "../../libultraship/libultraship/luslog.h"
#include <soh/Enhancements/item-tables/ItemTableTypes.h> #include <soh/Enhancements/item-tables/ItemTableTypes.h>
#include <soh/Enhancements/randomizer/randomizer_inf.h>
#if defined(INCLUDE_GAME_PRINTF) && !defined(NDEBUG) #if defined(INCLUDE_GAME_PRINTF) && !defined(NDEBUG)
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__) #define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__)
@ -454,6 +455,7 @@ u32 Actor_TextboxIsClosing(Actor* actor, GlobalContext* globalCtx);
s8 func_8002F368(GlobalContext* globalCtx); s8 func_8002F368(GlobalContext* globalCtx);
void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y); void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y);
u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx); u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx);
// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename func_8002F434 and func_8002F554.
s32 GiveItemEntryWithoutActor(GlobalContext* globalCtx, GetItemEntry getItemEntry); s32 GiveItemEntryWithoutActor(GlobalContext* globalCtx, GetItemEntry getItemEntry);
s32 GiveItemEntryFromActor(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry, f32 xzRange, f32 yRange); s32 GiveItemEntryFromActor(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry, f32 xzRange, f32 yRange);
void GiveItemEntryFromActorWithFixedRange(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry); void GiveItemEntryFromActorWithFixedRange(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry);
@ -557,6 +559,8 @@ s32 Flags_GetEventChkInf(s32 flag);
void Flags_SetEventChkInf(s32 flag); void Flags_SetEventChkInf(s32 flag);
s32 Flags_GetInfTable(s32 flag); s32 Flags_GetInfTable(s32 flag);
void Flags_SetInfTable(s32 flag); void Flags_SetInfTable(s32 flag);
s32 Flags_GetRandomizerInf(RandomizerInf flag);
void Flags_SetRandomizerInf(RandomizerInf flag);
u16 func_80037C30(GlobalContext* globalCtx, s16 arg1); u16 func_80037C30(GlobalContext* globalCtx, s16 arg1);
s32 func_80037D98(GlobalContext* globalCtx, Actor* actor, s16 arg2, s32* arg3); s32 func_80037D98(GlobalContext* globalCtx, Actor* actor, s16 arg2, s32* arg3);
s32 func_80038290(GlobalContext* globalCtx, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4); s32 func_80038290(GlobalContext* globalCtx, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4);
@ -858,6 +862,7 @@ void Cutscene_HandleEntranceTriggers(GlobalContext* globalCtx);
void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx); void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx);
void Cutscene_SetSegment(GlobalContext* globalCtx, void* segment); void Cutscene_SetSegment(GlobalContext* globalCtx, void* segment);
void GetItem_Draw(GlobalContext* globalCtx, s16 drawId); void GetItem_Draw(GlobalContext* globalCtx, s16 drawId);
void GetItemEntry_Draw(GlobalContext* globalCtx, GetItemEntry getItemEntry);
void SoundSource_InitAll(GlobalContext* globalCtx); void SoundSource_InitAll(GlobalContext* globalCtx);
void SoundSource_UpdateAll(GlobalContext* globalCtx); void SoundSource_UpdateAll(GlobalContext* globalCtx);
void SoundSource_PlaySfxAtFixedWorldPos(GlobalContext* globalCtx, Vec3f* pos, s32 duration, u16 sfxId); void SoundSource_PlaySfxAtFixedWorldPos(GlobalContext* globalCtx, Vec3f* pos, s32 duration, u16 sfxId);

View File

@ -3,32 +3,12 @@
#include "global.h" #include "global.h"
#include "message_data_fmt.h" #include "message_data_fmt.h"
#include "message_data_textbox_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef enum {
/* 0 */ TEXTBOX_TYPE_BLACK,
/* 1 */ TEXTBOX_TYPE_WOODEN,
/* 2 */ TEXTBOX_TYPE_BLUE,
/* 3 */ TEXTBOX_TYPE_OCARINA,
/* 4 */ TEXTBOX_TYPE_NONE_BOTTOM,
/* 5 */ TEXTBOX_TYPE_NONE_NO_SHADOW,
/* 11 */ TEXTBOX_TYPE_CREDITS = 11
} TextBoxType;
typedef enum {
/* 0 */ TEXTBOX_BG_CROSS
} TextBoxBackground;
typedef enum {
/* 0 */ TEXTBOX_POS_VARIABLE,
/* 1 */ TEXTBOX_POS_TOP,
/* 2 */ TEXTBOX_POS_MIDDLE,
/* 3 */ TEXTBOX_POS_BOTTOM
} TextBoxPosition;
typedef struct { typedef struct {
u16 textId; u16 textId;
u8 typePos; u8 typePos;

View File

@ -0,0 +1,25 @@
#ifndef MESSAGE_DATA_TEXTBOX_TYPES_H
#define MESSAGE_DATA_TEXTBOX_TYPES_H
typedef enum {
/* 0 */ TEXTBOX_TYPE_BLACK,
/* 1 */ TEXTBOX_TYPE_WOODEN,
/* 2 */ TEXTBOX_TYPE_BLUE,
/* 3 */ TEXTBOX_TYPE_OCARINA,
/* 4 */ TEXTBOX_TYPE_NONE_BOTTOM,
/* 5 */ TEXTBOX_TYPE_NONE_NO_SHADOW,
/* 11 */ TEXTBOX_TYPE_CREDITS = 11
} TextBoxType;
typedef enum {
/* 0 */ TEXTBOX_BG_CROSS
} TextBoxBackground;
typedef enum {
/* 0 */ TEXTBOX_POS_VARIABLE,
/* 1 */ TEXTBOX_POS_TOP,
/* 2 */ TEXTBOX_POS_MIDDLE,
/* 3 */ TEXTBOX_POS_BOTTOM
} TextBoxPosition;
#endif

View File

@ -271,7 +271,8 @@ typedef enum {
/* 0x16 */ ITEM00_SHIELD_HYLIAN, /* 0x16 */ ITEM00_SHIELD_HYLIAN,
/* 0x17 */ ITEM00_TUNIC_ZORA, /* 0x17 */ ITEM00_TUNIC_ZORA,
/* 0x18 */ ITEM00_TUNIC_GORON, /* 0x18 */ ITEM00_TUNIC_GORON,
/* 0x19 */ ITEM00_BOMBS_SPECIAL /* 0x19 */ ITEM00_BOMBS_SPECIAL,
/* 0x20 */ ITEM00_BOMBCHU,
} Item00Type; } Item00Type;
struct EnItem00; struct EnItem00;

View File

@ -359,7 +359,7 @@ typedef struct {
/* 0x00 */ s32 active; /* 0x00 */ s32 active;
/* 0x04 */ Vec3f tip; /* 0x04 */ Vec3f tip;
/* 0x10 */ Vec3f base; /* 0x10 */ Vec3f base;
} WeaponInfo; // size = 0x1C\ } WeaponInfo; // size = 0x1C
typedef enum { typedef enum {
FLAG_NONE, FLAG_NONE,
@ -368,7 +368,7 @@ typedef enum {
FLAG_SCENE_CLEAR, FLAG_SCENE_CLEAR,
FLAG_SCENE_COLLECTIBLE, FLAG_SCENE_COLLECTIBLE,
FLAG_EVENT_CHECK_INF, FLAG_EVENT_CHECK_INF,
FLAG_COW_MILKED FLAG_RANDOMIZER_INF
} FlagType; } FlagType;
typedef struct { typedef struct {

View File

@ -5,6 +5,7 @@
#include "z64math.h" #include "z64math.h"
#include "z64audio.h" #include "z64audio.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/randomizer/randomizer_inf.h"
typedef struct { typedef struct {
/* 0x00 */ u8 buttonItems[8]; /* 0x00 */ u8 buttonItems[8];
@ -182,10 +183,7 @@ typedef struct {
char ganonHintText[150]; char ganonHintText[150];
char ganonText[250]; char ganonText[250];
u8 seedIcons[5]; u8 seedIcons[5];
u8 dungeonsDone[8]; u16 randomizerInf[4];
u8 trialsDone[6];
u8 cowsMilked[10];
u8 scrubsPurchased[35];
u8 shopItemsPurchased[48]; u8 shopItemsPurchased[48];
u8 temporaryWeapon; u8 temporaryWeapon;
u16 adultTradeItems; u16 adultTradeItems;

View File

@ -25,6 +25,7 @@ void BootCommands_Init()
CVar_RegisterS32("gDebugEnabled", 0); CVar_RegisterS32("gDebugEnabled", 0);
CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French
CVar_RegisterS32("gHudColors", 1); //0 = N64 / 1 = NGC / 2 = Custom CVar_RegisterS32("gHudColors", 1); //0 = N64 / 1 = NGC / 2 = Custom
CVar_RegisterS32("gInvertYAxis", 1);
#if defined(__SWITCH__) || defined(__WIIU__) #if defined(__SWITCH__) || defined(__WIIU__)
CVar_RegisterS32("gControlNav", 1); // always enable controller nav on switch/wii u CVar_RegisterS32("gControlNav", 1); // always enable controller nav on switch/wii u
#endif #endif

View File

@ -216,7 +216,27 @@ namespace GameControlEditor {
ImGui::EndTable(); ImGui::EndTable();
} }
void DrawUI(bool& open) { void DrawCameraControlPanel() {
if (!ImGui::CollapsingHeader("Camera Controls")) {
return;
}
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
SohImGui::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis");
SohImGui::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis");
SohImGui::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming");
SohImGui::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons");
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
SohImGui::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView");
SohImGui::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming");
}
void DrawUI(bool& open) {
if (!open) { if (!open) {
CVar_SetS32("gGameControlEditorEnabled", false); CVar_SetS32("gGameControlEditorEnabled", false);
return; return;
@ -225,6 +245,7 @@ namespace GameControlEditor {
ImGui::SetNextWindowSize(ImVec2(465, 430), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(465, 430), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Game Controls Configuration", &open)) { if (ImGui::Begin("Game Controls Configuration", &open)) {
DrawOcarinaControlPanel(); DrawOcarinaControlPanel();
DrawCameraControlPanel();
} }
ImGui::End(); ImGui::End();
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,407 @@
#pragma once #pragma once
#include "../libultraship/ImGuiImpl.h"
#define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define RANDOMIZE_32(Max) GetRandomValue(Max);
#define CATEGORY_NPC 0
#define CATEGORY_ITEMS 1
#define CATEGORY_MENU 2
#define CATEGORY_HUD 3
#define CATEGORY_MISC 4
typedef struct {
const std::string Name;
const std::string ToolTip;
const std::string CvarName;
ImVec4 ModifiedColor;
ImVec4 DefaultColor;
bool canRainbow;
bool hasAlpha;
bool sameLine;
} CosmeticsColorIndividual;
typedef struct {
CosmeticsColorIndividual* Element;
bool Nextcol;
bool NextLine;
} CosmeticsColorSection;
static float TablesCellsWidth = 300.0f;
static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV;
static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort;
static ImVec4 hearts_colors; static ImVec4 hearts_dd_colors; static ImVec4 hearts_ddi_colors;
static ImVec4 a_btn_colors; static ImVec4 b_btn_colors; static ImVec4 c_btn_colors; static ImVec4 start_btn_colors;
static ImVec4 c_btn_u_colors; static ImVec4 c_btn_l_colors; static ImVec4 c_btn_d_colors; static ImVec4 c_btn_r_colors;
static ImVec4 magic_border_colors; static ImVec4 magic_remaining_colors; static ImVec4 magic_use_colors;
static ImVec4 minimap_colors; static ImVec4 dgn_minimap_colors;
static ImVec4 cp_minimap_colors; static ImVec4 le_minimap_colors;
static ImVec4 rupee_colors; static ImVec4 smolekey_colors; static ImVec4 magic_bordern_colors;
static ImVec4 fileselect_colors; static ImVec4 fileselect_text_colors;
static ImVec4 kokiri_col; static ImVec4 goron_col; static ImVec4 zora_col;
static ImVec4 navi_idle_i_col; static ImVec4 navi_idle_o_col;
static ImVec4 navi_npc_i_col; static ImVec4 navi_npc_o_col;
static ImVec4 navi_enemy_i_col; static ImVec4 navi_enemy_o_col;
static ImVec4 navi_prop_i_col; static ImVec4 navi_prop_o_col;
static ImVec4 trailscol;
static ImVec4 crtfilter;
static ImVec4 firearrow_col; static ImVec4 icearrow_col; static ImVec4 lightarrow_col;
static ImVec4 firearrow_colenv; static ImVec4 icearrow_colenv; static ImVec4 lightarrow_colenv;
static ImVec4 charged1_col; static ImVec4 charged2_col;
static ImVec4 charged1_colenv; static ImVec4 charged2_colenv;
static ImVec4 Keese1_primcol; static ImVec4 Keese2_primcol;
static ImVec4 Keese1_envcol; static ImVec4 Keese2_envcol;
static ImVec4 doggo1col; static ImVec4 doggo2col;
static ImVec4 df_col; static ImVec4 df_colenv;
static ImVec4 nl_diam_col; static ImVec4 nl_diam_colenv;
static ImVec4 nl_orb_col; static ImVec4 nl_orb_colenv;
static ImVec4 tc_ou_colors; static ImVec4 tc_bu_colors;
static ImVec4 dpad_colors;
static ImVec4 visualagony_colors;
static ImVec4 tc_fire_colors; static ImVec4 tc_fire_colors_env;
/*ImVec4 menu_equips_colors;
ImVec4 menu_items_colors;
ImVec4 menu_map_colors;
ImVec4 menu_quest_colors;
ImVec4 menu_save_colors;
ImVec4 menu_gameover_colors;*/
//Navi
static CosmeticsColorIndividual Navi_Idle_Inner = { "Navi Idle (Primary)", "Inner color for Navi (idle flying around)", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Idle_Outer = { "Navi Idle (Secondary)", "Outer color for Navi (idle flying around)", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(0, 0, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Npc_Inner = { "Navi NPC (Primary)", "Inner color for Navi (when Navi fly around NPCs)", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(150, 150, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Npc_Outer = { "Navi NPC (Secondary)", "Outer color for Navi (when Navi fly around NPCs)", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(150, 150, 255, 255), false, false, false };
static CosmeticsColorIndividual Navi_Enemy_Inner = { "Navi Enemy (Primary)", "Inner color for Navi (when Navi fly around Enemies or Bosses)", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Enemy_Outer = { "Navi Enemy (Secondary)", "Outer color for Navi (when Navi fly around Enemies or Bosses)", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Prop_Inner = { "Navi Enemy (Primary)", "Inner color for Navi (when Navi fly around props (signs etc))", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0, 255, 0, 255), false, false, false };
static CosmeticsColorIndividual Navi_Prop_Outer = { "Navi Enemy (Secondary)", "Outer color for Navi (when Navi fly around props (signs etc))", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0, 255, 0, 255), false, false, false };
//Keese
static CosmeticsColorIndividual Keese1_prim = { "Fire Primary color", "Affects the primary color of the Fire itself of the Keese", "gKeese1_Ef_Prim", Keese1_primcol, ImVec4(255, 255, 100, 255), true, false, false };
static CosmeticsColorIndividual Keese2_prim = { "Ice Primary color", "Affects the primary color of the Ice itself of the Keese", "gKeese2_Ef_Prim", Keese2_primcol, ImVec4(100, 200, 255, 255), true, false, false };
static CosmeticsColorIndividual Keese1_env = { "Fire Secondary color", "Affects the secondary color of the Fire itself of the Keese", "gKeese1_Ef_Env", Keese1_envcol, ImVec4(255, 50, 0, 255), true, false, false };
static CosmeticsColorIndividual Keese2_env = { "Ice Secondary color", "Affects the secondary color of the Ice itself of the Keese", "gKeese2_Ef_Env", Keese2_envcol, ImVec4(0, 0, 255, 255), true, false, false };
//Good old Dogs, we all love them
static CosmeticsColorIndividual DogN1 = { "Dog white", "Affects the colors of the white dog", "gDog1Col", doggo1col, ImVec4(255,255,200,255), true, false, true };
static CosmeticsColorIndividual DogN2 = { "Dog brown", "Affects the colors of the brown dog", "gDog2Col", doggo2col, ImVec4(150,100,50,255), true, false, true };
//Tunics colors
static CosmeticsColorIndividual KokiriTunic = { "Kokiri Tunic", "Affects Kokiri Tunic color", "gTunic_Kokiri", kokiri_col, ImVec4(30, 105, 27, 255), true, false, true };
static CosmeticsColorIndividual GoronTunic = { "Goron Tunic", "Affects Goron Tunic color", "gTunic_Goron", goron_col, ImVec4(100, 20, 0, 255), true, false, true };
static CosmeticsColorIndividual ZoraTunic = { "Zora Tunic", "Affects Zora Tunic color", "gTunic_Zora", zora_col, ImVec4(0, 60, 100, 255), true, false, true };
//Arrows (Fire -> Ice -> Light)
static CosmeticsColorIndividual Fire_Arrow_Prim = { "Fire Arrows (primary)", "Affects Primary color", "gFireArrowCol", firearrow_col, ImVec4(255,200,0,255), true, false, false };
static CosmeticsColorIndividual Fire_Arrow_Env = { "Fire Arrows (Secondary)", "Affects Secondary color", "gFireArrowColEnv", firearrow_colenv, ImVec4(255,0,0,255), true, false, false };
static CosmeticsColorIndividual Ice_Arrow_Prim = { "Ice Arrows (Primary)", "Affects Primary color", "gIceArrowCol", icearrow_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Ice_Arrow_Env = { "Ice Arrows (Secondary)", "Affects Secondary color", "gIceArrowColEnv", icearrow_colenv, ImVec4(0,0,255,255), true, false, false };
static CosmeticsColorIndividual Light_Arrow_Prim = { "Light Arrows (Primary)", "Affects Primary color", "gLightArrowCol", lightarrow_col, ImVec4(255,255,170,255), true, false, false };
static CosmeticsColorIndividual Light_Arrow_Env = { "Light Arrows (Secondary)", "Affects Secondary color", "gLightArrowColEnv", lightarrow_colenv, ImVec4(255,255,0,255), true, false, false };
//Spells
static CosmeticsColorIndividual Din_Fire_Prim = { "Din's Fire (primary)", "Affects Primary color", "gDF_Col", df_col, ImVec4(255,200,0,255), true, false, false };
static CosmeticsColorIndividual Din_Fire_Env = { "Din's Fire (Secondary)", "Affects Secondary color", "gDF_Env", df_colenv, ImVec4(255,0,0,255), true, false, false };
static CosmeticsColorIndividual Nayru_Diamond_Prim = { "Nayru's Love Diamond (primary)", "Affects Primary color", "gNL_Diamond_Col", nl_diam_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Nayru_Diamond_Env = { "Nayru's Love Diamond (Secondary)", "Affects Secondary color", "gNL_Diamond_Env", nl_diam_colenv, ImVec4(100,255,128,255), true, false, false };
static CosmeticsColorIndividual Nayru_Orb_Prim = { "Nayru's Love Orb (primary)", "Affects Primary color", "gNL_Orb_Col", nl_orb_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Nayru_Orb_Env = { "Nayru's Love Orb (Secondary)", "Affects Secondary color", "gNL_Orb_Env", nl_orb_colenv, ImVec4(150,255,255,255), true, false, false };
//Spin attacks colors
static CosmeticsColorIndividual Spin_Lv1_Prim = { "Level 1 (primary)", "Affects Primary color", "gCharged1Col", charged1_col, ImVec4(170,255,255,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv1_Env = { "Level 1 (Secondary)", "Affects Secondary color", "gCharged1ColEnv", charged1_colenv, ImVec4(0,100,255,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv2_Prim = { "Level 2 (primary)", "Affects Primary color", "gCharged2Col", charged2_col, ImVec4(255,255,170,255), true, false, false };
static CosmeticsColorIndividual Spin_Lv2_Env = { "Level 2 (Secondary)", "Affects Secondary color", "gCharged2ColEnv", charged2_colenv, ImVec4(255,100,0,255), true, false, false };
//Trails
static CosmeticsColorIndividual Trails_col = { "Trails color", "Affects Swords slash, boomerang and Bombchu trails color", "gTrailCol", trailscol, ImVec4(255,255,255,255), true, false, false };
//Menus - File Choose
static CosmeticsColorIndividual FileChoose_Background = { "Main menu color", "Affects the File Select menu background.", "gCCFileChoosePrim", fileselect_colors, ImVec4(100, 150, 255, 255), true, false, false };
static CosmeticsColorIndividual FileChoose_BottomText = { "Bottom texts color", "Affects the File Select texts.", "gCCFileChooseTextPrim", fileselect_text_colors, ImVec4(100, 255, 255, 255), true, false, false };
//Hud Stuff (Dpad, Buttons etc)
static CosmeticsColorIndividual A_Btn = { "A Button", "Affects the A button colors (and various cursors that use the same theme)", "gCCABtnPrim", a_btn_colors, ImVec4(0, 200, 50, 255), true, false, false };
static CosmeticsColorIndividual B_Btn = { "B Button", "Affects the B button color", "gCCBBtnPrim", b_btn_colors, ImVec4(255, 30, 30, 255), true, false, false };
static CosmeticsColorIndividual C_Btn = { "C-Buttons", "Affects the C Buttons' color (if not using separate colors)\nAnd various cursor that use C-Buttons colors", "gCCCBtnPrim", c_btn_colors, ImVec4(255, 160, 0, 255), true, false, false };
static CosmeticsColorIndividual C_Btn_U = { "C-Buttons Up", "Affects C-Buttons Up colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCUBtnPrim", c_btn_u_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_D = { "C-Buttons Down", "Affects C-Buttons Down colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCDBtnPrim", c_btn_d_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_L = { "C-Buttons Left", "Affects C-Buttons Left colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCLBtnPrim", c_btn_l_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual C_Btn_R = { "C-Buttons Right", "Affects C-Buttons Right colors, but not C cursor colors\nTo edit C Cursor check C-Buttons color on top", "gCCCRBtnPrim", c_btn_r_colors, ImVec4(255,160,0,255), true, false, false };
static CosmeticsColorIndividual Start_btn = { "Start Button", "Affects the Start button color", "gCCStartBtnPrim", start_btn_colors, ImVec4(200, 0, 0, 255), true, false, false };
static CosmeticsColorIndividual DPad_Items = { "DPad background", "DPad background color, White is the default value", "gCCDpadPrim", dpad_colors, ImVec4(255, 255, 255, 255), true, false, false };
//Hearts colors
static CosmeticsColorIndividual Hearts_NInner = { "Inner (Normal)", "Affects the inner color", "gCCHeartsPrim", hearts_colors, ImVec4(255,70,50,255), true, false, false };
static CosmeticsColorIndividual Hearts_DDInner = { "Inner (Double defense)", "Affects the inner color", "gCCDDHeartsPrim", hearts_ddi_colors, ImVec4(255,70,50,255), true, false, false };
static CosmeticsColorIndividual Hearts_DDOutline = { "Outline (Double defense)", "Affects the outline color of hearts when you have Double Defense\nWhite is the default value", "gDDCCHeartsPrim", hearts_dd_colors, ImVec4(255,255,255,255), true, false, false };
//Magic Meter colors
static CosmeticsColorIndividual Magic_Borders = { "Borders", "Affects the border of the magic meter\nWhite is the default value, color change only when used one time", "gCCMagicBorderNormPrim", magic_bordern_colors, ImVec4(255,255,255,255), false, false, false };
static CosmeticsColorIndividual Magic_InUse_Borders = { "Borders in use", "Affects the border of the magic meter when being used\nWhite is the default value", "gCCMagicBorderPrim", magic_border_colors, ImVec4(255,255,255,255), false, false, false };
static CosmeticsColorIndividual Magic_Meter = { "Main color", "Affects the magic meter color\nGreen is the default value", "gCCMagicPrim", magic_remaining_colors, ImVec4(0,200,0,255), true, false, false };
static CosmeticsColorIndividual Magic_InUse_Meter = { "Main color in use", "Affects the magic meter when being used\nYellow is the default value", "gCCMagicUsePrim", magic_use_colors, ImVec4(250,250,0,255), true, false, false };
//Minimap and it's arrow colors
static CosmeticsColorIndividual Minimap_OW = { "Overworlds", "Affects the Overworld minimaps", "gCCMinimapPrim", minimap_colors, ImVec4(0, 255, 255, 255), true, false, false };
static CosmeticsColorIndividual Minimap_DG = { "Dungeons", "Affects the Dungeon minimaps", "gCCMinimapDGNPrim", dgn_minimap_colors, ImVec4(100, 255, 255, 255), true, false, false };
static CosmeticsColorIndividual Minimap_CP = { "Current position arrow", "Affects the current position arrow on the minimap\nYellow is the default value", "gCCMinimapCPPrim", cp_minimap_colors, ImVec4(200, 255, 0, 255), true, false, false };
static CosmeticsColorIndividual Minimap_LE = { "Last entrance arrow", "Affects the last entrance position arrow on the minimap\nRed is the default value", "gCCMinimapLEPrim", le_minimap_colors, ImVec4(200, 0, 0, 255), true, false, false };
//Title Cards colors
static CosmeticsColorIndividual TitleCards_OW = { "Main color (Overworld)", "Affects all the overworld title cards color, white is the default value", "gCCTC_OW_U_Prim", tc_ou_colors, ImVec4(255, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual TitleCards_DG = { "Main color (Dungeon)", "Affects all the bosses title cards color, white is the default value", "gCCTC_B_U_Prim", tc_bu_colors, ImVec4(255, 255, 255, 255), false, false, false };
//Misc. colors, the one I have no clue where to put nor that aren't that important
#ifdef MASTER_QUEST
static CosmeticsColorIndividual TitleScreen_fire_Prim = { "Opening logo fire (Primary)", "Affects the fire behind the title screen logo", "gCCTCFirePrim", tc_fire_colors, ImVec4(170, 255, 255, 255), false, false, false };
static CosmeticsColorIndividual TitleScreen_fire_Env = { "Opening logo fire (Secondary)", "Affects the fire behind the title screen logo", "gCCTCFireEnv", tc_fire_colors_env, ImVec4(200, 255, 0, 255), false, false, false };
#else
static CosmeticsColorIndividual TitleScreen_fire_Prim = { "Opening logo fire (Primary)", "Affects the fire behind the title screen logo", "gCCTCFirePrim", tc_fire_colors, ImVec4(255, 255, 170, 255), false, false, false };
static CosmeticsColorIndividual TitleScreen_fire_Env = { "Opening logo fire (Secondary)", "Affects the fire behind the title screen logo", "gCCTCFireEnv", tc_fire_colors_env, ImVec4(255, 100, 0, 255), false, false, false };
#endif
static CosmeticsColorIndividual Rupee_Icon = { "Rupee icon", "Affects the Rupee icon on interface\nGreen is the default value", "gCCRupeePrim", rupee_colors, ImVec4(200, 255, 100, 255), true, false, false };
static CosmeticsColorIndividual SmallKeys_Icon = { "Small Keys icon", "Affects the Small keys icon on interface\nGray is the default value", "gCCKeysPrim", smolekey_colors, ImVec4(200, 230, 255, 255), true, false, false };
static CosmeticsColorIndividual VSOA_Icon = { "Visual Stone of agony icon", "Affects the Stone of Agony icon on interface\nWhite is the default value\nRequire room reload or activation", "gCCVSOAPrim", visualagony_colors, ImVec4(255, 255, 255, 255), true, false, false };
//Sections creation, here I regroup them in some sort of a Theme, all navi stuff together etc. It will be used to create the menu.
static CosmeticsColorSection Navi_Section[] = {
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false }
};
static CosmeticsColorSection Keese_Section[] = {
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false }
};
static CosmeticsColorSection Dogs_Section[] = {
{ &DogN1, false, false },
{ &DogN2, true, false }
};
static CosmeticsColorSection Tunics_Section[] = {
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false }
};
static CosmeticsColorSection Arrows_section[] = {
{ &Fire_Arrow_Prim, false, false },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false }
};
static CosmeticsColorSection Spells_section[] = {
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false }
};
static CosmeticsColorSection SpinAtk_section[] = {
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false }
};
static CosmeticsColorSection Trails_section[] = {
{ &Trails_col, false, false }
};
static CosmeticsColorSection FileChoose_section[] = {
{ &FileChoose_Background, false, false },
{ &FileChoose_BottomText, true, false }
};
static CosmeticsColorSection A_Btn_section[] = {
{ &A_Btn, false, false }
};
static CosmeticsColorSection B_Btn_section[] = {
{ &B_Btn, false, false }
};
static CosmeticsColorSection C_Btn_Unified_section[] = {
{ &C_Btn, false, false }
};
static CosmeticsColorSection C_Btn_Separated_section[] = {
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true }
};
static CosmeticsColorSection Start_Btn_section[] = {
{ &Start_btn, false, false }
};
static CosmeticsColorSection DPad_section[] = {
{ &DPad_Items, false, false }
};
static CosmeticsColorSection Hearts_section[] = {
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false }
};
static CosmeticsColorSection Magic_Meter_section[] = {
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false }
};
static CosmeticsColorSection Minimap_section[] = {
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true }
};
static CosmeticsColorSection TitleCards_section[] = {
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false }
};
static CosmeticsColorSection Misc_section[] = {
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true },
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true }
};
//Randomizer specific stuff (by randomizer I mean within cosmetics, these section are there just for the purpose of randomizing their colors)
static CosmeticsColorSection Everything_Section[] = {
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true },
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false },
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false },
{ &DogN1, false, false },
{ &DogN2, true, false },
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false },
{ &Fire_Arrow_Prim, false, false },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false },
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false },
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false },
{ &Trails_col, false, false },
{ &FileChoose_Background, false, false },
{ &FileChoose_BottomText, true, false },
{ &A_Btn, false, false },
{ &B_Btn, false, false },
{ &C_Btn, false, false },
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true },
{ &Start_btn, false, false },
{ &DPad_Items, false, false },
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false },
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false },
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true },
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false },
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true }
};
static CosmeticsColorSection Buttons_section[]{
{ &DPad_Items, false, false },
{ &C_Btn_U, false, false },
{ &C_Btn_D, false, true },
{ &C_Btn_L, false, true },
{ &C_Btn_R, false, true },
{ &C_Btn, false, false },
{ &B_Btn, false, false },
{ &A_Btn, false, false },
{ &Start_btn, false, false }
};
static CosmeticsColorSection Misc_Interface_section[]{
{ &Hearts_NInner, false, false },
{ &Hearts_DDInner, true, false },
{ &Hearts_DDOutline, true, false },
{ &Magic_Borders, false, false },
{ &Magic_InUse_Borders, true, false },
{ &Magic_Meter, false, true },
{ &Magic_InUse_Meter, true, false },
{ &Minimap_OW, false, false },
{ &Minimap_DG, false, true },
{ &Minimap_CP, false, true },
{ &Minimap_LE, false, true },
{ &TitleCards_OW, false, false },
{ &TitleCards_DG, true, false },
{ &Rupee_Icon, false, false },
{ &SmallKeys_Icon, false, true },
{ &VSOA_Icon, false, true },
{ &TitleScreen_fire_Prim, false, true },
{ &TitleScreen_fire_Env, false, true }
};
static CosmeticsColorSection NPCs_section[]{
{ &Navi_Idle_Inner, false, false },
{ &Navi_Idle_Outer, true, false },
{ &Navi_Npc_Inner, false, true },
{ &Navi_Npc_Outer, true, false },
{ &Navi_Enemy_Inner, false, true },
{ &Navi_Enemy_Outer, true, false },
{ &Navi_Prop_Inner, false, true },
{ &Navi_Prop_Outer, true, false },
{ &Keese1_prim, false, false },
{ &Keese2_prim, true, false },
{ &Keese1_env, false, true },
{ &Keese2_env, true, false },
{ &DogN1, false, false },
{ &DogN2, true, false }
};
static CosmeticsColorSection AllItemsSkills_section[]{
{ &KokiriTunic, false, false },
{ &GoronTunic, true, false },
{ &ZoraTunic, true, false },
{ &Fire_Arrow_Prim, false, false },
{ &Fire_Arrow_Env, true, false },
{ &Ice_Arrow_Prim, false, true },
{ &Ice_Arrow_Env, true, false },
{ &Light_Arrow_Prim, false, true },
{ &Light_Arrow_Env, true, false },
{ &Din_Fire_Prim, false, false },
{ &Din_Fire_Env, true, false },
{ &Nayru_Diamond_Prim, false, true },
{ &Nayru_Diamond_Env, true, false },
{ &Nayru_Orb_Prim, false, true },
{ &Nayru_Orb_Env, true, false },
{ &Spin_Lv1_Prim, false, false },
{ &Spin_Lv1_Env, true, false },
{ &Spin_Lv2_Prim, false, true },
{ &Spin_Lv2_Env, true, false },
{ &Trails_col, false, false }
};
void InitCosmeticsEditor();//Init the menu itself void InitCosmeticsEditor();//Init the menu itself
void LoadRainbowColor(); void LoadRainbowColor();

View File

@ -47,7 +47,7 @@ void CustomMessageManager::ReplaceColors(std::string& string) {
} }
} }
void CustomMessageManager::FormatCustomMessage(std::string& message, uint16_t iid) { void CustomMessageManager::FormatCustomMessage(std::string& message, ItemID iid) {
message.insert(0, ITEM_OBTAINED(iid)); message.insert(0, ITEM_OBTAINED(iid));
size_t start_pos = 0; size_t start_pos = 0;
std::replace(message.begin(), message.end(), '&', NEWLINE()[0]); std::replace(message.begin(), message.end(), '&', NEWLINE()[0]);
@ -81,7 +81,7 @@ bool CustomMessageManager::InsertCustomMessage(std::string tableID, uint16_t tex
return messageInsertResult.second; return messageInsertResult.second;
} }
bool CustomMessageManager::CreateGetItemMessage(std::string tableID, uint16_t giid, uint16_t iid, bool CustomMessageManager::CreateGetItemMessage(std::string tableID, uint16_t giid, ItemID iid,
CustomMessageEntry messageEntry) { CustomMessageEntry messageEntry) {
FormatCustomMessage(messageEntry.english, iid); FormatCustomMessage(messageEntry.english, iid);
FormatCustomMessage(messageEntry.german, iid); FormatCustomMessage(messageEntry.german, iid);

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "../../../include/z64item.h" #include "../../../include/z64item.h"
#include "../../../include/message_data_textbox_types.h"
#undef MESSAGE_END #undef MESSAGE_END
@ -14,31 +15,6 @@
#define QM_YELLOW 0x46 #define QM_YELLOW 0x46
#define QM_BLACK 0x47 #define QM_BLACK 0x47
#ifndef MESSAGE_DATA_STATIC_H
typedef enum {
/* 0 */ TEXTBOX_TYPE_BLACK,
/* 1 */ TEXTBOX_TYPE_WOODEN,
/* 2 */ TEXTBOX_TYPE_BLUE,
/* 3 */ TEXTBOX_TYPE_OCARINA,
/* 4 */ TEXTBOX_TYPE_NONE_BOTTOM,
/* 5 */ TEXTBOX_TYPE_NONE_NO_SHADOW,
/* 11 */ TEXTBOX_TYPE_CREDITS = 11
} TextBoxType;
typedef enum {
/* 0 */ TEXTBOX_BG_CROSS
} TextBoxBackground;
typedef enum {
/* 0 */ TEXTBOX_POS_VARIABLE,
/* 1 */ TEXTBOX_POS_TOP,
/* 2 */ TEXTBOX_POS_MIDDLE,
/* 3 */ TEXTBOX_POS_BOTTOM
} TextBoxPosition;
#endif
typedef struct { typedef struct {
TextBoxType textBoxType; TextBoxType textBoxType;
TextBoxPosition textBoxPos; TextBoxPosition textBoxPos;
@ -89,7 +65,7 @@ class CustomMessageManager {
with the provided giid (getItemID) as its key. This function also inserts the icon corresponding to with the provided giid (getItemID) as its key. This function also inserts the icon corresponding to
the provided iid (itemID) at the beginning of each page of the textbox. the provided iid (itemID) at the beginning of each page of the textbox.
*/ */
bool CreateGetItemMessage(std::string tableID, uint16_t giid, uint16_t iid, CustomMessageEntry messages); bool CreateGetItemMessage(std::string tableID, uint16_t giid, ItemID iid, CustomMessageEntry messages);
/* /*
Formats the provided Custom Message Entry and inserts it into the table with the provided tableID, Formats the provided Custom Message Entry and inserts it into the table with the provided tableID,
@ -122,7 +98,7 @@ class CustomMessageManager {
& for newline, ^ for wait-for-input, and @ for the player name, & for newline, ^ for wait-for-input, and @ for the player name,
as well as %<letter> for colors (i.e. %r for red and %w for white). as well as %<letter> for colors (i.e. %r for red and %w for white).
*/ */
void FormatCustomMessage(std::string& message, uint16_t iid); void FormatCustomMessage(std::string& message, ItemID iid);
/* /*
Replaces special characters and certain symbols with control codes Replaces special characters and certain symbols with control codes

View File

@ -11,14 +11,19 @@ typedef enum {
TEXT_ALTAR_CHILD = 0x7040, TEXT_ALTAR_CHILD = 0x7040,
TEXT_ALTAR_ADULT = 0x7088, TEXT_ALTAR_ADULT = 0x7088,
TEXT_GANONDORF = 0x70CC, TEXT_GANONDORF = 0x70CC,
TEXT_GANONDORF_NOHINT = 0x70CD TEXT_GANONDORF_NOHINT = 0x70CD,
TEXT_BLUE_RUPEE = 0xCC,
TEXT_RED_RUPEE = 0xF0,
TEXT_PURPLE_RUPEE = 0xF1,
TEXT_HUGE_RUPEE = 0xF2,
TEXT_BEAN_SALESMAN = 0x405E
} TextIDs; } TextIDs;
#ifdef __cplusplus #ifdef __cplusplus
typedef struct { typedef struct {
u16 giid; u16 giid;
u16 iid; ItemID iid;
std::string english; std::string english;
std::string german; std::string german;
std::string french; std::string french;

View File

@ -1,7 +1,3 @@
#ifdef _MSC_VER
#define NOGDI
#endif
#include "debugconsole.h" #include "debugconsole.h"
#include "../libultraship/ImGuiImpl.h" #include "../libultraship/ImGuiImpl.h"
#include "savestates.h" #include "savestates.h"
@ -313,6 +309,69 @@ static bool EntranceHandler(std::shared_ptr<Ship::Console> Console, const std::v
gSaveContext.nextTransition = 11; gSaveContext.nextTransition = 11;
} }
static bool VoidHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (gGlobalCtx != nullptr) {
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwchFlags = gGlobalCtx->actorCtx.flags.tempSwch;
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = gGlobalCtx->actorCtx.flags.tempCollect;
gSaveContext.respawnFlag = 1;
gGlobalCtx->sceneLoadFlag = 0x14;
gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex;
gGlobalCtx->fadeTransition = 2;
gSaveContext.nextTransition = 2;
} else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED;
}
return CMD_SUCCESS;
}
static bool ReloadHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (gGlobalCtx != nullptr) {
gGlobalCtx->nextEntranceIndex = gSaveContext.entranceIndex;
gGlobalCtx->sceneLoadFlag = 0x14;
gGlobalCtx->fadeTransition = 11;
gSaveContext.nextTransition = 11;
} else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED;
}
return CMD_SUCCESS;
}
static bool FWHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (gGlobalCtx != nullptr) {
if (gSaveContext.respawn[RESPAWN_MODE_TOP].data > 0) {
gGlobalCtx->sceneLoadFlag = 0x14;
gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex;
gGlobalCtx->fadeTransition = 5;
} else {
SohImGui::console->SendErrorMessage("Farore's wind not set!");
}
}
else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED;
}
return CMD_SUCCESS;
}
static bool FileSelectHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
if (gGlobalCtx != nullptr) {
SET_NEXT_GAMESTATE(&gGlobalCtx->state, FileChoose_Init, FileChooseContext);
gGlobalCtx->state.running = 0;
} else {
SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr");
return CMD_FAILED;
}
return CMD_SUCCESS;
}
static bool QuitHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
gGlobalCtx->state.running = 0;
return CMD_SUCCESS;
}
static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) { static bool SaveStateHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE }); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE });
@ -500,6 +559,11 @@ void DebugConsole_Init(void) {
CMD_REGISTER("entrance", { EntranceHandler, CMD_REGISTER("entrance", { EntranceHandler,
"Sends player to the entered entrance (hex)", "Sends player to the entered entrance (hex)",
{ { "entrance", Ship::ArgumentType::NUMBER } } }); { { "entrance", Ship::ArgumentType::NUMBER } } });
CMD_REGISTER("void", {VoidHandler, "Voids out of the current map.",});
CMD_REGISTER("reload", {ReloadHandler, "Reloads the current map.",});
CMD_REGISTER("file_select", {FileSelectHandler, "Returns to the file select.",});
CMD_REGISTER("fw", {FWHandler,"Spawns the player where Farore's Wind is set.", });
CMD_REGISTER("quit", {QuitHandler, "Quits the game.",});
CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." }); CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." });
CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." }); CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." });

View File

@ -911,15 +911,19 @@ void DrawFlagsTab() {
setMask <<= 1; setMask <<= 1;
} }
static bool keepGsCountUpdated = true; // If playing a Randomizer Save with Shuffle Skull Tokens on anything other than "Off" we don't want to keep
ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated); // GS Token Count updated, since Gold Skulltulas killed will not correlate to GS Tokens Collected.
InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags"); if (!(gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS))) {
int32_t gsCount = 0; static bool keepGsCountUpdated = true;
if (keepGsCountUpdated) { ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated);
for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) { InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags.");
gsCount += std::popcount(static_cast<uint32_t>(gSaveContext.gsFlags[gsFlagIndex])); int32_t gsCount = 0;
if (keepGsCountUpdated) {
for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) {
gsCount += std::popcount(static_cast<uint32_t>(gSaveContext.gsFlags[gsFlagIndex]));
}
gSaveContext.inventory.gsTokens = gsCount;
} }
gSaveContext.inventory.gsTokens = gsCount;
} }
}); });

View File

@ -7,12 +7,20 @@
#define CHEST_ANIM_LONG 1 #define CHEST_ANIM_LONG 1
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, modIndex, getItemId) \ #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, modIndex, getItemId) \
{ itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId, modIndex, getItemId, drawId, true } { itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId, modIndex, getItemId, drawId, true, NULL }
#define GET_ITEM_NONE \ #define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, false } { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, false, NULL }
typedef struct { #define GET_ITEM_CUSTOM_DRAW(itemId, objectId, drawId, textId, field, chestAnim, modIndex, getItemId, drawFunc) \
{ itemId, field (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId, modIndex, getItemId, drawId, true, drawFunc }
typedef struct GlobalContext GlobalContext;
typedef struct GetItemEntry GetItemEntry;
typedef void (*CustomDrawFunc)(GlobalContext* globalCtx, GetItemEntry* getItemEntry);
typedef struct GetItemEntry {
/* 0x00 */ uint16_t itemId; /* 0x00 */ uint16_t itemId;
/* 0x01 */ uint16_t field; // various bit-packed data /* 0x01 */ uint16_t field; // various bit-packed data
/* 0x02 */ int16_t gi; // defines the draw id and chest opening animation /* 0x02 */ int16_t gi; // defines the draw id and chest opening animation
@ -22,4 +30,5 @@ typedef struct {
/* 0x08 */ int16_t getItemId; /* 0x08 */ int16_t getItemId;
/* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference. /* 0x0A */ uint16_t gid; // Stores the GID value unmodified for future reference.
/* 0x0C */ uint16_t collectable; // determines whether the item can be collected on the overworld. Will be true in most cases. /* 0x0C */ uint16_t collectable; // determines whether the item can be collected on the overworld. Will be true in most cases.
} GetItemEntry; // size = 0x0F CustomDrawFunc drawFunc;
}; // size = 0x0F

View File

@ -1040,7 +1040,7 @@ int Fill() {
std::vector<uint32_t> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); std::vector<uint32_t> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
FastFill(remainingPool, GetAllEmptyLocations(), false); FastFill(remainingPool, GetAllEmptyLocations(), false);
// Add prices for scrubsanity //Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile.
if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) { if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) {
for (size_t i = 0; i < ScrubLocations.size(); i++) { for (size_t i = 0; i < ScrubLocations.size(); i++) {
Location(ScrubLocations[i])->SetScrubsanityPrice(10); Location(ScrubLocations[i])->SetScrubsanityPrice(10);

View File

@ -6,9 +6,7 @@
#include "rando_main.hpp" #include "rando_main.hpp"
// #include <soh/Enhancements/randomizer.h> // #include <soh/Enhancements/randomizer.h>
#include <Cvar.h> #include <Cvar.h>
#define NOGDI #include <Window.h>
#define WIN32_LEAN_AND_MEAN
#include <GlobalCtx2.h>
#include <PR/ultra64/types.h> #include <PR/ultra64/types.h>
#define TICKS_PER_SEC 268123480.0 #define TICKS_PER_SEC 268123480.0
@ -21,7 +19,7 @@ void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarS
// std::string settingsFileName = "./randomizer/latest_settings.json"; // std::string settingsFileName = "./randomizer/latest_settings.json";
// CVar_SetString("gLoadedPreset", settingsFileName.c_str()); // CVar_SetString("gLoadedPreset", settingsFileName.c_str());
std::string fileName = Ship::GlobalCtx2::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations).c_str()); std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations).c_str());
CVar_SetString("gSpoilerLog", fileName.c_str()); CVar_SetString("gSpoilerLog", fileName.c_str());
CVar_Save(); CVar_Save();

View File

@ -2553,6 +2553,7 @@ namespace Settings {
ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]); ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]);
ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]); ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]);
ShuffleMagicBeans.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MAGIC_BEANS]);
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina" // the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]); StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);

View File

@ -26,9 +26,7 @@
#include <filesystem> #include <filesystem>
#include <variables.h> #include <variables.h>
#define NOGDI #include "Window.h"
#define WIN32_LEAN_AND_MEAN
#include "GlobalCtx2.h"
using json = nlohmann::json; using json = nlohmann::json;
@ -675,12 +673,22 @@ static void WriteHints(int language) {
static void WriteAllLocations(int language) { static void WriteAllLocations(int language) {
for (const uint32_t key : allLocations) { for (const uint32_t key : allLocations) {
ItemLocation* location = Location(key); ItemLocation* location = Location(key);
std::string placedItemName = language == 2 ? location->GetPlacedItemName().french : location->GetPlacedItemName().english; std::string placedItemName;
switch (language) {
case 0:
default:
placedItemName = location->GetPlacedItemName().english;
break;
case 2:
placedItemName = location->GetPlacedItemName().french;
break;
}
// Eventually check for other things here like fake name // Eventually check for other things here like fake name
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice() || location->GetPrice() > 0) { if (location->HasScrubsanityPrice() || location->HasShopsanityPrice() || location->GetPrice() > 0) {
jsonData["locations"][location->GetName()]["item"] = placedItemName; jsonData["locations"][location->GetName()]["item"] = placedItemName;
jsonData["locations"][location->GetName()]["price"] = location->GetPrice();; jsonData["locations"][location->GetName()]["price"] = location->GetPrice();
} else { } else {
jsonData["locations"][location->GetName()] = placedItemName; jsonData["locations"][location->GetName()] = placedItemName;
} }
@ -727,12 +735,12 @@ const char* SpoilerLog_Write(int language) {
//WriteShuffledEntrances(spoilerLog); //WriteShuffledEntrances(spoilerLog);
WriteAllLocations(language); WriteAllLocations(language);
if (!std::filesystem::exists(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer"))) { if (!std::filesystem::exists(Ship::Window::GetPathRelativeToAppDirectory("Randomizer"))) {
std::filesystem::create_directory(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer")); std::filesystem::create_directory(Ship::Window::GetPathRelativeToAppDirectory("Randomizer"));
} }
std::string jsonString = jsonData.dump(4); std::string jsonString = jsonData.dump(4);
std::ofstream jsonFile(Ship::GlobalCtx2::GetPathRelativeToAppDirectory( std::ofstream jsonFile(Ship::Window::GetPathRelativeToAppDirectory(
(std::string("Randomizer/") + std::string(Settings::seed) + std::string(".json")).c_str())); (std::string("Randomizer/") + std::string(Settings::seed) + std::string(".json")).c_str()));
jsonFile << std::setw(4) << jsonString << std::endl; jsonFile << std::setw(4) << jsonString << std::endl;
jsonFile.close(); jsonFile.close();

View File

@ -0,0 +1,109 @@
#include "draw.h"
#include "z64.h"
#include "macros.h"
#include "functions.h"
#include "randomizerTypes.h"
#include <array>
#include "objects/object_gi_key/object_gi_key.h"
#include "objects/object_gi_bosskey/object_gi_bosskey.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
extern "C" void Randomizer_DrawSmallKey(GlobalContext* globalCtx, GetItemEntry* getItemEntry) {
s32 pad;
s16 color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_SMALL_KEY;
s16 colors[9][3] = {
{ 4, 195, 46 }, // Forest Temple
{ 237, 95, 95 }, // Fire Temple
{ 85, 180, 223 }, // Water Temple
{ 222, 158, 47 }, // Spirit Temple
{ 126, 16, 177 }, // Shadow Temple
{ 227, 110, 255 }, // Bottom of the Well
{ 221, 212, 60 }, // Gerudo Training Grounds
{ 255, 255, 255 }, // Theive's Hideout (unused)
{ 80, 80, 80 } // Ganon's Castle
};
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gsDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gsSPGrayscale(POLY_OPA_DISP++, true);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
gsSPGrayscale(POLY_OPA_DISP++, false);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
extern "C" void Randomizer_DrawBossKey(GlobalContext* globalCtx, GetItemEntry* getItemEntry) {
s32 pad;
s16 color_slot;
color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY;
s16 colors[6][3] = {
{ 4, 195, 46 }, // Forest Temple
{ 237, 95, 95 }, // Fire Temple
{ 85, 180, 223 }, // Water Temple
{ 222, 158, 47 }, // Spirit Temple
{ 126, 16, 177 }, // Shadow Temple
{ 210, 0, 0 } // Ganon's Castle
};
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
if (color_slot == 5) { // Ganon's Boss Key
gsDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255);
gsSPGrayscale(POLY_OPA_DISP++, true);
}
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBossKeyDL);
if (color_slot == 5) { // Ganon's Boss Key
gsSPGrayscale(POLY_OPA_DISP++, false);
}
func_80093D84(globalCtx->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
gsDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2],
255);
gsSPGrayscale(POLY_XLU_DISP++, true);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBossKeyGemDL);
gsSPGrayscale(POLY_XLU_DISP++, false);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
extern "C" void Randomizer_DrawDoubleDefense(GlobalContext* globalCtx, GetItemEntry getItemEntry) {
s32 pad;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D84(globalCtx->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gsDPSetGrayscaleColor(POLY_XLU_DISP++, 255, 255, 255, 255);
gsSPGrayscale(POLY_XLU_DISP++, true);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiHeartBorderDL);
gsSPGrayscale(POLY_XLU_DISP++, false);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiHeartContainerDL);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}

View File

@ -0,0 +1,13 @@
#ifndef RANDODRAW_H
#define RANDODRAW_H
#pragma once
#include "../item-tables/ItemTableTypes.h"
typedef struct GlobalContext GlobalContext;
extern "C" void Randomizer_DrawSmallKey(GlobalContext* globalCtx, GetItemEntry* getItemEntry);
extern "C" void Randomizer_DrawBossKey(GlobalContext* globalCtx, GetItemEntry* getItemEntry);
extern "C" void Randomizer_DrawDoubleDefense(GlobalContext* globalCtx, GetItemEntry getItemEntry);
#endif

View File

@ -14,12 +14,12 @@
#include "3drando/rando_main.hpp" #include "3drando/rando_main.hpp"
#include <soh/Enhancements/debugger/ImGuiHelpers.h> #include <soh/Enhancements/debugger/ImGuiHelpers.h>
#include "Lib/ImGui/imgui_internal.h" #include "Lib/ImGui/imgui_internal.h"
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
#include <soh/Enhancements/custom-message/CustomMessageTypes.h> #include <soh/Enhancements/custom-message/CustomMessageTypes.h>
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include <soh/Enhancements/item-tables/ItemTableManager.h>
#include <stdexcept> #include <stdexcept>
#include "randomizer_check_objects.h" #include "randomizer_check_objects.h"
#include <sstream> #include <sstream>
#include "draw.h"
using json = nlohmann::json; using json = nlohmann::json;
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
@ -33,7 +33,30 @@ u8 generated;
const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::getItemMessageTableID = "Randomizer";
const std::string Randomizer::hintMessageTableID = "RandomizerHints"; const std::string Randomizer::hintMessageTableID = "RandomizerHints";
const std::string Randomizer::shopMessageTableID = "RandomizerShops"; const std::string Randomizer::shopMessageTableID = "RandomizerShops";
const std::string Randomizer::scrubMessageTableID = "RandomizerScrubs"; const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants";
const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees";
const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi";
static const char* englishRupeeNames[44] = {
"Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings",
"Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs",
"Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars",
"Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids",
"Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold",
"Shillings", "Pounds", "Glimmer", "Potch"
};
static const char* germanRupeeNames[1] = {
"Rubine"
};
static const char* frenchRupeeNames[36] = {
"Rubis", "Bitcoin", "Bananes", "Euros", "Dollars", "Émeraudes", "Joyaux", "Diamants",
"Balles", "Pokémon", "Pièces", "Lunes", "Étoiles", "Dogecoin", "Anneaux", "Radis",
"Pokédollars", "Zennies", "Pépètes", "Mailles", "Éthers", "Clochettes", "Capsules", "Gils",
"Champignons", "Blés", "Halos", "Munnies", "Orens", "Florens", "Crédits", "Galds",
"Bling", "Orbes", "Baguettes", "Croissants"
};
Randomizer::Randomizer() { Randomizer::Randomizer() {
Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 }; Sprite bowSprite = { dgFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 };
@ -82,7 +105,7 @@ Sprite* Randomizer::GetSeedTexture(uint8_t index) {
Randomizer::~Randomizer() { Randomizer::~Randomizer() {
this->randoSettings.clear(); this->randoSettings.clear();
this->itemLocations.clear(); this->itemLocations.clear();
this->scrubPrices.clear(); this->randomizerMerchantPrices.clear();
} }
std::unordered_map<s16, s16> getItemIdToItemId = { std::unordered_map<s16, s16> getItemIdToItemId = {
@ -530,6 +553,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS }, { "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
{ "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS},
{ "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD },
{ "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD },
{ "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA },
@ -871,6 +895,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD: case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
case RSK_SHUFFLE_COWS: case RSK_SHUFFLE_COWS:
case RSK_SHUFFLE_ADULT_TRADE: case RSK_SHUFFLE_ADULT_TRADE:
case RSK_SHUFFLE_MAGIC_BEANS:
case RSK_RANDOM_TRIALS: case RSK_RANDOM_TRIALS:
case RSK_STARTING_DEKU_SHIELD: case RSK_STARTING_DEKU_SHIELD:
case RSK_STARTING_KOKIRI_SWORD: case RSK_STARTING_KOKIRI_SWORD:
@ -1201,8 +1226,7 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()]; gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()];
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()]; gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()];
} else if (itemit.key() == "price") { } else if (itemit.key() == "price") {
scrubPrices[gSaveContext.itemLocations[index].check] = itemit.value(); randomizerMerchantPrices[gSaveContext.itemLocations[index].check] = itemit.value();
// TODO: Handle shop prices
} }
} }
} else { } else {
@ -1245,7 +1269,7 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) {
case RG_GIANTS_KNIFE: case RG_GIANTS_KNIFE:
return GI_SWORD_KNIFE; return GI_SWORD_KNIFE;
case RG_BIGGORON_SWORD: case RG_BIGGORON_SWORD:
return !CHECK_OWNED_EQUIP(EQUIP_SWORD, 2) ? GI_SWORD_BGS : GI_RUPEE_BLUE; return !gSaveContext.bgsFlag ? GI_SWORD_BGS : GI_RUPEE_BLUE;
case RG_DEKU_SHIELD: case RG_DEKU_SHIELD:
case RG_BUY_DEKU_SHIELD: case RG_BUY_DEKU_SHIELD:
@ -1302,8 +1326,6 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) {
case RG_MAGIC_BEAN: case RG_MAGIC_BEAN:
return GI_BEAN; return GI_BEAN;
case RG_MAGIC_BEAN_PACK:
return GI_BEAN; //todo make it 10 of them
case RG_WEIRD_EGG: case RG_WEIRD_EGG:
return GI_WEIRD_EGG; return GI_WEIRD_EGG;
@ -1729,12 +1751,12 @@ std::string Randomizer::GetGanonHintText() const {
ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) { ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
struct ScrubIdentity scrubIdentity; struct ScrubIdentity scrubIdentity;
scrubIdentity.scrubId = -1;
scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK; scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
scrubIdentity.getItemId = GI_NONE; scrubIdentity.getItemId = GI_NONE;
scrubIdentity.itemPrice = -1; scrubIdentity.itemPrice = -1;
scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0; scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0;
// Based on z_en_dns.c 93-113
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.getItemId = GI_NUTS_5_2; scrubIdentity.getItemId = GI_NUTS_5_2;
@ -1776,20 +1798,20 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_DDAN: // Dodongo's Cavern case SCENE_DDAN: // Dodongo's Cavern
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x00; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT;
break; break;
case 0x01: case 0x01:
scrubIdentity.scrubId = 0x01; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x02; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT;
break; break;
case 0x04: case 0x04:
scrubIdentity.scrubId = 0x03; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
break; break;
} }
@ -1797,7 +1819,7 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_BDAN: // Jabu Jabu's Belly case SCENE_BDAN: // Jabu Jabu's Belly
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x04; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB;
scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB; scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB;
break; break;
} }
@ -1805,31 +1827,30 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_GANONTIKA: // Ganon's Castle case SCENE_GANONTIKA: // Ganon's Castle
switch (actorParams) { switch (actorParams) {
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x05; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x06; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
break; break;
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x07; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x08; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT;
break; break;
} }
break; break;
case SCENE_KAKUSIANA: // Grotto case SCENE_KAKUSIANA: // Grotto
// Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando
switch (respawnData) { switch (respawnData) {
case 0xE6: // Hyrule Field Scrub Grotto case 0xE6: // Hyrule Field Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x02: case 0x02:
scrubIdentity.scrubId = 0x09; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO;
scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO; scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1838,11 +1859,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEB: // ZR Scrub Grotto case 0xEB: // ZR Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x0A; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x0B; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1850,11 +1871,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEE: // Sacred Forest Meadow Scrub Grotto case 0xEE: // Sacred Forest Meadow Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x0C; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x0D; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1862,16 +1883,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEF: // Lake Hylia Scrub Grotto case 0xEF: // Lake Hylia Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x0E; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x0F; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x10; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1879,11 +1900,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xF0: // Gerudo Valley Scrub Grotto case 0xF0: // Gerudo Valley Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x11; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x12; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1892,11 +1913,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
switch (actorParams) { switch (actorParams) {
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x13; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x0A: case 0x0A:
scrubIdentity.scrubId = 0x14; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1905,16 +1926,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xF9: // Death Mountain Crater Scrub Grotto case 0xF9: // Death Mountain Crater Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x15; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x16; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x17; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1922,16 +1943,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFB: // Gerudo City Scrub Grotto case 0xFB: // Gerudo City Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x18; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x19; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x1A; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1939,16 +1960,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFC: // Lon Lon Ranch Scrub Grotto case 0xFC: // Lon Lon Ranch Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x1B; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x1C; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x1D; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1956,11 +1977,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFD: // Desert Colossus Scrub Grotto case 0xFD: // Desert Colossus Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x1E; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x1F; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1970,15 +1991,15 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_SPOT10: // Lost woods case SCENE_SPOT10: // Lost woods
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x20; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
break; break;
case 0x01: case 0x01:
scrubIdentity.scrubId = 0x21; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
break; break;
case 0x09: case 0x09:
scrubIdentity.scrubId = 0x22; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1987,15 +2008,15 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_SPOT17: // Death Mountain Crater case SCENE_SPOT17: // Death Mountain Crater
switch (actorParams) { switch (actorParams) {
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x23; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB;
break; break;
} }
break; break;
} }
if (scrubPrices.find(scrubIdentity.randomizerCheck) != scrubPrices.end()) { if (randomizerMerchantPrices.find(scrubIdentity.randomizerCheck) != randomizerMerchantPrices.end()) {
scrubIdentity.itemPrice = scrubPrices[scrubIdentity.randomizerCheck]; scrubIdentity.itemPrice = randomizerMerchantPrices[scrubIdentity.randomizerCheck];
} }
return scrubIdentity; return scrubIdentity;
@ -3310,6 +3331,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_SCRUBS] = CVar_GetS32("gRandomizeShuffleScrubs", 0); cvarSettings[RSK_SHUFFLE_SCRUBS] = CVar_GetS32("gRandomizeShuffleScrubs", 0);
cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0);
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVar_GetS32("gRandomizeShuffleBeans", 0);
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
// if we skip child zelda, we start with zelda's letter, and malon starts // if we skip child zelda, we start with zelda's letter, and malon starts
@ -3804,6 +3826,20 @@ void DrawRandoEditor(bool& open) {
SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0);
PaddedSeparator(); PaddedSeparator();
// Shuffle Scrubs
ImGui::Text(Settings::Scrubsanity.GetName().c_str());
InsertHelpHoverText(
"Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game (PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n"
"\n"
"Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n"
"\n"
"Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n"
"\n"
"Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"
);
SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
PaddedSeparator();
// Shuffle Tokens // Shuffle Tokens
ImGui::Text(Settings::Tokensanity.GetName().c_str()); ImGui::Text(Settings::Tokensanity.GetName().c_str());
InsertHelpHoverText("Shuffles Golden Skulltula Tokens into the item pool. This means " InsertHelpHoverText("Shuffles Golden Skulltula Tokens into the item pool. This means "
@ -3824,34 +3860,24 @@ void DrawRandoEditor(bool& open) {
"expected to be collected after getting Sun's Song."); "expected to be collected after getting Sun's Song.");
PaddedSeparator(); PaddedSeparator();
// Shopsanity // Shopsanity
ImGui::Text(Settings::Shopsanity.GetName().c_str()); ImGui::Text(Settings::Shopsanity.GetName().c_str());
InsertHelpHoverText( InsertHelpHoverText(
"Off - All shop items will be the same as vanilla.\n" "Off - All shop items will be the same as vanilla.\n"
"\n" "\n"
"0 - Vanilla shop items will be shuffled among different shops.\n" "0 - Vanilla shop items will be shuffled among different shops.\n"
"\n" "\n"
"1-4 - Vanilla shop items will be shuffled among different shops, and each shop will contain 1-4 non-vanilla shop items.\n" "1-4 - Vanilla shop items will be shuffled among different shops, and each shop will contain 1-4 non-vanilla shop items.\n"
"\n" "\n"
"Random - Vanilla shop items will be shuffled among different shops, and each shop will contain a random number of non-vanilla shop items.\n" "Random - Vanilla shop items will be shuffled among different shops, and each shop will contain a random number of non-vanilla shop items.\n"
); );
SohImGui::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, 7, 0); SohImGui::EnhancementCombobox("gRandomizeShopsanity", randoShopsanity, 7, 0);
PaddedSeparator(); PaddedSeparator();
// Shuffle Scrubs // Shuffle Cows
ImGui::Text(Settings::Scrubsanity.GetName().c_str()); SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
InsertHelpHoverText( InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
"Off - Scrubs will not be shuffled.\n" PaddedSeparator();
"\n"
"Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n"
);
SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
PaddedSeparator();
// Shuffle Cows
SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
PaddedSeparator();
// Shuffle Adult Trade Quest // Shuffle Adult Trade Quest
SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(),
@ -3866,6 +3892,11 @@ void DrawRandoEditor(bool& open) {
"If disabled, only the Claim Check will be found in the pool."); "If disabled, only the Claim Check will be found in the pool.");
PaddedSeparator(); PaddedSeparator();
SohImGui::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans");
InsertHelpHoverText("Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean Salesman to sell a"
"random item at a price of 60 rupees.");
PaddedSeparator();
if (CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { if (CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) {
// Shuffle Kokiri Sword // Shuffle Kokiri Sword
SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(),
@ -4043,8 +4074,8 @@ void DrawRandoEditor(bool& open) {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding);
if (ImGui::BeginTable("tableRandoOther", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { if (ImGui::BeginTable("tableRandoOther", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) {
ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableSetupColumn("Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::TableSetupColumn("Item Pool Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("Item Pool & Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f);
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
ImGui::PopItemFlag(); ImGui::PopItemFlag();
@ -4116,10 +4147,49 @@ void DrawRandoEditor(bool& open) {
"The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. "
"These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise.");
// COLUMN 2 - HINT SETTINGS // COLUMN 2 - WORLD SETTINGS
ImGui::TableNextColumn(); ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::PushItemWidth(-FLT_MIN); ImGui::PushItemWidth(-FLT_MIN);
ImGui::Text("Coming soon");
ImGui::PopItemWidth();
// COLUMN 3 - ITEM POOL & HINT SETTINGS
ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::PushItemWidth(-FLT_MIN);
ImGui::Text(Settings::ItemPoolValue.GetName().c_str());
InsertHelpHoverText("Sets how many major items appear in the item pool.\n"
"\n"
"Plentiful - Extra major items are added to the pool.\n"
"\n"
"Balanced - Original item pool.\n"
"\n"
"Scarce - Some excess items are removed, including health upgrades.\n"
"\n"
"Minimal - Most excess items are removed.");
SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1);
PaddedSeparator();
// Ice Traps
ImGui::Text(Settings::IceTrapValue.GetName().c_str());
InsertHelpHoverText("Sets how many items are replaced by ice traps.\n"
"\n"
"Off - No ice traps.\n"
"\n"
"Normal - Only Ice Traps from the base item pool are shuffled in.\n"
"\n"
"Extra - Chance to replace added junk items with additional ice traps.\n"
"\n"
"Mayhem - All added junk items will be Ice Traps.\n"
"\n"
"Onslaught - All junk items will be replaced by Ice Traps, even those "
"in the base pool.");
SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1);
PaddedSeparator();
// Gossip Stone Hints // Gossip Stone Hints
ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); ImGui::Text(Settings::GossipStoneHints.GetName().c_str());
@ -4169,40 +4239,7 @@ void DrawRandoEditor(bool& open) {
SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1);
ImGui::Unindent(); ImGui::Unindent();
} }
ImGui::PopItemWidth();
// COLUMN 3 - ITEM POOL SETTINGS
ImGui::TableNextColumn();
window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::PushItemWidth(-FLT_MIN);
ImGui::Text(Settings::ItemPoolValue.GetName().c_str());
InsertHelpHoverText("Sets how many major items appear in the item pool.\n"
"\n"
"Plentiful - Extra major items are added to the pool.\n"
"\n"
"Balanced - Original item pool.\n"
"\n"
"Scarce - Some excess items are removed, including health upgrades.\n"
"\n"
"Minimal - Most excess items are removed.");
SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1);
PaddedSeparator();
// Ice Traps
ImGui::Text(Settings::IceTrapValue.GetName().c_str());
InsertHelpHoverText("Sets how many items are replaced by ice traps.\n"
"\n"
"Off - No ice traps.\n"
"\n"
"Normal - Only Ice Traps from the base item pool are shuffled in.\n"
"\n"
"Extra - Chance to replace added junk items with additional ice traps.\n"
"\n"
"Mayhem - All added junk items will be Ice Traps.\n"
"\n"
"Onslaught - All junk items will be replaced by Ice Traps, even those "
"in the base pool.");
SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::EndTable(); ImGui::EndTable();
} }
@ -4435,11 +4472,20 @@ void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
} }
} }
void CreateScrubMessages() { // Currently these are generated at runtime, one for each price between 0-95. We're soon going to migrate this
// to being generated at save load, with only messages specific to each scrub.
void CreateMerchantMessages() {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance; CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID); customMessageManager->AddCustomMessageTable(Randomizer::merchantMessageTableID);
for (u32 price = 0; price <= 95; price += 5) { customMessageManager->CreateMessage(Randomizer::merchantMessageTableID, 0,
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"\x12\x38\x82\All right! You win! In return for&sparing me, I will give you a&%gmysterious item%w!&Please, take it!\x07\x10\xA3",
"\x12\x38\x82\In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen %gmysteriösen&Gegenstand%w geben! Bitte nimm ihn!\x07\x10\xA3",
"\x12\x38\x82\D'accord! Vous avez gagné! En échange&de m'épargner, je vous donnerai un &%gobjet mystérieux%w! S'il vous plaît,&prenez-le!\x07\x10\xA3",
});
for (u32 price = 5; price <= 95; price += 5) {
customMessageManager->CreateMessage(Randomizer::merchantMessageTableID, price,
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, { TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" + "\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
std::to_string(price) + " Rupees%w it is!\x07\x10\xA3", std::to_string(price) + " Rupees%w it is!\x07\x10\xA3",
@ -4450,6 +4496,154 @@ void CreateScrubMessages() {
std::to_string(price) + " Rubis%w!\x07\x10\xA3" std::to_string(price) + " Rubis%w!\x07\x10\xA3"
}); });
} }
customMessageManager->CreateMessage(
Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN,
{
TEXTBOX_TYPE_BLACK,
TEXTBOX_POS_BOTTOM,
"I tried to be a %rmagic bean%w salesman,&but it turns out my marketing skills&weren't worth "
"beans!^Anyway, want to buy my&%gmysterious item%w for 60 Rupees?\x1B&%gYes&No%w",
"Möchten Sie einen geheimnisvollen&Gegenstand für 60 Rubine?\x1B&%gJa&Nein%w",
"J'ai essayé d'être un vendeur de&%rharicots magiques%w, mais j'étais&mauvais au niveau du marketing et&ça "
"me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter un&"
"%gobjet mystérieux%w pour 60 Rubis?\x1B&%gOui&Non%w",
});
}
void CreateRupeeMessages() {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID);
const std::vector<u8> rupees = { TEXT_BLUE_RUPEE, TEXT_RED_RUPEE, TEXT_PURPLE_RUPEE, TEXT_HUGE_RUPEE };
std::string rupeeText = " ";
for (u8 rupee : rupees) {
switch (rupee) {
case TEXT_BLUE_RUPEE:
rupeeText = "\x05\x03 5 #RUPEE#\x05\x00";
break;
case TEXT_RED_RUPEE:
rupeeText = "\x05\x01 20 #RUPEE#\x05\x00";
break;
case TEXT_PURPLE_RUPEE:
rupeeText = "\x05\x05 50 #RUPEE#\x05\x00";
break;
case TEXT_HUGE_RUPEE:
rupeeText = "\x05\x06 200 #RUPEE#\x05\x00";
break;
}
customMessageManager->CreateMessage(Randomizer::rupeeMessageTableID, rupee,
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
"You found" + rupeeText + " !",
"Du hast" + rupeeText + " gefunden!",
"Vous obtenez" + rupeeText + " !"
});
}
}
std::string Randomizer::RandomizeRupeeName(std::string message, int language) {
int randomIndex;
std::string replaceWith;
switch (language) {
case LANGUAGE_ENG:
randomIndex = rand() % (sizeof(englishRupeeNames) / sizeof(englishRupeeNames[0]));
replaceWith = englishRupeeNames[randomIndex];
break;
case LANGUAGE_GER:
randomIndex = rand() % (sizeof(germanRupeeNames) / sizeof(germanRupeeNames[0]));
replaceWith = germanRupeeNames[randomIndex];
break;
case LANGUAGE_FRA:
randomIndex = rand() % (sizeof(frenchRupeeNames) / sizeof(frenchRupeeNames[0]));
replaceWith = frenchRupeeNames[randomIndex];
break;
}
std::string replaceString = "#RUPEE#";
size_t pos = message.find(replaceString);
size_t len = replaceString.length();
message.replace(pos, len, replaceWith);
CustomMessageManager::Instance->FormatCustomMessage(message);
return message;
}
CustomMessageEntry Randomizer::GetRupeeMessage(u16 rupeeTextId) {
CustomMessageEntry messageEntry =
CustomMessageManager::Instance->RetrieveMessage(Randomizer::rupeeMessageTableID, rupeeTextId);
messageEntry.english = Randomizer::RandomizeRupeeName(messageEntry.english, LANGUAGE_ENG);
messageEntry.german = Randomizer::RandomizeRupeeName(messageEntry.german, LANGUAGE_GER);
messageEntry.french = Randomizer::RandomizeRupeeName(messageEntry.french, LANGUAGE_FRA);
return messageEntry;
}
CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = {
{ "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!",
"%cFehlt dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!",
"%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" },
{ "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!",
"%cManchmal kannst du den %rStahlhammer&%cstatt Bomben verwenden!",
"%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" },
{ "%cThere are three %gbusiness scrubs %cin &Hyrule who sell %wmysterious items%c. Do&you know where they are?",
"%cEs gibt drei %gDeku-Händler %cin Hyrule&die mysteriöse Gegenstände&verkaufen. Weißt du wo Sie sind?",
"%cIl y a trois %gPestes Marchandes%c en&Hyrule qui vendent des %wobjets&mystérieux%c. Tu sais où elles sont?" },
{ "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...",
"%cHängst du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...",
"%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." },
{ "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?",
"%cWusstest du, dass du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?",
"%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables mouvants%c?" },
{ "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!",
"%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem du von&der Baustelle aus mit einem %rHuhn&%cspringst!",
"%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec une&%rcocotte%c!" },
{ "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?",
"%cDie %yGeister-Prüfung %cin %pGanons&Schloss %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?",
"%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu le savais&déjà?" },
{ "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is junk!",
"%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört dass sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!",
"%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont intéréssant?" },
{ "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!",
"%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen dass&man damit %rKrabbelminen %cdetonieren&kann!",
"%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" },
{ "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your safety!",
"%cVielleicht verbleibt dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. Dies&ist zu deiner Sicherheit!",
"%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. C'est pour ta&propre sécurité!" },
{ "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with %warrows%c!",
"%cNur weil du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&du sie immernoch mit %rFeuer %coder&%wPfeilen %cdetonieren!",
"%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du %rFeu %cou avec des %wflèches%c!" },
{ "%cEven an adult can't push large&blocks without some %wextra&strength%c!",
"%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!",
"%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" },
{ "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?",
"%cIch habe gehört dass der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?",
"%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as essayé?" },
{ "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!",
"%cFehlt dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuch&Sie mit einem %wKrug %cabzuwerfen!",
"%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une %wjarre&%cà la figure?" },
{ "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!",
"%cIch habe gehört dass die Stelle&%wfeuchten Bodens %cim %bZora-Fluss %cals&einzige keine %rSkulltula %cbeherbergt.",
"%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne contienne pas&d'%raraignée%c." },
};
void CreateNaviRandoMessages() {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::NaviRandoMessageTableID);
for (u8 i = 0; i <= (NUM_NAVI_MESSAGES - 1); i++) {
customMessageManager->CreateMessage(Randomizer::NaviRandoMessageTableID, i,
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, NaviMessages[i].english,
NaviMessages[i].german, NaviMessages[i].french });
}
} }
void Randomizer::CreateCustomMessages() { void Randomizer::CreateCustomMessages() {
@ -4458,75 +4652,124 @@ void Randomizer::CreateCustomMessages() {
const std::vector<GetItemMessage> getItemMessages = { const std::vector<GetItemMessage> getItemMessages = {
GIMESSAGE(RG_ICE_TRAP, ITEM_NONE, "\x08\x06\x30You are a %bFOWL%w!\x0E\x20", GIMESSAGE(RG_ICE_TRAP, ITEM_NONE, "\x08\x06\x30You are a %bFOWL%w!\x0E\x20",
"\x08\x06\x15 Du bist ein %bDUMMKOPF%w!\x0E\x20", "\x08\x06\x50%bIDIOT%w\x0E\x20"), "\x08\x06\x15 Du bist ein %bDUMMKOPF%w!\x0E\x20", "\x08\x06\x50%bIDIOT%w\x0E\x20"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, GIMESSAGE_NO_GERMAN(
"You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!",
"Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"), "Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE, GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE,
"You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!", "You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!",
"Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"), "Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE,
"You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", "You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre %rénergie vitale%w&ainsi que votre %gmagie%w!"), "Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre "
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FISH, ITEM_FISH, "%rénergie vitale%w&ainsi que votre %gmagie%w!"),
"You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", GIMESSAGE_NO_GERMAN(
"Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu %wen&serait friand!"), RG_BOTTLE_WITH_FISH, ITEM_FISH,
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_BUGS, ITEM_BUG, "You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!",
"You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!", "Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu "
"Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"), "%wen&serait friand!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY, GIMESSAGE_NO_GERMAN(
"You got a %rFairy in a Bottle%w!&Use it wisely!", RG_BOTTLE_WITH_BUGS, ITEM_BUG, "You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!",
"Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"), "Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY, "You got a %rFairy in a Bottle%w!&Use it wisely!",
"You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!", "Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"),
"Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"), GIMESSAGE_NO_GERMAN(
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED,
"You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!", "You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!",
"Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"), "Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTLE_WITH_POE, ITEM_POE, GIMESSAGE_NO_GERMAN(
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...", RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN,
"Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "), "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!",
"Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"),
GIMESSAGE_NO_GERMAN(
RG_BOTTLE_WITH_POE, ITEM_POE,
"You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...",
"Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "),
GIMESSAGE_NO_GERMAN(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"), GIMESSAGE_NO_GERMAN(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!",
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"), "Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"), GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!",
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"), "Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"), GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!",
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"), "Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %Puits%w!"), GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!",
GIMESSAGE_NO_GERMAN(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training &Grounds %wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"), "Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!", "Vous obtenez une %rPetite Clé %w&du %Château de Ganon%w!"), GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pBottom of the &Well %wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %Puits%w!"),
GIMESSAGE_NO_GERMAN(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yGerudo Training &Grounds %wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!",
"Vous obtenez une %rPetite Clé %w&du %Château de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"), GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!",
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"), "Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"), GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!",
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"), "Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"), GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!",
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!", "Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"), "Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!",
"Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!", "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w!"), GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!",
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!", "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w!"), "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!", "Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w!"), GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!",
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w!"), "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%rTemple du Feu%w!"), GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!",
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w!"), "Vous obtenez la %rCarte %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w!"), GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!",
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!", "Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w!"), "Vous obtenez la %rCarte %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!", "Vous obtenez la %rCarte %wdu &%pPuits%w!"), GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!",
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!", "Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w!"), "Vous obtenez la %rCarte %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!",
"Vous obtenez la %rCarte %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!",
"Vous obtenez la %rCarte %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!",
"Vous obtenez la %rCarte %wde &la %cCaverne Polaire%w!"),
GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!", "Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"), GIMESSAGE_NO_GERMAN(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!",
GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!", "Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"), "Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"),
GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!", "Vous obtenez la %rBoussole %wdu &%bVentre de Jabu-Jabu%w!"), GIMESSAGE_NO_GERMAN(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!",
GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%gTemple de la Forêt%w!"), "Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"),
GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%rTemple du Feu%w!"), GIMESSAGE_NO_GERMAN(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!",
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%bTemple de l'Eau%w!"), "Vous obtenez la %rBoussole %wdu &%bVentre de Jabu-Jabu%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%yTemple de l'Esprit%w!"), GIMESSAGE_NO_GERMAN(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!",
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!", "Vous obtenez la %rBoussole %wdu &%pTemple de l'Ombre%w!"), "Vous obtenez la %rBoussole %wdu &%gTemple de la Forêt%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the &Well %wCompass!", "Vous obtenez la %rBoussole %wdu &%pPuits%w!"), GIMESSAGE_NO_GERMAN(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!",
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!", "Vous obtenez la %rBoussole %wde &la %cCaverne Polaire%w!"), "Vous obtenez la %rBoussole %wdu &%rTemple du Feu%w!"),
GIMESSAGE_NO_GERMAN(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%bTemple de l'Eau%w!"),
GIMESSAGE_NO_GERMAN(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%yTemple de l'Esprit%w!"),
GIMESSAGE_NO_GERMAN(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!",
"Vous obtenez la %rBoussole %wdu &%pTemple de l'Ombre%w!"),
GIMESSAGE_NO_GERMAN(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS,
"You found the %pBottom of the &Well %wCompass!",
"Vous obtenez la %rBoussole %wdu &%pPuits%w!"),
GIMESSAGE_NO_GERMAN(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!",
"Vous obtenez la %rBoussole %wde &la %cCaverne Polaire%w!"),
GIMESSAGE(RG_MAGIC_BEAN_PACK, ITEM_BEAN,
"You got a %rPack of Magic Beans%w!&Find a suitable spot for a garden&and plant them. Then, wait for&something fun to happen!",
"Du hast eine %rPackung&Magic Beans%w! Finde&einen geeigneten Platz fur einen&Garten und pflanze sie. Dann^warte auf etwas Lustiges passiert!",
"Vous avez un %rPack de&haricots magiques%w ! Trouvez&un endroit convenable pour un&jardin et plantez-les.^Ensuite, attendez quelque&chose d'amusant doit arriver !")
}; };
CreateGetItemMessages(getItemMessages); CreateGetItemMessages(getItemMessages);
CreateScrubMessages(); CreateMerchantMessages();
CreateRupeeMessages();
CreateNaviRandoMessages();
} }
class ExtendedVanillaTableInvalidItemIdException: public std::exception { class ExtendedVanillaTableInvalidItemIdException: public std::exception {
@ -4621,12 +4864,21 @@ void InitRandoItemTable() {
GET_ITEM(RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_SHADOW_TEMPLE_COMPASS), GET_ITEM(RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_SHADOW_TEMPLE_COMPASS),
GET_ITEM(RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_BOTTOM_OF_THE_WELL_COMPASS), GET_ITEM(RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_BOTTOM_OF_THE_WELL_COMPASS),
GET_ITEM(RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_ICE_CAVERN_COMPASS), GET_ITEM(RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_ICE_CAVERN_COMPASS),
GET_ITEM(RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, MOD_RANDOMIZER, RG_MAGIC_BEAN_PACK)
}; };
ItemTableManager::Instance->AddItemTable(MOD_RANDOMIZER); ItemTableManager::Instance->AddItemTable(MOD_RANDOMIZER);
for (int i = 0; i < ARRAY_COUNT(extendedVanillaGetItemTable); i++) { for (int i = 0; i < ARRAY_COUNT(extendedVanillaGetItemTable); i++) {
ItemTableManager::Instance->AddItemEntry(MOD_RANDOMIZER, extendedVanillaGetItemTable[i].getItemId, extendedVanillaGetItemTable[i]); ItemTableManager::Instance->AddItemEntry(MOD_RANDOMIZER, extendedVanillaGetItemTable[i].getItemId, extendedVanillaGetItemTable[i]);
} }
for (int i = 0; i < ARRAY_COUNT(randoGetItemTable); i++) { for (int i = 0; i < ARRAY_COUNT(randoGetItemTable); i++) {
if (randoGetItemTable[i].itemId >= RG_FOREST_TEMPLE_SMALL_KEY && randoGetItemTable[i].itemId <= RG_GANONS_CASTLE_SMALL_KEY
&& randoGetItemTable[i].itemId != RG_GERUDO_FORTRESS_SMALL_KEY) {
randoGetItemTable[i].drawFunc = (CustomDrawFunc)Randomizer_DrawSmallKey;
} else if (randoGetItemTable[i].itemId >= RG_FOREST_TEMPLE_BOSS_KEY && randoGetItemTable[i].itemId <= RG_GANONS_CASTLE_BOSS_KEY) {
randoGetItemTable[i].drawFunc = (CustomDrawFunc)Randomizer_DrawBossKey;
} else if (randoGetItemTable[i].itemId == RG_DOUBLE_DEFENSE) {
randoGetItemTable[i].drawFunc = (CustomDrawFunc)Randomizer_DrawDoubleDefense;
}
ItemTableManager::Instance->AddItemEntry(MOD_RANDOMIZER, randoGetItemTable[i].itemId, randoGetItemTable[i]); ItemTableManager::Instance->AddItemEntry(MOD_RANDOMIZER, randoGetItemTable[i].itemId, randoGetItemTable[i]);
} }
} }

View File

@ -6,6 +6,9 @@
#include "../../../include/z64item.h" #include "../../../include/z64item.h"
#include <memory> #include <memory>
#include <soh/Enhancements/randomizer/randomizerTypes.h> #include <soh/Enhancements/randomizer/randomizerTypes.h>
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
#define NUM_NAVI_MESSAGES 15
class Randomizer { class Randomizer {
private: private:
@ -16,7 +19,7 @@ class Randomizer {
std::string ganonHintText; std::string ganonHintText;
std::string ganonText; std::string ganonText;
std::unordered_map<RandomizerSettingKey, u8> randoSettings; std::unordered_map<RandomizerSettingKey, u8> randoSettings;
std::unordered_map<RandomizerCheck, u16> scrubPrices; std::unordered_map<RandomizerCheck, u16> randomizerMerchantPrices;
s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId); s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId);
s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId); s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId);
void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseRandomizerSettingsFile(const char* spoilerFileName);
@ -32,7 +35,9 @@ class Randomizer {
static const std::string getItemMessageTableID; static const std::string getItemMessageTableID;
static const std::string hintMessageTableID; static const std::string hintMessageTableID;
static const std::string shopMessageTableID; static const std::string shopMessageTableID;
static const std::string scrubMessageTableID; static const std::string merchantMessageTableID;
static const std::string rupeeMessageTableID;
static const std::string NaviRandoMessageTableID;
static Sprite* GetSeedTexture(uint8_t index); static Sprite* GetSeedTexture(uint8_t index);
s16 GetItemModelFromId(s16 itemId); s16 GetItemModelFromId(s16 itemId);
@ -53,6 +58,8 @@ class Randomizer {
s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
static void CreateCustomMessages(); static void CreateCustomMessages();
static std::string RandomizeRupeeName(std::string message, int language);
static CustomMessageEntry GetRupeeMessage(u16 rupeeTextId);
bool CheckContainsVanillaItem(RandomizerCheck randoCheck); bool CheckContainsVanillaItem(RandomizerCheck randoCheck);
}; };

View File

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "z64item.h" #include "z64item.h"
#include "randomizer_inf.h"
// This should probably go in a less rando-specific location // This should probably go in a less rando-specific location
// but the best location will probably be in the modding engine // but the best location will probably be in the modding engine
@ -1016,11 +1017,12 @@ typedef enum {
RSK_COMPLETE_MASK_QUEST, RSK_COMPLETE_MASK_QUEST,
RSK_ENABLE_GLITCH_CUTSCENES, RSK_ENABLE_GLITCH_CUTSCENES,
RSK_SKULLS_SUNS_SONG, RSK_SKULLS_SUNS_SONG,
RSK_SHUFFLE_ADULT_TRADE RSK_SHUFFLE_ADULT_TRADE,
RSK_SHUFFLE_MAGIC_BEANS
} RandomizerSettingKey; } RandomizerSettingKey;
typedef struct ScrubIdentity { typedef struct ScrubIdentity {
int32_t scrubId; RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck; RandomizerCheck randomizerCheck;
GetItemID getItemId; GetItemID getItemId;
int32_t itemPrice; int32_t itemPrice;

View File

@ -0,0 +1,72 @@
#pragma once
typedef enum {
RAND_INF_DUNGEONS_DONE_DEKU_TREE,
RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN,
RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY,
RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE,
RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE,
RAND_INF_DUNGEONS_DONE_WATER_TEMPLE,
RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE,
RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE,
RAND_INF_TRIALS_DONE_LIGHT_TRIAL,
RAND_INF_TRIALS_DONE_FOREST_TRIAL,
RAND_INF_TRIALS_DONE_FIRE_TRIAL,
RAND_INF_TRIALS_DONE_WATER_TRIAL,
RAND_INF_TRIALS_DONE_SPIRIT_TRIAL,
RAND_INF_TRIALS_DONE_SHADOW_TRIAL,
RAND_INF_COWS_MILKED_LINKS_HOUSE_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW,
RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW,
RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW,
RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW,
RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW,
RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW,
RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW,
RAND_INF_COWS_MILKED_GV_COW,
RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT,
RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO,
RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB,
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,
} RandomizerInf;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,26 @@
#pragma once #pragma once
#include <string>
#include <vector>
void InitItemTracker(); void InitItemTracker();
void DrawItemTracker(bool& open); void DrawItemTracker(bool& open);
void DrawItemAmmo(int itemId); void DrawItemAmmo(int itemId);
typedef struct ItemTrackerItem {
uint32_t id;
std::string name;
std::string nameFaded;
uint32_t data;
void (*drawFunc)(ItemTrackerItem);
} ItemTrackerItem;
#define ITEM_TRACKER_ITEM(id, data, drawFunc) \
{ \
id, #id, #id "_Faded", data, drawFunc \
}
typedef struct ItemTrackerDungeon {
uint32_t id;
std::vector<uint32_t> items;
} ItemTrackerDungeon;

View File

@ -3,8 +3,8 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
#include <locale> #include <fstream>
#include "GlobalCtx2.h"
#include "ResourceMgr.h" #include "ResourceMgr.h"
#include "DisplayList.h" #include "DisplayList.h"
#include "PlayerAnimation.h" #include "PlayerAnimation.h"
@ -33,6 +33,7 @@
#include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h"
#include "Enhancements/debugconsole.h" #include "Enhancements/debugconsole.h"
#include "Enhancements/debugger/debugger.h" #include "Enhancements/debugger/debugger.h"
#include <soh/Enhancements/randomizer/randomizer.h>
#include <soh/Enhancements/randomizer/randomizer_item_tracker.h> #include <soh/Enhancements/randomizer/randomizer_item_tracker.h>
#include "Enhancements/n64_weird_frame_data.inc" #include "Enhancements/n64_weird_frame_data.inc"
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
@ -42,6 +43,9 @@
#include "Hooks.h" #include "Hooks.h"
#include <soh/Enhancements/custom-message/CustomMessageManager.h> #include <soh/Enhancements/custom-message/CustomMessageManager.h>
#include "Lib/Fast3D/gfx_pc.h"
#include "Lib/Fast3D/gfx_rendering_api.h"
#ifdef __APPLE__ #ifdef __APPLE__
#include <SDL_scancode.h> #include <SDL_scancode.h>
#else #else
@ -65,10 +69,9 @@ CustomMessageManager* CustomMessageManager::Instance;
ItemTableManager* ItemTableManager::Instance; ItemTableManager* ItemTableManager::Instance;
OTRGlobals::OTRGlobals() { OTRGlobals::OTRGlobals() {
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian"); context = Ship::Window::CreateInstance("Ship of Harkinian");
gSaveStateMgr = std::make_shared<SaveStateMgr>(); gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandomizer = std::make_shared<Randomizer>(); gRandomizer = std::make_shared<Randomizer>();
context->GetWindow()->Init();
} }
OTRGlobals::~OTRGlobals() { OTRGlobals::~OTRGlobals() {
@ -380,14 +383,14 @@ extern "C" uint64_t GetPerfCounter() {
// C->C++ Bridge // C->C++ Bridge
extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) { extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) {
OTRGlobals::Instance->context->GetWindow()->MainLoop(run_one_game_iter); OTRGlobals::Instance->context->MainLoop(run_one_game_iter);
} }
extern "C" void Graph_StartFrame() { extern "C" void Graph_StartFrame() {
#ifndef __WIIU__ #ifndef __WIIU__
// Why -1? // Why -1?
int32_t dwScancode = OTRGlobals::Instance->context->GetWindow()->GetLastScancode(); int32_t dwScancode = OTRGlobals::Instance->context->GetLastScancode();
OTRGlobals::Instance->context->GetWindow()->SetLastScancode(-1); OTRGlobals::Instance->context->SetLastScancode(-1);
switch (dwScancode - 1) { switch (dwScancode - 1) {
case SDL_SCANCODE_F5: { case SDL_SCANCODE_F5: {
@ -443,7 +446,14 @@ extern "C" void Graph_StartFrame() {
} }
} }
#endif #endif
OTRGlobals::Instance->context->GetWindow()->StartFrame(); OTRGlobals::Instance->context->StartFrame();
}
void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements) {
for (const auto& m : mtx_replacements) {
gfx_run(Commands, m);
gfx_end_frame();
}
} }
// C->C++ Bridge // C->C++ Bridge
@ -484,12 +494,12 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
time -= fps; time -= fps;
OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps); OTRGlobals::Instance->context->SetTargetFps(fps);
int threshold = CVar_GetS32("gExtraLatencyThreshold", 80); int threshold = CVar_GetS32("gExtraLatencyThreshold", 80);
OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1); OTRGlobals::Instance->context->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1);
OTRGlobals::Instance->context->GetWindow()->RunCommands(commands, mtx_replacements); RunCommands(commands, mtx_replacements);
last_fps = fps; last_fps = fps;
last_update_rate = R_UPDATE_RATE; last_update_rate = R_UPDATE_RATE;
@ -502,19 +512,19 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
} }
// OTRTODO: FIGURE OUT END FRAME POINT // OTRTODO: FIGURE OUT END FRAME POINT
/* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1) /* if (OTRGlobals::Instance->context->lastScancode != -1)
OTRGlobals::Instance->context->GetWindow()->lastScancode = -1;*/ OTRGlobals::Instance->context->lastScancode = -1;*/
} }
float divisor_num = 0.0f; float divisor_num = 0.0f;
extern "C" void OTRGetPixelDepthPrepare(float x, float y) { extern "C" void OTRGetPixelDepthPrepare(float x, float y) {
OTRGlobals::Instance->context->GetWindow()->GetPixelDepthPrepare(x, y); OTRGlobals::Instance->context->GetPixelDepthPrepare(x, y);
} }
extern "C" uint16_t OTRGetPixelDepth(float x, float y) { extern "C" uint16_t OTRGetPixelDepth(float x, float y) {
return OTRGlobals::Instance->context->GetWindow()->GetPixelDepth(x, y); return OTRGlobals::Instance->context->GetPixelDepth(x, y);
} }
extern "C" uint32_t ResourceMgr_GetGameVersion() extern "C" uint32_t ResourceMgr_GetGameVersion()
@ -1326,7 +1336,7 @@ extern "C" s32* ResourceMgr_LoadCSByName(const char* path)
} }
std::filesystem::path GetSaveFile(std::shared_ptr<Mercury> Conf) { std::filesystem::path GetSaveFile(std::shared_ptr<Mercury> Conf) {
const std::string fileName = Conf->getString("Game.SaveName", Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.sav")); const std::string fileName = Conf->getString("Game.SaveName", Ship::Window::GetPathRelativeToAppDirectory("oot_save.sav"));
std::filesystem::path saveFile = std::filesystem::absolute(fileName); std::filesystem::path saveFile = std::filesystem::absolute(fileName);
if (!exists(saveFile.parent_path())) { if (!exists(saveFile.parent_path())) {
@ -1457,15 +1467,15 @@ extern "C" void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(vo
} }
extern "C" uint32_t OTRGetCurrentWidth() { extern "C" uint32_t OTRGetCurrentWidth() {
return OTRGlobals::Instance->context->GetWindow()->GetCurrentWidth(); return OTRGlobals::Instance->context->GetCurrentWidth();
} }
extern "C" uint32_t OTRGetCurrentHeight() { extern "C" uint32_t OTRGetCurrentHeight() {
return OTRGlobals::Instance->context->GetWindow()->GetCurrentHeight(); return OTRGlobals::Instance->context->GetCurrentHeight();
} }
extern "C" void OTRControllerCallback(ControllerCallback* controller) { extern "C" void OTRControllerCallback(ControllerCallback* controller) {
auto controlDeck = Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) { for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) {
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i); auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i);
@ -1497,33 +1507,33 @@ extern "C" int16_t OTRGetRectDimensionFromRightEdge(float v) {
} }
extern "C" bool AudioPlayer_Init(void) { extern "C" bool AudioPlayer_Init(void) {
if (OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer() != nullptr) { if (OTRGlobals::Instance->context->GetAudioPlayer() != nullptr) {
return OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer()->Init(); return OTRGlobals::Instance->context->GetAudioPlayer()->Init();
} }
return false; return false;
} }
extern "C" int AudioPlayer_Buffered(void) { extern "C" int AudioPlayer_Buffered(void) {
if (OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer() != nullptr) { if (OTRGlobals::Instance->context->GetAudioPlayer() != nullptr) {
return OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer()->Buffered(); return OTRGlobals::Instance->context->GetAudioPlayer()->Buffered();
} }
} }
extern "C" int AudioPlayer_GetDesiredBuffered(void) { extern "C" int AudioPlayer_GetDesiredBuffered(void) {
if (OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer() != nullptr) { if (OTRGlobals::Instance->context->GetAudioPlayer() != nullptr) {
return OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer()->GetDesiredBuffered(); return OTRGlobals::Instance->context->GetAudioPlayer()->GetDesiredBuffered();
} }
} }
extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) { extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) {
if (OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer() != nullptr) { if (OTRGlobals::Instance->context->GetAudioPlayer() != nullptr) {
OTRGlobals::Instance->context->GetWindow()->GetAudioPlayer()->Play(buf, len); OTRGlobals::Instance->context->GetAudioPlayer()->Play(buf, len);
} }
} }
extern "C" int Controller_ShouldRumble(size_t i) { extern "C" int Controller_ShouldRumble(size_t i) {
auto controlDeck = Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) { for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) {
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i); auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i);
@ -1581,7 +1591,12 @@ extern "C" ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, s32 actorP
} }
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(s16 itemPrice) { extern "C" CustomMessageEntry Randomizer_GetScrubMessage(s16 itemPrice) {
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, itemPrice); return CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, itemPrice);
}
extern "C" CustomMessageEntry Randomizer_GetNaviMessage() {
u16 naviTextId = rand() % NUM_NAVI_MESSAGES;
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId);
} }
extern "C" CustomMessageEntry Randomizer_GetShopMessage(s16 shopItemId) { extern "C" CustomMessageEntry Randomizer_GetShopMessage(s16 shopItemId) {
@ -1610,7 +1625,7 @@ extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(RandomizerCheck check)
} }
extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) { extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) {
GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID); GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(OTRGlobals::Instance->getItemModIndex, getItemID);
return giEntry; return giEntry;
} }
@ -1641,12 +1656,12 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi
return ItemTable_RetrieveEntry(getItemModIndex, itemID); return ItemTable_RetrieveEntry(getItemModIndex, itemID);
} }
extern "C" u32 Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) { extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) {
return gSaveContext.n64ddFlag && (actor->parent != NULL) && return gSaveContext.n64ddFlag && (actor->parent != NULL) &&
Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP;
} }
extern "C" u32 Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) { extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) {
return gSaveContext.n64ddFlag && Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; return gSaveContext.n64ddFlag && Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP;
} }
@ -1713,6 +1728,15 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
messageEntry = Randomizer_GetScrubMessage((textId & ((1 << 8) - 1))); messageEntry = Randomizer_GetScrubMessage((textId & ((1 << 8) - 1)));
} else if (textId >= 0x9100 && textId <= 0x9160) { } else if (textId >= 0x9100 && textId <= 0x9160) {
messageEntry = Randomizer_GetShopMessage((textId & ((1 << 8) - 1))); messageEntry = Randomizer_GetShopMessage((textId & ((1 << 8) - 1)));
} else if (CVar_GetS32("gRandomizeRupeeNames", 0) &&
(textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE ||
textId == TEXT_HUGE_RUPEE)) {
messageEntry = Randomizer::GetRupeeMessage(textId);
// In rando, replace Navi's general overworld hints with rando-related gameplay tips
} else if (CVar_GetS32("gRandoRelevantNavi", 1) && textId >= 0x0140 && textId <= 0x015F) {
messageEntry = Randomizer_GetNaviMessage();
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN);
} }
} }
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
@ -1742,7 +1766,6 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
case LANGUAGE_GER: case LANGUAGE_GER:
return msgCtx->msgLength = font->msgLength = return msgCtx->msgLength = font->msgLength =
CopyStringToCharBuffer(messageEntry.german, buffer, maxBufferSize); CopyStringToCharBuffer(messageEntry.german, buffer, maxBufferSize);
case LANGUAGE_ENG: case LANGUAGE_ENG:
default: default:
return msgCtx->msgLength = font->msgLength = return msgCtx->msgLength = font->msgLength =

View File

@ -3,11 +3,11 @@
#pragma once #pragma once
#include "GlobalCtx2.h"
#include "SaveManager.h" #include "SaveManager.h"
#include <soh/Enhancements/item-tables/ItemTableTypes.h> #include <soh/Enhancements/item-tables/ItemTableTypes.h>
#ifdef __cplusplus #ifdef __cplusplus
#include "Window.h"
#include "Enhancements/savestates.h" #include "Enhancements/savestates.h"
#include "Enhancements/randomizer/randomizer.h" #include "Enhancements/randomizer/randomizer.h"
@ -18,7 +18,7 @@ class OTRGlobals
public: public:
static OTRGlobals* Instance; static OTRGlobals* Instance;
std::shared_ptr<Ship::GlobalCtx2> context; std::shared_ptr<Ship::Window> context;
std::shared_ptr<SaveStateMgr> gSaveStateMgr; std::shared_ptr<SaveStateMgr> gSaveStateMgr;
std::shared_ptr<Randomizer> gRandomizer; std::shared_ptr<Randomizer> gRandomizer;
uint16_t getItemModIndex; uint16_t getItemModIndex;

View File

@ -16,7 +16,7 @@
extern "C" SaveContext gSaveContext; extern "C" SaveContext gSaveContext;
std::filesystem::path SaveManager::GetFileName(int fileNum) { std::filesystem::path SaveManager::GetFileName(int fileNum) {
const std::filesystem::path sSavePath(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Save")); const std::filesystem::path sSavePath(Ship::Window::GetPathRelativeToAppDirectory("Save"));
return sSavePath / ("file" + std::to_string(fileNum + 1) + ".sav"); return sSavePath / ("file" + std::to_string(fileNum + 1) + ".sav");
} }
@ -137,10 +137,10 @@ void SaveManager::SaveRandomizer() {
} }
void SaveManager::Init() { void SaveManager::Init() {
const std::filesystem::path sSavePath(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Save")); const std::filesystem::path sSavePath(Ship::Window::GetPathRelativeToAppDirectory("Save"));
const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav"); const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav");
auto sOldSavePath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.sav"); auto sOldSavePath = Ship::Window::GetPathRelativeToAppDirectory("oot_save.sav");
auto sOldBackupSavePath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.bak"); auto sOldBackupSavePath = Ship::Window::GetPathRelativeToAppDirectory("oot_save.bak");
// If the save directory does not exist, create it // If the save directory does not exist, create it
if (!std::filesystem::exists(sSavePath)) { if (!std::filesystem::exists(sSavePath)) {
@ -758,19 +758,8 @@ void SaveManager::LoadBaseVersion1() {
SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle); SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle);
}); });
SaveManager::Instance->LoadArray("dungeonsDone", ARRAY_COUNT(gSaveContext.dungeonsDone), [](size_t i) { SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.dungeonsDone[i]); SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]);
});
SaveManager::Instance->LoadArray("trialsDone", ARRAY_COUNT(gSaveContext.trialsDone),
[](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.trialsDone[i]); });
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
});
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
}); });
SaveManager::Instance->LoadArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) { SaveManager::Instance->LoadArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) {
@ -930,19 +919,8 @@ void SaveManager::LoadBaseVersion2() {
SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle); SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle);
}); });
SaveManager::Instance->LoadArray("dungeonsDone", ARRAY_COUNT(gSaveContext.dungeonsDone), [](size_t i) { SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.dungeonsDone[i]); SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]);
});
SaveManager::Instance->LoadArray("trialsDone", ARRAY_COUNT(gSaveContext.trialsDone),
[](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.trialsDone[i]); });
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
});
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
}); });
SaveManager::Instance->LoadArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) { SaveManager::Instance->LoadArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) {
@ -1098,19 +1076,8 @@ void SaveManager::SaveBase() {
SaveManager::Instance->SaveData("angle", gSaveContext.horseData.angle); SaveManager::Instance->SaveData("angle", gSaveContext.horseData.angle);
}); });
SaveManager::Instance->SaveArray("dungeonsDone", ARRAY_COUNT(gSaveContext.dungeonsDone), [](size_t i) { SaveManager::Instance->SaveArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.dungeonsDone[i]); SaveManager::Instance->SaveData("", gSaveContext.randomizerInf[i]);
});
SaveManager::Instance->SaveArray("trialsDone", ARRAY_COUNT(gSaveContext.trialsDone),
[](size_t i) { SaveManager::Instance->SaveData("", gSaveContext.trialsDone[i]); });
SaveManager::Instance->SaveArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.cowsMilked[i]);
});
SaveManager::Instance->SaveArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.scrubsPurchased[i]);
}); });
SaveManager::Instance->SaveArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) { SaveManager::Instance->SaveArray("shopItemsPurchased", ARRAY_COUNT(gSaveContext.shopItemsPurchased), [](size_t i) {

View File

@ -69,7 +69,7 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) {
gSaveContext.worldMapArea = 0; gSaveContext.worldMapArea = 0;
OTRScene_ExecuteCommands(globalCtx, globalCtx->sceneSegment); OTRScene_ExecuteCommands(globalCtx, globalCtx->sceneSegment);
Gameplay_InitEnvironment(globalCtx, globalCtx->skyboxId); Gameplay_InitEnvironment(globalCtx, globalCtx->skyboxId);
/* auto data = static_cast<Ship::Vertex*>(Ship::GlobalCtx2::GetInstance() /* auto data = static_cast<Ship::Vertex*>(Ship::Window::GetInstance()
->GetResourceManager() ->GetResourceManager()
->LoadResource("object_link_child\\object_link_childVtx_01FE08") ->LoadResource("object_link_child\\object_link_childVtx_01FE08")
.get()); .get());

View File

@ -1009,20 +1009,15 @@ void TitleCard_InitPlaceName(GlobalContext* globalCtx, TitleCardContext* titleCt
} }
void TitleCard_Update(GlobalContext* globalCtx, TitleCardContext* titleCtx) { void TitleCard_Update(GlobalContext* globalCtx, TitleCardContext* titleCtx) {
s16* TitleCard_Colors[3] = {255,255,255}; const Color_RGB8 TitleCard_Colors_ori = {255,255,255};
if (titleCtx->isBossCard && CVar_GetS32("gHudColors", 1) == 2) {//Bosses cards. Color_RGB8 TitleCard_Colors = {255,255,255};
TitleCard_Colors[0] = CVar_GetS32("gCCTC_B_U_PrimR", 255); if (titleCtx->isBossCard && CVar_GetS32("gHudColors", 1) == 2) {//Bosses cards.
TitleCard_Colors[1] = CVar_GetS32("gCCTC_B_U_PrimG", 255); TitleCard_Colors = CVar_GetRGB("gCCTC_B_U_Prim", TitleCard_Colors_ori);
TitleCard_Colors[2] = CVar_GetS32("gCCTC_B_U_PrimB", 255); } else if (!titleCtx->isBossCard && CVar_GetS32("gHudColors", 1) == 2) {
} else if (!titleCtx->isBossCard && CVar_GetS32("gHudColors", 1) == 2) { TitleCard_Colors = CVar_GetRGB("gCCTC_OW_U_Prim", TitleCard_Colors_ori);
TitleCard_Colors[0] = CVar_GetS32("gCCTC_OW_U_PrimR", 255); } else {
TitleCard_Colors[1] = CVar_GetS32("gCCTC_OW_U_PrimG", 255); TitleCard_Colors = TitleCard_Colors_ori;
TitleCard_Colors[2] = CVar_GetS32("gCCTC_OW_U_PrimB", 255); }
} else {
TitleCard_Colors[0] = 255;
TitleCard_Colors[1] = 255;
TitleCard_Colors[2] = 255;
}
if (DECR(titleCtx->delayTimer) == 0) { if (DECR(titleCtx->delayTimer) == 0) {
if (DECR(titleCtx->durationTimer) == 0) { if (DECR(titleCtx->durationTimer) == 0) {
@ -1032,9 +1027,9 @@ void TitleCard_Update(GlobalContext* globalCtx, TitleCardContext* titleCtx) {
Math_StepToS(&titleCtx->intensityB, 0, 70); Math_StepToS(&titleCtx->intensityB, 0, 70);
} else { } else {
Math_StepToS(&titleCtx->alpha, 255, 10); Math_StepToS(&titleCtx->alpha, 255, 10);
Math_StepToS(&titleCtx->intensityR, TitleCard_Colors[0], 20); Math_StepToS(&titleCtx->intensityR, TitleCard_Colors.r, 20);
Math_StepToS(&titleCtx->intensityG, TitleCard_Colors[1], 20); Math_StepToS(&titleCtx->intensityG, TitleCard_Colors.g, 20);
Math_StepToS(&titleCtx->intensityB, TitleCard_Colors[2], 20); Math_StepToS(&titleCtx->intensityB, TitleCard_Colors.b, 20);
} }
} }
} }
@ -1195,7 +1190,8 @@ void Actor_Init(Actor* actor, GlobalContext* globalCtx) {
actor->uncullZoneDownward = 700.0f; actor->uncullZoneDownward = 700.0f;
if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
&& (globalCtx->sceneNum != SCENE_DDAN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
actor->uncullZoneForward = 32767.0f; actor->uncullZoneForward = 32767.0f;
actor->uncullZoneScale = 32767.0f; actor->uncullZoneScale = 32767.0f;
actor->uncullZoneDownward = 32767.0f; actor->uncullZoneDownward = 32767.0f;
@ -1955,6 +1951,15 @@ u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx) {
} }
} }
/**
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
* where Link holds an item over his head. This function does not require an actor for giving
* the player an item, instead setting the player as their own interactRangeActor and getItemDirection.
*
* \param globalCtx the Global Context
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
* \return true if the player can receive an item, false if not.
*/
s32 GiveItemEntryWithoutActor(GlobalContext* globalCtx, GetItemEntry getItemEntry) { s32 GiveItemEntryWithoutActor(GlobalContext* globalCtx, GetItemEntry getItemEntry) {
Player* player = GET_PLAYER(globalCtx); Player* player = GET_PLAYER(globalCtx);
@ -1979,6 +1984,22 @@ s32 GiveItemEntryWithoutActor(GlobalContext* globalCtx, GetItemEntry getItemEntr
return false; return false;
} }
/**
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
* where Link holds an item over his head. This uses data from the actor link is receiving
* the item from to set the player's interactRangeActor and getItemDirection. It also checks
* a range from which Link must be from said actor in order to receive the item.
*
* \param actor the actor link is receiving an item from. Will usually be a chest but can also
* be an npc.
* \param globalCtx the Global Context
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
* \param xzRange the distance on the x and z axes that the player can be from the target
* actor to receive the item.
* \param yRange the distance on the y axis that the player can be from the target actor
* to receive the item.
* \return true if the player can receive an item, false if not.
*/
s32 GiveItemEntryFromActor(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry, f32 xzRange, f32 yRange) { s32 GiveItemEntryFromActor(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry, f32 xzRange, f32 yRange) {
Player* player = GET_PLAYER(globalCtx); Player* player = GET_PLAYER(globalCtx);
@ -2005,6 +2026,15 @@ s32 GiveItemEntryFromActor(Actor* actor, GlobalContext* globalCtx, GetItemEntry
return false; return false;
} }
/**
* Uses the given `GetItemEntry` to prepare the player to receive an item via the animation
* where Link holds an item over his head. This is a wrapper function around `GiveItemEntryFromActor`
* that supplies a fixed xzRange of 50.0f and a fixed yRange of 10.0f.
*
* \param actor the target actor that link is receiving an item from.
* \param globalCtx the Global Context
* \param getItemEntry the GetItemEntry for the item you want the player to receive.
*/
void GiveItemEntryFromActorWithFixedRange(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry) { void GiveItemEntryFromActorWithFixedRange(Actor* actor, GlobalContext* globalCtx, GetItemEntry getItemEntry) {
GiveItemEntryFromActor(actor, globalCtx, getItemEntry, 50.0f, 10.0f); GiveItemEntryFromActor(actor, globalCtx, getItemEntry, 50.0f, 10.0f);
} }
@ -2806,7 +2836,8 @@ s32 func_800314D4(GlobalContext* globalCtx, Actor* actor, Vec3f* arg2, f32 arg3)
if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
&& (globalCtx->sceneNum != SCENE_DDAN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
return true; return true;
} }
@ -4674,6 +4705,20 @@ void Flags_SetInfTable(s32 flag) {
gSaveContext.infTable[flag >> 4] |= (1 << (flag & 0xF)); gSaveContext.infTable[flag >> 4] |= (1 << (flag & 0xF));
} }
/**
* Tests if "randomizerInf" flag is set.
*/
s32 Flags_GetRandomizerInf(RandomizerInf flag) {
return gSaveContext.randomizerInf[flag >> 4] & (1 << (flag & 0xF));
}
/**
* Sets "randomizerInf" flag.
*/
void Flags_SetRandomizerInf(RandomizerInf flag) {
gSaveContext.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
}
u32 func_80035BFC(GlobalContext* globalCtx, s16 arg1) { u32 func_80035BFC(GlobalContext* globalCtx, s16 arg1) {
u16 retTextId = 0; u16 retTextId = 0;

View File

@ -1488,8 +1488,8 @@ s32 Camera_Free(Camera* camera) {
f32 newCamX = -D_8015BD7C->state.input[0].cur.right_stick_x * 10.0f; f32 newCamX = -D_8015BD7C->state.input[0].cur.right_stick_x * 10.0f;
f32 newCamY = D_8015BD7C->state.input[0].cur.right_stick_y * 10.0f; f32 newCamY = D_8015BD7C->state.input[0].cur.right_stick_y * 10.0f;
camera->globalCtx->camX += newCamX; camera->globalCtx->camX += newCamX * (CVar_GetS32("gInvertXAxis", 0) ? -1 : 1);
camera->globalCtx->camY += newCamY; camera->globalCtx->camY += newCamY * (CVar_GetS32("gInvertYAxis", 0) ? 1 : -1);
if (camera->globalCtx->camY > 0x32A4) { if (camera->globalCtx->camY > 0x32A4) {
camera->globalCtx->camY = 0x32A4; camera->globalCtx->camY = 0x32A4;

View File

@ -395,6 +395,20 @@ void GetItem_Draw(GlobalContext* globalCtx, s16 drawId) {
sDrawItemTable[drawId].drawFunc(globalCtx, drawId); sDrawItemTable[drawId].drawFunc(globalCtx, drawId);
} }
/**
* Draw "Get Item" Model from a `GetItemEntry`
* Uses the Custom Draw Function if it exists, or just calls `GetItem_Draw`
*/
void GetItemEntry_Draw(GlobalContext* globalCtx, GetItemEntry getItemEntry) {
// RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future.
if (getItemEntry.drawFunc != NULL &&
(CVar_GetS32("gRandoMatchKeyColors", 0) || getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) {
getItemEntry.drawFunc(globalCtx, &getItemEntry);
} else {
GetItem_Draw(globalCtx, getItemEntry.gid);
}
}
// All remaining functions in this file are draw functions referenced in the table and called by the function above // All remaining functions in this file are draw functions referenced in the table and called by the function above
/* 0x0178 */ u8 primXluColor[3]; /* 0x0178 */ u8 primXluColor[3];

View File

@ -3,6 +3,8 @@
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
const Color_RGB8 Trails_Color_ori = {255,255,255};
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2) { void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2) {
EffectBlureElement* elem; EffectBlureElement* elem;
s32 numElements; s32 numElements;
@ -198,6 +200,7 @@ s32 EffectBlure_Update(void* thisx) {
s16 GreenColor; s16 GreenColor;
s16 BlueColor; s16 BlueColor;
s16 TrailDuration; s16 TrailDuration;
Color_RGB8 Trails_col = CVar_GetRGB("gTrailCol", Trails_Color_ori);
if (this == NULL) { if (this == NULL) {
return 0; return 0;
@ -208,16 +211,17 @@ s32 EffectBlure_Update(void* thisx) {
} }
if (CVar_GetS32("gUseTrailsCol", 0) !=0) { if (CVar_GetS32("gUseTrailsCol", 0) !=0) {
RedColor = CVar_GetS32("gTrailColR",255); RedColor = Trails_col.r;
GreenColor = CVar_GetS32("gTrailColG",255); GreenColor = Trails_col.g;
BlueColor = CVar_GetS32("gTrailColB",255); BlueColor = Trails_col.b;
TrailDuration = 4.0f*CVar_GetS32("gTrailDurantion",1); TrailDuration = 4.0f * CVar_GetS32("gTrailDurantion",1);
} else { } else {
RedColor = 255; RedColor = Trails_Color_ori.r;
GreenColor = 255; GreenColor = Trails_Color_ori.g;
BlueColor = 255; BlueColor = Trails_Color_ori.b;
TrailDuration=4.0f; TrailDuration=4.0f;
} }
this->p1StartColor.r = RedColor; this->p1StartColor.r = RedColor;
this->p2StartColor.r = RedColor; this->p2StartColor.r = RedColor;
this->p1EndColor.r = RedColor; this->p1EndColor.r = RedColor;

View File

@ -70,6 +70,7 @@ static void* sItemDropTex[] = {
gDropRecoveryHeartTex, gDropBombTex, gDropArrows1Tex, gDropArrows2Tex, gDropRecoveryHeartTex, gDropBombTex, gDropArrows1Tex, gDropArrows2Tex,
gDropArrows3Tex, gDropBombTex, gDropDekuNutTex, gDropDekuStickTex, gDropArrows3Tex, gDropBombTex, gDropDekuNutTex, gDropDekuStickTex,
gDropMagicLargeTex, gDropMagicSmallTex, gDropDekuSeedsTex, gDropKeySmallTex, gDropMagicLargeTex, gDropMagicSmallTex, gDropDekuSeedsTex, gDropKeySmallTex,
// OTRTODO: use 2D bombchu texture
}; };
static u8 sItemDropIds[] = { static u8 sItemDropIds[] = {
@ -390,6 +391,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
case ITEM00_RUPEE_ORANGE: case ITEM00_RUPEE_ORANGE:
case ITEM00_RUPEE_PURPLE: case ITEM00_RUPEE_PURPLE:
case ITEM00_FLEXIBLE: case ITEM00_FLEXIBLE:
case ITEM00_BOMBCHU:
yOffset = 500.0f; yOffset = 500.0f;
Actor_SetScale(&this->actor, 0.01f); Actor_SetScale(&this->actor, 0.01f);
this->scale = 0.01f; this->scale = 0.01f;
@ -507,11 +509,16 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
case ITEM00_TUNIC_GORON: case ITEM00_TUNIC_GORON:
case ITEM00_BOMBS_SPECIAL: case ITEM00_BOMBS_SPECIAL:
break; break;
case ITEM00_BOMBCHU:
Item_Give(globalCtx, ITEM_BOMBCHUS_5);
break;
} }
if (!Actor_HasParent(&this->actor, globalCtx)) { if (!Actor_HasParent(&this->actor, globalCtx)) {
if (!gSaveContext.n64ddFlag && getItemId != GI_NONE) { if (!gSaveContext.n64ddFlag) {
func_8002F554(&this->actor, globalCtx, getItemId); if (getItemId != GI_NONE) {
func_8002F554(&this->actor, globalCtx, getItemId);
}
} else { } else {
getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem);
@ -535,7 +542,8 @@ void func_8001DFC8(EnItem00* this, GlobalContext* globalCtx) {
(this->actor.params == ITEM00_HEART_PIECE)) { (this->actor.params == ITEM00_HEART_PIECE)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else { } else {
if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL)) { if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
(this->actor.params != ITEM00_BOMBCHU)) {
if (this->unk_15A == -1) { if (this->unk_15A == -1) {
if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) == if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) ==
0) { 0) {
@ -638,7 +646,8 @@ void func_8001E304(EnItem00* this, GlobalContext* globalCtx) {
if (this->actor.params <= ITEM00_RUPEE_RED) { if (this->actor.params <= ITEM00_RUPEE_RED) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL)) { } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
(this->actor.params != ITEM00_BOMBCHU)) {
this->actor.world.rot.x -= 700; this->actor.world.rot.x -= 700;
this->actor.shape.rot.y += 400; this->actor.shape.rot.y += 400;
this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000; this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000;
@ -720,7 +729,8 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
EnItem00* this = (EnItem00*)thisx; EnItem00* this = (EnItem00*)thisx;
s32 pad; s32 pad;
if (CVar_GetS32("gNewDrops", 0)) { //set the rotation system on selected model only :) // OTRTODO: remove special case for bombchu when its 2D drop is implemented
if (CVar_GetS32("gNewDrops", 0) || this->actor.params == ITEM00_BOMBCHU) { //set the rotation system on selected model only :)
if ((this->actor.params == ITEM00_RUPEE_GREEN) || (this->actor.params == ITEM00_RUPEE_BLUE) || if ((this->actor.params == ITEM00_RUPEE_GREEN) || (this->actor.params == ITEM00_RUPEE_BLUE) ||
(this->actor.params == ITEM00_RUPEE_RED) || (this->actor.params == ITEM00_ARROWS_SINGLE) || (this->actor.params == ITEM00_RUPEE_RED) || (this->actor.params == ITEM00_ARROWS_SINGLE) ||
(this->actor.params == ITEM00_ARROWS_SMALL) || (this->actor.params == ITEM00_ARROWS_MEDIUM) || (this->actor.params == ITEM00_ARROWS_SMALL) || (this->actor.params == ITEM00_ARROWS_MEDIUM) ||
@ -728,7 +738,8 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
(this->actor.params == ITEM00_BOMBS_B) || (this->actor.params == ITEM00_NUTS) || (this->actor.params == ITEM00_BOMBS_B) || (this->actor.params == ITEM00_NUTS) ||
(this->actor.params == ITEM00_MAGIC_SMALL) || (this->actor.params == ITEM00_SEEDS) || (this->actor.params == ITEM00_MAGIC_SMALL) || (this->actor.params == ITEM00_SEEDS) ||
(this->actor.params == ITEM00_MAGIC_LARGE) || (this->actor.params == ITEM00_HEART) || (this->actor.params == ITEM00_MAGIC_LARGE) || (this->actor.params == ITEM00_HEART) ||
(this->actor.params == ITEM00_BOMBS_SPECIAL) || this->actor.params == ITEM00_HEART_PIECE) { (this->actor.params == ITEM00_BOMBS_SPECIAL) || this->actor.params == ITEM00_HEART_PIECE ||
(this->actor.params == ITEM00_BOMBCHU)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} }
if (this->actor.params == ITEM00_SMALL_KEY && !gSaveContext.n64ddFlag) { if (this->actor.params == ITEM00_SMALL_KEY && !gSaveContext.n64ddFlag) {
@ -889,6 +900,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
break; break;
case ITEM00_BOMBS_SPECIAL: case ITEM00_BOMBS_SPECIAL:
break; break;
case ITEM00_BOMBCHU:
Item_Give(globalCtx, ITEM_BOMBCHUS_5);
break;
} }
params = &this->actor.params; params = &this->actor.params;
@ -1210,6 +1224,15 @@ void EnItem00_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnItem00_DrawCollectible(this, globalCtx); EnItem00_DrawCollectible(this, globalCtx);
break; break;
} }
case ITEM00_BOMBCHU:
// OTRTODO: Stop forcing chu drops to be 3D when the texture is added
Actor_SetScale(&this->actor, 0.2f);
this->scale = 0.2f;
this->actor.shape.yOffset = 50.0f;
this->actor.world.rot.x = 0x4000;
this->actor.shape.shadowScale = 0.3f;
GetItem_Draw(globalCtx, GID_BOMBCHU);
break;
case ITEM00_SHIELD_DEKU: case ITEM00_SHIELD_DEKU:
GetItem_Draw(globalCtx, GID_SHIELD_DEKU); GetItem_Draw(globalCtx, GID_SHIELD_DEKU);
break; break;
@ -1267,10 +1290,11 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
switch (giEntry.itemId) { switch (giEntry.itemId) {
case RG_MAGIC_SINGLE: case RG_MAGIC_SINGLE:
case RG_MAGIC_DOUBLE: case RG_MAGIC_DOUBLE:
case RG_MAGIC_BEAN_PACK:
color_slot = 0; color_slot = 0;
break; break;
case RG_DOUBLE_DEFENSE: case RG_DOUBLE_DEFENSE:
color_slot = 1; color_slot = 8;
break; break;
default: default:
return; return;
@ -1282,14 +1306,14 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
s16* colors[9][3] = { s16* colors[9][3] = {
{ 34, 255, 76 }, // Minuet and Magic Upgrades Colors { 34, 255, 76 }, // Minuet and Magic Upgrades Colors
{ 177, 35, 35 }, // Bolero and Double Defense Colors { 177, 35, 35 }, // Bolero Colors
{ 115, 251, 253 }, // Serenade Color { 115, 251, 253 }, // Serenade Color
{ 177, 122, 35 }, // Requiem Color { 177, 122, 35 }, // Requiem Color
{ 177, 28, 212 }, // Nocturne Color { 177, 28, 212 }, // Nocturne Color
{ 255, 255, 92 }, // Prelude Color { 255, 255, 92 }, // Prelude Color
{ 31, 152, 49 }, // Stick Upgrade Color { 31, 152, 49 }, // Stick Upgrade Color
{ 222, 182, 20 }, // Nut Upgrade Color { 222, 182, 20 }, // Nut Upgrade Color
{ 255, 255, 255 } // White Color placeholder { 255, 255, 255 } // Double Defense Color
}; };
s16* colorsEnv[9][3] = { s16* colorsEnv[9][3] = {
@ -1358,7 +1382,7 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) {
GetItemEntry randoGetItemEntry = GetItemEntry randoGetItemEntry =
Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry);
GetItem_Draw(globalCtx, randoGetItemEntry.gid); GetItemEntry_Draw(globalCtx, randoGetItemEntry);
} else { } else {
s32 texIndex = this->actor.params - 3; s32 texIndex = this->actor.params - 3;
@ -1368,6 +1392,9 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) {
if (this->actor.params == ITEM00_BOMBS_SPECIAL) { if (this->actor.params == ITEM00_BOMBS_SPECIAL) {
texIndex = 1; texIndex = 1;
// OTRTODO: 2D bombchu drops
//} else if (this->actor.params == ITEM00_BOMBCHU) {
// texIndex = 12;
} else if (this->actor.params >= ITEM00_ARROWS_SMALL) { } else if (this->actor.params >= ITEM00_ARROWS_SMALL) {
texIndex -= 3; texIndex -= 3;
} }
@ -1417,7 +1444,7 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
GetItemEntry randoGetItemEntry = GetItemEntry randoGetItemEntry =
Randomizer_GetRandomizedItem(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum); Randomizer_GetRandomizedItem(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry);
GetItem_Draw(globalCtx, randoGetItemEntry.gid); GetItemEntry_Draw(globalCtx, randoGetItemEntry);
} else { } else {
s32 pad; s32 pad;
@ -1433,6 +1460,36 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
} }
} }
/**
* Sometimes convert the given drop ID into a bombchu.
* Returns the new drop type ID.
*/
s16 EnItem00_ConvertBombDropToBombchu(s16 dropId) {
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
return dropId;
}
if (INV_CONTENT(ITEM_BOMB) == ITEM_NONE) {
return ITEM00_BOMBCHU;
}
if (AMMO(ITEM_BOMB) <= 15) {
// Player needs bombs and might need chus, so drop whichever has less
if (AMMO(ITEM_BOMB) <= AMMO(ITEM_BOMBCHU)) {
return dropId;
} else {
return ITEM00_BOMBCHU;
}
} else {
// Player has enough bombs, so drop chus if they need some, else it's 50/50
if (AMMO(ITEM_BOMBCHU) <= 15) {
return ITEM00_BOMBCHU;
} else {
return Rand_Next() % 2 ? dropId : ITEM00_BOMBCHU;
}
}
}
/** /**
* Converts a given drop type ID based on link's current age, health and owned items. * Converts a given drop type ID based on link's current age, health and owned items.
* Returns a new drop type ID or -1 to cancel the drop. * Returns a new drop type ID or -1 to cancel the drop.
@ -1450,6 +1507,11 @@ s16 func_8001F404(s16 dropId) {
} }
} }
if (CVar_GetS32("gBombchuDrops", 0) &&
(dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) {
dropId = EnItem00_ConvertBombDropToBombchu(dropId);
}
// This is convoluted but it seems like it must be a single condition to match // This is convoluted but it seems like it must be a single condition to match
// clang-format off // clang-format off
if (((dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_SPECIAL || dropId == ITEM00_BOMBS_B) && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || if (((dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_SPECIAL || dropId == ITEM00_BOMBS_B) && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) ||

View File

@ -112,9 +112,12 @@ static s16 sHeartsDDEnvFactors[3][3] = {
}; };
// Current colors for the double defense hearts // Current colors for the double defense hearts
s16 HeartInner[3] = {HEARTS_PRIM_R,HEARTS_PRIM_G,HEARTS_PRIM_B}; Color_RGB8 HeartInner_ori = {HEARTS_PRIM_R,HEARTS_PRIM_G,HEARTS_PRIM_B};
s16 HeartDDOutline[3] = {HEARTS_DD_PRIM_R,HEARTS_DD_PRIM_G,HEARTS_DD_PRIM_B}; Color_RGB8 HeartDDOutline_ori = {HEARTS_DD_PRIM_R,HEARTS_DD_PRIM_G,HEARTS_DD_PRIM_B};
s16 HeartDDInner[3] = {HEARTS_DD_ENV_R,HEARTS_DD_ENV_G,HEARTS_DD_ENV_B}; Color_RGB8 HeartDDInner_ori = {HEARTS_DD_ENV_R,HEARTS_DD_ENV_G,HEARTS_DD_ENV_B};
Color_RGB8 HeartInner;
Color_RGB8 HeartDDOutline;
Color_RGB8 HeartDDInner;
s16 sBeatingHeartsDDPrim[3]; s16 sBeatingHeartsDDPrim[3];
s16 sBeatingHeartsDDEnv[3]; s16 sBeatingHeartsDDEnv[3];
s16 sHeartsDDPrim[2][3]; s16 sHeartsDDPrim[2][3];
@ -123,19 +126,13 @@ s16 sHeartsDDEnv[2][3];
void HealthMeter_Init(GlobalContext* globalCtx) { void HealthMeter_Init(GlobalContext* globalCtx) {
InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", 90); HeartInner = CVar_GetRGB("gCCHeartsPrim", HeartInner_ori);
HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", 90); HeartDDInner = CVar_GetRGB("gCCDDHeartsPrim", HeartDDInner_ori);
HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", 90); HeartDDOutline = CVar_GetRGB("gDDCCHeartsPrim", HeartDDOutline_ori);
HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", 90);
HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", 90);
HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", 90);
} else { } else {
HeartInner[0] = HEARTS_PRIM_R; HeartInner = HeartInner_ori;
HeartInner[1] = HEARTS_PRIM_G; HeartDDInner = HeartDDInner_ori;
HeartInner[2] = HEARTS_PRIM_B; HeartDDOutline = HeartDDOutline_ori;
HeartDDOutline[0] = HEARTS_DD_PRIM_R;
HeartDDOutline[1] = HEARTS_DD_PRIM_G;
HeartDDOutline[2] = HEARTS_DD_PRIM_B;
} }
interfaceCtx->unk_228 = 0x140; interfaceCtx->unk_228 = 0x140;
@ -143,33 +140,33 @@ void HealthMeter_Init(GlobalContext* globalCtx) {
interfaceCtx->unk_22A = interfaceCtx->unk_1FE = 0; interfaceCtx->unk_22A = interfaceCtx->unk_1FE = 0;
interfaceCtx->unk_22C = interfaceCtx->unk_200 = 0; interfaceCtx->unk_22C = interfaceCtx->unk_200 = 0;
interfaceCtx->heartsPrimR[0] = HeartInner[0]; interfaceCtx->heartsPrimR[0] = HeartInner.r;
interfaceCtx->heartsPrimG[0] = HeartInner[1]; interfaceCtx->heartsPrimG[0] = HeartInner.g;
interfaceCtx->heartsPrimB[0] = HeartInner[2]; interfaceCtx->heartsPrimB[0] = HeartInner.b;
interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R; interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G; interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B; interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B;
interfaceCtx->heartsPrimR[1] = HeartInner[0]; interfaceCtx->heartsPrimR[1] = HeartInner.r;
interfaceCtx->heartsPrimG[1] = HeartInner[1]; interfaceCtx->heartsPrimG[1] = HeartInner.g;
interfaceCtx->heartsPrimB[1] = HeartInner[2]; interfaceCtx->heartsPrimB[1] = HeartInner.b;
interfaceCtx->heartsEnvR[1] = HEARTS_ENV_R; interfaceCtx->heartsEnvR[1] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[1] = HEARTS_ENV_G; interfaceCtx->heartsEnvG[1] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[1] = HEARTS_ENV_B; interfaceCtx->heartsEnvB[1] = HEARTS_ENV_B;
sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HeartDDOutline[0]; sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HeartDDOutline.r;
sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HeartDDOutline[1]; sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HeartDDOutline.b;
sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HeartDDOutline[2]; sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HeartDDOutline.b;
// sHeartsDDPrim[2][0] = HeartInner[0]; // sHeartsDDPrim[2][0] = HeartInner[0];
// sHeartsDDPrim[2][1] = HeartInner[1]; // sHeartsDDPrim[2][1] = HeartInner[1];
// sHeartsDDPrim[2][2] = HeartInner[2]; // sHeartsDDPrim[2][2] = HeartInner[2];
sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HeartDDInner[0]; sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HeartDDInner.r;
sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HeartDDInner[1]; sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HeartDDInner.g;
sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HeartDDInner[2]; sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HeartDDInner.b;
} }
void HealthMeter_Update(GlobalContext* globalCtx) { void HealthMeter_Update(GlobalContext* globalCtx) {
@ -188,19 +185,13 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
Bottom_LM_Margin = CVar_GetS32("gHUDMargin_B", 0); Bottom_LM_Margin = CVar_GetS32("gHUDMargin_B", 0);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", sHeartsPrimColors[0][0]); HeartInner = CVar_GetRGB("gCCHeartsPrim", HeartInner_ori);
HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", sHeartsPrimColors[0][1]); HeartDDInner = CVar_GetRGB("gCCDDHeartsPrim", HeartDDInner_ori);
HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", sHeartsPrimColors[0][2]); HeartDDOutline = CVar_GetRGB("gDDCCHeartsPrim", HeartDDOutline_ori);
HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", sHeartsDDPrim[0][0]);
HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", sHeartsDDPrim[0][1]);
HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", sHeartsDDPrim[0][2]);
} else { } else {
HeartInner[0] = HEARTS_PRIM_R; HeartInner = HeartInner_ori;
HeartInner[1] = HEARTS_PRIM_G; HeartDDInner = HeartDDInner_ori;
HeartInner[2] = HEARTS_PRIM_B; HeartDDOutline = HeartDDOutline_ori;
HeartDDOutline[0] = HEARTS_DD_PRIM_R;
HeartDDOutline[1] = HEARTS_DD_PRIM_G;
HeartDDOutline[2] = HEARTS_DD_PRIM_B;
} }
if (interfaceCtx->unk_200 != 0) { if (interfaceCtx->unk_200 != 0) {
@ -219,18 +210,18 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
ddFactor = factor; ddFactor = factor;
interfaceCtx->heartsPrimR[0] = HeartInner[0]; interfaceCtx->heartsPrimR[0] = HeartInner.r;
interfaceCtx->heartsPrimG[0] = HeartInner[1]; interfaceCtx->heartsPrimG[0] = HeartInner.g;
interfaceCtx->heartsPrimB[0] = HeartInner[2]; interfaceCtx->heartsPrimB[0] = HeartInner.b;
interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R; interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G; interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B; interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
interfaceCtx->heartsPrimR[1] = HeartInner[0]; interfaceCtx->heartsPrimR[1] = HeartInner.r;
interfaceCtx->heartsPrimG[1] = HeartInner[1]; interfaceCtx->heartsPrimG[1] = HeartInner.g;
interfaceCtx->heartsPrimB[1] = HeartInner[2]; interfaceCtx->heartsPrimB[1] = HeartInner.b;
} else { } else {
interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0]; interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0];
interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1]; interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1];
@ -245,9 +236,9 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
gFactor = sHeartsPrimFactors[0][1] * factor; gFactor = sHeartsPrimFactors[0][1] * factor;
bFactor = sHeartsPrimFactors[0][2] * factor; bFactor = sHeartsPrimFactors[0][2] * factor;
interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HeartInner[0]) & 0xFF; interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HeartInner.r) & 0xFF;
interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HeartInner[1]) & 0xFF; interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HeartInner.g) & 0xFF;
interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HeartInner[2]) & 0xFF; interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HeartInner.b) & 0xFF;
rFactor = sHeartsEnvFactors[0][0] * factor; rFactor = sHeartsEnvFactors[0][0] * factor;
gFactor = sHeartsEnvFactors[0][1] * factor; gFactor = sHeartsEnvFactors[0][1] * factor;
@ -259,50 +250,48 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
ddType = type; ddType = type;
sHeartsDDPrim[0][0] = HeartDDOutline[0]; sHeartsDDPrim[0][0] = HeartDDOutline.r;
sHeartsDDPrim[0][1] = HeartDDOutline[1]; sHeartsDDPrim[0][1] = HeartDDOutline.g;
sHeartsDDPrim[0][2] = HeartDDOutline[2]; sHeartsDDPrim[0][2] = HeartDDOutline.b;
sHeartsDDEnv[0][0] = HeartDDInner[0]; sHeartsDDEnv[0][0] = HeartDDInner.r;
sHeartsDDEnv[0][1] = HeartDDInner[1]; sHeartsDDEnv[0][1] = HeartDDInner.g;
sHeartsDDEnv[0][2] = HeartDDInner[2]; sHeartsDDEnv[0][2] = HeartDDInner.b;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
sHeartsDDPrim[2][0] = CVar_GetS32("gCCDDHeartsPrimR", 255); sHeartsDDPrim[2][0] = HeartDDInner.r;
sHeartsDDPrim[2][1] = CVar_GetS32("gCCDDHeartsPrimG", 70); sHeartsDDPrim[2][1] = HeartDDInner.g;
sHeartsDDPrim[2][2] = CVar_GetS32("gCCDDHeartsPrimB", 50); sHeartsDDPrim[2][2] = HeartDDInner.b;
sHeartsDDPrim[1][0] = HeartDDOutline[0]; sHeartsDDPrim[1][0] = HeartDDOutline.r;
sHeartsDDPrim[1][1] = HeartDDOutline[1]; sHeartsDDPrim[1][1] = HeartDDOutline.g;
sHeartsDDPrim[1][2] = HeartDDOutline[2]; sHeartsDDPrim[1][2] = HeartDDOutline.b;
sHeartsDDEnv[1][0] = CVar_GetS32("gCCDDHeartsPrimR", 255); sHeartsDDEnv[1][0] = HeartDDInner.r;
sHeartsDDEnv[1][1] = CVar_GetS32("gCCDDHeartsPrimG", 70); sHeartsDDEnv[1][1] = HeartDDInner.g;
sHeartsDDEnv[1][2] = CVar_GetS32("gCCDDHeartsPrimB", 50); sHeartsDDEnv[1][2] = HeartDDInner.b;
HeartDDInner[0] = CVar_GetS32("gCCDDHeartsPrimR", 255); HeartDDInner = CVar_GetRGB("gCCDDHeartsPrim", HeartDDInner_ori);
HeartDDInner[1] = CVar_GetS32("gCCDDHeartsPrimG", 70);
HeartDDInner[2] = CVar_GetS32("gCCDDHeartsPrimB", 50);
sHeartsDDEnv[0][0] = CVar_GetS32("gCCDDHeartsPrimR", 255); sHeartsDDEnv[0][0] = HeartDDInner.r;
sHeartsDDEnv[0][1] = CVar_GetS32("gCCDDHeartsPrimG", 70); sHeartsDDEnv[0][1] = HeartDDInner.g;
sHeartsDDEnv[0][2] = CVar_GetS32("gCCDDHeartsPrimB", 0); sHeartsDDEnv[0][2] = HeartDDInner.b;
rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor; rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor; gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor; bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor;
sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline[0]) & 0xFF; sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline.r) & 0xFF;
sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF; sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline.g) & 0xFF;
sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF; sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline.b) & 0xFF;
rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor; rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor; gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor; bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor;
sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner[0]) & 0xFF; sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner.r) & 0xFF;
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF; sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner.g) & 0xFF;
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF; sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner.b) & 0xFF;
} else { } else {
sHeartsDDPrim[0][0] = HEARTS_DD_PRIM_R; sHeartsDDPrim[0][0] = HEARTS_DD_PRIM_R;
sHeartsDDPrim[0][1] = HEARTS_DD_PRIM_G; sHeartsDDPrim[0][1] = HEARTS_DD_PRIM_G;
@ -413,6 +402,12 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
s32 curCombineModeSet = 0; s32 curCombineModeSet = 0;
u8* curBgImgLoaded = NULL; u8* curBgImgLoaded = NULL;
s32 ddHeartCountMinusOne = gSaveContext.inventory.defenseHearts - 1; s32 ddHeartCountMinusOne = gSaveContext.inventory.defenseHearts - 1;
float HeartsScale = 0.7f;
if (CVar_GetS32("gHeartsCountPosType", 0) != 0) {
HeartsScale = CVar_GetFloat("gHeartsCountScale", 0.7f);
}
static u32 epoch = 0;
epoch++;
OPEN_DISPS(gfxCtx); OPEN_DISPS(gfxCtx);
@ -433,14 +428,14 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
s16 PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins; s16 PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins;
s16 PosY_original = 0.0f+Y_Margins; s16 PosY_original = 0.0f+Y_Margins;
if (CVar_GetS32("gHeartsCountPosType", 0) != 0) { if (CVar_GetS32("gHeartsCountPosType", 0) != 0) {
offsetY = CVar_GetS32("gHeartsPosY", 0)+Y_Margins; offsetY = CVar_GetS32("gHeartsCountPosY", 0)+Y_Margins+(HeartsScale*15);
if (CVar_GetS32("gHeartsCountPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gHeartsCountPosType", 0) == 1) {//Anchor Left
offsetX = OTRGetDimensionFromLeftEdge(CVar_GetS32("gHeartsPosX", 0)+X_Margins); offsetX = OTRGetDimensionFromLeftEdge(CVar_GetS32("gHeartsCountPosX", 0)+X_Margins+70.0f);
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 2) {//Anchor Right } else if (CVar_GetS32("gHeartsCountPosType", 0) == 2) {//Anchor Right
X_Margins = Right_LM_Margin; X_Margins = Right_LM_Margin;
offsetX = OTRGetDimensionFromRightEdge(CVar_GetS32("gHeartsPosX", 0)+X_Margins); offsetX = OTRGetDimensionFromRightEdge(CVar_GetS32("gHeartsCountPosX", 0)+X_Margins+70.0f);
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 3) {//Anchor None } else if (CVar_GetS32("gHeartsCountPosType", 0) == 3) {//Anchor None
offsetX = CVar_GetS32("gHeartsPosX", 0); offsetX = CVar_GetS32("gHeartsCountPosX", 0)+70.0f;
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 4) {//Hidden } else if (CVar_GetS32("gHeartsCountPosType", 0) == 4) {//Hidden
offsetX = -9999; offsetX = -9999;
} }
@ -568,16 +563,27 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
} }
} }
temp3 = 26.0f + offsetY; temp3 = offsetY;
temp2 = 30.0f + offsetX; temp2 = offsetX;
temp4 = 1.0f; temp4 = 1.0f;//Heart texture size
temp4 /= 0.68f; temp4 /= 0.68f; //Hearts Scaled size
temp4 *= 1 << 10; temp4 *= 1 << 10;
temp1 = 8.0f; temp1 = 8.0f;
temp1 *= 0.68f; temp1 *= 0.68f;
gSPWideTextureRectangle(OVERLAY_DISP++, (s32)((temp2 - temp1) * 4), (s32)((temp3 - temp1) * 4), /*gSPWideTextureRectangle(OVERLAY_DISP++, (s32)((temp2 - temp1) * 4), (s32)((temp3 - temp1) * 4),
(s32)((temp2 + temp1) * 4), (s32)((temp3 + temp1) * 4), G_TX_RENDERTILE, 0, 0, (s32)((temp2 + temp1) * 4), (s32)((temp3 + temp1) * 4), G_TX_RENDERTILE, 0, 0,
(s32)temp4, (s32)temp4); (s32)temp4, (s32)temp4);*/
Mtx* matrix = Graph_Alloc(gfxCtx, sizeof(Mtx));
Matrix_SetTranslateScaleMtx2(matrix,
HeartsScale, //Scale X
HeartsScale, //Scale Y
HeartsScale, //Scale Z
-130+offsetX, //Pos X
(-94+offsetY) *-1, //Pos Y
0.0f); //Pos Z
gSPMatrix(OVERLAY_DISP++, matrix, G_MTX_MODELVIEW | G_MTX_LOAD);
gSPVertex(OVERLAY_DISP++, sp154, 4, 0);
gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0);
} else { } else {
if ((ddHeartCountMinusOne < 0) || (i > ddHeartCountMinusOne)) { if ((ddHeartCountMinusOne < 0) || (i > ddHeartCountMinusOne)) {
if (curCombineModeSet != 2) { if (curCombineModeSet != 2) {
@ -597,28 +603,33 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
{ {
Mtx* matrix = Graph_Alloc(gfxCtx, sizeof(Mtx)); Mtx* matrix = Graph_Alloc(gfxCtx, sizeof(Mtx));
Matrix_SetTranslateScaleMtx2(matrix, 1.0f - (0.32f * sp144), 1.0f - (0.32f * sp144), Matrix_SetTranslateScaleMtx2(matrix,
1.0f - (0.32f * sp144), -130.0f + offsetX, HeartsScale+(HeartsScale/3) - ((HeartsScale/3) * sp144),
94.5f - offsetY, 0.0f); HeartsScale+(HeartsScale/3) - ((HeartsScale/3) * sp144),
HeartsScale+(HeartsScale/3) - ((HeartsScale/3) * sp144),
-130+offsetX, //Pos X
(-94+offsetY) *-1, //Pos Y
0.0f);
gSPMatrix(OVERLAY_DISP++, matrix, G_MTX_MODELVIEW | G_MTX_LOAD); gSPMatrix(OVERLAY_DISP++, matrix, G_MTX_MODELVIEW | G_MTX_LOAD);
gSPVertex(OVERLAY_DISP++, sp154, 4, 0); gSPVertex(OVERLAY_DISP++, sp154, 4, 0);
gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0); gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0);
} }
} }
offsetX += 10.0f; //offsetX += 10.0f;
offsetX += (HeartsScale*14.5f);
if (i == 9) { if (i == 9) {
PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins; PosX_original = OTRGetDimensionFromLeftEdge(0.0f)+X_Margins;
PosY_original = 10.0f+Y_Margins; PosY_original = (HeartsScale*15)+Y_Margins;
if (CVar_GetS32("gHeartsCountPosType", 0) != 0) { if (CVar_GetS32("gHeartsCountPosType", 0) != 0) {
offsetY = CVar_GetS32("gHeartsPosY", 0)+Y_Margins+10.0f; offsetY = CVar_GetS32("gHeartsCountPosY", 0)+((HeartsScale*15)*2)+Y_Margins;
if (CVar_GetS32("gHeartsCountPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gHeartsCountPosType", 0) == 1) {//Anchor Left
offsetX = OTRGetDimensionFromLeftEdge(CVar_GetS32("gHeartsPosX", 0)+X_Margins); offsetX = OTRGetDimensionFromLeftEdge(CVar_GetS32("gHeartsCountPosX", 0)+X_Margins+70.0f);
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 2) {//Anchor Right } else if (CVar_GetS32("gHeartsCountPosType", 0) == 2) {//Anchor Right
X_Margins = Right_LM_Margin; X_Margins = Right_LM_Margin;
offsetX = OTRGetDimensionFromRightEdge(CVar_GetS32("gHeartsPosX", 0)+X_Margins); offsetX = OTRGetDimensionFromRightEdge(CVar_GetS32("gHeartsCountPosX", 0)+X_Margins+70.0f);
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 3) {//Anchor None } else if (CVar_GetS32("gHeartsCountPosType", 0) == 3) {//Anchor None
offsetX = CVar_GetS32("gHeartsPosX", 0); offsetX = CVar_GetS32("gHeartsCountPosX", 0)+70.0f;
} else if (CVar_GetS32("gHeartsCountPosType", 0) == 4) {//Hidden } else if (CVar_GetS32("gHeartsCountPosType", 0) == 4) {//Hidden
offsetX = -9999; offsetX = -9999;
} }

View File

@ -601,6 +601,8 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) {
s32 pad; s32 pad;
Player* player = GET_PLAYER(globalCtx); Player* player = GET_PLAYER(globalCtx);
s16 tempX, tempZ; s16 tempX, tempZ;
const Color_RGB8 LastEntrance_arrow = { 200, 0, 0 };
const Color_RGB8 CurrentPosition_arrow = { 200, 255, 0 };
s16 X_Margins_Minimap; s16 X_Margins_Minimap;
s16 Y_Margins_Minimap; s16 Y_Margins_Minimap;
if (CVar_GetS32("gMinimapUseMargins", 0) != 0) { if (CVar_GetS32("gMinimapUseMargins", 0) != 0) {
@ -658,9 +660,9 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, CVar_GetS32("gCCMinimapCPPrimR", 200), CVar_GetS32("gCCMinimapCPPrimG", 255), CVar_GetS32("gCCMinimapCPPrimB", 0), 255); gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, CVar_GetRGB("gCCMinimapCPPrim", CurrentPosition_arrow).r, CVar_GetRGB("gCCMinimapCPPrim", CurrentPosition_arrow).g, CVar_GetRGB("gCCMinimapCPPrim", CurrentPosition_arrow).b, 255);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, 200, 255, 0, 255); gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, CurrentPosition_arrow.r, CurrentPosition_arrow.g, CurrentPosition_arrow.b, 255);
} }
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL); gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
@ -699,9 +701,9 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, CVar_GetS32("gCCMinimapLEPrimR", 200), CVar_GetS32("gCCMinimapLEPrimG", 0), CVar_GetS32("gCCMinimapLEPrimB", 0), 255); gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, CVar_GetRGB("gCCMinimapLEPrim", LastEntrance_arrow).r,CVar_GetRGB("gCCMinimapLEPrim", LastEntrance_arrow).g,CVar_GetRGB("gCCMinimapLEPrim", LastEntrance_arrow).b, 255);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, 200, 0, 0, 255); gDPSetPrimColor(OVERLAY_DISP++, 0, 0xFF, LastEntrance_arrow.r, LastEntrance_arrow.g, LastEntrance_arrow.b, 255);
} }
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL); gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
} }
@ -713,6 +715,8 @@ void Minimap_Draw(GlobalContext* globalCtx) {
s32 pad[2]; s32 pad[2];
InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx;
s32 mapIndex = gSaveContext.mapIndex; s32 mapIndex = gSaveContext.mapIndex;
const Color_RGB8 Dungeon_minimap = {100, 255, 255};
const Color_RGB8 Overworld_minimap = {R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2)};
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
@ -751,9 +755,9 @@ void Minimap_Draw(GlobalContext* globalCtx) {
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) {
if (CVar_GetS32("gHudColors", 1) == 2) { //Dungeon minimap if (CVar_GetS32("gHudColors", 1) == 2) { //Dungeon minimap
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapDGNPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapDGNPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapDGNPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCMinimapDGNPrim", Dungeon_minimap).r,CVar_GetRGB("gCCMinimapDGNPrim", Dungeon_minimap).g,CVar_GetRGB("gCCMinimapDGNPrim", Dungeon_minimap).b, interfaceCtx->minimapAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 100, 255, 255, interfaceCtx->minimapAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, Dungeon_minimap.r, Dungeon_minimap.g, Dungeon_minimap.b, interfaceCtx->minimapAlpha);
} }
gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->mapSegment); gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->mapSegment);
@ -826,9 +830,9 @@ void Minimap_Draw(GlobalContext* globalCtx) {
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
if (CVar_GetS32("gHudColors", 1) == 2) {//Overworld minimap if (CVar_GetS32("gHudColors", 1) == 2) {//Overworld minimap
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCMinimapPrim", Overworld_minimap).r,CVar_GetRGB("gCCMinimapPrim", Overworld_minimap).g,CVar_GetRGB("gCCMinimapPrim", Overworld_minimap).b, interfaceCtx->minimapAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, Overworld_minimap.r, Overworld_minimap.g, Overworld_minimap.b, interfaceCtx->minimapAlpha);
} }
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_IA, gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_IA,
@ -858,7 +862,7 @@ void Minimap_Draw(GlobalContext* globalCtx) {
0, 1 << 10, 1 << 10); 0, 1 << 10, 1 << 10);
if (CVar_GetS32("gHudColors", 1) != 2) {//This need to be added else it will color dungeon entrance icon too. (it re-init prim color to default color) if (CVar_GetS32("gHudColors", 1) != 2) {//This need to be added else it will color dungeon entrance icon too. (it re-init prim color to default color)
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, Overworld_minimap.r, Overworld_minimap.g, Overworld_minimap.b, interfaceCtx->minimapAlpha);
} }
if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) && if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) &&

View File

@ -166,9 +166,8 @@ static u16 sCUpTimer = 0;
s16 gSpoilingItems[] = { ITEM_ODD_MUSHROOM, ITEM_FROG, ITEM_EYEDROPS }; s16 gSpoilingItems[] = { ITEM_ODD_MUSHROOM, ITEM_FROG, ITEM_EYEDROPS };
s16 gSpoilingItemReverts[] = { ITEM_COJIRO, ITEM_PRESCRIPTION, ITEM_PRESCRIPTION }; s16 gSpoilingItemReverts[] = { ITEM_COJIRO, ITEM_PRESCRIPTION, ITEM_PRESCRIPTION };
static s16 sMagicBorderR = 255; static Color_RGB8 sMagicBorder = {255,255,255};
static s16 sMagicBorderG = 255; static Color_RGB8 sMagicBorder_ori = {255,255,255};
static s16 sMagicBorderB = 255;
static s16 sExtraItemBases[] = { static s16 sExtraItemBases[] = {
ITEM_STICK, ITEM_STICK, ITEM_NUT, ITEM_NUT, ITEM_BOMB, ITEM_BOMB, ITEM_BOMB, ITEM_BOMB, ITEM_BOW, ITEM_STICK, ITEM_STICK, ITEM_NUT, ITEM_NUT, ITEM_BOMB, ITEM_BOMB, ITEM_BOMB, ITEM_BOMB, ITEM_BOW,
@ -1643,12 +1642,16 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
} else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) { } else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) {
gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD]; gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD];
// Both Giant's Knife and Biggoron Sword have the same Item ID, so this part handles both of them
if (item == ITEM_SWORD_BGS) { if (item == ITEM_SWORD_BGS) {
gSaveContext.swordHealth = 8; gSaveContext.swordHealth = 8;
if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF // In rando, when buying Giant's Knife, also check
||(gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) { // In rando, when buying Giant's Knife, also check // for 0xE in case we don't have Kokiri Sword
gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD]; // for 0xE in case we don't have Kokiri Sword if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF || (gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) {
gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD];
if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) { if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
Interface_LoadItemIcon1(globalCtx, 0); Interface_LoadItemIcon1(globalCtx, 0);
@ -2178,6 +2181,14 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return RG_NONE; return RG_NONE;
} }
if (item == RG_MAGIC_BEAN_PACK) {
if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
AMMO(ITEM_BEAN) = 10;
}
return RG_NONE;
}
if (item == RG_DOUBLE_DEFENSE) { if (item == RG_DOUBLE_DEFENSE) {
gSaveContext.doubleDefense = true; gSaveContext.doubleDefense = true;
gSaveContext.inventory.defenseHearts = 20; gSaveContext.inventory.defenseHearts = 20;
@ -2224,9 +2235,9 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
} }
} }
} else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) || } else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) ||
(item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) || (item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) ||
(item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) || (item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) ||
(item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) { (item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) {
int mapIndex = gSaveContext.mapIndex; int mapIndex = gSaveContext.mapIndex;
switch (item) { switch (item) {
case RG_DEKU_TREE_MAP: case RG_DEKU_TREE_MAP:
@ -2324,7 +2335,6 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return temp; return temp;
} }
u8 Item_CheckObtainability(u8 item) { u8 Item_CheckObtainability(u8 item) {
s16 i; s16 i;
s16 slot = SLOT(item); s16 slot = SLOT(item);
@ -2964,23 +2974,27 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
{ 255, 255, 150 }, { 255, 255, 150 },
{ 255, 255, 50 }, { 255, 255, 50 },
}; };
Color_RGB8 MagicBorder_0 = { 255, 255, 255 };
Color_RGB8 MagicBorder_1 = { 150, 150, 150 };
Color_RGB8 MagicBorder_2 = { 255, 255, 150 };
Color_RGB8 MagicBorder_3 = { 255, 255, 50 };
if (CVar_GetS32("gHudColors", 1) == 2) { //This will make custom color based on users selected colors. if (CVar_GetS32("gHudColors", 1) == 2) { //This will make custom color based on users selected colors.
sMagicBorderColors[0][0] = CVar_GetS32("gCCMagicBorderPrimR", 255); sMagicBorderColors[0][0] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_0).r;
sMagicBorderColors[0][1] = CVar_GetS32("gCCMagicBorderPrimG", 255); sMagicBorderColors[0][1] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_0).g;
sMagicBorderColors[0][2] = CVar_GetS32("gCCMagicBorderPrimB", 255); sMagicBorderColors[0][2] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_0).b;
sMagicBorderColors[1][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2; sMagicBorderColors[1][0] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_1).r/2;
sMagicBorderColors[1][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2; sMagicBorderColors[1][1] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_1).g/2;
sMagicBorderColors[1][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2; sMagicBorderColors[1][2] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_1).b/2;
sMagicBorderColors[2][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/3; sMagicBorderColors[2][0] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_2).r/2.5;
sMagicBorderColors[2][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/3; sMagicBorderColors[2][1] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_2).g/2.5;
sMagicBorderColors[2][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/3; sMagicBorderColors[2][2] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_2).b/2.5;
sMagicBorderColors[3][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2; sMagicBorderColors[3][0] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_3).r/3;
sMagicBorderColors[3][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2; sMagicBorderColors[3][1] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_3).g/3;
sMagicBorderColors[3][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2; sMagicBorderColors[3][2] = CVar_GetRGB("gCCMagicBorderPrim", MagicBorder_3).b/3;
} }
static s16 sMagicBorderIndexes[] = { 0, 1, 1, 0 }; static s16 sMagicBorderIndexes[] = { 0, 1, 1, 0 };
@ -3041,53 +3055,49 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
gSaveContext.magic = 0; gSaveContext.magic = 0;
gSaveContext.unk_13F0 = 3; gSaveContext.unk_13F0 = 3;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
sMagicBorderR = CVar_GetS32("gCCMagicBorderNormPrimR", 255); sMagicBorder = CVar_GetRGB("gCCMagicBorderNormPrim", sMagicBorder_ori);
sMagicBorderG = CVar_GetS32("gCCMagicBorderNormPrimG", 255);
sMagicBorderB = CVar_GetS32("gCCMagicBorderNormPrimB", 255);
} else { } else {
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorder = sMagicBorder_ori;
} }
} else if (gSaveContext.magic == gSaveContext.unk_13F8) { } else if (gSaveContext.magic == gSaveContext.unk_13F8) {
gSaveContext.unk_13F0 = 3; gSaveContext.unk_13F0 = 3;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
sMagicBorderR = CVar_GetS32("gCCMagicBorderNormPrimR", 255); sMagicBorder = CVar_GetRGB("gCCMagicBorderNormPrim", sMagicBorder_ori);
sMagicBorderG = CVar_GetS32("gCCMagicBorderNormPrimG", 255);
sMagicBorderB = CVar_GetS32("gCCMagicBorderNormPrimB", 255);
} else { } else {
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorder = sMagicBorder_ori;
} }
} }
case 3: case 3:
case 4: case 4:
case 6: case 6:
temp = sMagicBorderIndexes[sMagicBorderStep]; temp = sMagicBorderIndexes[sMagicBorderStep];
borderChangeR = ABS(sMagicBorderR - sMagicBorderColors[temp][0]) / sMagicBorderRatio; borderChangeR = ABS(sMagicBorder.r - sMagicBorderColors[temp][0]) / sMagicBorderRatio;
borderChangeG = ABS(sMagicBorderG - sMagicBorderColors[temp][1]) / sMagicBorderRatio; borderChangeG = ABS(sMagicBorder.g - sMagicBorderColors[temp][1]) / sMagicBorderRatio;
borderChangeB = ABS(sMagicBorderB - sMagicBorderColors[temp][2]) / sMagicBorderRatio; borderChangeB = ABS(sMagicBorder.b - sMagicBorderColors[temp][2]) / sMagicBorderRatio;
if (sMagicBorderR >= sMagicBorderColors[temp][0]) { if (sMagicBorder.r >= sMagicBorderColors[temp][0]) {
sMagicBorderR -= borderChangeR; sMagicBorder.r -= borderChangeR;
} else { } else {
sMagicBorderR += borderChangeR; sMagicBorder.r += borderChangeR;
} }
if (sMagicBorderG >= sMagicBorderColors[temp][1]) { if (sMagicBorder.g >= sMagicBorderColors[temp][1]) {
sMagicBorderG -= borderChangeG; sMagicBorder.g -= borderChangeG;
} else { } else {
sMagicBorderG += borderChangeG; sMagicBorder.g += borderChangeG;
} }
if (sMagicBorderB >= sMagicBorderColors[temp][2]) { if (sMagicBorder.b >= sMagicBorderColors[temp][2]) {
sMagicBorderB -= borderChangeB; sMagicBorder.b -= borderChangeB;
} else { } else {
sMagicBorderB += borderChangeB; sMagicBorder.b += borderChangeB;
} }
sMagicBorderRatio--; sMagicBorderRatio--;
if (sMagicBorderRatio == 0) { if (sMagicBorderRatio == 0) {
sMagicBorderR = sMagicBorderColors[temp][0]; sMagicBorder.r = sMagicBorderColors[temp][0];
sMagicBorderG = sMagicBorderColors[temp][1]; sMagicBorder.g = sMagicBorderColors[temp][1];
sMagicBorderB = sMagicBorderColors[temp][2]; sMagicBorder.b = sMagicBorderColors[temp][2];
sMagicBorderRatio = YREG(40 + sMagicBorderStep); sMagicBorderRatio = YREG(40 + sMagicBorderStep);
sMagicBorderStep++; sMagicBorderStep++;
if (sMagicBorderStep >= 4) { if (sMagicBorderStep >= 4) {
@ -3098,11 +3108,9 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
case 5: case 5:
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
sMagicBorderR = CVar_GetS32("gCCMagicBorderNormPrimR", 255); sMagicBorder = CVar_GetRGB("gCCMagicBorderNormPrim", sMagicBorder_ori);
sMagicBorderG = CVar_GetS32("gCCMagicBorderNormPrimG", 255);
sMagicBorderB = CVar_GetS32("gCCMagicBorderNormPrimB", 255);
} else { } else {
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorder = sMagicBorder_ori;
} }
gSaveContext.unk_13F0 = 0; gSaveContext.unk_13F0 = 0;
break; break;
@ -3126,11 +3134,9 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
&D_801333E8); &D_801333E8);
gSaveContext.unk_13F0 = 0; gSaveContext.unk_13F0 = 0;
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
sMagicBorderR = CVar_GetS32("gCCMagicBorderNormPrimR", 255); sMagicBorder = CVar_GetRGB("gCCMagicBorderNormPrim", sMagicBorder_ori);
sMagicBorderG = CVar_GetS32("gCCMagicBorderNormPrimG", 255);
sMagicBorderB = CVar_GetS32("gCCMagicBorderNormPrimB", 255);
} else { } else {
sMagicBorderR = sMagicBorderG = sMagicBorderB = 255; sMagicBorder = sMagicBorder_ori;
} }
break; break;
} }
@ -3143,33 +3149,33 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
} }
temp = sMagicBorderIndexes[sMagicBorderStep]; temp = sMagicBorderIndexes[sMagicBorderStep];
borderChangeR = ABS(sMagicBorderR - sMagicBorderColors[temp][0]) / sMagicBorderRatio; borderChangeR = ABS(sMagicBorder.r - sMagicBorderColors[temp][0]) / sMagicBorderRatio;
borderChangeG = ABS(sMagicBorderG - sMagicBorderColors[temp][1]) / sMagicBorderRatio; borderChangeG = ABS(sMagicBorder.g - sMagicBorderColors[temp][1]) / sMagicBorderRatio;
borderChangeB = ABS(sMagicBorderB - sMagicBorderColors[temp][2]) / sMagicBorderRatio; borderChangeB = ABS(sMagicBorder.b - sMagicBorderColors[temp][2]) / sMagicBorderRatio;
if (sMagicBorderR >= sMagicBorderColors[temp][0]) { if (sMagicBorder.r >= sMagicBorderColors[temp][0]) {
sMagicBorderR -= borderChangeR; sMagicBorder.r -= borderChangeR;
} else { } else {
sMagicBorderR += borderChangeR; sMagicBorder.r += borderChangeR;
} }
if (sMagicBorderG >= sMagicBorderColors[temp][1]) { if (sMagicBorder.g >= sMagicBorderColors[temp][1]) {
sMagicBorderG -= borderChangeG; sMagicBorder.g -= borderChangeG;
} else { } else {
sMagicBorderG += borderChangeG; sMagicBorder.g += borderChangeG;
} }
if (sMagicBorderB >= sMagicBorderColors[temp][2]) { if (sMagicBorder.b >= sMagicBorderColors[temp][2]) {
sMagicBorderB -= borderChangeB; sMagicBorder.b -= borderChangeB;
} else { } else {
sMagicBorderB += borderChangeB; sMagicBorder.b += borderChangeB;
} }
sMagicBorderRatio--; sMagicBorderRatio--;
if (sMagicBorderRatio == 0) { if (sMagicBorderRatio == 0) {
sMagicBorderR = sMagicBorderColors[temp][0]; sMagicBorder.r = sMagicBorderColors[temp][0];
sMagicBorderG = sMagicBorderColors[temp][1]; sMagicBorder.g = sMagicBorderColors[temp][1];
sMagicBorderB = sMagicBorderColors[temp][2]; sMagicBorder.b = sMagicBorderColors[temp][2];
sMagicBorderRatio = YREG(40 + sMagicBorderStep); sMagicBorderRatio = YREG(40 + sMagicBorderStep);
sMagicBorderStep++; sMagicBorderStep++;
if (sMagicBorderStep >= 4) { if (sMagicBorderStep >= 4) {
@ -3197,6 +3203,8 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
void Interface_DrawMagicBar(GlobalContext* globalCtx) { void Interface_DrawMagicBar(GlobalContext* globalCtx) {
InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx; InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx;
s16 magicBarY; s16 magicBarY;
Color_RGB8 magicbar_yellow = {250,250,0}; //Magic bar being used
Color_RGB8 magicbar_green = {R_MAGIC_FILL_COLOR(0),R_MAGIC_FILL_COLOR(1),R_MAGIC_FILL_COLOR(2)}; //Magic bar fill
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
@ -3265,7 +3273,7 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
} else { } else {
gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255); gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255);
} }
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorder.r, sMagicBorder.g, sMagicBorder.b, interfaceCtx->magicAlpha);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, PosX_Start, magicBarY, 8, 16, 1 << 10, 1 << 10); OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, PosX_Start, magicBarY, 8, 16, 1 << 10, 1 << 10);
@ -3286,9 +3294,9 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
if (gSaveContext.unk_13F0 == 4) { if (gSaveContext.unk_13F0 == 4) {
// Yellow part of the bar indicating the amount of magic to be subtracted // Yellow part of the bar indicating the amount of magic to be subtracted
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicUsePrimR", 250), CVar_GetS32("gCCMagicUsePrimG", 250), CVar_GetS32("gCCMagicUsePrimB", 0), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCMagicUsePrim", magicbar_yellow).r, CVar_GetRGB("gCCMagicUsePrim", magicbar_yellow).g, CVar_GetRGB("gCCMagicUsePrim", magicbar_yellow).b, interfaceCtx->magicAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_yellow.r, magicbar_yellow.g, magicbar_yellow.b, interfaceCtx->magicAlpha);
} }
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0,
@ -3302,9 +3310,9 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
// Fill the rest of the bar with the normal magic color // Fill the rest of the bar with the normal magic color
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCMagicPrim", magicbar_green).r, CVar_GetRGB("gCCMagicPrim", magicbar_green).g, CVar_GetRGB("gCCMagicPrim", magicbar_green).b, interfaceCtx->magicAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha);
} }
gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2, gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2,
@ -3313,9 +3321,9 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
} else { } else {
// Fill the whole bar with the normal magic color // Fill the whole bar with the normal magic color
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCMagicPrim", magicbar_green).r, CVar_GetRGB("gCCMagicPrim", magicbar_green).g, CVar_GetRGB("gCCMagicPrim", magicbar_green).b, interfaceCtx->magicAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha);
} }
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0,
@ -3389,10 +3397,28 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
s16 dxdy; s16 dxdy;
s16 width; s16 width;
s16 height; s16 height;
Color_RGB8 A_button_ori = {R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2)};
Color_RGB8 A_button = CVar_GetRGB("gCCABtnPrim", A_button_ori);
Color_RGB8 B_button_ori = {R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2)};
Color_RGB8 B_button = CVar_GetRGB("gCCBBtnPrim", B_button_ori);
Color_RGB8 Start_button_ori = {120, 120, 120};
Color_RGB8 Start_button = CVar_GetRGB("gCCStartBtnPrim", Start_button_ori);
Color_RGB8 C_button_ori = {R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2)};
Color_RGB8 C_button_uni = CVar_GetRGB("gCCCBtnPrim", C_button_ori);
Color_RGB8 C_button_U = CVar_GetRGB("gCCCUBtnPrim", C_button_ori);
Color_RGB8 C_button_D = CVar_GetRGB("gCCCDBtnPrim", C_button_ori);
Color_RGB8 C_button_L = CVar_GetRGB("gCCCLBtnPrim", C_button_ori);
Color_RGB8 C_button_R = CVar_GetRGB("gCCCRBtnPrim", C_button_ori);
//B Button //B Button
s16 X_Margins_BtnB; s16 X_Margins_BtnB;
s16 Y_Margins_BtnB; s16 Y_Margins_BtnB;
s16 BBtn_Size = 32;
int BBtnScaled = BBtn_Size * 0.95f;
if (CVar_GetS32("gBBtnPosType", 0) != 0) {
BBtnScaled = BBtn_Size * CVar_GetFloat("gBBtnScale", 0.95f);
}
int BBtn_factor = (1 << 10) * BBtn_Size / BBtnScaled;
if (CVar_GetS32("gBBtnUseMargins", 0) != 0) { if (CVar_GetS32("gBBtnUseMargins", 0) != 0) {
if (CVar_GetS32("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;}; if (CVar_GetS32("gBBtnPosType", 0) == 0) {X_Margins_BtnB = Right_HUD_Margin;};
Y_Margins_BtnB = (Top_HUD_Margin*-1); Y_Margins_BtnB = (Top_HUD_Margin*-1);
@ -3435,49 +3461,40 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
} }
s16 StartBtn_Icon_H = 32; s16 StartBtn_Icon_H = 32;
s16 StartBtn_Icon_W = 32; s16 StartBtn_Icon_W = 32;
int StartBTN_H_Scaled = StartBtn_Icon_H * 0.75f; float Start_BTN_Scale = 0.75f;
int StartBTN_W_Scaled = StartBtn_Icon_W * 0.75f; if (CVar_GetS32("gStartBtnPosType", 0) != 0) {
Start_BTN_Scale = CVar_GetFloat("gStartBtnScale", 0.75f);
}
int StartBTN_H_Scaled = StartBtn_Icon_H * Start_BTN_Scale;
int StartBTN_W_Scaled = StartBtn_Icon_W * Start_BTN_Scale;
int StartBTN_W_factor = (1 << 10) * StartBtn_Icon_W / StartBTN_W_Scaled; int StartBTN_W_factor = (1 << 10) * StartBtn_Icon_W / StartBTN_W_Scaled;
int StartBTN_H_factor = (1 << 10) * StartBtn_Icon_H / StartBTN_H_Scaled; int StartBTN_H_factor = (1 << 10) * StartBtn_Icon_H / StartBTN_H_Scaled;
const s16 rStartLabelX_ori = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)+X_Margins_StartBtn);
const s16 rStartLabelY_ori = R_START_LABEL_Y(gSaveContext.language)+Y_Margins_StartBtn;
const s16 PosX_StartBtn_ori = OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+X_Margins_StartBtn); const s16 PosX_StartBtn_ori = OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+X_Margins_StartBtn);
const s16 PosY_StartBtn_ori = 16+Y_Margins_StartBtn; const s16 PosY_StartBtn_ori = 16+Y_Margins_StartBtn;
s16 StartBTN_Label_W = DO_ACTION_TEX_WIDTH(); s16 StartBTN_Label_W = DO_ACTION_TEX_WIDTH();
s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT(); s16 StartBTN_Label_H = DO_ACTION_TEX_HEIGHT();
int StartBTN_Label_H_Scaled = StartBTN_Label_H * 1.0f;
int StartBTN_Label_W_Scaled = StartBTN_Label_W * 1.0f;
int StartBTN_Label_W_factor = (1 << 10) * StartBTN_Label_W / StartBTN_Label_W_Scaled;
int StartBTN_Label_H_factor = (1 << 10) * StartBTN_Label_H / StartBTN_Label_H_Scaled;
const s16 StartBtn_Label_W_ori = StartBTN_Label_W / (R_START_LABEL_DD(gSaveContext.language) / 100.0f);
const s16 StartBtn_Label_H_ori = StartBTN_Label_H / (R_START_LABEL_DD(gSaveContext.language) / 100.0f);
s16 PosX_StartBtn; s16 PosX_StartBtn;
s16 PosY_StartBtn; s16 PosY_StartBtn;
s16 rStartLabelX;
s16 rStartLabelY;
if (CVar_GetS32("gStartBtnPosType", 0) != 0) { if (CVar_GetS32("gStartBtnPosType", 0) != 0) {
PosY_StartBtn = CVar_GetS32("gStartBtnPosY", 0)+Y_Margins_StartBtn; PosY_StartBtn = CVar_GetS32("gStartBtnPosY", 0)-(Start_BTN_Scale*13)+Y_Margins_StartBtn;
rStartLabelY = CVar_GetS32("gStartBtnPosY", 0)+Y_Margins_StartBtn+3;
if (CVar_GetS32("gStartBtnPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gStartBtnPosType", 0) == 1) {//Anchor Left
if (CVar_GetS32("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;}; if (CVar_GetS32("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Left_HUD_Margin;};
PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVar_GetS32("gStartBtnPosX", 0)+X_Margins_StartBtn); PosX_StartBtn = OTRGetDimensionFromLeftEdge(CVar_GetS32("gStartBtnPosX", 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn);
rStartLabelX = OTRGetDimensionFromLeftEdge(CVar_GetS32("gStartBtnPosX", 0)+X_Margins_StartBtn-12);
} else if (CVar_GetS32("gStartBtnPosType", 0) == 2) {//Anchor Right } else if (CVar_GetS32("gStartBtnPosType", 0) == 2) {//Anchor Right
if (CVar_GetS32("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;}; if (CVar_GetS32("gStartBtnUseMargins", 0) != 0) {X_Margins_StartBtn = Right_HUD_Margin;};
PosX_StartBtn = OTRGetDimensionFromRightEdge(CVar_GetS32("gStartBtnPosX", 0)+X_Margins_StartBtn); PosX_StartBtn = OTRGetDimensionFromRightEdge(CVar_GetS32("gStartBtnPosX", 0)-(Start_BTN_Scale*13)+X_Margins_StartBtn);
rStartLabelX = OTRGetDimensionFromRightEdge(CVar_GetS32("gStartBtnPosX", 0)+X_Margins_StartBtn-12);
} else if (CVar_GetS32("gStartBtnPosType", 0) == 3) {//Anchor None } else if (CVar_GetS32("gStartBtnPosType", 0) == 3) {//Anchor None
PosX_StartBtn = CVar_GetS32("gStartBtnPosX", 0); PosX_StartBtn = CVar_GetS32("gStartBtnPosX", 0);
rStartLabelX = CVar_GetS32("gStartBtnPosX", 0)-12;
} else if (CVar_GetS32("gStartBtnPosType", 0) == 4) {//Hidden } else if (CVar_GetS32("gStartBtnPosType", 0) == 4) {//Hidden
PosX_StartBtn = -9999; PosX_StartBtn = -9999;
rStartLabelX = -9999;
} }
} else { } else {
StartBTN_H_Scaled = StartBtn_Icon_H * 0.75f;
StartBTN_W_Scaled = StartBtn_Icon_W * 0.75f;
StartBTN_W_factor = (1 << 10) * StartBtn_Icon_W / StartBTN_W_Scaled;
StartBTN_H_factor = (1 << 10) * StartBtn_Icon_H / StartBTN_H_Scaled;
PosY_StartBtn = PosY_StartBtn_ori; PosY_StartBtn = PosY_StartBtn_ori;
PosX_StartBtn = PosX_StartBtn_ori; PosX_StartBtn = PosX_StartBtn_ori;
rStartLabelY = rStartLabelY_ori;
rStartLabelX = rStartLabelX_ori;
} }
//C Buttons position //C Buttons position
s16 X_Margins_CL; s16 X_Margins_CL;
@ -3527,6 +3544,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
s16 C_Up_BTN_Pos[2]; s16 C_Up_BTN_Pos[2];
s16 C_Down_BTN_Pos[2]; s16 C_Down_BTN_Pos[2];
//C button Left //C button Left
s16 C_Left_BTN_Size = 32;
float CLeftScale = CVar_GetFloat("gCBtnLScale", 0.87f);
int CLeftScaled = C_Left_BTN_Size * 0.87f;
if (CVar_GetS32("gCBtnLPosType", 0) != 0) {
CLeftScaled = C_Left_BTN_Size * CLeftScale;
}
int CLeft_factor = (1 << 10) * C_Left_BTN_Size / CLeftScaled;
if (CVar_GetS32("gCBtnLPosType", 0) != 0) { if (CVar_GetS32("gCBtnLPosType", 0) != 0) {
C_Left_BTN_Pos[1] = CVar_GetS32("gCBtnLPosY", 0)+Y_Margins_CL; C_Left_BTN_Pos[1] = CVar_GetS32("gCBtnLPosY", 0)+Y_Margins_CL;
if (CVar_GetS32("gCBtnLPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gCBtnLPosType", 0) == 1) {//Anchor Left
@ -3545,6 +3569,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
C_Left_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos_ori[0]); C_Left_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos_ori[0]);
} }
//C button Right //C button Right
s16 C_Right_BTN_Size = 32;
float CRightScale = CVar_GetFloat("gCBtnRScale", 0.87f);
int CRightScaled = C_Right_BTN_Size * 0.87f;
if (CVar_GetS32("gCBtnRPosType", 0) != 0) {
CRightScaled = C_Right_BTN_Size * CRightScale;
}
int CRight_factor = (1 << 10) * C_Right_BTN_Size / CRightScaled;
if (CVar_GetS32("gCBtnRPosType", 0) != 0) { if (CVar_GetS32("gCBtnRPosType", 0) != 0) {
C_Right_BTN_Pos[1] = CVar_GetS32("gCBtnRPosY", 0)+Y_Margins_CR; C_Right_BTN_Pos[1] = CVar_GetS32("gCBtnRPosY", 0)+Y_Margins_CR;
if (CVar_GetS32("gCBtnRPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gCBtnRPosType", 0) == 1) {//Anchor Left
@ -3563,6 +3594,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
C_Right_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos_ori[0]); C_Right_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos_ori[0]);
} }
//C Button Up //C Button Up
s16 C_Up_BTN_Size = 32;
int CUpScaled = C_Up_BTN_Size * 0.5f;
float CUpScale = CVar_GetFloat("gCBtnUScale", 0.5f);
if (CVar_GetS32("gCBtnUPosType", 0) != 0) {
CUpScaled = C_Up_BTN_Size * CUpScale;
}
int CUp_factor = (1 << 10) * C_Up_BTN_Size / CUpScaled;
if (CVar_GetS32("gCBtnUPosType", 0) != 0) { if (CVar_GetS32("gCBtnUPosType", 0) != 0) {
C_Up_BTN_Pos[1] = CVar_GetS32("gCBtnUPosY", 0)+Y_Margins_CU; C_Up_BTN_Pos[1] = CVar_GetS32("gCBtnUPosY", 0)+Y_Margins_CU;
if (CVar_GetS32("gCBtnUPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gCBtnUPosType", 0) == 1) {//Anchor Left
@ -3581,6 +3619,14 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
C_Up_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Up_BTN_Pos_ori[0]); C_Up_BTN_Pos[0] = OTRGetRectDimensionFromRightEdge(C_Up_BTN_Pos_ori[0]);
} }
//C Button down //C Button down
s16 C_Down_BTN_Size = 32;
float CDownScale = CVar_GetFloat("gCBtnDScale", 0.87f);
if (CVar_GetS32("gCBtnDPosType", 0) == 0) {
CDownScale = 0.87f;
}
int CDownScaled = C_Down_BTN_Size * CDownScale;
int CDown_factor = (1 << 10) * C_Down_BTN_Size / CDownScaled;
int PositionAdjustment = CDownScaled/2;
if (CVar_GetS32("gCBtnDPosType", 0) != 0) { if (CVar_GetS32("gCBtnDPosType", 0) != 0) {
C_Down_BTN_Pos[1] = CVar_GetS32("gCBtnDPosY", 0)+Y_Margins_CD; C_Down_BTN_Pos[1] = CVar_GetS32("gCBtnDPosY", 0)+Y_Margins_CD;
if (CVar_GetS32("gCBtnDPosType", 0) == 1) {//Anchor Left if (CVar_GetS32("gCBtnDPosType", 0) == 1) {//Anchor Left
@ -3608,24 +3654,24 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 150, 0, interfaceCtx->bAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 150, 0, interfaceCtx->bAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2), interfaceCtx->bAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, B_button_ori.r,B_button_ori.g,B_button_ori.b, interfaceCtx->bAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) { } else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCBBtnPrimR", R_B_BTN_COLOR(0)), CVar_GetS32("gCCBBtnPrimG", R_B_BTN_COLOR(1)), CVar_GetS32("gCCBBtnPrimB", R_B_BTN_COLOR(2)), interfaceCtx->bAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, B_button.r,B_button.g,B_button.b, interfaceCtx->bAlpha);
} }
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, 32, 32, PosX_BtnB, PosY_BtnB, R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_DD(0) << 1, R_ITEM_BTN_DD(0) << 1); OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, BBtn_Size, BBtn_Size, PosX_BtnB, PosY_BtnB, BBtnScaled, BBtnScaled, BBtn_factor, BBtn_factor);
// C-Left Button Color & Texture // C-Left Button Color & Texture
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cLeftAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cLeftAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cLeftAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_uni.r, C_button_uni.g, C_button_uni.b, interfaceCtx->cLeftAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCLBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCLBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCLBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cLeftAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_L.r, C_button_L.g, C_button_L.b, interfaceCtx->cLeftAlpha);
} }
gSPWideTextureRectangle(OVERLAY_DISP++, C_Left_BTN_Pos[0] << 2, C_Left_BTN_Pos[1] << 2, gSPWideTextureRectangle(OVERLAY_DISP++, C_Left_BTN_Pos[0] << 2, C_Left_BTN_Pos[1] << 2,
(C_Left_BTN_Pos[0] + R_ITEM_BTN_WIDTH(1)) << 2, (C_Left_BTN_Pos[0] + R_ITEM_BTN_WIDTH(1)) << 2,
@ -3634,13 +3680,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
// C-Down Button Color & Texture // C-Down Button Color & Texture
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cDownAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_uni.r, C_button_uni.g, C_button_uni.b, interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCDBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCDBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCDBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cDownAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_D.r, C_button_D.g, C_button_D.b, interfaceCtx->cDownAlpha);
} }
gSPWideTextureRectangle(OVERLAY_DISP++, C_Down_BTN_Pos[0] << 2, C_Down_BTN_Pos[1] << 2, gSPWideTextureRectangle(OVERLAY_DISP++, C_Down_BTN_Pos[0] << 2, C_Down_BTN_Pos[1] << 2,
(C_Down_BTN_Pos[0] + R_ITEM_BTN_WIDTH(2)) << 2, (C_Down_BTN_Pos[0] + R_ITEM_BTN_WIDTH(2)) << 2,
@ -3649,13 +3695,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
// C-Right Button Color & Texture // C-Right Button Color & Texture
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cRightAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cRightAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_uni.r, C_button_uni.g, C_button_uni.b, interfaceCtx->cRightAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCRBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCRBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCRBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_R.r, C_button_R.g, C_button_R.b, interfaceCtx->cRightAlpha);
} }
gSPWideTextureRectangle(OVERLAY_DISP++, C_Right_BTN_Pos[0] << 2, C_Right_BTN_Pos[1] << 2, gSPWideTextureRectangle(OVERLAY_DISP++, C_Right_BTN_Pos[0] << 2, C_Right_BTN_Pos[1] << 2,
(C_Right_BTN_Pos[0] + R_ITEM_BTN_WIDTH(3)) << 2, (C_Right_BTN_Pos[0] + R_ITEM_BTN_WIDTH(3)) << 2,
@ -3670,9 +3716,9 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, interfaceCtx->startAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, interfaceCtx->startAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 120, 120, interfaceCtx->startAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, Start_button_ori.r, Start_button_ori.g, Start_button_ori.b, interfaceCtx->startAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) { } else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCStartBtnPrimR", 120), CVar_GetS32("gCCStartBtnPrimG", 120), CVar_GetS32("gCCStartBtnPrimB", 120), interfaceCtx->startAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, Start_button.r, Start_button.g, Start_button.b, interfaceCtx->startAlpha);
} }
gSPWideTextureRectangle(OVERLAY_DISP++, PosX_StartBtn << 2, PosY_StartBtn << 2, gSPWideTextureRectangle(OVERLAY_DISP++, PosX_StartBtn << 2, PosY_StartBtn << 2,
(PosX_StartBtn + StartBTN_W_Scaled) << 2, (PosY_StartBtn + StartBTN_H_Scaled) << 2, (PosX_StartBtn + StartBTN_W_Scaled) << 2, (PosY_StartBtn + StartBTN_H_Scaled) << 2,
@ -3707,11 +3753,19 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
DO_ACTION_TEX_WIDTH(), DO_ACTION_TEX_HEIGHT(), 0, G_TX_NOMIRROR | G_TX_WRAP, DO_ACTION_TEX_WIDTH(), DO_ACTION_TEX_HEIGHT(), 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
//const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)+Right_HUD_Margin); gDPPipeSync(OVERLAY_DISP++);
gSPWideTextureRectangle( gSPSetGeometryMode(OVERLAY_DISP++, G_CULL_BACK);
OVERLAY_DISP++, rStartLabelX << 2, rStartLabelY << 2, gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
(rStartLabelX + StartBTN_Label_W) << 2, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
(rStartLabelY + StartBTN_Label_H) << 2, G_TX_RENDERTILE, 0, 0, StartBTN_Label_W_factor, StartBTN_Label_H_factor); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->startAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0);
Matrix_Translate(PosX_StartBtn-160+((Start_BTN_Scale+Start_BTN_Scale/3)*11.5f), (PosY_StartBtn-120+((Start_BTN_Scale+Start_BTN_Scale/3)*11.5f)) * -1, 1.0f, MTXMODE_NEW);
Matrix_Scale(Start_BTN_Scale+(Start_BTN_Scale/3), Start_BTN_Scale+(Start_BTN_Scale/3), Start_BTN_Scale+(Start_BTN_Scale/3), MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPVertex(OVERLAY_DISP++, &interfaceCtx->actionVtx[4], 4, 0);
Interface_DrawActionLabel(globalCtx->state.gfxCtx, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE() * 2);
gDPPipeSync(OVERLAY_DISP++);
} }
} }
@ -3731,13 +3785,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
} }
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, temp);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, temp);
} else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), temp); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_uni.r, C_button_uni.g, C_button_uni.b, temp);
} else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated",0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCUBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCUBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCUBtnPrimB", R_C_BTN_COLOR(2)), temp); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_U.r, C_button_U.g, C_button_U.b, temp);
} }
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0] << 2, C_Up_BTN_Pos[1] << 2, (C_Up_BTN_Pos[0] + 16) << 2, gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0] << 2, C_Up_BTN_Pos[1] << 2, (C_Up_BTN_Pos[0] + 16) << 2,
@ -3796,6 +3850,11 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
X_Margins_CD = 0; X_Margins_CD = 0;
Y_Margins_CD = 0; Y_Margins_CD = 0;
} }
const s16 ItemIconWidthFactor[3][2] = {
{ CLeftScaled, CLeft_factor },
{ CDownScaled, CDown_factor },
{ CRightScaled, CRight_factor },
};
const s16 ItemIconPos_ori[3][2] = { const s16 ItemIconPos_ori[3][2] = {
{ R_ITEM_ICON_X(1)+X_Margins_CL, R_ITEM_ICON_Y(1)+Y_Margins_CL }, { R_ITEM_ICON_X(1)+X_Margins_CL, R_ITEM_ICON_Y(1)+Y_Margins_CL },
{ R_ITEM_ICON_X(2)+X_Margins_CD, R_ITEM_ICON_Y(2)+Y_Margins_CD }, { R_ITEM_ICON_X(2)+X_Margins_CD, R_ITEM_ICON_Y(2)+Y_Margins_CD },
@ -3858,40 +3917,34 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
} }
if (temp == 1) { if (temp == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cLeftAlpha);
interfaceCtx->cLeftAlpha);
} else if (temp == 2) { } else if (temp == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cDownAlpha);
interfaceCtx->cDownAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_ori.r, C_button_ori.g, C_button_ori.b, interfaceCtx->cRightAlpha);
interfaceCtx->cRightAlpha);
} }
if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated", 0)) { if (CVar_GetS32("gHudColors", 1) == 2 && !CVar_GetS32("gCCparated", 0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_uni.r, C_button_uni.g, C_button_uni.b, interfaceCtx->cRightAlpha);
} else if (temp == 1 && CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) { } else if (temp == 1 && CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCLBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCLBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCLBtnPrimB", R_C_BTN_COLOR(2)), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_L.r, C_button_L.g, C_button_L.b, interfaceCtx->cLeftAlpha);
interfaceCtx->cLeftAlpha);
} else if (temp == 2 && CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) { } else if (temp == 2 && CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCDBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCDBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCDBtnPrimB", R_C_BTN_COLOR(2)), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_D.r, C_button_D.g, C_button_D.b, interfaceCtx->cDownAlpha);
interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) { } else if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gCCparated", 0)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCRBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCRBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCRBtnPrimB", R_C_BTN_COLOR(2)), gDPSetPrimColor(OVERLAY_DISP++, 0, 0, C_button_R.r, C_button_R.g, C_button_R.b, interfaceCtx->cRightAlpha);
interfaceCtx->cRightAlpha);
} }
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32,
ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], R_ITEM_BTN_WIDTH(temp), ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], ItemIconWidthFactor[temp-1][0],
R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1); ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][1], ItemIconWidthFactor[temp-1][1]);
const char* cButtonIcons[] = { gButtonBackgroundTex, gEquippedItemOutlineTex, gEmptyCLeftArrowTex, const char* cButtonIcons[] = { gButtonBackgroundTex, gEquippedItemOutlineTex, gEmptyCLeftArrowTex,
gEmptyCDownArrowTex, gEmptyCRightArrowTex gEmptyCDownArrowTex, gEmptyCRightArrowTex
}; };
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, cButtonIcons[(temp + 1)], 32, 32, OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, cButtonIcons[(temp + 1)], 32, 32,
ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], R_ITEM_BTN_WIDTH(temp), ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], ItemIconWidthFactor[temp-1][0],
R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1); ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][1], ItemIconWidthFactor[temp-1][1]);
} }
} }
@ -3903,6 +3956,8 @@ int16_t gItemIconDD[] = { 550, 680, 680, 680, 1024, 1024, 1024, 1024 };
void Interface_DrawItemIconTexture(GlobalContext* globalCtx, void* texture, s16 button) { void Interface_DrawItemIconTexture(GlobalContext* globalCtx, void* texture, s16 button) {
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx;
s16 X_Margins_CL; s16 X_Margins_CL;
s16 X_Margins_CR; s16 X_Margins_CR;
s16 X_Margins_CD; s16 X_Margins_CD;
@ -3958,6 +4013,16 @@ void Interface_DrawItemIconTexture(GlobalContext* globalCtx, void* texture, s16
{ DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items },
{ DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items } { DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items }
}; };
u16 ItemsSlotsAlpha[8] = {
interfaceCtx->bAlpha,
interfaceCtx->cLeftAlpha,
interfaceCtx->cRightAlpha,
interfaceCtx->cDownAlpha,
interfaceCtx->dpadUpAlpha,
interfaceCtx->dpadDownAlpha,
interfaceCtx->dpadLeftAlpha,
interfaceCtx->dpadRightAlpha
};
s16 DPad_ItemsOffset[4][2] = { s16 DPad_ItemsOffset[4][2] = {
{ 7,-8},//Up { 7,-8},//Up
{ 7,24},//Down { 7,24},//Down
@ -4495,7 +4560,12 @@ void Interface_Draw(GlobalContext* globalCtx) {
{ 0x82, 0x82, 0xFF }, // Adult's Wallet (Blue) { 0x82, 0x82, 0xFF }, // Adult's Wallet (Blue)
{ 0xFF, 0x64, 0x64 }, // Giant's Wallet (Red) { 0xFF, 0x64, 0x64 }, // Giant's Wallet (Red)
}; };
s16 rColor[3] = { 200, 255, 100 }; Color_RGB8 rColor_ori = { 200, 255, 100 };
Color_RGB8 rColor;
Color_RGB8 keyColor_ori = { 200, 230, 255 };
Color_RGB8 keyColor;
Color_RGB8 DPad_colors_ori = {255, 255, 255};
Color_RGB8 DPad_colors = CVar_GetRGB("gCCDpadPrim", DPad_colors_ori);
static s16 spoilingItemEntrances[] = { 0x01AD, 0x0153, 0x0153 }; static s16 spoilingItemEntrances[] = { 0x01AD, 0x0153, 0x0153 };
static f32 D_80125B54[] = { -40.0f, -35.0f }; // unused static f32 D_80125B54[] = { -40.0f, -35.0f }; // unused
static s16 D_80125B5C[] = { 91, 91 }; // unused static s16 D_80125B5C[] = { 91, 91 }; // unused
@ -4542,25 +4612,23 @@ void Interface_Draw(GlobalContext* globalCtx) {
//Custom Color is on but check if Dynamic Wallet is on. //Custom Color is on but check if Dynamic Wallet is on.
if (CVar_GetS32("gDynamicWalletIcon", 0) != 0) { if (CVar_GetS32("gDynamicWalletIcon", 0) != 0) {
//if on let's use Dynamic Colors //if on let's use Dynamic Colors
rColor[0] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][0]; rColor.r = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][0];
rColor[1] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][1]; rColor.g = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][1];
rColor[2] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][2]; rColor.b = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][2];
} else { } else {
//else use our custom color //else use our custom color
rColor[0] = CVar_GetS32("gCCRupeePrimR", &rupeeWalletColors[0][0]); rColor = CVar_GetRGB("gCCRupeePrim", rColor_ori);
rColor[1] = CVar_GetS32("gCCRupeePrimG", &rupeeWalletColors[0][1]);
rColor[2] = CVar_GetS32("gCCRupeePrimB", &rupeeWalletColors[0][2]);
} }
} else { } else {
//Custom colors is off so check if Dynamic Wallet is on. //Custom colors is off so check if Dynamic Wallet is on.
if (CVar_GetS32("gDynamicWalletIcon", 0) != 0) { if (CVar_GetS32("gDynamicWalletIcon", 0) != 0) {
rColor[0] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][0]; rColor.r = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][0];
rColor[1] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][1]; rColor.g = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][1];
rColor[2] = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][2]; rColor.b = rupeeWalletColors[CUR_UPG_VALUE(UPG_WALLET)][2];
} else { } else {
rColor[0] = rupeeWalletColors[0][0]; rColor.r = rupeeWalletColors[0][0];
rColor[1] = rupeeWalletColors[0][1]; rColor.g = rupeeWalletColors[0][1];
rColor[2] = rupeeWalletColors[0][2]; rColor.b = rupeeWalletColors[0][2];
} }
} }
if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gDynamicWalletIcon", 0) != 1) { if (CVar_GetS32("gHudColors", 1) == 2 && CVar_GetS32("gDynamicWalletIcon", 0) != 1) {
@ -4598,7 +4666,7 @@ void Interface_Draw(GlobalContext* globalCtx) {
PosY_RC = PosY_RC_ori; PosY_RC = PosY_RC_ori;
PosX_RC = PosX_RC_ori; PosX_RC = PosX_RC_ori;
} }
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor[0], rColor[1], rColor[2], interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor.r, rColor.g, rColor.b, interfaceCtx->magicAlpha);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10); OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, PosX_RC, PosY_RC, 16, 16, 1 << 10, 1 << 10);
switch (globalCtx->sceneNum) { switch (globalCtx->sceneNum) {
@ -4651,10 +4719,10 @@ void Interface_Draw(GlobalContext* globalCtx) {
gDPPipeSync(OVERLAY_DISP++); gDPPipeSync(OVERLAY_DISP++);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCKeysPrimR", 200), CVar_GetS32("gCCKeysPrimG", 230), CVar_GetS32("gCCKeysPrimB", 255), interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCKeysPrim", keyColor_ori).r,CVar_GetRGB("gCCKeysPrim", keyColor_ori).g,CVar_GetRGB("gCCKeysPrim", keyColor_ori).b, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :) gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :)
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 230, 255, interfaceCtx->magicAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, keyColor_ori.r, keyColor_ori.g, keyColor_ori.b, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255); gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255);
} }
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, PosX_SKC, PosY_SKC, 16, 16, OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, PosX_SKC, PosY_SKC, 16, 16,
@ -4909,9 +4977,9 @@ void Interface_Draw(GlobalContext* globalCtx) {
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
if (CVar_GetS32("gHudColors", 1) == 2) { if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCDpadPrimR", 255), CVar_GetS32("gCCDpadPrimG", 255), CVar_GetS32("gCCDpadPrimB", 255), dpadAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, DPad_colors.r,DPad_colors.g,DPad_colors.b, dpadAlpha);
} else { } else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, dpadAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, DPad_colors_ori.r,DPad_colors_ori.g,DPad_colors_ori.b, dpadAlpha);
} }
if (fullUi) { if (fullUi) {
gDPLoadTextureBlock(OVERLAY_DISP++, ResourceMgr_LoadFileRaw("assets/ship_of_harkinian/buttons/dpad.bin"), gDPLoadTextureBlock(OVERLAY_DISP++, ResourceMgr_LoadFileRaw("assets/ship_of_harkinian/buttons/dpad.bin"),
@ -4969,6 +5037,7 @@ void Interface_Draw(GlobalContext* globalCtx) {
// A Button // A Button
func_80094A14(globalCtx->state.gfxCtx); func_80094A14(globalCtx->state.gfxCtx);
const Color_RGB8 A_Button_Colors = {R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2)};
s16 X_Margins_BtnA; s16 X_Margins_BtnA;
s16 Y_Margins_BtnA; s16 Y_Margins_BtnA;
if (CVar_GetS32("gABtnUseMargins", 0) != 0) { if (CVar_GetS32("gABtnUseMargins", 0) != 0) {
@ -5015,9 +5084,9 @@ void Interface_Draw(GlobalContext* globalCtx) {
if (CVar_GetS32("gHudColors", 1) == 0) { if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 90, 90, 255, interfaceCtx->aAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 90, 90, 255, interfaceCtx->aAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) { } else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2), interfaceCtx->aAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, A_Button_Colors.r, A_Button_Colors.g, A_Button_Colors.b, interfaceCtx->aAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) { } else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", R_A_BTN_COLOR(0)), CVar_GetS32("gCCABtnPrimG", R_A_BTN_COLOR(1)), CVar_GetS32("gCCABtnPrimB", R_A_BTN_COLOR(2)), interfaceCtx->aAlpha); gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetRGB("gCCABtnPrim", A_Button_Colors).r,CVar_GetRGB("gCCABtnPrim", A_Button_Colors).g,CVar_GetRGB("gCCABtnPrim", A_Button_Colors).b, interfaceCtx->aAlpha);
} }
if (fullUi) { if (fullUi) {
Interface_DrawActionButton(globalCtx, PosX_BtnA, PosY_BtnA); Interface_DrawActionButton(globalCtx, PosX_BtnA, PosY_BtnA);

View File

@ -255,10 +255,10 @@ void GivePlayerRandoRewardSariaGift(GlobalContext* globalCtx, RandomizerCheck ch
if (gSaveContext.entranceIndex == 0x05E0) { if (gSaveContext.entranceIndex == 0x05E0) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY);
if ((!Flags_GetEventChkInf(0xC1) || (player->getItemId == getItemEntry.getItemId && getItemEntry.getItemId != GI_ICE_TRAP)) && if (!Flags_GetEventChkInf(0xC1) && player != NULL && !Player_InBlockingCsMode(globalCtx, player)) {
player != NULL && !Player_InBlockingCsMode(globalCtx, player)) {
GiveItemEntryWithoutActor(globalCtx, getItemEntry); GiveItemEntryWithoutActor(globalCtx, getItemEntry);
Flags_SetEventChkInf(0xC1); player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
player->pendingFlag.flagID = 0xC1;
} }
} }
} }
@ -415,6 +415,13 @@ void Gameplay_Init(GameState* thisx) {
PreRender_SetValues(&globalCtx->pauseBgPreRender, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); PreRender_SetValues(&globalCtx->pauseBgPreRender, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
gTrnsnUnkState = 0; gTrnsnUnkState = 0;
globalCtx->transitionMode = 0; globalCtx->transitionMode = 0;
if (CVar_GetS32("gSceneTransitions", 255)!= 255){
globalCtx->transitionMode = CVar_GetS32("gSceneTransitions", 0);
gSaveContext.nextTransition = CVar_GetS32("gSceneTransitions", 0);
globalCtx->fadeTransition = CVar_GetS32("gSceneTransitions", 0);
}
FrameAdvance_Init(&globalCtx->frameAdvCtx); FrameAdvance_Init(&globalCtx->frameAdvCtx);
Rand_Seed((u32)osGetTime()); Rand_Seed((u32)osGetTime());
Matrix_Init(&globalCtx->state); Matrix_Init(&globalCtx->state);

View File

@ -1170,7 +1170,13 @@ void Player_DrawGetItemImpl(GlobalContext* globalCtx, Player* this, Vec3f* refPo
Matrix_RotateZYX(0, globalCtx->gameplayFrames * 1000, 0, MTXMODE_APPLY); Matrix_RotateZYX(0, globalCtx->gameplayFrames * 1000, 0, MTXMODE_APPLY);
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY); Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
GetItem_Draw(globalCtx, drawIdPlusOne - 1); // RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future.
if (this->getItemEntry.drawFunc != NULL &&
(CVar_GetS32("gRandoMatchKeyColors", 0) || this->getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) {
this->getItemEntry.drawFunc(globalCtx, &this->getItemEntry);
} else {
GetItem_Draw(globalCtx, drawIdPlusOne - 1);
}
CLOSE_DISPS(globalCtx->state.gfxCtx); CLOSE_DISPS(globalCtx->state.gfxCtx);
} }

View File

@ -3,6 +3,8 @@
#include <string.h> #include <string.h>
#include <soh/Enhancements/randomizer/randomizerTypes.h> #include <soh/Enhancements/randomizer/randomizerTypes.h>
#include <soh/Enhancements/randomizer/randomizer_inf.h>
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define NUM_DUNGEONS 8 #define NUM_DUNGEONS 8
#define NUM_TRIALS 6 #define NUM_TRIALS 6
@ -309,6 +311,11 @@ void GiveLinkDekuNutUpgrade(GetItemID giid) {
} }
} }
void GiveLinkSkullToken() {
gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
gSaveContext.inventory.gsTokens++;
}
void GiveLinkMagic(GetItemID giid) { void GiveLinkMagic(GetItemID giid) {
if (giid == RG_MAGIC_SINGLE) { if (giid == RG_MAGIC_SINGLE) {
gSaveContext.magicLevel = 1; gSaveContext.magicLevel = 1;
@ -508,6 +515,53 @@ void GiveLinkDungeonItem(GetItemID getItemId) {
} }
} }
void GiveLinkAdultTradeItem(GetItemID giid) {
ItemID item;
switch (giid) {
case GI_POCKET_EGG:
item = ITEM_POCKET_EGG;
break;
case GI_POCKET_CUCCO:
item = ITEM_POCKET_CUCCO;
break;
case GI_COJIRO:
item = ITEM_COJIRO;
break;
case GI_ODD_MUSHROOM:
item = ITEM_ODD_MUSHROOM;
break;
case GI_ODD_POTION:
item = ITEM_ODD_POTION;
break;
case GI_SAW:
item = ITEM_SAW;
break;
case GI_SWORD_BROKEN:
item = ITEM_SWORD_BROKEN;
break;
case GI_PRESCRIPTION:
item = ITEM_PRESCRIPTION;
break;
case GI_FROG:
item = ITEM_FROG;
break;
case GI_EYEDROPS:
item = ITEM_EYEDROPS;
break;
case GI_CLAIM_CHECK:
item = ITEM_CLAIM_CHECK;
break;
}
if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
if (item >= ITEM_POCKET_EGG) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item);
}
INV_CONTENT(item) = item;
}
void GiveLinksPocketMedallion() { void GiveLinksPocketMedallion() {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
@ -704,24 +758,9 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
fileChooseCtx->n64ddFlag = 1; fileChooseCtx->n64ddFlag = 1;
gSaveContext.n64ddFlag = 1; gSaveContext.n64ddFlag = 1;
// Sets all the dungeons to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/82 // Sets all rando flags to false
for (u8 i = 0; i < NUM_DUNGEONS; i++) { for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
gSaveContext.dungeonsDone[i] = 0; gSaveContext.randomizerInf[i] = 0;
}
// Sets all Ganon's Trials to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131
for (u8 i = 0; i < NUM_TRIALS; i++) {
gSaveContext.trialsDone[i] = 0;
}
// Sets all cows to unmilked when generating a rando save.
for (u8 i = 0; i < NUM_COWS; i++) {
gSaveContext.cowsMilked[i] = 0;
}
// Sets all scrubs to not purchased when generating a rando save.
for (u8 i = 0; i < NUM_SCRUBS; i++) {
gSaveContext.scrubsPurchased[i] = 0;
} }
// Sets all shop items to not purchased when generating a rando save. // Sets all shop items to not purchased when generating a rando save.
@ -812,7 +851,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
s32 giid = getItem.getItemId; s32 giid = getItem.getItemId;
if (getItem.modIndex == MOD_NONE) { if (getItem.modIndex == MOD_NONE) {
if(getItem.itemId >= ITEM_KOKIRI_EMERALD && getItem.itemId <= ITEM_MEDALLION_LIGHT) { if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) {
GiveLinkDungeonReward(getItem.getItemId); GiveLinkDungeonReward(getItem.getItemId);
} else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED ||
giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) {
@ -869,6 +908,10 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkDekuStickUpgrade(giid); GiveLinkDekuStickUpgrade(giid);
} else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) { } else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) {
GiveLinkDekuNutUpgrade(giid); GiveLinkDekuNutUpgrade(giid);
} else if (giid == GI_SKULL_TOKEN) {
GiveLinkSkullToken();
} else if (giid >= GI_POCKET_EGG && giid <= GI_CLAIM_CHECK) {
GiveLinkAdultTradeItem(giid);
} else { } else {
s32 iid = getItem.itemId; s32 iid = getItem.itemId;
if (iid != -1) INV_CONTENT(iid) = iid; if (iid != -1) INV_CONTENT(iid) = iid;

View File

@ -194,6 +194,10 @@ void ArrowFire_Draw(Actor* thisx, GlobalContext* globalCtx2) {
u32 stateFrames; u32 stateFrames;
EnArrow* arrow; EnArrow* arrow;
Actor* tranform; Actor* tranform;
Color_RGB8 Arrow_env_ori = {255,0,0};
Color_RGB8 Arrow_col_ori = {255,200,0};
Color_RGB8 Arrow_env = CVar_GetRGB("gFireArrowColEnv", Arrow_env_ori);
Color_RGB8 Arrow_col = CVar_GetRGB("gFireArrowCol", Arrow_col_ori);
stateFrames = globalCtx->state.frames; stateFrames = globalCtx->state.frames;
arrow = (EnArrow*)this->actor.parent; arrow = (EnArrow*)this->actor.parent;
@ -214,9 +218,9 @@ void ArrowFire_Draw(Actor* thisx, GlobalContext* globalCtx2) {
POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP); POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0,
(s32)(CVar_GetS32("gFireArrowColEnvR", 40) * this->unk_15C) & 0xFF, (s32)(Arrow_env.r * this->unk_15C) & 0xFF,
(s32)(CVar_GetS32("gFireArrowColEnvG", 0) * this->unk_15C) & 0xFF, (s32)(Arrow_env.g * this->unk_15C) & 0xFF,
(s32)(CVar_GetS32("gFireArrowColEnvB", 0) * this->unk_15C) & 0xFF, (s32)(Arrow_env.b * this->unk_15C) & 0xFF,
(s32)(30.0f * this->unk_15C) & 0xFF); //Intentionnally made Alpha lower. (s32)(30.0f * this->unk_15C) & 0xFF); //Intentionnally made Alpha lower.
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s32)(40.0f * this->unk_15C) & 0xFF, 0, 0, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s32)(40.0f * this->unk_15C) & 0xFF, 0, 0,
@ -230,11 +234,11 @@ void ArrowFire_Draw(Actor* thisx, GlobalContext* globalCtx2) {
// Draw fire on the arrow // Draw fire on the arrow
func_80093D84(globalCtx->state.gfxCtx); func_80093D84(globalCtx->state.gfxCtx);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, CVar_GetS32("gFireArrowColR", 255), CVar_GetS32("gFireArrowColG", 200), CVar_GetS32("gFireArrowColB", 0), this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col.r, Arrow_col.g, Arrow_col.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, CVar_GetS32("gFireArrowColEnvR", 255), CVar_GetS32("gFireArrowColEnvG", 0), CVar_GetS32("gFireArrowColEnvB", 0), 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env.r, Arrow_env.g, Arrow_env.b, 128);
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 200, 0, this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col_ori.r, Arrow_col_ori.g, Arrow_col_ori.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env_ori.r, Arrow_env_ori.g, Arrow_env_ori.b, 128);
} }
Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY); Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY);
if (this->timer != 0) { if (this->timer != 0) {

View File

@ -195,6 +195,10 @@ void ArrowIce_Draw(Actor* thisx, GlobalContext* globalCtx) {
Actor* tranform; Actor* tranform;
u32 stateFrames = globalCtx->state.frames; u32 stateFrames = globalCtx->state.frames;
EnArrow* arrow = (EnArrow*)this->actor.parent; EnArrow* arrow = (EnArrow*)this->actor.parent;
Color_RGB8 Arrow_env_ori = {0,0,255};
Color_RGB8 Arrow_col_ori = {170, 255, 255};
Color_RGB8 Arrow_env = CVar_GetRGB("gIceArrowColEnv", Arrow_env_ori);
Color_RGB8 Arrow_col = CVar_GetRGB("gIceArrowCol", Arrow_col_ori);
if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) { if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) {
tranform = (arrow->hitFlags & 2) ? &this->actor : &arrow->actor; tranform = (arrow->hitFlags & 2) ? &this->actor : &arrow->actor;
@ -212,9 +216,9 @@ void ArrowIce_Draw(Actor* thisx, GlobalContext* globalCtx) {
POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP); POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0,
(s32)(CVar_GetS32("gIceArrowColEnvR", 0) * this->unk_164) & 0xFF, (s32)(Arrow_env.r * this->unk_164) & 0xFF,
(s32)(CVar_GetS32("gIceArrowColEnvG", 10) * this->unk_164) & 0xFF, (s32)(Arrow_env.g * this->unk_164) & 0xFF,
(s32)(CVar_GetS32("gIceArrowColEnvB", 50) * this->unk_164) & 0xFF, (s32)(Arrow_env.b * this->unk_164) & 0xFF,
(s32)(30.0f * this->unk_164) & 0xFF); //Intentionnally made Alpha lower. (s32)(30.0f * this->unk_164) & 0xFF); //Intentionnally made Alpha lower.
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, (s32)(10.0f * this->unk_164) & 0xFF, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, (s32)(10.0f * this->unk_164) & 0xFF,
@ -228,11 +232,11 @@ void ArrowIce_Draw(Actor* thisx, GlobalContext* globalCtx) {
// Draw ice on the arrow // Draw ice on the arrow
func_80093D84(globalCtx->state.gfxCtx); func_80093D84(globalCtx->state.gfxCtx);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, CVar_GetS32("gIceArrowColR", 170), CVar_GetS32("gIceArrowColG", 255), CVar_GetS32("gIceArrowColB", 255), this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col.r, Arrow_col.g, Arrow_col.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, CVar_GetS32("gIceArrowColEnvR", 0), CVar_GetS32("gIceArrowColEnvG", 0), CVar_GetS32("gIceArrowColEnvB", 255), 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env.r, Arrow_env.g, Arrow_env.b, 128);
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 170, 255, 255, this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col_ori.r, Arrow_col_ori.g, Arrow_col_ori.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 255, 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env_ori.r, Arrow_env_ori.g, Arrow_env_ori.b, 128);
} }
Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY); Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY);
if (this->timer != 0) { if (this->timer != 0) {

View File

@ -193,6 +193,10 @@ void ArrowLight_Draw(Actor* thisx, GlobalContext* globalCtx) {
u32 stateFrames = globalCtx->state.frames; u32 stateFrames = globalCtx->state.frames;
EnArrow* arrow = (EnArrow*)this->actor.parent; EnArrow* arrow = (EnArrow*)this->actor.parent;
Actor* tranform; Actor* tranform;
Color_RGB8 Arrow_env_ori = {255, 255, 0};
Color_RGB8 Arrow_col_ori = {255, 255, 170};
Color_RGB8 Arrow_env = CVar_GetRGB("gLightArrowColEnv", Arrow_env_ori);
Color_RGB8 Arrow_col = CVar_GetRGB("gLightArrowCol", Arrow_col_ori);
if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) { if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) {
tranform = (arrow->hitFlags & 2) ? &this->actor : &arrow->actor; tranform = (arrow->hitFlags & 2) ? &this->actor : &arrow->actor;
@ -210,9 +214,9 @@ void ArrowLight_Draw(Actor* thisx, GlobalContext* globalCtx) {
POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP); POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0,
(s32)(CVar_GetS32("gLightArrowColEnvR", 30) * this->unk_164) & 0xFF, (s32)(Arrow_env.r * this->unk_164) & 0xFF,
(s32)(CVar_GetS32("gLightArrowColEnvG", 40) * this->unk_164) & 0xFF, (s32)(Arrow_env.g * this->unk_164) & 0xFF,
(s32)(CVar_GetS32("gLightArrowColEnvB", 0) * this->unk_164) & 0xFF, (s32)(Arrow_env.b * this->unk_164) & 0xFF,
(s32)(30.0f * this->unk_164) & 0xFF); //Intentionnally made Alpha lower. (s32)(30.0f * this->unk_164) & 0xFF); //Intentionnally made Alpha lower.
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s32)(30.0f * this->unk_164) & 0xFF, gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s32)(30.0f * this->unk_164) & 0xFF,
@ -226,11 +230,11 @@ void ArrowLight_Draw(Actor* thisx, GlobalContext* globalCtx) {
// Draw light on the arrow // Draw light on the arrow
func_80093D84(globalCtx->state.gfxCtx); func_80093D84(globalCtx->state.gfxCtx);
if (CVar_GetS32("gUseArrowsCol", 0)) { if (CVar_GetS32("gUseArrowsCol", 0)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, CVar_GetS32("gLightArrowColR", 255), CVar_GetS32("gLightArrowColG", 255), CVar_GetS32("gLightArrowColB", 170), this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col.r, Arrow_col.g, Arrow_col.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, CVar_GetS32("gLightArrowColEnvR", 255), CVar_GetS32("gLightArrowColEnvG", 255), CVar_GetS32("gLightArrowColEnvB", 0), 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env.r, Arrow_env.g, Arrow_env.b, 128);
} else { } else {
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 170, this->alpha); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, Arrow_col_ori.r, Arrow_col_ori.g, Arrow_col_ori.b, this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 0, 128); gDPSetEnvColor(POLY_XLU_DISP++, Arrow_env_ori.r, Arrow_env_ori.g, Arrow_env_ori.b, 128);
} }
Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY); Matrix_RotateZYX(0x4000, 0x0, 0x0, MTXMODE_APPLY);
if (this->timer != 0) { if (this->timer != 0) {

View File

@ -132,35 +132,35 @@ u8 CheckMedallionCount() {
u8 CheckDungeonCount() { u8 CheckDungeonCount() {
u8 dungeonCount = 0; u8 dungeonCount = 0;
if (gSaveContext.dungeonsDone[0] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[1] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[2] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[3] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[4] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[5] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[6] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
dungeonCount++; dungeonCount++;
} }
if (gSaveContext.dungeonsDone[7] == 1) { if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
dungeonCount++; dungeonCount++;
} }

View File

@ -152,7 +152,7 @@ void BgSpot06Objects_Init(Actor* thisx, GlobalContext* globalCtx) {
if (LINK_IS_ADULT && if (LINK_IS_ADULT &&
((!gSaveContext.n64ddFlag && !(gSaveContext.eventChkInf[6] & 0x200)) || ((!gSaveContext.n64ddFlag && !(gSaveContext.eventChkInf[6] & 0x200)) ||
(gSaveContext.n64ddFlag && !gSaveContext.dungeonsDone[5]))) { (gSaveContext.n64ddFlag && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) {
if (gSaveContext.sceneSetupIndex < 4) { if (gSaveContext.sceneSetupIndex < 4) {
this->lakeHyliaWaterLevel = -681.0f; this->lakeHyliaWaterLevel = -681.0f;
globalCtx->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = globalCtx->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface =

View File

@ -2089,6 +2089,10 @@ void DemoEffect_DrawGetItem(Actor* thisx, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_BDAN) { if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_BDAN) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
this->getItem.drawId = getItemEntry.gid; this->getItem.drawId = getItemEntry.gid;
func_8002EBCC(thisx, globalCtx, 0);
func_8002ED80(thisx, globalCtx, 0);
GetItemEntry_Draw(globalCtx, getItemEntry);
return;
} }
func_8002EBCC(thisx, globalCtx, 0); func_8002EBCC(thisx, globalCtx, 0);
func_8002ED80(thisx, globalCtx, 0); func_8002ED80(thisx, globalCtx, 0);

View File

@ -76,27 +76,27 @@ s32 DemoKekkai_CheckEventFlag(s32 params) {
u32 TrialsDoneCount() { u32 TrialsDoneCount() {
u8 trialCount = 0; u8 trialCount = 0;
if (gSaveContext.trialsDone[0] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) {
trialCount++; trialCount++;
} }
if (gSaveContext.trialsDone[1] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) {
trialCount++; trialCount++;
} }
if (gSaveContext.trialsDone[2] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) {
trialCount++; trialCount++;
} }
if (gSaveContext.trialsDone[3] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) {
trialCount++; trialCount++;
} }
if (gSaveContext.trialsDone[4] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) {
trialCount++; trialCount++;
} }
if (gSaveContext.trialsDone[5] == 1) { if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) {
trialCount++; trialCount++;
} }
@ -249,22 +249,22 @@ void DemoKekkai_TrialBarrierDispel(Actor* thisx, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
switch (thisx->params) { switch (thisx->params) {
case KEKKAI_WATER: case KEKKAI_WATER:
gSaveContext.trialsDone[2] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL);
break; break;
case KEKKAI_LIGHT: case KEKKAI_LIGHT:
gSaveContext.trialsDone[5] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL);
break; break;
case KEKKAI_FIRE: case KEKKAI_FIRE:
gSaveContext.trialsDone[1] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL);
break; break;
case KEKKAI_SHADOW: case KEKKAI_SHADOW:
gSaveContext.trialsDone[3] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL);
break; break;
case KEKKAI_SPIRIT: case KEKKAI_SPIRIT:
gSaveContext.trialsDone[4] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL);
break; break;
case KEKKAI_FOREST: case KEKKAI_FOREST:
gSaveContext.trialsDone[0] = 1; Flags_SetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL);
break; break;
} }
Flags_SetEventChkInf(eventFlags[thisx->params]); Flags_SetEventChkInf(eventFlags[thisx->params]);

View File

@ -546,7 +546,7 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (globalCtx->sceneNum == SCENE_DDAN_BOSS) { if (globalCtx->sceneNum == SCENE_DDAN_BOSS) {
if (!Flags_GetEventChkInf(0x25)) { if (!Flags_GetEventChkInf(0x25)) {
Flags_SetEventChkInf(0x25); Flags_SetEventChkInf(0x25);
gSaveContext.dungeonsDone[0] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x47A; globalCtx->nextEntranceIndex = 0x47A;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
@ -563,7 +563,7 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (!Flags_GetEventChkInf(7) || gSaveContext.n64ddFlag) { if (!Flags_GetEventChkInf(7) || gSaveContext.n64ddFlag) {
Flags_SetEventChkInf(7); Flags_SetEventChkInf(7);
Flags_SetEventChkInf(9); Flags_SetEventChkInf(9);
gSaveContext.dungeonsDone[1] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x0457; globalCtx->nextEntranceIndex = 0x0457;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
@ -671,7 +671,7 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) { if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) {
gSaveContext.eventChkInf[3] |= 0x80; gSaveContext.eventChkInf[3] |= 0x80;
gSaveContext.dungeonsDone[2] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x10E; globalCtx->nextEntranceIndex = 0x10E;
@ -785,7 +785,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (globalCtx->sceneNum == SCENE_MORIBOSSROOM) { if (globalCtx->sceneNum == SCENE_MORIBOSSROOM) {
if (!(gSaveContext.eventChkInf[4] & 0x100)) { if (!(gSaveContext.eventChkInf[4] & 0x100)) {
gSaveContext.eventChkInf[4] |= 0x100; gSaveContext.eventChkInf[4] |= 0x100;
gSaveContext.dungeonsDone[3] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x608; globalCtx->nextEntranceIndex = 0x608;
@ -807,7 +807,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} else if (globalCtx->sceneNum == SCENE_FIRE_BS) { } else if (globalCtx->sceneNum == SCENE_FIRE_BS) {
if (!(gSaveContext.eventChkInf[4] & 0x200)) { if (!(gSaveContext.eventChkInf[4] & 0x200)) {
gSaveContext.eventChkInf[4] |= 0x200; gSaveContext.eventChkInf[4] |= 0x200;
gSaveContext.dungeonsDone[4] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x564; globalCtx->nextEntranceIndex = 0x564;
@ -828,7 +828,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} else if (globalCtx->sceneNum == SCENE_MIZUSIN_BS) { } else if (globalCtx->sceneNum == SCENE_MIZUSIN_BS) {
if (!(gSaveContext.eventChkInf[4] & 0x400)) { if (!(gSaveContext.eventChkInf[4] & 0x400)) {
gSaveContext.eventChkInf[4] |= 0x400; gSaveContext.eventChkInf[4] |= 0x400;
gSaveContext.dungeonsDone[5] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x60C; globalCtx->nextEntranceIndex = 0x60C;
@ -849,7 +849,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} }
} else if (globalCtx->sceneNum == SCENE_JYASINBOSS) { } else if (globalCtx->sceneNum == SCENE_JYASINBOSS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || gSaveContext.n64ddFlag) { if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || gSaveContext.n64ddFlag) {
gSaveContext.dungeonsDone[6] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x610; globalCtx->nextEntranceIndex = 0x610;
@ -870,7 +870,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} }
} else if (globalCtx->sceneNum == SCENE_HAKADAN_BS) { } else if (globalCtx->sceneNum == SCENE_HAKADAN_BS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || gSaveContext.n64ddFlag) { if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || gSaveContext.n64ddFlag) {
gSaveContext.dungeonsDone[7] = 1; Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x580; globalCtx->nextEntranceIndex = 0x580;

View File

@ -218,51 +218,51 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) {
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) { CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) {
struct CowInfo cowInfo; struct CowInfo cowInfo;
cowInfo.cowId = -1; cowInfo.randomizerInf = -1;
cowInfo.randomizerCheck = RC_UNKNOWN_CHECK; cowInfo.randomizerCheck = RC_UNKNOWN_CHECK;
switch (globalCtx->sceneNum) { switch (globalCtx->sceneNum) {
case SCENE_SOUKO: // Lon Lon Tower case SCENE_SOUKO: // Lon Lon Tower
if (this->actor.world.pos.x == -229 && this->actor.world.pos.z == 157) { if (this->actor.world.pos.x == -229 && this->actor.world.pos.z == 157) {
cowInfo.cowId = 0; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_LEFT_COW; cowInfo.randomizerCheck = RC_LLR_TOWER_LEFT_COW;
} else if (this->actor.world.pos.x == -142 && this->actor.world.pos.z == -140) { } else if (this->actor.world.pos.x == -142 && this->actor.world.pos.z == -140) {
cowInfo.cowId = 1; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_RIGHT_COW; cowInfo.randomizerCheck = RC_LLR_TOWER_RIGHT_COW;
} }
break; break;
case SCENE_MALON_STABLE: case SCENE_MALON_STABLE:
if (this->actor.world.pos.x == 116 && this->actor.world.pos.z == -254) { if (this->actor.world.pos.x == 116 && this->actor.world.pos.z == -254) {
cowInfo.cowId = 2; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_RIGHT_COW; cowInfo.randomizerCheck = RC_LLR_STABLES_RIGHT_COW;
} else if (this->actor.world.pos.x == -122 && this->actor.world.pos.z == -254) { } else if (this->actor.world.pos.x == -122 && this->actor.world.pos.z == -254) {
cowInfo.cowId = 3; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_LEFT_COW; cowInfo.randomizerCheck = RC_LLR_STABLES_LEFT_COW;
} }
break; break;
case SCENE_KAKUSIANA: // Grotto case SCENE_KAKUSIANA: // Grotto
if (this->actor.world.pos.x == 2444 && this->actor.world.pos.z == -471) { if (this->actor.world.pos.x == 2444 && this->actor.world.pos.z == -471) {
cowInfo.cowId = 4; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_DMT_COW_GROTTO_COW; cowInfo.randomizerCheck = RC_DMT_COW_GROTTO_COW;
} else if (this->actor.world.pos.x == 3485 && this->actor.world.pos.z == -291) { } else if (this->actor.world.pos.x == 3485 && this->actor.world.pos.z == -291) {
cowInfo.cowId = 5; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_HF_COW_GROTTO_COW; cowInfo.randomizerCheck = RC_HF_COW_GROTTO_COW;
} }
break; break;
case SCENE_LINK_HOME: case SCENE_LINK_HOME:
cowInfo.cowId = 6; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LINKS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KF_LINKS_HOUSE_COW; cowInfo.randomizerCheck = RC_KF_LINKS_HOUSE_COW;
break; break;
case SCENE_LABO: // Impa's house case SCENE_LABO: // Impa's house
cowInfo.cowId = 7; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KAK_IMPAS_HOUSE_COW; cowInfo.randomizerCheck = RC_KAK_IMPAS_HOUSE_COW;
break; break;
case SCENE_SPOT09: // Gerudo Valley case SCENE_SPOT09: // Gerudo Valley
cowInfo.cowId = 8; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_GV_COW;
cowInfo.randomizerCheck = RC_GV_COW; cowInfo.randomizerCheck = RC_GV_COW;
break; break;
case SCENE_SPOT08: // Jabu's Belly case SCENE_BDAN: // Jabu's Belly
cowInfo.cowId = 9; cowInfo.randomizerInf = RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW;
cowInfo.randomizerCheck = RC_JABU_JABUS_BELLY_MQ_COW; cowInfo.randomizerCheck = RC_JABU_JABUS_BELLY_MQ_COW;
break; break;
} }
@ -290,8 +290,8 @@ void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) {
void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) { void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
Player* player = GET_PLAYER(globalCtx); Player* player = GET_PLAYER(globalCtx);
player->pendingFlag.flagID = cowInfo.cowId; player->pendingFlag.flagID = cowInfo.randomizerInf;
player->pendingFlag.flagType = FLAG_COW_MILKED; player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
} }
void func_809DF778(EnCow* this, GlobalContext* globalCtx) { void func_809DF778(EnCow* this, GlobalContext* globalCtx) {
@ -337,7 +337,7 @@ void func_809DF8FC(EnCow* this, GlobalContext* globalCtx) {
bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) { bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx); CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
return gSaveContext.cowsMilked[cowInfo.cowId]; return Flags_GetRandomizerInf(cowInfo.randomizerInf);
} }
void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) { void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) {

View File

@ -22,7 +22,7 @@ typedef struct EnCow {
} EnCow; // size = 0x0280 } EnCow; // size = 0x0280
typedef struct CowInfo { typedef struct CowInfo {
int cowId; RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck; RandomizerCheck randomizerCheck;
} CowInfo; } CowInfo;

View File

@ -168,6 +168,7 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actor.textId = D_809F040C[this->actor.params]; this->actor.textId = D_809F040C[this->actor.params];
this->dnsItemEntry = sItemEntries[this->actor.params]; this->dnsItemEntry = sItemEntries[this->actor.params];
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
// Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
this->scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData); this->scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
@ -180,6 +181,8 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck; this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck;
this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase; this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase;
this->dnsItemEntry->itemAmount = 1; this->dnsItemEntry->itemAmount = 1;
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice; this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
} }
} }
@ -204,7 +207,7 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
/* Item give checking functions */ /* Item give checking functions */
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) { u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) {
if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] == 1) { if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) {
return 0; return 0;
} }
return 4; return 4;
@ -308,7 +311,7 @@ u32 func_809EF9A4(EnDns* this) {
/* Paying and flagging functions */ /* Paying and flagging functions */
void EnDns_RandomizerPurchase(EnDns* this) { void EnDns_RandomizerPurchase(EnDns* this) {
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] = 1; Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf);
} }
void func_809EF9F8(EnDns* this) { void func_809EF9F8(EnDns* this) {
@ -513,6 +516,8 @@ void EnDns_Update(Actor* thisx, GlobalContext* globalCtx) {
this->dustTimer++; this->dustTimer++;
this->actor.textId = D_809F040C[this->actor.params]; this->actor.textId = D_809F040C[this->actor.params];
if (gSaveContext.n64ddFlag && this->scrubIdentity.isShuffled) { if (gSaveContext.n64ddFlag && this->scrubIdentity.isShuffled) {
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice; this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
} }
Actor_SetFocus(&this->actor, 60.0f); Actor_SetFocus(&this->actor, 60.0f);

View File

@ -472,6 +472,10 @@ void EnDog_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Ve
void EnDog_Draw(Actor* thisx, GlobalContext* globalCtx) { void EnDog_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnDog* this = (EnDog*)thisx; EnDog* this = (EnDog*)thisx;
Color_RGBA8 colors[] = { { 255, 255, 200, 0 }, { 150, 100, 50, 0 } }; Color_RGBA8 colors[] = { { 255, 255, 200, 0 }, { 150, 100, 50, 0 } };
Color_RGB8 Dog1_ori = {colors[0].r, colors[0].g, colors[0].b};
Color_RGB8 Dog2_ori = {colors[1].r, colors[1].g, colors[1].b};
Color_RGB8 Dog1 = CVar_GetRGB("gDog1Col", Dog1_ori);
Color_RGB8 Dog2 = CVar_GetRGB("gDog2Col", Dog2_ori);
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
@ -479,19 +483,19 @@ void EnDog_Draw(Actor* thisx, GlobalContext* globalCtx) {
gDPPipeSync(POLY_OPA_DISP++); gDPPipeSync(POLY_OPA_DISP++);
if (CVar_GetS32("gUseDogsCol",0)) { if (CVar_GetS32("gUseDogsCol",0)) {
colors[0].r = CVar_GetS32("gDog1ColR", 255); colors[0].r = Dog1.r;
colors[0].g = CVar_GetS32("gDog1ColG", 255); colors[0].g = Dog1.g;
colors[0].b = CVar_GetS32("gDog1ColB", 200); colors[0].b = Dog1.b;
colors[1].r = CVar_GetS32("gDog2ColR", 150); colors[1].r = Dog2.r;
colors[1].g = CVar_GetS32("gDog2ColG", 100); colors[1].g = Dog2.g;
colors[1].b = CVar_GetS32("gDog2ColB", 50); colors[1].b = Dog2.b;
} else { } else {
colors[0].r = 255; colors[0].r = Dog1_ori.r;
colors[0].g = 255; colors[0].g = Dog1_ori.g;
colors[0].b = 200; colors[0].b = Dog1_ori.b;
colors[1].r = 150; colors[1].r = Dog2_ori.r;
colors[1].g = 100; colors[1].g = Dog2_ori.g;
colors[1].b = 50; colors[1].b = Dog2_ori.b;
} }
gDPSetEnvColor(POLY_OPA_DISP++, colors[this->actor.params & 0xF].r, colors[this->actor.params & 0xF].g, gDPSetEnvColor(POLY_OPA_DISP++, colors[this->actor.params & 0xF].r, colors[this->actor.params & 0xF].g,
colors[this->actor.params & 0xF].b, colors[this->actor.params & 0xF].a); colors[this->actor.params & 0xF].b, colors[this->actor.params & 0xF].a);

View File

@ -521,9 +521,14 @@ void EnExItem_DrawItems(EnExItem* this, GlobalContext* globalCtx) {
case EXITEM_BOMBCHUS_COUNTER: case EXITEM_BOMBCHUS_COUNTER:
randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10);
break; break;
case EXITEM_BULLET_BAG:
randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50);
break;
} }
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
GetItemEntry_Draw(globalCtx, randoGetItem);
return;
} }
GetItem_Draw(globalCtx, this->giDrawId); GetItem_Draw(globalCtx, this->giDrawId);
@ -536,7 +541,7 @@ void EnExItem_DrawHeartPiece(EnExItem* this, GlobalContext* globalCtx) {
GetItemEntry randoGetItem = GetItemEntry randoGetItem =
Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
GetItem_Draw(globalCtx, randoGetItem.gid); GetItemEntry_Draw(globalCtx, randoGetItem);
} else { } else {
GetItem_Draw(globalCtx, GID_HEART_PIECE); GetItem_Draw(globalCtx, GID_HEART_PIECE);
} }

Some files were not shown because too many files have changed in this diff Show More