diff --git a/.gitignore b/.gitignore index 5a201405d..4b6eb3968 100644 --- a/.gitignore +++ b/.gitignore @@ -405,3 +405,4 @@ tags oot.otr *.sav shipofharkinian.ini +shipofharkinian.json \ No newline at end of file diff --git a/BUILDING.md b/BUILDING.md index 08ea20b35..1821f2bc3 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -12,7 +12,7 @@ 8. Build the solution. 9. Launching `OTRExporter/extract_assets.py` will generate an `oot.otr` archive file in `OTRExporter/oot.otr`. 10. Run `soh/soh.sln` - 11. Switch the solution to `Release x86`. + 11. Switch the solution to `Release x86` or `Release x64`. 12. Build the solution. 13. Copy the `OTRExporter/oot.otr` archive file to `soh/Release`. 14. Launch `soh.exe`. @@ -63,9 +63,10 @@ make setup -j8 DEBUG=0 # Compile the code (watch the -j parameter as above) make -j8 DEBUG=0 # Create macOS app bundle -make filledappbundle +make appbundle ``` -9. Launch soh app in the soh folder! +9. Copy your OTR file to ~/Library/Application\ Support/com.shipofharkinian.soh +10. Launch soh app in the soh folder! # Compatible Roms ``` diff --git a/Jenkinsfile b/Jenkinsfile index 8ea6317a4..7f3589ec8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -125,6 +125,11 @@ pipeline { agent { label "SoH-Mac-Builders" } + environment { + CC = 'clang -arch arm64 -arch x86_64' + CXX = 'clang++ -arch arm64 -arch x86_64' + MACOSX_DEPLOYMENT_TARGET = 10.15 + } steps { checkout([ $class: 'GitSCM', @@ -137,8 +142,8 @@ pipeline { sh ''' cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 cd soh - export CC="clang -arch arm64 -arch x86_64"; export CXX="clang++ -arch arm64 -arch x86_64"; make setup -j4 OPTFLAGS=-O2 DEBUG=0 LD="ld" - export CC="clang -arch arm64 -arch x86_64"; export CXX="clang++ -arch arm64 -arch x86_64"; make -j4 DEBUG=0 OPTFLAGS=-O2 LD="ld" + make setup -j4 OPTFLAGS=-O2 DEBUG=0 LD="ld" + make -j4 DEBUG=0 OPTFLAGS=-O2 LD="ld" make -j4 appbundle mv ../README.md readme.txt 7z a soh-mac.7z soh.app readme.txt diff --git a/OTRExporter/extract_assets.py b/OTRExporter/extract_assets.py index 67b4ca6e4..6862fb074 100755 --- a/OTRExporter/extract_assets.py +++ b/OTRExporter/extract_assets.py @@ -4,10 +4,15 @@ import os, sys, shutil import shutil from rom_info import Z64Rom import rom_chooser +import struct def BuildOTR(xmlPath, rom): shutil.copytree("assets", "Extract/assets") + checksum = int(Z64Rom(rom).checksum.value, 16) + with open("Extract/version", "wb") as f: + f.write(struct.pack(' /dev/null 2>&1 cp "$ASSETDIR"/oot.otr "$OLDPWD" echo "Restart $APPIMAGE to play!" @@ -31,7 +42,11 @@ while [[ ! -e "$PWD"/oot.otr ]]; do rm -r "$ASSETDIR" break else - echo -e "\nPlace ROM in this folder\n" + if [ -n "$ZENITY" ]; then + zenity --error --timeout=5 --text="Place ROM in $OWD" --title="Missing ROM file" --width=500 --width=200 + else + echo -e "\nPlace ROM in this folder\n" + fi exit fi done diff --git a/libultraship/Makefile b/libultraship/Makefile index b3b7d2836..18dfca271 100644 --- a/libultraship/Makefile +++ b/libultraship/Makefile @@ -2,7 +2,7 @@ CXX ?= g++ CC ?= gcc -AR := ar +AR := ar FORMAT := clang-format-11 UNAME := $(shell uname) @@ -11,6 +11,15 @@ DEBUG ?= 1 OPTFLAGS ?= -O0 LTO ?= 0 +# flag to save whether the compiler being used is clang or gcc by checking CXX --version +CXX_IS_CLANG ?= $(shell $(CXX) --version | grep -c clang) +ifeq ($(CXX_IS_CLANG),1) + MXX := $(CXX) +else + MXX ?= clang++ +endif + + WARN := -Wall -Wextra -Werror \ -Wno-unused-variable \ -Wno-unused-parameter \ @@ -29,8 +38,7 @@ WARN := -Wall -Wextra -Werror \ CWARN := CXXWARN := -Wno-deprecated-enum-enum-conversion -Wno-deprecated-copy -COMPILER_VERSION := $(shell $(CXX) --version) -ifneq '' '$(findstring g++,$(COMPILER_VERSION))' +ifneq ($(CXX_IS_CLANG),1) WARN += -Wno-error=stringop-overflow CXXWARN += -Wno-error=maybe-uninitialized endif @@ -39,12 +47,17 @@ CXXFLAGS := $(WARN) $(CXXWARN) -std=c++20 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG CFLAGS := $(WARN) $(CWARN) -std=c99 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0 CPPFLAGS := -MMD -ifeq ($(UNAME), Darwin) #APPLE - CPPFLAGS += $(shell pkg-config --cflags sdl2 glew) -framework OpenGL +MMFLAGS := -Wno-deprecated-declarations -ObjC++ -fobjc-weak -fobjc-arc + +# if not using clang, ask clang to use gcc standard library +ifneq ($(CXX_IS_CLANG),1) + STD_ISYSTEM=$(shell ${CXX} -xc++ -E -v - < /dev/null 2>&1 | grep "> search starts here" -A2 | tail -n 2 | head -n 1) + CXX_ISYSTEM=$(shell ${CXX} -xc++ -E -v - < /dev/null 2>&1 | grep "> search starts here" -A2 | tail -n 2 | tail -n 1) + MMFLAGS += -stdlib++-isystem ${STD_ISYSTEM} -cxx-isystem ${CXX_ISYSTEM} endif -ifeq ($(UNAME), Linux) - WARN += -Wno-error=stringop-overflow # This is required with clang on Linux. +ifeq ($(UNAME), Darwin) #APPLE + CPPFLAGS += $(shell pkg-config --cflags sdl2 glew) -framework OpenGL -framework Foundation endif ifneq ($(DEBUG),0) @@ -69,6 +82,7 @@ CXX_FILES := \ $(shell find libultraship/Lib/Fast3D -name "*.cpp") \ $(shell find libultraship -maxdepth 1 -name "*.cpp") \ $(shell find libultraship/Lib/ImGui -maxdepth 1 -name "*.cpp") \ + $(shell find libultraship/Lib/Mercury -maxdepth 1 -name "*.cpp") \ libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp \ libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp \ libultraship/Lib/StrHash64.cpp \ @@ -78,12 +92,19 @@ C_FILES := \ libultraship/mixer.c \ libultraship/Lib/stb/stb_impl.c +MM_FILES := \ + libultraship/OSXFolderManager.mm + FMT_FILES := $(shell find libultraship/ -type f \( -name "*.cpp" -o -name "*.h" \) -a -not -path "libultraship/Lib/*") O_FILES := \ $(CXX_FILES:%.cpp=build/%.o) \ $(C_FILES:%.c=build/%.o) +ifeq ($(UNAME), Darwin) #APPLE + O_FILES += $(MM_FILES:%.mm=build/%.o) +endif + D_FILES := $(O_FILES:%.o=%.d) LIB := libultraship.a @@ -94,6 +115,7 @@ INC_DIRS := $(addprefix -I, \ libultraship/Lib/spdlog \ libultraship/Lib/spdlog/include \ libultraship/Lib/ImGui \ + libultraship/Lib/Mercury \ libultraship \ ../StormLib/src \ ) @@ -117,6 +139,9 @@ build/%.o: %.cpp build/%.o: %.c $(CC) $(CFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(INC_DIRS) -c $< -o $@ +build/%.o: %.mm + $(MXX) $(MMFLAGS) $(CXXFLAGS) $(OPTFLAGS) $(INC_DIRS) -c $< -o $@ + $(LIB): $(O_FILES) $(AR) rcs $@ $^ diff --git a/libultraship/libultraship/ConfigFile.cpp b/libultraship/libultraship/ConfigFile.cpp deleted file mode 100644 index 43dde4d8a..000000000 --- a/libultraship/libultraship/ConfigFile.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "ConfigFile.h" -#include "spdlog/spdlog.h" -#include "GlobalCtx2.h" -#include "Window.h" -#include "GameSettings.h" - -namespace Ship { - ConfigFile::ConfigFile(std::shared_ptr Context, const std::string& Path) : Context(Context), Path(Path), File(Path.c_str()) { - if (Path.empty()) { - SPDLOG_ERROR("ConfigFile received an empty file name"); - exit(EXIT_FAILURE); - } - - if (!File.read(Val)) { - if (!CreateDefaultConfig()) { - SPDLOG_ERROR("Failed to create default configs"); - exit(EXIT_FAILURE); - } - } - } - - ConfigFile::~ConfigFile() { - if (!Save()) { - SPDLOG_ERROR("Failed to save configs!!!"); - } - - SPDLOG_INFO("destruct configfile"); - } - - mINI::INIMap& ConfigFile::operator[](const std::string& Section) { - return Val[Section]; - } - - mINI::INIMap ConfigFile::get(const std::string& Section) { - return Val.get(Section); - } - - bool ConfigFile::has(const std::string& Section) { - return Val.has(Section); - } - - bool ConfigFile::remove(const std::string& Section) { - return Val.remove(Section); - } - - void ConfigFile::clear() { - Val.clear(); - } - - std::size_t ConfigFile::size() const { - return Val.size(); - } - - bool ConfigFile::Save() { - return File.write(Val); - } - - bool ConfigFile::CreateDefaultConfig() { - (*this)["ARCHIVE"]["Main Archive"] = "oot.otr"; - (*this)["ARCHIVE"]["Patches Directory"] = ""; - - (*this)["SAVE"]["Save Filename"] = "oot_save.sav"; - - (*this)["CONTROLLERS"]["CONTROLLER 1"] = "Auto"; - (*this)["CONTROLLERS"]["CONTROLLER 2"] = "Unplugged"; - (*this)["CONTROLLERS"]["CONTROLLER 3"] = "Unplugged"; - (*this)["CONTROLLERS"]["CONTROLLER 4"] = "Unplugged"; - - (*this)["KEYBOARD SHORTCUTS"]["KEY_FULLSCREEN"] = std::to_string(0x044); - (*this)["KEYBOARD SHORTCUTS"]["KEY_CONSOLE"] = std::to_string(0x029); - - (*this)["WINDOW"]["WINDOW WIDTH"] = std::to_string(640); - (*this)["WINDOW"]["WINDOW HEIGHT"] = std::to_string(480); - (*this)["WINDOW"]["FULLSCREEN WIDTH"] = std::to_string(1920); - (*this)["WINDOW"]["FULLSCREEN HEIGHT"] = std::to_string(1080); - (*this)["WINDOW"]["FULLSCREEN"] = std::to_string(false); - (*this)["WINDOW"]["GFX BACKEND"] = ""; - - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CRIGHT)] = std::to_string(0x14D); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CLEFT)] = std::to_string(0x14B); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CDOWN)] = std::to_string(0x150); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CUP)] = std::to_string(0x148); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_R)] = std::to_string(0x013); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_L)] = std::to_string(0x012); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_DRIGHT)] = std::to_string(0x023); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_DLEFT)] = std::to_string(0x021); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_DDOWN)] = std::to_string(0x022); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_DUP)] = std::to_string(0x014); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_START)] = std::to_string(0x039); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_Z)] = std::to_string(0x02C); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_B)] = std::to_string(0x02E); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_A)] = std::to_string(0x02D); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_STICKRIGHT)] = std::to_string(0x020); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_STICKLEFT)] = std::to_string(0x01E); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_STICKDOWN)] = std::to_string(0x01F); - (*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_STICKUP)] = std::to_string(0x011); - - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_CRIGHT)] = std::to_string(0x14D); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_CLEFT)] = std::to_string(0x14B); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_CDOWN)] = std::to_string(0x150); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_CUP)] = std::to_string(0x148); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_R)] = std::to_string(0x013); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_L)] = std::to_string(0x012); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_DRIGHT)] = std::to_string(0x023); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_DLEFT)] = std::to_string(0x021); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_DDOWN)] = std::to_string(0x022); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_DUP)] = std::to_string(0x014); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_START)] = std::to_string(0x039); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_Z)] = std::to_string(0x02C); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_B)] = std::to_string(0x02E); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_A)] = std::to_string(0x02D); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_STICKRIGHT)] = std::to_string(0x020); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_STICKLEFT)] = std::to_string(0x01E); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_STICKDOWN)] = std::to_string(0x01F); - (*this)["KEYBOARD CONTROLLER BINDING 2"][STR(BTN_STICKUP)] = std::to_string(0x011); - - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_CRIGHT)] = std::to_string(0x14D); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_CLEFT)] = std::to_string(0x14B); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_CDOWN)] = std::to_string(0x150); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_CUP)] = std::to_string(0x148); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_R)] = std::to_string(0x013); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_L)] = std::to_string(0x012); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_DRIGHT)] = std::to_string(0x023); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_DLEFT)] = std::to_string(0x021); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_DDOWN)] = std::to_string(0x022); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_DUP)] = std::to_string(0x014); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_START)] = std::to_string(0x039); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_Z)] = std::to_string(0x02C); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_B)] = std::to_string(0x02E); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_A)] = std::to_string(0x02D); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_STICKRIGHT)] = std::to_string(0x020); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_STICKLEFT)] = std::to_string(0x01E); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_STICKDOWN)] = std::to_string(0x01F); - (*this)["KEYBOARD CONTROLLER BINDING 3"][STR(BTN_STICKUP)] = std::to_string(0x011); - - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_CRIGHT)] = std::to_string(0x14D); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_CLEFT)] = std::to_string(0x14B); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_CDOWN)] = std::to_string(0x150); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_CUP)] = std::to_string(0x148); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_R)] = std::to_string(0x013); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_L)] = std::to_string(0x012); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_DRIGHT)] = std::to_string(0x023); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_DLEFT)] = std::to_string(0x021); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_DDOWN)] = std::to_string(0x022); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_DUP)] = std::to_string(0x014); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_START)] = std::to_string(0x039); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_Z)] = std::to_string(0x02C); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_B)] = std::to_string(0x02E); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_A)] = std::to_string(0x02D); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_STICKRIGHT)] = std::to_string(0x020); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_STICKLEFT)] = std::to_string(0x01E); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_STICKDOWN)] = std::to_string(0x01F); - (*this)["KEYBOARD CONTROLLER BINDING 4"][STR(BTN_STICKUP)] = std::to_string(0x011); - - (*this)["ENHANCEMENT SETTINGS"]["TEXT_SPEED"] = "1"; - - (*this)["SDL CONTROLLER 1"]["GUID"] = ""; - (*this)["SDL CONTROLLER 2"]["GUID"] = ""; - (*this)["SDL CONTROLLER 3"]["GUID"] = ""; - (*this)["SDL CONTROLLER 4"]["GUID"] = ""; - - return File.generate(Val); - } -} diff --git a/libultraship/libultraship/ConfigFile.h b/libultraship/libultraship/ConfigFile.h deleted file mode 100644 index b94e22f88..000000000 --- a/libultraship/libultraship/ConfigFile.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef CONFIG_FILE_H -#define CONFIG_FILE_H - -#pragma once - -#include -#include -#include "Lib/mINI/src/mini/ini.h" -#include "UltraController.h" -#include "LUSMacros.h" - -namespace Ship { - class GlobalCtx2; - - class ConfigFile { - public: - ConfigFile(std::shared_ptr Context, const std::string& Path); - ~ConfigFile(); - - bool Save(); - - // Expose the ini values. - mINI::INIMap& operator[](const std::string& Section); - mINI::INIMap get(const std::string& Section); - bool has(const std::string& Section); - bool remove(const std::string& Section); - void clear(); - std::size_t size() const; - std::shared_ptr GetContext() { return Context.lock(); } - - protected: - bool CreateDefaultConfig(); - - private: - mINI::INIStructure Val; - std::weak_ptr Context; - std::string Path; - mINI::INIFile File; - }; -} - -#endif diff --git a/libultraship/libultraship/ControlDeck.cpp b/libultraship/libultraship/ControlDeck.cpp new file mode 100644 index 000000000..ff7a1d243 --- /dev/null +++ b/libultraship/libultraship/ControlDeck.cpp @@ -0,0 +1,146 @@ +#include "ControlDeck.h" + +#include "Window.h" +#include "Controller.h" +#include "DisconnectedController.h" +#include "KeyboardController.h" +#include "SDLController.h" +#include + +uint8_t* controllerBits; + +void Ship::ControlDeck::Init(uint8_t* bits) { + ScanPhysicalDevices(); + controllerBits = bits; +} + +void Ship::ControlDeck::ScanPhysicalDevices() { + + virtualDevices.clear(); + physicalDevices.clear(); + + for (int i = 0; i < SDL_NumJoysticks(); i++) { + if (SDL_IsGameController(i)) { + auto sdl = std::make_shared(i); + sdl->Open(); + physicalDevices.push_back(sdl); + } + } + + physicalDevices.push_back(std::make_shared()); + physicalDevices.push_back(std::make_shared()); + + for (const auto& device : physicalDevices) { + for (int i = 0; i < MAXCONTROLLERS; i++) { + device->CreateDefaultBinding(i); + } + } + + for (int i = 0; i < MAXCONTROLLERS; i++) { + virtualDevices.push_back(i == 0 ? 0 : static_cast(physicalDevices.size()) - 1); + } + + LoadControllerSettings(); +} + +void Ship::ControlDeck::SetPhysicalDevice(int slot, int deviceSlot) { + const std::shared_ptr backend = physicalDevices[deviceSlot]; + virtualDevices[slot] = deviceSlot; + *controllerBits |= (backend->Connected()) << slot; +} + +void Ship::ControlDeck::WriteToPad(OSContPad* pad) const { + for (size_t i = 0; i < virtualDevices.size(); i++) { + physicalDevices[virtualDevices[i]]->Read(&pad[i], i); + } +} + +#define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), slot, __VA_ARGS__) + +void Ship::ControlDeck::LoadControllerSettings() { + std::shared_ptr Config = GlobalCtx2::GetInstance()->GetConfig(); + + for (auto const& val : Config->rjson["Controllers"]["Deck"].items()) { + int slot = std::stoi(val.key().substr(5)); + + for (size_t dev = 0; dev < physicalDevices.size(); dev++) { + std::string guid = physicalDevices[dev]->GetGuid(); + if(guid != val.value()) continue; + + virtualDevices[slot] = dev; + } + } + + for (size_t i = 0; i < virtualDevices.size(); i++) { + std::shared_ptr backend = physicalDevices[virtualDevices[i]]; + Config->setString(StringHelper::Sprintf("Controllers.Deck.Slot_%d", (int)i), backend->GetGuid()); + } + + for (const auto& device : physicalDevices) { + + std::string guid = device->GetGuid(); + + for (int slot = 0; slot < MAXCONTROLLERS; slot++) { + + if (!(Config->rjson["Controllers"].contains(guid) && Config->rjson["Controllers"][guid].contains(StringHelper::Sprintf("Slot_%d", slot)))) continue; + + auto& profile = device->profiles[slot]; + auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", slot)]; + + profile.Mappings.clear(); + profile.Thresholds.clear(); + profile.UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); + profile.RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); + profile.UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); + + for (auto const& val : rawProfile["Thresholds"].items()) { + profile.Thresholds[static_cast(std::stoi(val.key()))] = val.value(); + } + + for (auto const& val : rawProfile["Mappings"].items()) { + device->SetButtonMapping(slot, std::stoi(val.key().substr(4)), val.value()); + } + } + } +} + +void Ship::ControlDeck::SaveControllerSettings() { + std::shared_ptr Config = GlobalCtx2::GetInstance()->GetConfig(); + + for (size_t i = 0; i < virtualDevices.size(); i++) { + std::shared_ptr backend = physicalDevices[virtualDevices[i]]; + Config->setString(StringHelper::Sprintf("Controllers.Deck.Slot_%d", (int)i), backend->GetGuid()); + } + + for (const auto& device : physicalDevices) { + + int slot = 0; + std::string guid = device->GetGuid(); + + for (const auto& profile : device->profiles) { + + if (!device->Connected()) continue; + + auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", slot)]; + Config->setBool(NESTED("Rumble.Enabled", ""), profile.UseRumble); + Config->setFloat(NESTED("Rumble.Strength", ""), profile.RumbleStrength); + Config->setBool(NESTED("Gyro.Enabled", ""), profile.UseGyro); + + for (auto const& val : rawProfile["Mappings"].items()) { + Config->setInt(NESTED("Mappings.%s", val.key().c_str()), -1); + } + + for (auto const& [key, val] : profile.Thresholds) { + Config->setFloat(NESTED("Thresholds.%d", key), val); + } + + for (auto const& [key, val] : profile.Mappings) { + Config->setInt(NESTED("Mappings.BTN_%d", val), key); + } + + slot++; + } + } + + Config->save(); +} diff --git a/libultraship/libultraship/ControlDeck.h b/libultraship/libultraship/ControlDeck.h new file mode 100644 index 000000000..fbbaca7ab --- /dev/null +++ b/libultraship/libultraship/ControlDeck.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Controller.h" +#include +#include + +namespace Ship { + + class ControlDeck { + public: + std::vector virtualDevices; + std::vector> physicalDevices = {}; + void Init(uint8_t* controllerBits); + void ScanPhysicalDevices(); + void WriteToPad(OSContPad* pad) const; + void LoadControllerSettings(); + void SaveControllerSettings(); + void SetPhysicalDevice(int slot, int deviceSlot); + }; +} diff --git a/libultraship/libultraship/Controller.cpp b/libultraship/libultraship/Controller.cpp index e400f6e18..6fc99c5c2 100644 --- a/libultraship/libultraship/Controller.cpp +++ b/libultraship/libultraship/Controller.cpp @@ -1,96 +1,80 @@ #include "Controller.h" -#include "GlobalCtx2.h" -#include "stox.h" #include +#include +#if __APPLE__ +#include +#else +#include +#endif namespace Ship { - Controller::Controller(int32_t dwControllerNumber) : dwControllerNumber(dwControllerNumber) { - dwPressedButtons = 0; - wStickX = 0; - wStickY = 0; - wGyroX = 0; - wGyroY = 0; + + Controller::Controller() : isRumbling(false), wStickX(0), wStickY(0), wGyroX(0), wGyroY(0), dwPressedButtons(0){ Attachment = nullptr; + profiles.resize(MAXCONTROLLERS); + for(int slot = 0; slot < MAXCONTROLLERS; slot++) { + dwPressedButtons.push_back(0); + } } - void Controller::Read(OSContPad* pad) { - ReadFromSource(); + void Controller::Read(OSContPad* pad, int32_t slot) { + ReadFromSource(slot); - pad->button |= dwPressedButtons & 0xFFFF; + SDL_PumpEvents(); - if (pad->stick_x == 0) { - if (dwPressedButtons & BTN_STICKLEFT) { + // Button Inputs + pad->button |= dwPressedButtons[slot] & 0xFFFF; + + // Stick Inputs + if (wStickX == 0) { + if (dwPressedButtons[slot] & BTN_STICKLEFT) { pad->stick_x = -128; - } - else if (dwPressedButtons & BTN_STICKRIGHT) { + } else if (dwPressedButtons[slot] & BTN_STICKRIGHT) { pad->stick_x = 127; } - else { - pad->stick_x = wStickX; - } + } else { + pad->stick_x = wStickX; } - if (pad->stick_y == 0) { - if (dwPressedButtons & BTN_STICKDOWN) { + if (wStickY == 0) { + if (dwPressedButtons[slot] & BTN_STICKDOWN) { pad->stick_y = -128; - } - else if (dwPressedButtons & BTN_STICKUP) { + } else if (dwPressedButtons[slot] & BTN_STICKUP) { pad->stick_y = 127; } - else { - pad->stick_y = wStickY; - } + } else { + pad->stick_y = wStickY; } + // Stick Inputs + if (wCamX == 0) { + if (dwPressedButtons[slot] & BTN_VSTICKLEFT) { + pad->cam_x = -128 * 10.0f; + } else if (dwPressedButtons[slot] & BTN_VSTICKRIGHT) { + pad->cam_x = 127 * 10.0f; + } + } else { + pad->cam_x = wCamX; + } + + if (wCamY == 0) { + if (dwPressedButtons[slot] & BTN_VSTICKDOWN) { + pad->cam_y = -128 * 10.0f; + } else if (dwPressedButtons[slot] & BTN_VSTICKUP) { + pad->cam_y = 127 * 10.0f; + } + } else { + pad->cam_y = wCamY; + } + + // Gyro pad->gyro_x = wGyroX; pad->gyro_y = wGyroY; } - void Controller::SetButtonMapping(const std::string& szButtonName, int32_t dwScancode) { - // Update the config value. - std::string ConfSection = GetBindingConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); - Conf[ConfSection][szButtonName] = dwScancode; - - // Reload the button mapping from Config - LoadBinding(); + void Controller::SetButtonMapping(int slot, int32_t n64Button, int32_t dwScancode) { + std::map& Mappings = profiles[slot].Mappings; + std::erase_if(Mappings, [n64Button](const std::pair& bin) { return bin.second == n64Button; }); + Mappings[dwScancode] = n64Button; } - - void Controller::LoadBinding() { - std::string ConfSection = GetBindingConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); - - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CRIGHT)])] = BTN_CRIGHT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CLEFT)])] = BTN_CLEFT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CDOWN)])] = BTN_CDOWN; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CUP)])] = BTN_CUP; - //ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CRIGHT + "_2")])] = BTN_CRIGHT; - //ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CLEFT + "_2")])] = BTN_CLEFT; - //ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CDOWN + "_2")])] = BTN_CDOWN; - //ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_CUP + "_2")])] = BTN_CUP; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_R)])] = BTN_R; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_L)])] = BTN_L; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_DRIGHT)])] = BTN_DRIGHT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_DLEFT)])] = BTN_DLEFT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_DDOWN)])] = BTN_DDOWN; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_DUP)])] = BTN_DUP; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_START)])] = BTN_START; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_Z)])] = BTN_Z; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_B)])] = BTN_B; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_A)])] = BTN_A; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_STICKRIGHT)])] = BTN_STICKRIGHT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_STICKLEFT)])] = BTN_STICKLEFT; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_STICKDOWN)])] = BTN_STICKDOWN; - ButtonMapping[Ship::stoi(Conf[ConfSection][STR(BTN_STICKUP)])] = BTN_STICKUP; - } - - std::string Controller::GetConfSection() { - return GetControllerType() + " CONTROLLER " + std::to_string(GetControllerNumber() + 1); - } - - std::string Controller::GetBindingConfSection() { - return GetControllerType() + " CONTROLLER BINDING " + std::to_string(GetControllerNumber() + 1); - } -} \ No newline at end of file +} diff --git a/libultraship/libultraship/Controller.h b/libultraship/libultraship/Controller.h index 256b31fee..70c339d25 100644 --- a/libultraship/libultraship/Controller.h +++ b/libultraship/libultraship/Controller.h @@ -1,51 +1,81 @@ #pragma once -#include #include +#include #include -#include #include "stdint.h" #include "UltraController.h" #include "ControllerAttachment.h" +#include +#include #define EXTENDED_SCANCODE_BIT (1 << 8) #define AXIS_SCANCODE_BIT (1 << 9) namespace Ship { + + enum ControllerThresholds { + LEFT_STICK = 1, + RIGHT_STICK = 2, + LEFT_TRIGGER = 3, + RIGHT_TRIGGER = 4, + DRIFT_X = 5, + DRIFT_Y = 6, + SENSITIVITY = 7, + GYRO_SENSITIVITY = 8 + }; + + struct DeviceProfile { + bool UseRumble = false; + bool UseGyro = false; + float RumbleStrength = 1.0f; + std::unordered_map Thresholds; + std::map Mappings; + }; + class Controller { - public: - Controller(int32_t dwControllerNumber); - - void Read(OSContPad* pad); - virtual void ReadFromSource() = 0; - virtual void WriteToSource(ControllerCallback* controller) = 0; + virtual ~Controller() = default; + Controller(); + void Read(OSContPad* pad, int32_t slot); + virtual void ReadFromSource(int32_t slot) = 0; + virtual void WriteToSource(int32_t slot, ControllerCallback* controller) = 0; virtual bool Connected() const = 0; virtual bool CanRumble() const = 0; + virtual bool CanGyro() const = 0; + virtual void CreateDefaultBinding(int32_t slot) = 0; bool isRumbling; + std::vector profiles; - void SetButtonMapping(const std::string& szButtonName, int32_t dwScancode); + virtual void ClearRawPress() = 0; + virtual int32_t ReadRawPress() = 0; + void SetButtonMapping(int slot, int32_t n64Button, int32_t dwScancode); std::shared_ptr GetAttachment() { return Attachment; } - int32_t GetControllerNumber() { return dwControllerNumber; } - virtual bool HasPadConf() const = 0; - virtual std::optional GetPadConfSection() = 0; + std::string GetGuid() { return GUID; } + virtual const char* GetButtonName(int slot, int n64Button) = 0; + virtual const char* GetControllerName() = 0; - protected: - int32_t dwPressedButtons; - std::map ButtonMapping; int8_t wStickX; int8_t wStickY; float wGyroX; float wGyroY; - - virtual std::string GetControllerType() = 0; - virtual std::string GetConfSection() = 0; - virtual std::string GetBindingConfSection() = 0; + float wCamX; + float wCamY; + + protected: + std::vector dwPressedButtons; + std::string GUID; + void LoadBinding(); private: std::shared_ptr Attachment; - int32_t dwControllerNumber; }; + + struct ControllerEntry { + uint8_t* controllerBits; + Controller* entryIO; + }; + } diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index 55fc70793..231308fe7 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "imgui_internal.h" std::map, std::less<>> cvars; @@ -70,7 +71,7 @@ extern "C" void CVar_SetString(const char* name, const char* value) { cvar = std::make_unique(); } cvar->type = CVAR_TYPE_STRING; - cvar->value.valueStr = value; + cvar->value.valueStr = ImStrdup(value); } extern "C" void CVar_RegisterS32(const char* name, s32 defaultValue) { diff --git a/libultraship/libultraship/DisconnectedController.h b/libultraship/libultraship/DisconnectedController.h new file mode 100644 index 000000000..9cbc2b99c --- /dev/null +++ b/libultraship/libultraship/DisconnectedController.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include + +#include "Controller.h" + +class DisconnectedController final : public Ship::Controller { +public: + DisconnectedController() { + GUID = "Disconnected"; + } + + std::map, int32_t> ReadButtonPress(); + void ReadFromSource(int32_t slot) override {} + const char* GetControllerName() override { return "Disconnected"; } + const char* GetButtonName(int slot, int n64Button) override { return "None"; } + void WriteToSource(int32_t slot, ControllerCallback* controller) override { } + bool Connected() const override { return false; } + bool CanRumble() const override { return false; } + bool CanGyro() const override { return false; } + + void ClearRawPress() override {} + int32_t ReadRawPress() override { return -1; } + bool HasPadConf() const { return true; } + std::optional GetPadConfSection() { return "Unk"; } + void CreateDefaultBinding(int32_t slot) override {} +protected: + std::string GetControllerType() { return "Unk"; } + std::string GetConfSection() { return "Unk"; } + std::string GetBindingConfSection() { return "Unk"; } +}; diff --git a/libultraship/libultraship/GameSettings.cpp b/libultraship/libultraship/GameSettings.cpp index 0cfbbd21a..e3f95ad76 100644 --- a/libultraship/libultraship/GameSettings.cpp +++ b/libultraship/libultraship/GameSettings.cpp @@ -7,7 +7,6 @@ #include #include -#include "ConfigFile.h" #include "Cvar.h" #include "GlobalCtx2.h" #include "ImGuiImpl.h" @@ -33,18 +32,6 @@ namespace Game { Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); } - void LoadPadSettings() { - const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf; - - for (const auto& [i, controllers] : Ship::Window::Controllers) { - for (const auto& controller : controllers) { - if (auto padConfSection = controller->GetPadConfSection()) { - } - } - } - } - void LoadSettings() { DebugConsole_LoadCVars(); } @@ -58,6 +45,7 @@ namespace Game { ModInternal::RegisterHook([] { gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", FILTER_THREE_POINT)); SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0); + SohImGui::controller->Opened = CVar_GetS32("gControllerConfigurationEnabled", 0); UpdateAudio(); }); } diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp index 6da741283..329644192 100644 --- a/libultraship/libultraship/GlobalCtx2.cpp +++ b/libultraship/libultraship/GlobalCtx2.cpp @@ -8,6 +8,9 @@ #include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/sohconsole_sink.h" #include "ModManager.h" +#ifdef __APPLE__ +#include "OSXFolderManager.h" +#endif namespace Ship { std::weak_ptr GlobalCtx2::Context; @@ -29,7 +32,23 @@ namespace Ship { return GetInstance(); } - GlobalCtx2::GlobalCtx2(const std::string& Name) : Name(Name), MainPath(""), PatchesPath("") { + 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)) { } @@ -40,22 +59,19 @@ namespace Ship { void GlobalCtx2::InitWindow() { InitLogging(); - Config = std::make_shared(GlobalCtx2::GetInstance(), "shipofharkinian.ini"); - MainPath = (*Config)["ARCHIVE"]["Main Archive"]; - if (MainPath.empty()) { - MainPath = "oot.otr"; - } - PatchesPath = (*Config)["ARCHIVE"]["Patches Directory"]; - if (PatchesPath.empty()) { - PatchesPath = "./"; - } - ResMan = std::make_shared(GlobalCtx2::GetInstance(), MainPath, PatchesPath); - Win = std::make_shared(GlobalCtx2::GetInstance()); + Config = std::make_shared(GetPathRelativeToAppDirectory("shipofharkinian.json")); + Config->reload(); + + MainPath = Config->getString("Game.Main Archive", GetPathRelativeToAppDirectory("oot.otr")); + PatchesPath = Config->getString("Game.Patches Archive", GetAppDirectoryPath() + "/mods"); + + ResMan = std::make_shared(GetInstance(), MainPath, PatchesPath); + Win = std::make_shared(GetInstance()); if (!ResMan->DidLoadSuccessfully()) { #ifdef _WIN32 - MessageBox(NULL, L"Main OTR file not found!", L"Uh oh", MB_OK); + MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK); #else SPDLOG_ERROR("Main OTR file not found!"); #endif @@ -67,11 +83,13 @@ namespace Ship { void GlobalCtx2::InitLogging() { try { + auto logPath = GetPathRelativeToAppDirectory(("logs/" + GetName() + ".log").c_str()); + // Setup Logging spdlog::init_thread_pool(8192, 1); auto SohConsoleSink = std::make_shared(); auto ConsoleSink = std::make_shared(); - auto FileSink = std::make_shared("logs/" + GetName() + ".log", 1024 * 1024 * 10, 10); + auto FileSink = std::make_shared(logPath, 1024 * 1024 * 10, 10); SohConsoleSink->set_level(spdlog::level::trace); ConsoleSink->set_level(spdlog::level::trace); FileSink->set_level(spdlog::level::trace); @@ -87,7 +105,7 @@ namespace Ship { } } - void GlobalCtx2::WriteSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size) { + 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); @@ -107,4 +125,4 @@ namespace Ship { saveFile.close(); } -} \ No newline at end of file +} diff --git a/libultraship/libultraship/GlobalCtx2.h b/libultraship/libultraship/GlobalCtx2.h index 4a7502393..21402070d 100644 --- a/libultraship/libultraship/GlobalCtx2.h +++ b/libultraship/libultraship/GlobalCtx2.h @@ -6,8 +6,9 @@ #ifdef __cplusplus #include #include +#include #include "spdlog/spdlog.h" -#include "ConfigFile.h" +#include "Lib/Mercury/Mercury.h" namespace Ship { class ResourceMgr; @@ -22,12 +23,15 @@ namespace Ship { std::shared_ptr GetWindow() { return Win; } std::shared_ptr GetResourceManager() { return ResMan; } std::shared_ptr GetLogger() { return Logger; } - std::shared_ptr GetConfig() { return Config; } + std::shared_ptr GetConfig() { return Config; } - void WriteSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size); + 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(const std::string& Name); + GlobalCtx2(std::string Name); ~GlobalCtx2(); protected: @@ -38,7 +42,7 @@ namespace Ship { static std::weak_ptr Context; std::shared_ptr Logger; std::shared_ptr Win; - std::shared_ptr Config; // Config needs to be after the Window because we call the Window during it's destructor. + std::shared_ptr Config; // Config needs to be after the Window because we call the Window during it's destructor. std::shared_ptr ResMan; std::string Name; std::string MainPath; diff --git a/libultraship/libultraship/Hooks.h b/libultraship/libultraship/Hooks.h index b5dec8159..411cffe42 100644 --- a/libultraship/libultraship/Hooks.h +++ b/libultraship/libultraship/Hooks.h @@ -5,6 +5,7 @@ #include #include "UltraController.h" +#include "Controller.h" #define DEFINE_HOOK(name, type) struct name { typedef std::function fn; } @@ -28,12 +29,11 @@ namespace ModInternal { } DEFINE_HOOK(ControllerRead, void(OSContPad* cont_pad)); - + DEFINE_HOOK(ControllerRawInput, void(Ship::Controller* backend, uint32_t raw)); DEFINE_HOOK(AudioInit, void()); - DEFINE_HOOK(LoadTexture, void(const char* path, uint8_t** texture)); - DEFINE_HOOK(GfxInit, void()); + DEFINE_HOOK(ExitGame, void()); } diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index bade9f04f..b9ce62aee 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -12,6 +12,7 @@ #include "GameSettings.h" #include "Console.h" #include "Hooks.h" +#define IMGUI_DEFINE_MATH_OPERATORS #include "Lib/ImGui/imgui_internal.h" #include "GlobalCtx2.h" #include "ResourceMgr.h" @@ -63,8 +64,11 @@ namespace SohImGui { ImGuiIO* io; Console* console = new Console; GameOverlay* overlay = new GameOverlay; + InputEditor* controller = new InputEditor; + static ImVector s_GroupPanelLabelStack; bool p_open = false; bool needs_save = false; + int lastBackendID = 0; const char* filters[3] = { "Three-Point", @@ -72,10 +76,45 @@ namespace SohImGui { "None" }; + std::pair backends[] = { +#ifdef _WIN32 + { "dx11", "DirectX" }, +#endif + { "sdl", "OpenGL" } + }; + + + const char* powers[9] = { + "Vanilla (1x)", + "Double (2x)", + "Quadruple (4x)", + "Octuple (8x)", + "Hexadecuple (16x)", + "Duotrigintuple (32x)", + "Quattuorsexagintuple (64x)", + "Octoviginticentuple (128x)", + "Hexaquinquagintiducentuple (256x)" + }; + std::map> hiddenwindowCategories; std::map> windowCategories; std::map customWindows; + int GetBackendID(std::shared_ptr cfg) { + std::string backend = cfg->getString("Window.GfxBackend"); + if (backend.empty()) { + return 0; + } + + for (size_t i = 0; i < (sizeof(backends) / sizeof(backends[0])); i++) { + if(backend == backends[i].first) { + return i; + } + } + + return 0; + } + int ClampFloatToInt(float value, int min, int max) { return fmin(fmax(value, min), max); } @@ -300,15 +339,23 @@ namespace SohImGui { io = &ImGui::GetIO(); io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->Fonts->AddFontDefault(); + + lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig()); if (CVar_GetS32("gOpenMenuBar", 0) != 1) { SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu"); } + auto imguiIniPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui.ini"); + auto imguiLogPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui_log.txt"); + io->IniFilename = strcpy(new char[imguiIniPath.length() + 1], imguiIniPath.c_str()); + io->LogFilename = strcpy(new char[imguiLogPath.length() + 1], imguiLogPath.c_str()); + if (UseViewports()) { io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; } console->Init(); overlay->Init(); + controller->Init(); ImGuiWMInit(); ImGuiBackendInit(); @@ -329,23 +376,17 @@ namespace SohImGui { LoadTexture("C-Down", "assets/ship_of_harkinian/buttons/CDown.png"); }); - for (const auto& [i, controllers] : Ship::Window::Controllers) - { - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", i).c_str(), 0); - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", i).c_str(), 0); - needs_save = true; - } - ModInternal::RegisterHook([](OSContPad* cont_pad) { pads = cont_pad; }); + Game::InitSettings(); CVar_SetS32("gRandoGenerating", 0); CVar_SetS32("gNewSeedGenerated", 0); CVar_SetS32("gNewFileDropped", 0); - CVar_SetString("gDroppedFile", ""); - Game::SaveSettings(); + CVar_SetString("gDroppedFile", "None"); + // Game::SaveSettings(); } void Update(EventImpl event) { @@ -436,11 +477,21 @@ namespace SohImGui { } } - void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue) + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) { int val = CVar_GetS32(cvarName, defaultValue); - ImGui::Text(text, val); + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + val--; + CVar_SetS32(cvarName, val); + needs_save = true; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } if (ImGui::SliderInt(id, &val, min, max, format)) { @@ -448,6 +499,18 @@ namespace SohImGui { needs_save = true; } + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + val++; + CVar_SetS32(cvarName, val); + needs_save = true; + } + } + if (val < min) { val = min; @@ -463,7 +526,7 @@ namespace SohImGui { } } - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage) + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) { float val = CVar_GetFloat(cvarName, defaultValue); @@ -472,12 +535,36 @@ namespace SohImGui { else ImGui::Text(text, static_cast(100 * val)); + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + val -= 0.1f; + CVar_SetFloat(cvarName, val); + needs_save = true; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } + if (ImGui::SliderFloat(id, &val, min, max, format)) { CVar_SetFloat(cvarName, val); needs_save = true; } + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + val += 0.1f; + CVar_SetFloat(cvarName, val); + needs_save = true; + } + } + if (val < min) { val = min; @@ -494,7 +581,7 @@ namespace SohImGui { } void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { - + if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { if (ImGui::Selectable(items[settingIndex].c_str())) { @@ -638,6 +725,8 @@ namespace SohImGui { ImGui::NewFrame(); const std::shared_ptr wnd = GlobalCtx2::GetInstance()->GetWindow(); + const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); + ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoResize; @@ -674,36 +763,32 @@ namespace SohImGui { needs_save = true; GlobalCtx2::GetInstance()->GetWindow()->dwMenubar = menu_bar; ShowCursor(menu_bar, Dialogues::dMenubar); - + GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->SaveControllerSettings(); if (CVar_GetS32("gControlNav", 0)) { if (CVar_GetS32("gOpenMenuBar", 0)) { io->ConfigFlags |=ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard; + } else { + io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; } - else - { - io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; - } - } - else - { - io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; + } else { + io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad; } } #if __APPLE__ if ((ImGui::IsKeyDown(ImGuiKey_LeftSuper) || - ImGui::IsKeyDown(ImGuiKey_RightSuper)) && + ImGui::IsKeyDown(ImGuiKey_RightSuper)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { console->Commands["reset"].handler(emptyArgs); } #else if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || - ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && + ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { console->Commands["reset"].handler(emptyArgs); } #endif - + if (ImGui::BeginMenuBar()) { if (DefaultAssets.contains("Game_Icon")) { ImGui::SetCursorPos(ImVec2(5, 2.5f)); @@ -723,7 +808,11 @@ namespace SohImGui { console->Commands["reset"].handler(emptyArgs); } ImGui::EndMenu(); - } + } + + ImGui::Separator(); + + ImGui::SetCursorPosY(0.0f); if (ImGui::BeginMenu("Audio")) { EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true); @@ -736,11 +825,16 @@ namespace SohImGui { ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Controller")) { EnhancementCheckbox("Use Controller Navigation", "gControlNav"); Tooltip("Allows controller navigation of the menu bar\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); + EnhancementCheckbox("Controller Configuration", "gControllerConfigurationEnabled"); + controller->Opened = CVar_GetS32("gControllerConfigurationEnabled", 0); + ImGui::Separator(); // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected @@ -754,45 +848,15 @@ namespace SohImGui { EnhancementCheckbox("Show Inputs", "gInputEnabled"); Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - EnhancementCheckbox("Rumble Enabled", "gRumbleEnabled"); EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); - Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); - - ImGui::Separator(); - - for (const auto& [i, controllers] : Ship::Window::Controllers) - { - bool hasPad = std::find_if(controllers.begin(), controllers.end(), [](const auto& c) { - return c->HasPadConf() && c->Connected(); - }) != controllers.end(); - - if (!hasPad) continue; - - auto menuLabel = "Controller " + std::to_string(i + 1); - if (ImGui::BeginMenu(menuLabel.c_str())) - { - EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i).c_str(), 0.0f, 1.0f, "", 1.0f, true); - - if (ImGui::Button("Recalibrate Gyro")) - { - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", i).c_str(), 0); - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", i).c_str(), 0); - needs_save = true; - } - - ImGui::Separator(); - - EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 0.0f, 1.0f, "", 1.0f, true); - - ImGui::EndMenu(); - } - ImGui::Separator(); - } + Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Graphics")) { EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true); @@ -818,6 +882,16 @@ namespace SohImGui { ImGui::Text("Jitter fix: >= %d FPS", fps); } + std::string MinusBTNELT = " - ##ExtraLatencyThreshold"; + std::string PlusBTNELT = " + ##ExtraLatencyThreshold"; + if (ImGui::Button(MinusBTNELT.c_str())) { + val--; + CVar_SetS32(cvar, val); + needs_save = true; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 250, "", ImGuiSliderFlags_AlwaysClamp)) { CVar_SetS32(cvar, val); @@ -830,6 +904,26 @@ namespace SohImGui { "to work on one frame while GPU works on the previous frame.\n" "This setting should be used when your computer is too slow\n" "to do CPU + GPU work in time."); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNELT.c_str())) { + val++; + CVar_SetS32(cvar, val); + needs_save = true; + } + } + + + ImGui::Text("Renderer API (Needs reload)"); + if (ImGui::BeginCombo("##RApi", backends[lastBackendID].second)) { + for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { + if (ImGui::Selectable(backends[i].second, i == lastBackendID)) { + pConf->setString("Window.GfxBackend", backends[i].first); + lastBackendID = i; + } + } + ImGui::EndCombo(); } EXPERIMENTAL(); @@ -841,6 +935,8 @@ namespace SohImGui { ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Languages")) { EnhancementRadioButton("English", "gLanguages", 0); EnhancementRadioButton("German", "gLanguages", 1); @@ -848,6 +944,8 @@ namespace SohImGui { ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Enhancements")) { if (ImGui::BeginMenu("Gameplay")) @@ -881,70 +979,94 @@ namespace SohImGui { if (ImGui::BeginMenu("Difficulty Options")) { - EnhancementSliderInt("Damage Multiplier %dx", "##DAMAGEMUL", "gDamageMul", 1, 4, ""); - Tooltip("Modifies all sources of damage not affected by other sliders"); - EnhancementSliderInt("Fall Damage Multiplier %dx", "##FALLDAMAGEMUL", "gFallDamageMul", 1, 4, ""); - Tooltip("Modifies all fall damage"); - EnhancementSliderInt("Void Damage Multiplier %dx", "##VOIDDAMAGEMUL", "gVoidDamageMul", 1, 4, ""); - Tooltip("Modifies damage taken after falling into a void"); + ImGui::Text("Damage Multiplier"); + EnhancementCombobox("gDamageMul", powers, 9, 0); + Tooltip("Modifies all sources of damage not affected by other sliders\n\ +2x: Can survive all common attacks from the start of the game\n\ +4x: Dies in 1 hit to any substantial attack from the start of the game\n\ +8x: Can only survive trivial damage from the start of the game\n\ +16x: Can survive all common attacks with max health without double defense\n\ +32x: Can survive all common attacks with max health and double defense\n\ +64x: Can survive trivial damage with max health without double defense\n\ +128x: Can survive trivial damage with max health and double defense\n\ +256x: Cannot survive damage"); + ImGui::Text("Fall Damage Multiplier"); + EnhancementCombobox("gFallDamageMul", powers, 8, 0); + Tooltip("Modifies all fall damage\n\ +2x: Can survive all fall damage from the start of the game\n\ +4x: Can only survive short fall damage from the start of the game\n\ +8x: Cannot survive any fall damage from the start of the game\n\ +16x: Can survive all fall damage with max health without double defense\n\ +32x: Can survive all fall damage with max health and double defense\n\ +64x: Can survive short fall damage with double defense\n\ +128x: Cannot survive fall damage"); + ImGui::Text("Void Damage Multiplier"); + EnhancementCombobox("gVoidDamageMul", powers, 7, 0); + Tooltip("Modifies damage taken after falling into a void\n\ +2x: Can survive void damage from the start of the game\n\ +4x: Cannot survive void damage from the start of the game\n\ +8x: Can survive void damage twice with max health without double defense\n\ +16x: Can survive void damage with max health without double defense\n\ +32x: Can survive void damage with max health and double defense\n\ +64x: Cannot survive void damage"); EnhancementCheckbox("No Random Drops", "gNoRandomDrops"); Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); EnhancementCheckbox("No Heart Drops", "gNoHeartDrops"); 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"); - + if (ImGui::BeginMenu("Potion Values")) { EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); Tooltip("Enable the following changes to the amount of health restored by Red Potions"); - EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, ""); + EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Red Potions"); EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore"); Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); - + EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); - EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, ""); + EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true); Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore"); Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); - EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, ""); + EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Blue Potions"); EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore"); Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); - - EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, ""); + + EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true); Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore"); Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); Tooltip("Enable the following changes to the amount of health restored by Milk"); - EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, ""); + EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Milk"); EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore"); Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect"); Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); - EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, ""); + EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Half Milk"); EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore"); Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); Tooltip("Enable the following changes to the amount of health restored by Fairies"); - EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, ""); + EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Fairies"); EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore"); Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); - EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, ""); + EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true); Tooltip("Changes the amount of health restored by Fairy Revivals"); EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore"); Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); @@ -978,7 +1100,7 @@ namespace SohImGui { ImGui::EndMenu(); } - + EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); Tooltip("Displays an icon and plays a sound when Stone of Agony\nshould be activated, for those without rumble"); EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots"); @@ -1033,7 +1155,7 @@ namespace SohImGui { EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); Tooltip("Randomize the animation played on the menu after a certain time"); if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { - EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, ""); + EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0, true); } ImGui::EndMenu(); @@ -1105,6 +1227,16 @@ namespace SohImGui { ImGui::Text("Frame interpolation: %d FPS", fps); } + std::string MinusBTNFPSI = " - ##FPSInterpolation"; + std::string PlusBTNFPSI = " + ##FPSInterpolation"; + if (ImGui::Button(MinusBTNFPSI.c_str())) { + val--; + CVar_SetS32(fps_cvar, val); + needs_save = true; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::SliderInt("##FPSInterpolation", &val, 20, 250, "", ImGuiSliderFlags_AlwaysClamp)) { CVar_SetS32(fps_cvar, val); @@ -1117,6 +1249,14 @@ namespace SohImGui { "and might give a worse result.\n" "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20\n" "Ctrl+Click for keyboard input"); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNFPSI.c_str())) { + val++; + CVar_SetS32(fps_cvar, val); + needs_save = true; + } } if (impl.backend == Backend::DX11) { @@ -1143,9 +1283,14 @@ namespace SohImGui { EnhancementCheckbox("Skip Text", "gSkipText"); Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); + EnhancementCheckbox("Free Camera", "gFreeCamera"); + Tooltip("Enables camera control\nNote: You must remap C buttons off of\nthe right stick in the controller\nconfig menu, and map the camera stick\nto the right stick."); + ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Cheats")) { if (ImGui::BeginMenu("Infinite...")) { @@ -1183,6 +1328,8 @@ namespace SohImGui { ImGui::EndMenu(); } + ImGui::SetCursorPosY(0.0f); + if (ImGui::BeginMenu("Developer Tools")) { EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); @@ -1203,6 +1350,7 @@ namespace SohImGui { } for (const auto& category : windowCategories) { + ImGui::SetCursorPosY(0.0f); if (ImGui::BeginMenu(category.first.c_str())) { for (const std::string& name : category.second) { std::string varName(name); @@ -1224,12 +1372,13 @@ namespace SohImGui { for (const auto& category : hiddenwindowCategories) { ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); ImGui::SetNextWindowSize(ImVec2 (0,0)); - ImGui::SetNextWindowPos(ImVec2 (-100,-100)); - ImGui::Begin(category.first.c_str(), nullptr, ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus); + ImGuiWindowFlags HiddenWndFlags = ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoNavInputs | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoDecoration; + ImGui::Begin(category.first.c_str(), nullptr, HiddenWndFlags); ImGui::End(); ImGui::PopStyleColor(); } - if (CVar_GetS32("gStatsEnabled", 0)) { const float framerate = ImGui::GetIO().Framerate; ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); @@ -1248,6 +1397,7 @@ namespace SohImGui { } console->Draw(); + controller->DrawHud(); for (auto& windowIter : customWindows) { CustomWindow& window = windowIter.second; @@ -1413,4 +1563,124 @@ namespace SohImGui { #endif return reinterpret_cast(id); } + + void BeginGroupPanel(const char* name, const ImVec2& size) + { + ImGui::BeginGroup(); + + // auto cursorPos = ImGui::GetCursorScreenPos(); + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + ImGui::BeginGroup(); + + ImVec2 effectiveSize = size; + if (size.x < 0.0f) + effectiveSize.x = ImGui::GetContentRegionAvail().x; + else + effectiveSize.x = size.x; + ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f)); + + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::BeginGroup(); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::SameLine(0.0f, 0.0f); + ImGui::TextUnformatted(name); + auto labelMin = ImGui::GetItemRectMin(); + auto labelMax = ImGui::GetItemRectMax(); + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y)); + ImGui::BeginGroup(); + + //ImGui::GetWindowDrawList()->AddRect(labelMin, labelMax, IM_COL32(255, 0, 255, 255)); + + ImGui::PopStyleVar(2); + +#if IMGUI_VERSION_NUM >= 17301 + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; + ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f; +#else + ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x -= frameHeight * 0.5f; +#endif + ImGui::GetCurrentWindow()->Size.x -= frameHeight; + + auto itemWidth = ImGui::CalcItemWidth(); + ImGui::PushItemWidth(ImMax(0.0f, itemWidth - frameHeight)); + s_GroupPanelLabelStack.push_back(ImRect(labelMin, labelMax)); + } + + void EndGroupPanel(float minHeight) { + ImGui::PopItemWidth(); + + auto itemSpacing = ImGui::GetStyle().ItemSpacing; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + + auto frameHeight = ImGui::GetFrameHeight(); + + ImGui::EndGroup(); + + //ImGui::GetWindowDrawList()->AddRectFilled(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(0, 255, 0, 64), 4.0f); + + ImGui::EndGroup(); + + ImGui::SameLine(0.0f, 0.0f); + ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); + ImGui::Dummy(ImVec2(0.0, std::max(frameHeight - frameHeight * 0.5f - itemSpacing.y, minHeight))); + + ImGui::EndGroup(); + + auto itemMin = ImGui::GetItemRectMin(); + auto itemMax = ImGui::GetItemRectMax(); + //ImGui::GetWindowDrawList()->AddRectFilled(itemMin, itemMax, IM_COL32(255, 0, 0, 64), 4.0f); + + auto labelRect = s_GroupPanelLabelStack.back(); + s_GroupPanelLabelStack.pop_back(); + + ImVec2 halfFrame = ImVec2(frameHeight * 0.25f, frameHeight) * 0.5f; + ImRect frameRect = ImRect(itemMin + halfFrame, itemMax - ImVec2(halfFrame.x, 0.0f)); + labelRect.Min.x -= itemSpacing.x; + labelRect.Max.x += itemSpacing.x; + for (int i = 0; i < 4; ++i) + { + switch (i) + { + // left half-plane + case 0: ImGui::PushClipRect(ImVec2(-FLT_MAX, -FLT_MAX), ImVec2(labelRect.Min.x, FLT_MAX), true); break; + // right half-plane + case 1: ImGui::PushClipRect(ImVec2(labelRect.Max.x, -FLT_MAX), ImVec2(FLT_MAX, FLT_MAX), true); break; + // top + case 2: ImGui::PushClipRect(ImVec2(labelRect.Min.x, -FLT_MAX), ImVec2(labelRect.Max.x, labelRect.Min.y), true); break; + // bottom + case 3: ImGui::PushClipRect(ImVec2(labelRect.Min.x, labelRect.Max.y), ImVec2(labelRect.Max.x, FLT_MAX), true); break; + } + + ImGui::GetWindowDrawList()->AddRect( + frameRect.Min, frameRect.Max, + ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)), + halfFrame.x); + + ImGui::PopClipRect(); + } + + ImGui::PopStyleVar(2); + +#if IMGUI_VERSION_NUM >= 17301 + ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; + ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f; +#else + ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x += frameHeight * 0.5f; +#endif + ImGui::GetCurrentWindow()->Size.x += frameHeight; + + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + + ImGui::EndGroup(); + } } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index 34bc368a6..580d5cdb6 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -3,6 +3,7 @@ #include "GameOverlay.h" #include "Lib/ImGui/imgui.h" #include "Console.h" +#include "InputEditor.h" struct GameAsset { uint32_t textureId; @@ -59,23 +60,24 @@ namespace SohImGui { } CustomWindow; extern Console* console; + extern Ship::InputEditor* controller; extern Ship::GameOverlay* overlay; extern bool needs_save; void Init(WindowImpl window_impl); void Update(EventImpl event); void Tooltip(const char* text); - + void EnhancementRadioButton(const char* text, const char* cvarName, int id); void EnhancementCheckbox(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); - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage); + 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 EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); void DrawMainMenuAndCalculateGameSize(void); - + void DrawFramebufferAndGameInput(void); void Render(void); void CancelFrame(void); @@ -90,4 +92,6 @@ namespace SohImGui { void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha); ImTextureID GetTextureByID(int id); ImTextureID GetTextureByName(const std::string& name); + void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f)); + void EndGroupPanel(float minHeight = 0.0f); } diff --git a/libultraship/libultraship/InputEditor.cpp b/libultraship/libultraship/InputEditor.cpp new file mode 100644 index 000000000..f03e94d57 --- /dev/null +++ b/libultraship/libultraship/InputEditor.cpp @@ -0,0 +1,279 @@ +#include "InputEditor.h" +#include "Controller.h" +#include "Window.h" +#include "Lib/ImGui/imgui.h" +#include "ImGuiImpl.h" +#include "Utils/StringHelper.h" +#include "Lib/ImGui/imgui_internal.h" +#include "Cvar.h" + +namespace Ship { + + extern "C" uint8_t __enableGameInput; + #define SEPARATION() ImGui::Dummy(ImVec2(0, 5)) + + void InputEditor::Init() { + BtnReading = -1; + } + + std::shared_ptr GetControllerPerSlot(int slot) { + const std::vector vDevices = Window::ControllerApi->virtualDevices; + return Window::ControllerApi->physicalDevices[vDevices[slot]]; + } + + void InputEditor::DrawButton(const char* label, int n64Btn) { + const std::shared_ptr backend = GetControllerPerSlot(CurrentPort); + + float size = 40; + bool readingMode = BtnReading == n64Btn; + bool disabled = BtnReading != -1 && !readingMode || !backend->Connected(); + ImVec2 len = ImGui::CalcTextSize(label); + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SetCursorPosY(pos.y + len.y / 4); + ImGui::SetCursorPosX(pos.x + abs(len.x - size)); + ImGui::Text("%s", label); + ImGui::SameLine(); + ImGui::SetCursorPosY(pos.y); + + if(disabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + + if(readingMode) { + const int32_t btn = backend->ReadRawPress(); + + if(btn != -1) { + backend->SetButtonMapping(CurrentPort, n64Btn, btn); + BtnReading = -1; + } + } + + const char* BtnName = backend->GetButtonName(CurrentPort, n64Btn); + + if (ImGui::Button(StringHelper::Sprintf("%s##HBTNID_%d", readingMode ? "Press a Key..." : BtnName, n64Btn).c_str())) { + BtnReading = n64Btn; + backend->ClearRawPress(); + } + + if(disabled) { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(); + } + } + + void InputEditor::DrawVirtualStick(const char* label, ImVec2 stick) { + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y)); + ImGui::BeginChild(label, ImVec2(68, 75), false); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + const ImVec2 p = ImGui::GetCursorScreenPos(); + + float sz = 45.0f; + float rad = sz * 0.5f; + ImVec2 pos = ImVec2(p.x + sz * 0.5f + 12, p.y + sz * 0.5f + 11); + + float stickX = (stick.x / 83.0f) * (rad * 0.5f); + float stickY = -(stick.y / 83.0f) * (rad * 0.5f); + + ImVec4 rect = ImVec4(p.x + 2, p.y + 2, 65, 65); + draw_list->AddRect(ImVec2(rect.x, rect.y), ImVec2(rect.x + rect.z, rect.y + rect.w), ImColor(100, 100, 100, 255), 0.0f, 0, 1.5f); + draw_list->AddCircleFilled(pos, rad, ImColor(130, 130, 130, 255), 8); + draw_list->AddCircleFilled(ImVec2(pos.x + stickX, pos.y + stickY), 5, ImColor(15, 15, 15, 255), 7); + ImGui::EndChild(); + } + + void InputEditor::DrawControllerSchema() { + + const std::vector vDevices = Window::ControllerApi->virtualDevices; + const std::vector> devices = Window::ControllerApi->physicalDevices; + + std::shared_ptr Backend = devices[vDevices[CurrentPort]]; + DeviceProfile& profile =Backend->profiles[CurrentPort]; + float sensitivity = profile.Thresholds[SENSITIVITY]; + bool IsKeyboard = Backend->GetGuid() == "Keyboard" || !Backend->Connected(); + const char* ControllerName = Backend->GetControllerName(); + + if (ControllerName != nullptr && ImGui::BeginCombo("##ControllerEntries", ControllerName)) { + for (uint8_t i = 0; i < devices.size(); i++) { + if (ImGui::Selectable(devices[i]->GetControllerName(), i == vDevices[CurrentPort])) { + Window::ControllerApi->SetPhysicalDevice(CurrentPort, i); + } + } + ImGui::EndCombo(); + } + + ImGui::SameLine(); + + if(ImGui::Button("Refresh")) { + Window::ControllerApi->ScanPhysicalDevices(); + } + + SohImGui::BeginGroupPanel("Buttons", ImVec2(150, 20)); + DrawButton("A", BTN_A); + DrawButton("B", BTN_B); + DrawButton("L", BTN_L); + DrawButton("R", BTN_R); + DrawButton("Z", BTN_Z); + DrawButton("START", BTN_START); + SEPARATION(); + SohImGui::EndGroupPanel(IsKeyboard ? 7.0f : 48.0f); + ImGui::SameLine(); + SohImGui::BeginGroupPanel("Digital Pad", ImVec2(150, 20)); + DrawButton("Up", BTN_DUP); + DrawButton("Down", BTN_DDOWN); + DrawButton("Left", BTN_DLEFT); + DrawButton("Right", BTN_DRIGHT); + SEPARATION(); + SohImGui::EndGroupPanel(IsKeyboard ? 53.0f : 94.0f); + ImGui::SameLine(); + SohImGui::BeginGroupPanel("Analog Stick", ImVec2(150, 20)); + DrawButton("Up", BTN_STICKUP); + DrawButton("Down", BTN_STICKDOWN); + DrawButton("Left", BTN_STICKLEFT); + DrawButton("Right", BTN_STICKRIGHT); + + if (!IsKeyboard) { + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); + DrawVirtualStick("##MainVirtualStick", ImVec2(Backend->wStickX, Backend->wStickY)); + ImGui::SameLine(); + + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + + ImGui::BeginChild("##MSInput", ImVec2(90, 50), false); + ImGui::Text("Deadzone"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##MDZone", &profile.Thresholds[LEFT_STICK], 1.0f, 0.0f, "%.0f"); + ImGui::PopItemWidth(); + ImGui::EndChild(); + } else { + ImGui::Dummy(ImVec2(0, 6)); + } + SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 24.0f); + ImGui::SameLine(); + + if (!IsKeyboard) { + ImGui::SameLine(); + SohImGui::BeginGroupPanel("Camera Stick", ImVec2(150, 20)); + DrawButton("Up", BTN_VSTICKUP); + DrawButton("Down", BTN_VSTICKDOWN); + DrawButton("Left", BTN_VSTICKLEFT); + DrawButton("Right", BTN_VSTICKRIGHT); + + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); + DrawVirtualStick("##CameraVirtualStick", ImVec2(Backend->wCamX / sensitivity, Backend->wCamY / sensitivity)); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + ImGui::BeginChild("##CSInput", ImVec2(90, 85), false); + ImGui::Text("Deadzone"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##MDZone", &profile.Thresholds[RIGHT_STICK], 1.0f, 0.0f, "%.0f"); + ImGui::PopItemWidth(); + ImGui::Text("Sensitivity"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##MSensitivity", &profile.Thresholds[SENSITIVITY], 1.0f, 0.0f, "%.0f"); + ImGui::PopItemWidth(); + ImGui::EndChild(); + SohImGui::EndGroupPanel(14.0f); + } + + if(Backend->CanGyro()) { + ImGui::SameLine(); + + SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20)); + float cursorX = ImGui::GetCursorPosX() + 5; + ImGui::SetCursorPosX(cursorX); + ImGui::Checkbox("Enable Gyro", &profile.UseGyro); + ImGui::SetCursorPosX(cursorX); + ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY])); + ImGui::PushItemWidth(135.0f); + ImGui::SetCursorPosX(cursorX); + ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, ""); + ImGui::PopItemWidth(); + ImGui::Dummy(ImVec2(0, 1)); + ImGui::SetCursorPosX(cursorX); + if (ImGui::Button("Recalibrate Gyro##RGyro")) { + profile.Thresholds[DRIFT_X] = 0.0f; + profile.Thresholds[DRIFT_Y] = 0.0f; + } + ImGui::SetCursorPosX(cursorX); + DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX)); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); + ImGui::BeginChild("##GyInput", ImVec2(90, 85), false); + ImGui::Text("Drift X"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f"); + ImGui::PopItemWidth(); + ImGui::Text("Drift Y"); + ImGui::PushItemWidth(80); + ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f"); + ImGui::PopItemWidth(); + ImGui::EndChild(); + SohImGui::EndGroupPanel(14.0f); + } + + ImGui::SameLine(); + + const ImVec2 cursor = ImGui::GetCursorPos(); + + SohImGui::BeginGroupPanel("C-Buttons", ImVec2(158, 20)); + DrawButton("Up", BTN_CUP); + DrawButton("Down", BTN_CDOWN); + DrawButton("Left", BTN_CLEFT); + DrawButton("Right", BTN_CRIGHT); + ImGui::Dummy(ImVec2(0, 5)); + SohImGui::EndGroupPanel(); + + ImGui::SetCursorPosX(cursor.x); + ImGui::SetCursorPosY(cursor.y + 120); + SohImGui::BeginGroupPanel("Options", ImVec2(158, 20)); + float cursorX = ImGui::GetCursorPosX() + 5; + ImGui::SetCursorPosX(cursorX); + ImGui::Checkbox("Rumble Enabled", &profile.UseRumble); + if (Backend->CanRumble()) { + ImGui::SetCursorPosX(cursorX); + ImGui::Text("Rumble Force: %d%%", static_cast(100.0f * profile.RumbleStrength)); + ImGui::SetCursorPosX(cursorX); + ImGui::PushItemWidth(135.0f); + ImGui::SliderFloat("##RStrength", &profile.RumbleStrength, 0.0f, 1.0f, ""); + ImGui::PopItemWidth(); + } + ImGui::Dummy(ImVec2(0, 5)); + SohImGui::EndGroupPanel(IsKeyboard ? 0.0f : 2.0f); + } + + void InputEditor::DrawHud() { + + __enableGameInput = true; + + if (!this->Opened) { + BtnReading = -1; + CVar_SetS32("gControllerConfigurationEnabled", 0); + return; + } + + ImGui::SetNextWindowSizeConstraints(ImVec2(641, 250), ImVec2(1200, 290)); + //OTRTODO: Disable this stupid workaround ( ReadRawPress() only works when the window is on the main viewport ) + ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID); + ImGui::Begin("Controller Configuration", &this->Opened, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize); + + ImGui::BeginTabBar("##Controllers"); + + for (int i = 0; i < 4; i++) { + if (ImGui::BeginTabItem(StringHelper::Sprintf("Port %d", i + 1).c_str())) { + CurrentPort = i; + ImGui::EndTabItem(); + } + } + + ImGui::EndTabBar(); + + // Draw current cfg + + DrawControllerSchema(); + + ImGui::End(); + } +} diff --git a/libultraship/libultraship/InputEditor.h b/libultraship/libultraship/InputEditor.h new file mode 100644 index 000000000..39bddd51d --- /dev/null +++ b/libultraship/libultraship/InputEditor.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "Lib/ImGui/imgui.h" + +namespace Ship { + + class InputEditor { + int CurrentPort = 0; + int BtnReading = -1; + public: + bool Opened = false; + void Init(); + void DrawButton(const char* label, int n64Btn); + void DrawVirtualStick(const char* label, ImVec2 stick); + void DrawControllerSchema(); + void DrawHud(); + }; +} diff --git a/libultraship/libultraship/KeyboardController.cpp b/libultraship/libultraship/KeyboardController.cpp index 13014c6a7..0ba08f415 100644 --- a/libultraship/libultraship/KeyboardController.cpp +++ b/libultraship/libultraship/KeyboardController.cpp @@ -1,56 +1,105 @@ #include "KeyboardController.h" + +#if __APPLE__ +#include +#else +#include +#endif + +#include "Hooks.h" #include "GlobalCtx2.h" +#include "Window.h" namespace Ship { - KeyboardController::KeyboardController(int32_t dwControllerNumber) : Controller(dwControllerNumber) { - LoadBinding(); - } - KeyboardController::~KeyboardController() { - + KeyboardController::KeyboardController() : Controller(), lastScancode(-1) { + GUID = "Keyboard"; } bool KeyboardController::PressButton(int32_t dwScancode) { - if (ButtonMapping.contains(dwScancode)) { - dwPressedButtons |= ButtonMapping[dwScancode]; - return true; + + lastKey = dwScancode; + + for (int slot = 0; slot < MAXCONTROLLERS; slot++) { + + if (profiles[slot].Mappings.contains(dwScancode)) { + dwPressedButtons[slot] |= profiles[slot].Mappings[dwScancode]; + return true; + } } return false; } bool KeyboardController::ReleaseButton(int32_t dwScancode) { - if (ButtonMapping.contains(dwScancode)) { - dwPressedButtons &= ~ButtonMapping[dwScancode]; - return true; + for (int slot = 0; slot < MAXCONTROLLERS; slot++) { + if (profiles[slot].Mappings.contains(dwScancode)) { + dwPressedButtons[slot] &= ~profiles[slot].Mappings[dwScancode]; + return true; + } } return false; } void KeyboardController::ReleaseAllButtons() { - dwPressedButtons = 0; + for(int slot = 0; slot < MAXCONTROLLERS; slot++) { + dwPressedButtons[slot] = 0; + } } - void KeyboardController::ReadFromSource() { + void KeyboardController::ReadFromSource(int32_t slot) { wStickX = 0; wStickY = 0; + wCamX = 0; + wCamY = 0; } - void KeyboardController::WriteToSource(ControllerCallback* controller) + int32_t KeyboardController::ReadRawPress() { + return lastKey; + } + + + void KeyboardController::WriteToSource(int32_t slot, ControllerCallback* controller) { } - std::string KeyboardController::GetControllerType() { - return "KEYBOARD"; + const char* KeyboardController::GetButtonName(int slot, int n64Button) { + std::map& Mappings = profiles[slot].Mappings; + const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair& pair) { + return pair.second == n64Button; + }); + + if (find == Mappings.end()) return "Unknown"; + const char* name = GlobalCtx2::GetInstance()->GetWindow()->GetKeyName(find->first); + return strlen(name) == 0 ? "Unknown" : name; } - std::string KeyboardController::GetConfSection() { - return GetControllerType() + " CONTROLLER " + std::to_string(GetControllerNumber() + 1); + + void KeyboardController::CreateDefaultBinding(int32_t slot) { + DeviceProfile& profile = profiles[slot]; + profile.Mappings[0x14D] = BTN_CRIGHT; + profile.Mappings[0x14B] = BTN_CLEFT; + profile.Mappings[0x150] = BTN_CDOWN; + profile.Mappings[0x148] = BTN_CUP; + profile.Mappings[0x13] = BTN_R; + profile.Mappings[0x12] = BTN_L; + profile.Mappings[0x023] = BTN_DRIGHT; + profile.Mappings[0x021] = BTN_DLEFT; + profile.Mappings[0x022] = BTN_DDOWN; + profile.Mappings[0x014] = BTN_DUP; + profile.Mappings[0x039] = BTN_START; + profile.Mappings[0x02C] = BTN_Z; + profile.Mappings[0x02E] = BTN_B; + profile.Mappings[0x02D] = BTN_A; + profile.Mappings[0x020] = BTN_STICKRIGHT; + profile.Mappings[0x01E] = BTN_STICKLEFT; + profile.Mappings[0x01F] = BTN_STICKDOWN; + profile.Mappings[0x011] = BTN_STICKUP; } - std::string KeyboardController::GetBindingConfSection() { - return GetControllerType() + " CONTROLLER BINDING " + std::to_string(GetControllerNumber() + 1); + const char* KeyboardController::GetControllerName() { + return "Keyboard"; } } diff --git a/libultraship/libultraship/KeyboardController.h b/libultraship/libultraship/KeyboardController.h index f6c109ca7..cc0aca04e 100644 --- a/libultraship/libultraship/KeyboardController.h +++ b/libultraship/libultraship/KeyboardController.h @@ -5,24 +5,34 @@ namespace Ship { class KeyboardController : public Controller { public: - KeyboardController(int32_t dwControllerNumber); - ~KeyboardController(); - - void ReadFromSource(); - void WriteToSource(ControllerCallback* controller); - bool Connected() const { return true; } - bool CanRumble() const { return false; } + KeyboardController(); + void ReadFromSource(int32_t slot) override; + void WriteToSource(int32_t slot, ControllerCallback* controller) override; + bool Connected() const override { return true; } + bool CanRumble() const override { return false; } + bool CanGyro() const override { return false; } + const char* GetControllerName() override; + const char* GetButtonName(int slot, int n64Button) override; bool PressButton(int32_t dwScancode); bool ReleaseButton(int32_t dwScancode); + + void ClearRawPress() override { + lastKey = -1; + } + + int32_t ReadRawPress() override; void ReleaseAllButtons(); - bool HasPadConf() const { return false; } - std::optional GetPadConfSection() { return {}; } + void SetLastScancode(int32_t key) { + lastScancode = key; + } + + int32_t GetLastScancode() { return lastScancode; } + void CreateDefaultBinding(int32_t slot) override; protected: - std::string GetControllerType(); - std::string GetConfSection(); - std::string GetBindingConfSection(); + int32_t lastScancode; + int32_t lastKey = -1; }; } diff --git a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/controller.h b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/controller.h index c2aafa919..af95c4212 100644 --- a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/controller.h +++ b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/controller.h @@ -112,9 +112,11 @@ typedef struct { /* 0x02 */ s8 stick_x; /* 0x03 */ s8 stick_y; /* 0x04 */ u8 err_no; - /* 0x05 */ f32 gyro_x; - /* 0x09 */ f32 gyro_y; -} OSContPad; // size = 0x0D + /* 0x05 */ f32 gyro_x; + /* 0x09 */ f32 gyro_y; + /* 0x1C */ f32 cam_x; + /* 0x20 */ f32 cam_y; +} OSContPad; // size = 0x24 typedef struct { /* 0x00 */ u8 rumble; diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp index 06ff5f60a..6e0c2e4d6 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp @@ -28,6 +28,7 @@ #include "gfx_pc.h" #include "../../ImGuiImpl.h" #include "../../Cvar.h" +#include "../../Hooks.h" #define DECLARE_GFX_DXGI_FUNCTIONS #include "gfx_dxgi.h" @@ -228,9 +229,8 @@ static void onkeyup(WPARAM w_param, LPARAM l_param) { } } -char fileName[256]; - static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) { + char fileName[256]; SohImGui::EventImpl event_impl; event_impl.win32 = { h_wnd, static_cast(message), static_cast(w_param), static_cast(l_param) }; SohImGui::Update(event_impl); @@ -240,6 +240,7 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par dxgi.current_height = (uint32_t)(l_param >> 16); break; case WM_DESTROY: + ModInternal::ExecuteHooks(); exit(0); case WM_PAINT: if (dxgi.in_paint) { @@ -718,6 +719,12 @@ void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message) { } } +const char* gfx_dxgi_get_key_name(int scancode) { + TCHAR* Text = new TCHAR[64]; + GetKeyNameText(scancode << 16, Text, 64); + return (char*) Text; +} + extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { gfx_dxgi_init, gfx_dxgi_set_keyboard_callbacks, @@ -734,6 +741,7 @@ extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { gfx_dxgi_set_target_fps, gfx_dxgi_set_maximum_frame_latency, gfx_dxgi_get_detected_hz, + gfx_dxgi_get_key_name }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index 44ad9ec37..cb0d7a7f0 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -23,6 +23,7 @@ #include "../../ImGuiImpl.h" #include "../../Cvar.h" +#include "../../Hooks.h" #include "gfx_window_manager_api.h" #include "gfx_screen_config.h" @@ -108,7 +109,7 @@ static void set_fullscreen(bool on, bool call_callback) { SDL_GetDesktopDisplayMode(0, &mode); window_width = mode.w; window_height = mode.h; - //SDL_ShowCursor(false); + SDL_ShowCursor(false); } else { window_width = DESIRED_SCREEN_WIDTH; window_height = DESIRED_SCREEN_HEIGHT; @@ -229,6 +230,15 @@ static int translate_scancode(int scancode) { } } +static int untranslate_scancode(int translatedScancode) { + for (int i = 0; i < 512; i++) { + if (inverted_scancode_table[i] == translatedScancode) { + return i; + } + } + return 0; +} + static void gfx_sdl_onkeydown(int scancode) { int key = translate_scancode(scancode); if (on_key_down_callback != NULL) { @@ -270,6 +280,7 @@ static void gfx_sdl_handle_events(void) { Game::SaveSettings(); break; case SDL_QUIT: + ModInternal::ExecuteHooks(); SDL_Quit(); // bandaid fix for linux window closing issue exit(0); } @@ -339,6 +350,10 @@ static float gfx_sdl_get_detected_hz(void) { return 0; } +static const char* gfx_sdl_get_key_name(int scancode) { + return SDL_GetScancodeName((SDL_Scancode) untranslate_scancode(scancode)); +} + struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_init, gfx_sdl_set_keyboard_callbacks, @@ -354,7 +369,8 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_get_time, gfx_sdl_set_target_fps, gfx_sdl_set_maximum_frame_latency, - gfx_sdl_get_detected_hz + gfx_sdl_get_detected_hz, + gfx_sdl_get_key_name }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h b/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h index 50618f661..99344940e 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_window_manager_api.h @@ -20,6 +20,7 @@ struct GfxWindowManagerAPI { void (*set_target_fps)(int fps); void (*set_maximum_frame_latency)(int latency); float (*get_detected_hz)(void); + const char* (*get_key_name)(int scancode); }; #endif diff --git a/libultraship/libultraship/Lib/Mercury/Mercury.cpp b/libultraship/libultraship/Lib/Mercury/Mercury.cpp new file mode 100644 index 000000000..d6bf734ea --- /dev/null +++ b/libultraship/libultraship/Lib/Mercury/Mercury.cpp @@ -0,0 +1,134 @@ +#include "Mercury.h" + +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; +using json = nlohmann::json; + +std::unordered_map ramMap; + +Mercury::Mercury(std::string path) : path_(std::move(path)) { + this->reload(); +} + +std::vector split(const std::string& s, const char delimiter) { + std::vector result; + std::stringstream ss(s); + std::string item; + while (getline(ss, item, delimiter)) { + result.push_back(item); + } + return result; +} + +std::string Mercury::formatNestedKey(const std::string& key) { + const std::vector dots = split(key, '.'); + std::string tmp; + if (dots.size() > 1) + for (const auto& dot : dots) { + tmp += "/" + dot; + } + else + tmp = "/" + dots[0]; + + return tmp; +} + +json Mercury::nested(const std::string& key) { + std::vector dots = split(key, '.'); + if (!this->vjson.is_object()) + return this->vjson; + json gjson = this->vjson.unflatten(); + + if (dots.size() > 1) { + for (auto& key : dots) { + if (key == "*" || gjson.contains(key)) + gjson = gjson[key]; + } + return gjson; + } + + return gjson[key]; +} + +std::string Mercury::getString(const std::string& key, const std::string& def) { + json n = this->nested(key); + if (n.is_string() && !n.get().empty()) + return n; + return def; +} + +float Mercury::getFloat(const std::string& key, float def) { + json n = this->nested(key); + if (n.is_number_float()) + return n; + return def; +} + +bool Mercury::getBool(const std::string& key, bool def) { + json n = this->nested(key); + if (n.is_boolean()) + return n; + return def; +} + +int Mercury::getInt(const std::string& key, int def) { + json n = this->nested(key); + if (n.is_number_integer()) + return n; + return def; +} + +bool Mercury::contains(const std::string& key) { + return !this->nested(key).is_null(); +} + +void Mercury::setString(const std::string& key, const std::string& value) { + this->vjson[formatNestedKey(key)] = value; +} + +void Mercury::setFloat(const std::string& key, float value) { + this->vjson[formatNestedKey(key)] = value; +} + +void Mercury::setBool(const std::string& key, bool value) { + this->vjson[formatNestedKey(key)] = value; +} + +void Mercury::setInt(const std::string& key, int value) { + this->vjson[formatNestedKey(key)] = value; +} + +void Mercury::setUInt(const std::string& key, uint32_t value) { + this->vjson[formatNestedKey(key)] = value; +} + +void Mercury::erase(const std::string& key) { + this->vjson.erase(formatNestedKey(key)); +} + +void Mercury::reload() { + if (this->path_ == "None" || !fs::exists(this->path_) || !fs::is_regular_file(this->path_)) { + this->isNewInstance = true; + this->vjson = json::object(); + return; + } + std::ifstream ifs(this->path_); + try { + this->rjson = json::parse(ifs); + this->vjson = this->rjson.flatten(); + } + catch (...) { + this->vjson = json::object(); + } +} + +void Mercury::save() const { + std::ofstream file(this->path_); + file << this->vjson.unflatten().dump(4); +} diff --git a/libultraship/libultraship/Lib/Mercury/Mercury.h b/libultraship/libultraship/Lib/Mercury/Mercury.h new file mode 100644 index 000000000..5c2646d36 --- /dev/null +++ b/libultraship/libultraship/Lib/Mercury/Mercury.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include "../nlohmann/json.hpp" + +class Mercury { +protected: + std::string path_; +public: + explicit Mercury(std::string path); + + nlohmann::json vjson; + nlohmann::json rjson; + nlohmann::json nested(const std::string& key); + static std::string formatNestedKey(const std::string& key); + std::string getString(const std::string& key, const std::string& def = ""); + float getFloat(const std::string& key, float defValue = 0.0f); + bool getBool(const std::string& key, bool defValue = false); + int getInt(const std::string& key, int defValue = 0); + bool contains(const std::string& key); + template< typename T > std::vector getArray(const std::string& key); + void setString(const std::string& key, const std::string& value); + void setFloat(const std::string& key, float value); + void setBool(const std::string& key, bool value); + void setInt(const std::string& key, int value); + void setUInt(const std::string& key, uint32_t value); + void erase(const std::string& key); + void set(const std::string& key, std::any value); + template< typename T > void setArray(const std::string& key, std::vector array); + + void reload(); + void save() const; + bool isNewInstance = false; +}; + +template< typename T > +std::vector Mercury::getArray(const std::string& key) { + if (nlohmann::json tmp = this->nested(key); tmp.is_array()) + return tmp.get>(); + return std::vector(); +}; + +template +void Mercury::setArray(const std::string& key, std::vector array) { + this->vjson[formatNestedKey(key)] = nlohmann::json(array); +} diff --git a/soh/soh/Lib/nlohmann/LICENSE.MIT b/libultraship/libultraship/Lib/nlohmann/LICENSE.MIT similarity index 100% rename from soh/soh/Lib/nlohmann/LICENSE.MIT rename to libultraship/libultraship/Lib/nlohmann/LICENSE.MIT diff --git a/soh/soh/Lib/nlohmann/json.hpp b/libultraship/libultraship/Lib/nlohmann/json.hpp similarity index 100% rename from soh/soh/Lib/nlohmann/json.hpp rename to libultraship/libultraship/Lib/nlohmann/json.hpp diff --git a/libultraship/libultraship/OSXFolderManager.h b/libultraship/libultraship/OSXFolderManager.h new file mode 100644 index 000000000..476b78d3c --- /dev/null +++ b/libultraship/libultraship/OSXFolderManager.h @@ -0,0 +1,60 @@ +// +// OSXFolderManager.h +// libultraship +// +// Created by David Chavez on 28.06.22. +// + +#ifndef OSXFolderManager_h +#define OSXFolderManager_h + +#include +namespace Ship { + enum { + NSApplicationDirectory = 1, + NSDemoApplicationDirectory, + NSDeveloperApplicationDirectory, + NSAdminApplicationDirectory, + NSLibraryDirectory, + NSDeveloperDirectory, + NSUserDirectory, + NSDocumentationDirectory, + NSDocumentDirectory, + NSCoreServiceDirectory, + NSAutosavedInformationDirectory = 11, + NSDesktopDirectory = 12, + NSCachesDirectory = 13, + NSApplicationSupportDirectory = 14, + NSDownloadsDirectory = 15, + NSInputMethodsDirectory = 16, + NSMoviesDirectory = 17, + NSMusicDirectory = 18, + NSPicturesDirectory = 19, + NSPrinterDescriptionDirectory = 20, + NSSharedPublicDirectory = 21, + NSPreferencePanesDirectory = 22, + NSApplicationScriptsDirectory = 23, + NSItemReplacementDirectory = 99, + NSAllApplicationsDirectory = 100, + NSAllLibrariesDirectory = 101, + NSTrashDirectory = 102 + }; + typedef unsigned long SearchPathDirectory; + + enum { + NSUserDomainMask = 1, // user's home directory --- place to install user's personal items (~) + NSLocalDomainMask = 2, // local to the current machine --- place to install items available to everyone on this machine (/Library) + NSNetworkDomainMask = 4, // publically available location in the local area network --- place to install items available on the network (/Network) + NSSystemDomainMask = 8, // provided by Apple, unmodifiable (/System) + NSAllDomainsMask = 0x0ffff // all domains: all of the above and future items + }; + typedef unsigned long SearchPathDomainMask; + + class FolderManager { + public: + const char *pathForDirectory(SearchPathDirectory directory, SearchPathDomainMask domainMask); + const char *pathForDirectoryAppropriateForItemAtPath(SearchPathDirectory directory, SearchPathDomainMask domainMask, const char *itemPath, bool create = false); + }; +}; + +#endif /* OSXFolderManager_h */ diff --git a/libultraship/libultraship/OSXFolderManager.mm b/libultraship/libultraship/OSXFolderManager.mm new file mode 100644 index 000000000..85bfb20a8 --- /dev/null +++ b/libultraship/libultraship/OSXFolderManager.mm @@ -0,0 +1,37 @@ +// +// OSXFolderManager.m +// libultraship +// +// Created by David Chavez on 28.06.22. +// + +#include "OSXFolderManager.h" +#import + +using namespace Ship; + +const char * FolderManager::pathForDirectory(SearchPathDirectory directory, SearchPathDomainMask domainMask) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSArray *URLs = [fileManager URLsForDirectory:(NSSearchPathDirectory)directory inDomains:domainMask]; + if (URLs.count == 0) return NULL; + + NSURL *URL = [URLs objectAtIndex:0]; + NSString *path = URL.path; + + // `fileSystemRepresentation` on an `NSString` gives a path suitable for POSIX APIs + return path.fileSystemRepresentation; +} + +const char * FolderManager::pathForDirectoryAppropriateForItemAtPath(SearchPathDirectory directory, + SearchPathDomainMask domainMask, const char *itemPath, bool create) { + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *nsPath = [fileManager stringWithFileSystemRepresentation:itemPath length:strlen(itemPath)]; + NSURL *itemURL = (nsPath ? [NSURL fileURLWithPath:nsPath] : nil); + + NSURL *URL = [fileManager URLForDirectory:(NSSearchPathDirectory)directory + inDomain:domainMask + appropriateForURL:itemURL + create:create error:NULL]; + return URL.path.fileSystemRepresentation; +} diff --git a/libultraship/libultraship/Resource.h b/libultraship/libultraship/Resource.h index 4e4d73b29..6bdae983e 100644 --- a/libultraship/libultraship/Resource.h +++ b/libultraship/libultraship/Resource.h @@ -63,8 +63,7 @@ namespace Ship Deckard = 0, Roy = 1, Rachael = 2, - Leon = 3, - Zhora = 4, + Zhora = 3, // ... }; diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index bc89cc78a..3d02a8614 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -1,103 +1,36 @@ #include "SDLController.h" - -#include "GameSettings.h" #include "GlobalCtx2.h" #include "spdlog/spdlog.h" -#include "stox.h" #include "Window.h" -#include "Cvar.h" #include extern "C" uint8_t __osMaxControllers; namespace Ship { - SDLController::SDLController(int32_t dwControllerNumber) : Controller(dwControllerNumber), Cont(nullptr), guid(INVALID_SDL_CONTROLLER_GUID) { - - } - - SDLController::~SDLController() { - Close(); - } - - bool SDLController::IsGuidInUse(const std::string& guid) { - // Check if the GUID is loaded in any other controller; - for (size_t i = 0; i < __osMaxControllers; i++) { - for (size_t j = 0; j < Window::Controllers[i].size(); j++) { - SDLController* OtherCont = dynamic_cast(Window::Controllers[i][j].get()); - - if (OtherCont != nullptr && OtherCont->GetGuid().compare(guid) == 0) { - return true; - } - } - } - - return false; - } bool SDLController::Open() { - std::string ConfSection = GetConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); - for (int i = 0; i < SDL_NumJoysticks(); i++) { - if (SDL_IsGameController(i)) { - // Get the GUID from SDL - char GuidBuf[33]; - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), GuidBuf, sizeof(GuidBuf)); - auto NewGuid = std::string(GuidBuf); + const auto NewCont = SDL_GameControllerOpen(physicalSlot); - // Invalid GUID read. Go to next. - if (NewGuid.compare(INVALID_SDL_CONTROLLER_GUID) == 0) { - SPDLOG_ERROR("SDL Controller returned invalid guid"); - continue; - } - - // The GUID is in use, we want to use a different physical controller. Go to next. - if (IsGuidInUse(NewGuid)) { - continue; - } - - // If the GUID is blank from the config, OR if the config GUID matches, load the controller. - if (Conf[ConfSection]["GUID"].compare("") == 0 || Conf[ConfSection]["GUID"].compare(INVALID_SDL_CONTROLLER_GUID) == 0 || Conf[ConfSection]["GUID"].compare(NewGuid) == 0) { - auto NewCont = SDL_GameControllerOpen(i); - - // We failed to load the controller. Go to next. - if (NewCont == nullptr) { - SPDLOG_ERROR("SDL Controller failed to open: ({})", SDL_GetError()); - continue; - } - - if (SDL_GameControllerHasSensor(NewCont, SDL_SENSOR_GYRO)) - { - SDL_GameControllerSetSensorEnabled(NewCont, SDL_SENSOR_GYRO, SDL_TRUE); - } - - guid = NewGuid; - Cont = NewCont; - - std::string BindingConfSection = GetBindingConfSection(); - std::string PadConfSection = *GetPadConfSection(); - std::shared_ptr config = GlobalCtx2::GetInstance()->GetConfig(); - - if (!config->has(BindingConfSection)) { - CreateDefaultBinding(); - } - - if (!config->has(PadConfSection)) { - CreateDefaultPadConf(); - } - - LoadBinding(); - LoadAxisThresholds(); - // Update per-controller settings in ImGui menu after opening controller. - Game::LoadPadSettings(); - - break; - } - } + // We failed to load the controller. Go to next. + if (NewCont == nullptr) { + SPDLOG_ERROR("SDL Controller failed to open: ({})", SDL_GetError()); + return false; } - return Cont != nullptr; + if (SDL_GameControllerHasSensor(NewCont, SDL_SENSOR_GYRO)) { + SDL_GameControllerSetSensorEnabled(NewCont, SDL_SENSOR_GYRO, SDL_TRUE); + supportsGyro = true; + } + + char GuidBuf[33]; + SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(physicalSlot), GuidBuf, sizeof(GuidBuf)); + GUID = std::string(GuidBuf); + Cont = NewCont; + wCamX = 0; + wCamY = 0; + + return true; } bool SDLController::Close() { @@ -108,31 +41,14 @@ namespace Ship { SDL_GameControllerClose(Cont); } Cont = nullptr; - guid = ""; - ButtonMapping.clear(); - ThresholdMapping.clear(); - dwPressedButtons = 0; wStickX = 0; wStickY = 0; return true; } - void SDLController::LoadAxisThresholds() { - std::string ConfSection = GetBindingConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); - ThresholdMapping[SDL_CONTROLLER_AXIS_LEFTX] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_LEFTX) + "_threshold"]); - ThresholdMapping[SDL_CONTROLLER_AXIS_LEFTY] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_LEFTY) + "_threshold"]); - ThresholdMapping[SDL_CONTROLLER_AXIS_RIGHTX] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_RIGHTX) + "_threshold"]); - ThresholdMapping[SDL_CONTROLLER_AXIS_RIGHTY] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_RIGHTY) + "_threshold"]); - ThresholdMapping[SDL_CONTROLLER_AXIS_TRIGGERLEFT] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_TRIGGERLEFT) + "_threshold"]); - ThresholdMapping[SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = Ship::stoi(Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_TRIGGERRIGHT) + "_threshold"]); - } - - - void SDLController::NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold) { + void SDLController::NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold, bool isRightStick, float sensitivity) { //scale {-32768 ... +32767} to {-84 ... +84} auto ax = wAxisValueX * 85.0 / 32767.0; auto ay = wAxisValueY * 85.0 / 32767.0; @@ -163,14 +79,59 @@ namespace Ship { ay *= scale; } - wStickX = +ax; - wStickY = -ay; + if (!isRightStick) { + wStickX = +ax; + wStickY = -ay; + } else { + wCamX = +ax * sensitivity; + wCamY = -ay * sensitivity; + } } - void SDLController::ReadFromSource() { - std::string ConfSection = GetBindingConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + + int32_t SDLController::ReadRawPress() { + SDL_GameControllerUpdate(); + + for (int32_t i = SDL_CONTROLLER_BUTTON_A; i < SDL_CONTROLLER_BUTTON_MAX; i++) { + if (SDL_GameControllerGetButton(Cont, static_cast(i))) { + return i; + } + } + + for (int32_t i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) { + const auto Axis = static_cast(i); + const auto AxisValue = SDL_GameControllerGetAxis(Cont, Axis) / 32767.0f; + + if (AxisValue < -0.7f) { + return -(Axis + AXIS_SCANCODE_BIT); + } + + if (AxisValue > 0.7f) { + return (Axis + AXIS_SCANCODE_BIT); + } + } + + return -1; + } + + ControllerThresholds SDLAxisToThreshold( uint32_t axis ){ + switch(axis){ + case SDL_CONTROLLER_AXIS_LEFTX: + case SDL_CONTROLLER_AXIS_LEFTY: + return LEFT_STICK; + case SDL_CONTROLLER_AXIS_RIGHTX: + case SDL_CONTROLLER_AXIS_RIGHTY: + return RIGHT_STICK; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: + return LEFT_TRIGGER; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + return RIGHT_TRIGGER; + default: return DRIFT_X; + } + } + + void SDLController::ReadFromSource(int32_t slot) { + DeviceProfile& profile = profiles[slot]; SDL_GameControllerUpdate(); @@ -187,17 +148,14 @@ namespace Ship { } } - if (SDL_GameControllerHasSensor(Cont, SDL_SENSOR_GYRO)) - { - size_t contNumber = GetControllerNumber(); + if (supportsGyro && profile.UseGyro) { float gyroData[3]; SDL_GameControllerGetSensorData(Cont, SDL_SENSOR_GYRO, gyroData, 3); - const char* contName = SDL_GameControllerName(Cont); - float gyro_drift_x = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", contNumber).c_str(), 0.0f); - float gyro_drift_y = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", contNumber).c_str(), 0.0f); - const float gyro_sensitivity = CVar_GetFloat(StringHelper::Sprintf("gCont%i_GyroSensitivity", contNumber).c_str(), 1.0f); + float gyro_drift_x = profile.Thresholds[DRIFT_X] / 100.0f; + float gyro_drift_y = profile.Thresholds[DRIFT_Y] / 100.0f; + const float gyro_sensitivity = profile.Thresholds[GYRO_SENSITIVITY]; if (gyro_drift_x == 0) { gyro_drift_x = gyroData[0]; @@ -207,8 +165,8 @@ namespace Ship { gyro_drift_y = gyroData[1]; } - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftX", contNumber).c_str(), gyro_drift_x); - CVar_SetFloat(StringHelper::Sprintf("gCont%i_GyroDriftY", contNumber).c_str(), gyro_drift_y); + profile.Thresholds[DRIFT_X] = gyro_drift_x * 100.0f; + profile.Thresholds[DRIFT_Y] = gyro_drift_y * 100.0f; wGyroX = gyroData[0] - gyro_drift_x; wGyroY = gyroData[1] - gyro_drift_y; @@ -217,29 +175,35 @@ namespace Ship { wGyroY *= gyro_sensitivity; } + dwPressedButtons[slot] = 0; + for (int32_t i = SDL_CONTROLLER_BUTTON_A; i < SDL_CONTROLLER_BUTTON_MAX; i++) { - if (ButtonMapping.contains(i)) { - if (SDL_GameControllerGetButton(Cont, (SDL_GameControllerButton)i)) { - dwPressedButtons |= ButtonMapping[i]; + if (profile.Mappings.contains(i)) { + if (SDL_GameControllerGetButton(Cont, static_cast(i))) { + dwPressedButtons[slot] |= profile.Mappings[i]; } else { - dwPressedButtons &= ~ButtonMapping[i]; + dwPressedButtons[slot] &= ~profile.Mappings[i]; } } } - SDL_GameControllerAxis StickAxisX = SDL_CONTROLLER_AXIS_INVALID; - SDL_GameControllerAxis StickAxisY = SDL_CONTROLLER_AXIS_INVALID; - int32_t StickDeadzone = 0; + SDL_GameControllerAxis LStickAxisX = SDL_CONTROLLER_AXIS_INVALID; + SDL_GameControllerAxis LStickAxisY = SDL_CONTROLLER_AXIS_INVALID; + int32_t LStickDeadzone = 0; + + SDL_GameControllerAxis RStickAxisX = SDL_CONTROLLER_AXIS_INVALID; + SDL_GameControllerAxis RStickAxisY = SDL_CONTROLLER_AXIS_INVALID; + int32_t RStickDeadzone = 0; for (int32_t i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) { - auto Axis = (SDL_GameControllerAxis)i; - auto PosScancode = i + AXIS_SCANCODE_BIT; - auto NegScancode = -PosScancode; - auto AxisThreshold = ThresholdMapping[i]; - auto PosButton = ButtonMapping[PosScancode]; - auto NegButton = ButtonMapping[NegScancode]; - auto AxisValue = SDL_GameControllerGetAxis(Cont, Axis); + const auto Axis = static_cast(i); + const auto PosScancode = i + AXIS_SCANCODE_BIT; + const auto NegScancode = -PosScancode; + const auto AxisThreshold = static_cast(profile.Thresholds[SDLAxisToThreshold(i)]); + const auto PosButton = profile.Mappings[PosScancode]; + const auto NegButton = profile.Mappings[NegScancode]; + const auto AxisValue = SDL_GameControllerGetAxis(Cont, Axis); #ifdef TARGET_WEB // Firefox has a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1606562 @@ -252,94 +216,176 @@ namespace Ship { } #endif - // If the axis is NOT mapped to the control stick. if (!( PosButton == BTN_STICKLEFT || PosButton == BTN_STICKRIGHT || PosButton == BTN_STICKUP || PosButton == BTN_STICKDOWN || NegButton == BTN_STICKLEFT || NegButton == BTN_STICKRIGHT || NegButton == BTN_STICKUP || NegButton == BTN_STICKDOWN)) { - if (AxisValue > AxisThreshold) { - dwPressedButtons |= PosButton; - dwPressedButtons &= ~NegButton; + + if (AxisValue > 0x1E00) { + dwPressedButtons[slot] |= PosButton; + dwPressedButtons[slot] &= ~NegButton; } - else if (AxisValue < -AxisThreshold) { - dwPressedButtons &= ~PosButton; - dwPressedButtons |= NegButton; + else if (AxisValue < -0x1E00) { + dwPressedButtons[slot] &= ~PosButton; + dwPressedButtons[slot] |= NegButton; } else { - dwPressedButtons &= ~PosButton; - dwPressedButtons &= ~NegButton; + dwPressedButtons[slot] &= ~PosButton; + dwPressedButtons[slot] &= ~NegButton; } } else { if (PosButton == BTN_STICKLEFT || PosButton == BTN_STICKRIGHT) { - if (StickAxisX != SDL_CONTROLLER_AXIS_INVALID && StickAxisX != Axis) { - SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", StickAxisX, Axis); + if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisX != Axis) { + SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", LStickAxisX, Axis); } - if (StickDeadzone != 0 && StickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", StickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", LStickDeadzone, AxisThreshold); } - StickDeadzone = AxisThreshold; - StickAxisX = Axis; + LStickDeadzone = AxisThreshold; + LStickAxisX = Axis; } if (PosButton == BTN_STICKUP || PosButton == BTN_STICKDOWN) { - if (StickAxisY != SDL_CONTROLLER_AXIS_INVALID && StickAxisY != Axis) { - SPDLOG_TRACE("Invalid PosStickY configured. Neg was {} and Pos is {}", StickAxisY, Axis); + if (LStickAxisY != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != Axis) { + SPDLOG_TRACE("Invalid PosStickY configured. Neg was {} and Pos is {}", LStickAxisY, Axis); } - if (StickDeadzone != 0 && StickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", StickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); } - StickDeadzone = AxisThreshold; - StickAxisY = Axis; + LStickDeadzone = AxisThreshold; + LStickAxisY = Axis; } if (NegButton == BTN_STICKLEFT || NegButton == BTN_STICKRIGHT) { - if (StickAxisX != SDL_CONTROLLER_AXIS_INVALID && StickAxisX != Axis) { - SPDLOG_TRACE("Invalid NegStickX configured. Pos was {} and Neg is {}", StickAxisX, Axis); + if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisX != Axis) { + SPDLOG_TRACE("Invalid NegStickX configured. Pos was {} and Neg is {}", LStickAxisX, Axis); } - if (StickDeadzone != 0 && StickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", StickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); } - StickDeadzone = AxisThreshold; - StickAxisX = Axis; + LStickDeadzone = AxisThreshold; + LStickAxisX = Axis; } if (NegButton == BTN_STICKUP || NegButton == BTN_STICKDOWN) { - if (StickAxisY != SDL_CONTROLLER_AXIS_INVALID && StickAxisY != Axis) { - SPDLOG_TRACE("Invalid NegStickY configured. Pos was {} and Neg is {}", StickAxisY, Axis); + if (LStickAxisY != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != Axis) { + SPDLOG_TRACE("Invalid NegStickY configured. Pos was {} and Neg is {}", LStickAxisY, Axis); } - if (StickDeadzone != 0 && StickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", StickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); } - StickDeadzone = AxisThreshold; - StickAxisY = Axis; + LStickDeadzone = AxisThreshold; + LStickAxisY = Axis; } } - if (StickAxisX != SDL_CONTROLLER_AXIS_INVALID && StickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - auto AxisValueX = SDL_GameControllerGetAxis(Cont, StickAxisX); - auto AxisValueY = SDL_GameControllerGetAxis(Cont, StickAxisY); - NormalizeStickAxis(AxisValueX, AxisValueY, StickDeadzone); + if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + const auto AxisValueX = SDL_GameControllerGetAxis(Cont, LStickAxisX); + const auto AxisValueY = SDL_GameControllerGetAxis(Cont, LStickAxisY); + NormalizeStickAxis(AxisValueX, AxisValueY, LStickDeadzone, false, profile.Thresholds[SENSITIVITY]); + } + + // Right Stick + // If the axis is NOT mapped to the control stick. + if (!( + PosButton == BTN_VSTICKLEFT || PosButton == BTN_VSTICKRIGHT || + PosButton == BTN_VSTICKUP || PosButton == BTN_VSTICKDOWN || + NegButton == BTN_VSTICKLEFT || NegButton == BTN_VSTICKRIGHT || + NegButton == BTN_VSTICKUP || NegButton == BTN_VSTICKDOWN)) { + + if (AxisValue > 0x1E00) { + dwPressedButtons[slot] |= PosButton; + dwPressedButtons[slot] &= ~NegButton; + } + else if (AxisValue < -0x1E00) { + dwPressedButtons[slot] &= ~PosButton; + dwPressedButtons[slot] |= NegButton; + } + else { + dwPressedButtons[slot] &= ~PosButton; + dwPressedButtons[slot] &= ~NegButton; + } + + } else { + if (PosButton == BTN_VSTICKLEFT || PosButton == BTN_VSTICKRIGHT) { + if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisX != Axis) { + SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", RStickAxisX, Axis); + } + + if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", RStickDeadzone, AxisThreshold); + } + + RStickDeadzone = AxisThreshold; + RStickAxisX = Axis; + } + + if (PosButton == BTN_VSTICKUP || PosButton == BTN_VSTICKDOWN) { + if (RStickAxisY != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != Axis) { + SPDLOG_TRACE("Invalid PosStickY configured. Neg was {} and Pos is {}", RStickAxisY, Axis); + } + + if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + } + + RStickDeadzone = AxisThreshold; + RStickAxisY = Axis; + } + + if (NegButton == BTN_VSTICKLEFT || NegButton == BTN_VSTICKRIGHT) { + if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisX != Axis) { + SPDLOG_TRACE("Invalid NegStickX configured. Pos was {} and Neg is {}", RStickAxisX, Axis); + } + + if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + } + + RStickDeadzone = AxisThreshold; + RStickAxisX = Axis; + } + + if (NegButton == BTN_VSTICKUP || NegButton == BTN_VSTICKDOWN) { + if (RStickAxisY != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != Axis) { + SPDLOG_TRACE("Invalid NegStickY configured. Pos was {} and Neg is {}", RStickAxisY, Axis); + } + + if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { + SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + } + + RStickDeadzone = AxisThreshold; + RStickAxisY = Axis; + } + } + + if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + const auto AxisValueX = SDL_GameControllerGetAxis(Cont, RStickAxisX); + const auto AxisValueY = SDL_GameControllerGetAxis(Cont, RStickAxisY); + NormalizeStickAxis(AxisValueX, AxisValueY, RStickDeadzone, true, profile.Thresholds[SENSITIVITY]); } } } - void SDLController::WriteToSource(ControllerCallback* controller) + void SDLController::WriteToSource(int32_t slot, ControllerCallback* controller) { - if (CanRumble()) { + if (CanRumble() && profiles[slot].UseRumble) { if (controller->rumble > 0) { - float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", GetControllerNumber()).c_str(), 1.0f); + float rumble_strength = profiles[slot].RumbleStrength; SDL_GameControllerRumble(Cont, 0xFFFF * rumble_strength, 0xFFFF * rumble_strength, 0); - } else { + } + else { SDL_GameControllerRumble(Cont, 0, 0, 0); } } @@ -362,73 +408,74 @@ namespace Ship { } } - void SDLController::CreateDefaultBinding() { - std::string ConfSection = GetBindingConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + const char* AxisNames[] = { + "Left Stick X", + "Left Stick Y", + "Right Stick X", + "Right Stick Y", + "Left Trigger", + "Right Trigger", + "Start Button" + }; - Conf[ConfSection][STR(BTN_CRIGHT)] = std::to_string((SDL_CONTROLLER_AXIS_RIGHTX + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_CLEFT)] = std::to_string(-(SDL_CONTROLLER_AXIS_RIGHTX + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_CDOWN)] = std::to_string((SDL_CONTROLLER_AXIS_RIGHTY + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_CUP)] = std::to_string(-(SDL_CONTROLLER_AXIS_RIGHTY + AXIS_SCANCODE_BIT)); - //Conf[ConfSection][STR(BTN_CRIGHT + "_2")] = std::to_string(SDL_CONTROLLER_BUTTON_X); - //Conf[ConfSection][STR(BTN_CLEFT + "_2")] = std::to_string(SDL_CONTROLLER_BUTTON_Y); - //Conf[ConfSection][STR(BTN_CDOWN + "_2")] = std::to_string(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - //Conf[ConfSection][STR(BTN_CUP + "_2")] = std::to_string(SDL_CONTROLLER_BUTTON_RIGHTSTICK); - Conf[ConfSection][STR(BTN_R)] = std::to_string((SDL_CONTROLLER_AXIS_TRIGGERRIGHT + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_L)] = std::to_string(SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - Conf[ConfSection][STR(BTN_DRIGHT)] = std::to_string(SDL_CONTROLLER_BUTTON_DPAD_RIGHT); - Conf[ConfSection][STR(BTN_DLEFT)] = std::to_string(SDL_CONTROLLER_BUTTON_DPAD_LEFT); - Conf[ConfSection][STR(BTN_DDOWN)] = std::to_string(SDL_CONTROLLER_BUTTON_DPAD_DOWN); - Conf[ConfSection][STR(BTN_DUP)] = std::to_string(SDL_CONTROLLER_BUTTON_DPAD_UP); - Conf[ConfSection][STR(BTN_START)] = std::to_string(SDL_CONTROLLER_BUTTON_START); - Conf[ConfSection][STR(BTN_Z)] = std::to_string((SDL_CONTROLLER_AXIS_TRIGGERLEFT + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_B)] = std::to_string(SDL_CONTROLLER_BUTTON_B); - Conf[ConfSection][STR(BTN_A)] = std::to_string(SDL_CONTROLLER_BUTTON_A); - Conf[ConfSection][STR(BTN_STICKRIGHT)] = std::to_string((SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_STICKLEFT)] = std::to_string(-(SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_STICKDOWN)] = std::to_string((SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT)); - Conf[ConfSection][STR(BTN_STICKUP)] = std::to_string(-(SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT)); + char buffer[50]; + const char* SDLController::GetButtonName(int slot, int n64Button) { + std::map& Mappings = profiles[slot].Mappings; + const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair& pair) { + return pair.second == n64Button; + }); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_LEFTX) + "_threshold"] = std::to_string(16.0); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_LEFTY) + "_threshold"] = std::to_string(16.0); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_RIGHTX) + "_threshold"] = std::to_string(0x4000); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_RIGHTY) + "_threshold"] = std::to_string(0x4000); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_TRIGGERLEFT) + "_threshold"] = std::to_string(0x1E00); - Conf[ConfSection][STR(SDL_CONTROLLER_AXIS_TRIGGERRIGHT) + "_threshold"] = std::to_string(0x1E00); + if (find == Mappings.end()) return "Unknown"; - Conf.Save(); - } + int btn = abs(find->first); - void SDLController::CreateDefaultPadConf() { - std::string ConfSection = *GetPadConfSection(); - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + if(btn >= AXIS_SCANCODE_BIT) { + btn -= AXIS_SCANCODE_BIT; - Conf.Save(); - } - - void SDLController::SetButtonMapping(const std::string& szButtonName, int32_t dwScancode) { - if (guid.compare(INVALID_SDL_CONTROLLER_GUID)) { - return; + snprintf(buffer, sizeof(buffer), "%s%s", AxisNames[btn], find->first > 0 ? "+" : "-"); + return buffer; } - Controller::SetButtonMapping(szButtonName, dwScancode); + snprintf(buffer, sizeof(buffer), "Button %d", btn); + return buffer; } - std::string SDLController::GetControllerType() { - return "SDL"; - } - - std::string SDLController::GetConfSection() { - return GetControllerType() + " CONTROLLER " + std::to_string(GetControllerNumber() + 1); + const char* SDLController::GetControllerName() { + return SDL_GameControllerNameForIndex(physicalSlot); } - std::string SDLController::GetBindingConfSection() { - return GetControllerType() + " CONTROLLER BINDING " + guid; - } + void SDLController::CreateDefaultBinding(int32_t slot) { + DeviceProfile& profile = profiles[slot]; + profile.Mappings.clear(); - std::optional SDLController::GetPadConfSection() { - return GetControllerType() + " CONTROLLER PAD " + guid; + profile.UseRumble = true; + profile.RumbleStrength = 1.0f; + profile.UseGyro = false; + profile.Mappings[ SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT] = BTN_CRIGHT; + profile.Mappings[-(SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT)] = BTN_CLEFT; + profile.Mappings[ SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT] = BTN_CDOWN; + profile.Mappings[-(SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT)] = BTN_CUP; + profile.Mappings[SDL_CONTROLLER_AXIS_TRIGGERRIGHT + AXIS_SCANCODE_BIT] = BTN_R; + profile.Mappings[SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = BTN_L; + profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = BTN_DRIGHT; + profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_LEFT] = BTN_DLEFT; + profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_DOWN] = BTN_DDOWN; + profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_UP] = BTN_DUP; + profile.Mappings[SDL_CONTROLLER_BUTTON_START] = BTN_START; + profile.Mappings[SDL_CONTROLLER_AXIS_TRIGGERLEFT + AXIS_SCANCODE_BIT] = BTN_Z; + profile.Mappings[SDL_CONTROLLER_BUTTON_B] = BTN_B; + profile.Mappings[SDL_CONTROLLER_BUTTON_A] = BTN_A; + profile.Mappings[(SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)] = BTN_STICKRIGHT; + profile.Mappings[-(SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)] = BTN_STICKLEFT; + profile.Mappings[SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT] = BTN_STICKDOWN; + profile.Mappings[-(SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT)] = BTN_STICKUP; + profile.Thresholds[LEFT_STICK] = 16.0f; + profile.Thresholds[RIGHT_STICK] = 16.0f; + profile.Thresholds[LEFT_TRIGGER] = 0x1E00; + profile.Thresholds[RIGHT_TRIGGER] = 0x1E00; + profile.Thresholds[DRIFT_X] = 0.0f; + profile.Thresholds[DRIFT_Y] = 0.0f; + profile.Thresholds[SENSITIVITY] = 16.0f; + profile.Thresholds[GYRO_SENSITIVITY] = 1.0f; } } diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h index 2493efbbc..ae239a2f1 100644 --- a/libultraship/libultraship/SDLController.h +++ b/libultraship/libultraship/SDLController.h @@ -6,46 +6,35 @@ #include #endif -#define INVALID_SDL_CONTROLLER_GUID (std::string("00000000000000000000000000000000")) - namespace Ship { class SDLController : public Controller { public: - SDLController(int32_t dwControllerNumber); - ~SDLController(); - - void ReadFromSource(); - void WriteToSource(ControllerCallback* controller); - bool Connected() const { return Cont != nullptr; } - bool CanRumble() const { + SDLController(int slot) : Controller(), Cont(nullptr), physicalSlot(slot) { } + void ReadFromSource(int32_t slot) override; + const char* GetControllerName() override; + const char* GetButtonName(int slot, int n64Button) override; + void WriteToSource(int32_t slot, 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 true; } - std::string GetGuid() { return guid; }; - - bool HasPadConf() const { return true; } - std::optional GetPadConfSection(); + bool Open(); + void ClearRawPress() override {} + int32_t ReadRawPress() override; protected: - std::string GetControllerType(); - void SetButtonMapping(const std::string& szButtonName, int32_t dwScancode); - std::string GetConfSection(); - std::string GetBindingConfSection(); - void CreateDefaultBinding(); - void CreateDefaultPadConf(); - static bool IsGuidInUse(const std::string& guid); + void CreateDefaultBinding(int32_t slot) override; private: SDL_GameController* Cont; - std::string guid; - std::map ThresholdMapping; - - void LoadAxisThresholds(); - void NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold); - bool Open(); + int physicalSlot; + bool supportsGyro; + void NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold, bool isRightStick, float sensitivity); bool Close(); }; } diff --git a/libultraship/libultraship/UltraController.h b/libultraship/libultraship/UltraController.h index 1c18dcd9b..41ea7f082 100644 --- a/libultraship/libultraship/UltraController.h +++ b/libultraship/libultraship/UltraController.h @@ -101,6 +101,10 @@ #define BTN_STICKRIGHT 0x20000 #define BTN_STICKDOWN 0x40000 #define BTN_STICKUP 0x80000 +#define BTN_VSTICKUP 0x100000 +#define BTN_VSTICKDOWN 0x200000 +#define BTN_VSTICKLEFT 0x400000 +#define BTN_VSTICKRIGHT 0x800000 typedef struct { /* 0x00 */ int32_t ram[15]; @@ -120,7 +124,9 @@ typedef struct { /* 0x04 */ uint8_t err_no; /* 0x05 */ float gyro_x; /* 0x09 */ float gyro_y; -} OSContPad; // size = 0x0D + /* 0x1C */ float cam_x; + /* 0x20 */ float cam_y; +} OSContPad; // size = 0x24 typedef struct { /* 0x00 */ uint8_t rumble; diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 91878b890..9d28ecf5e 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -38,8 +38,7 @@ extern "C" { uint8_t __enableGameInput = 1; int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) { - std::shared_ptr pConf = Ship::GlobalCtx2::GetInstance()->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); + *controllerBits = 0; if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) { SPDLOG_ERROR("Failed to initialize SDL game controllers ({})", SDL_GetError()); @@ -54,43 +53,7 @@ extern "C" { SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError()); } - // TODO: This for loop is debug. Burn it with fire. - for (int i = 0; i < SDL_NumJoysticks(); i++) { - if (SDL_IsGameController(i)) { - // Get the GUID from SDL - char buf[33]; - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i), buf, sizeof(buf)); - auto guid = std::string(buf); - auto name = std::string(SDL_GameControllerNameForIndex(i)); - - SPDLOG_INFO("Found Controller \"{}\" with ID \"{}\"", name, guid); - } - } - - for (int32_t i = 0; i < __osMaxControllers; i++) { - std::string ControllerType = Conf["CONTROLLERS"]["CONTROLLER " + std::to_string(i+1)]; - mINI::INIStringUtil::toLower(ControllerType); - - if (ControllerType == "auto") { - Ship::Window::Controllers[i].push_back(std::make_shared(i)); - Ship::Window::Controllers[i].push_back(std::make_shared(i)); - } else if (ControllerType == "keyboard") { - Ship::Window::Controllers[i].push_back(std::make_shared(i)); - } else if (ControllerType == "usb") { - Ship::Window::Controllers[i].push_back(std::make_shared(i)); - } else if (ControllerType == "unplugged") { - // Do nothing for unplugged controllers - } else { - SPDLOG_ERROR("Invalid Controller Type: {}", ControllerType); - } - } - - *controllerBits = 0; - for (size_t i = 0; i < __osMaxControllers; i++) { - if (Ship::Window::Controllers[i].size() > 0) { - *controllerBits |= 1 << i; - } - } + Ship::Window::ControllerApi->Init(controllerBits); return 0; } @@ -103,17 +66,14 @@ extern "C" { pad->button = 0; pad->stick_x = 0; pad->stick_y = 0; + pad->cam_x = 0; + pad->cam_y = 0; pad->err_no = 0; pad->gyro_x = 0; pad->gyro_y = 0; - if (__enableGameInput) - { - for (size_t i = 0; i < __osMaxControllers; i++) { - for (size_t j = 0; j < Ship::Window::Controllers[i].size(); j++) { - Ship::Window::Controllers[i][j]->Read(&pad[i]); - } - } + if (__enableGameInput) { + Ship::Window::ControllerApi->WriteToPad(pad); } ModInternal::ExecuteHooks(pad); @@ -129,15 +89,10 @@ extern "C" { if (hashStr != nullptr) { auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); + return (Vtx*)res->vertices.data(); + } - //if (res != nullptr) - return (Vtx*)res->vertices.data(); - //else - //return (Vtx*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadFile(hashStr)->buffer.get(); - } - else { - return nullptr; - } + return nullptr; } int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) { @@ -146,9 +101,9 @@ extern "C" { if (hashStr != nullptr) { auto res = std::static_pointer_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str())); return (int32_t*)res->mtx.data(); - } else { - return nullptr; } + + return nullptr; } Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) { @@ -233,7 +188,7 @@ extern GfxWindowManagerAPI gfx_sdl; void SetWindowManager(GfxWindowManagerAPI** WmApi, GfxRenderingAPI** RenderingApi, const std::string& gfx_backend); namespace Ship { - std::map>> Window::Controllers; + int32_t Window::lastScancode; Window::Window(std::shared_ptr Context) : Context(Context), APlayer(nullptr) { @@ -248,26 +203,55 @@ namespace Ship { SPDLOG_INFO("destruct window"); } + void Window::CreateDefaults() { + const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); + if (pConf->isNewInstance) { + pConf->setInt("Window.Width", 640); + pConf->setInt("Window.Height", 480); + pConf->setBool("Window.Options", false); + pConf->setString("Window.GfxBackend", ""); + + pConf->setBool("Window.Fullscreen.Enabled", false); + pConf->setInt("Window.Fullscreen.Width", 1920); + pConf->setInt("Window.Fullscreen.Height", 1080); + + pConf->setString("Game.SaveName", ""); + pConf->setString("Game.Main Archive", ""); + pConf->setString("Game.Patches Archive", ""); + + pConf->setInt("Shortcuts.Fullscreen", 0x044); + pConf->setInt("Shortcuts.Console", 0x029); + pConf->save(); + } + } + void Window::Init() { - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); + + CreateDefaults(); SetAudioPlayer(); - bIsFullscreen = Ship::stob(Conf["WINDOW"]["FULLSCREEN"]); + bIsFullscreen = pConf->getBool("Window.Fullscreen.Enabled", false); + if (bIsFullscreen) { - dwWidth = Ship::stoi(Conf["WINDOW"]["FULLSCREEN WIDTH"], 1920); - dwHeight = Ship::stoi(Conf["WINDOW"]["FULLSCREEN HEIGHT"], 1080); + dwWidth = pConf->getInt("Window.Fullscreen.Width", 1920); + dwHeight = pConf->getInt("Window.Fullscreen.Height", 1080); } else { - dwWidth = Ship::stoi(Conf["WINDOW"]["WINDOW WIDTH"], 640); - dwHeight = Ship::stoi(Conf["WINDOW"]["WINDOW HEIGHT"], 480); + dwWidth = pConf->getInt("Window.Width", 640); + dwHeight = pConf->getInt("Window.Height", 480); } - dwMenubar = Ship::stoi(Conf["WINDOW"]["menubar"], 0); - const std::string& gfx_backend = Conf["WINDOW"]["GFX BACKEND"]; + + dwMenubar = pConf->getBool("Window.Options", false); + const std::string& gfx_backend = pConf->getString("Window.GfxBackend"); SetWindowManager(&WmApi, &RenderingApi, gfx_backend); gfx_init(WmApi, RenderingApi, GetContext()->GetName().c_str(), bIsFullscreen, dwWidth, dwHeight); - WmApi->set_fullscreen_changed_callback(Window::OnFullscreenChanged); - WmApi->set_keyboard_callbacks(Window::KeyDown, Window::KeyUp, Window::AllKeysUp); + WmApi->set_fullscreen_changed_callback(OnFullscreenChanged); + WmApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp); + + ModInternal::RegisterHook([]() { + ControllerApi->SaveControllerSettings(); + }); } void Window::StartFrame() { @@ -318,30 +302,26 @@ namespace Ship { void Window::MainLoop(void (*MainFunction)(void)) { WmApi->main_loop(MainFunction); } + bool Window::KeyUp(int32_t dwScancode) { - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - if (dwScancode == Ship::stoi(Conf["KEYBOARD SHORTCUTS"]["KEY_FULLSCREEN"])) { + if (dwScancode == pConf->getInt("Shortcuts.Fullscreen", 0x044)) { GlobalCtx2::GetInstance()->GetWindow()->ToggleFullscreen(); } - - // OTRTODO: Rig with Kirito's console? //if (dwScancode == Ship::stoi(Conf["KEYBOARD SHORTCUTS"]["KEY_CONSOLE"])) { // ToggleConsole(); //} + + lastScancode = -1; bool bIsProcessed = false; - for (size_t i = 0; i < __osMaxControllers; i++) { - for (size_t j = 0; j < Controllers[i].size(); j++) { - KeyboardController* pad = dynamic_cast(Ship::Window::Controllers[i][j].get()); - if (pad != nullptr) { - if (pad->ReleaseButton(dwScancode)) { - bIsProcessed = true; - } - } + const auto pad = dynamic_cast(ControllerApi->physicalDevices[ControllerApi->physicalDevices.size() - 2].get()); + if (pad != nullptr) { + if (pad->ReleaseButton(dwScancode)) { + bIsProcessed = true; } } @@ -350,14 +330,11 @@ namespace Ship { bool Window::KeyDown(int32_t dwScancode) { bool bIsProcessed = false; - for (size_t i = 0; i < __osMaxControllers; i++) { - for (size_t j = 0; j < Controllers[i].size(); j++) { - KeyboardController* pad = dynamic_cast(Ship::Window::Controllers[i][j].get()); - if (pad != nullptr) { - if (pad->PressButton(dwScancode)) { - bIsProcessed = true; - } - } + + const auto pad = dynamic_cast(ControllerApi->physicalDevices[ControllerApi->physicalDevices.size() - 2].get()); + if (pad != nullptr) { + if (pad->PressButton(dwScancode)) { + bIsProcessed = true; } } @@ -368,21 +345,17 @@ namespace Ship { void Window::AllKeysUp(void) { - for (size_t i = 0; i < __osMaxControllers; i++) { - for (size_t j = 0; j < Controllers[i].size(); j++) { - KeyboardController* pad = dynamic_cast(Ship::Window::Controllers[i][j].get()); - if (pad != nullptr) { - pad->ReleaseAllButtons(); - } - } + const auto pad = dynamic_cast(ControllerApi->physicalDevices[ControllerApi->physicalDevices.size() - 2].get()); + if (pad != nullptr) { + pad->ReleaseAllButtons(); } } void Window::OnFullscreenChanged(bool bIsFullscreen) { - std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf.get(); + std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); + GlobalCtx2::GetInstance()->GetWindow()->bIsFullscreen = bIsFullscreen; - Conf["WINDOW"]["FULLSCREEN"] = std::to_string(bIsFullscreen); + pConf->setBool("Window.Fullscreen.Enabled", bIsFullscreen); GlobalCtx2::GetInstance()->GetWindow()->ShowCursor(!bIsFullscreen); } diff --git a/libultraship/libultraship/Window.h b/libultraship/libultraship/Window.h index a3087bf0c..1fa43abeb 100644 --- a/libultraship/libultraship/Window.h +++ b/libultraship/libultraship/Window.h @@ -5,17 +5,22 @@ #include "UltraController.h" #include "Controller.h" #include "GlobalCtx2.h" +#include "ControlDeck.h" +#include + +#include "Lib/Fast3D/gfx_window_manager_api.h" namespace Ship { class AudioPlayer; class Window { public: - static std::map>> Controllers; static int32_t lastScancode; + inline static ControlDeck* ControllerApi = new ControlDeck; Window(std::shared_ptr Context); ~Window(); + void CreateDefaults(); void MainLoop(void (*MainFunction)(void)); void Init(); void StartFrame(); @@ -31,9 +36,11 @@ namespace Ship { bool IsFullscreen() { return bIsFullscreen; } uint32_t GetCurrentWidth(); uint32_t GetCurrentHeight(); + ControlDeck* GetControlDeck() { return ControllerApi; }; uint32_t dwMenubar; std::shared_ptr GetContext() { return Context.lock(); } std::shared_ptr GetAudioPlayer() { return APlayer; } + const char* GetKeyName(int scancode) { return WmApi->get_key_name(scancode); } protected: private: @@ -46,11 +53,10 @@ namespace Ship { std::weak_ptr Context; std::shared_ptr APlayer; - GfxWindowManagerAPI* WmApi; GfxRenderingAPI* RenderingApi; + GfxWindowManagerAPI* WmApi; bool bIsFullscreen; uint32_t dwWidth; uint32_t dwHeight; }; } - diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj index d37915482..27e868afa 100644 --- a/libultraship/libultraship/libultraship.vcxproj +++ b/libultraship/libultraship/libultraship.vcxproj @@ -256,13 +256,16 @@ + + + @@ -279,7 +282,6 @@ - @@ -342,13 +344,18 @@ + + + + + @@ -404,7 +411,6 @@ - diff --git a/libultraship/libultraship/libultraship.vcxproj.filters b/libultraship/libultraship/libultraship.vcxproj.filters index d1682c86f..ec1c6f870 100644 --- a/libultraship/libultraship/libultraship.vcxproj.filters +++ b/libultraship/libultraship/libultraship.vcxproj.filters @@ -31,9 +31,6 @@ {c0f07350-c627-444e-9f66-23e19407ad9a} - - {9cf4833f-e90c-4a9d-8747-d47cde657beb} - {2aa34c3b-6148-480f-a4fc-19c4e0f8c822} @@ -94,6 +91,15 @@ {db6e02cc-fc4c-4138-8219-1d281ad93ec2} + + {2be7c90f-ba21-455d-8a11-6f99452be15c} + + + {7e415dd2-403b-4d4d-b4f2-3e311f91db19} + + + {010dc29b-d1f6-4793-a4e7-4156aa4fcdd6} + @@ -165,9 +171,6 @@ Source Files\Controller\Attachment - - Source Files\Config - Source Files\Resources\Files @@ -354,6 +357,15 @@ Source Files\Resources\Factories + + Source Files\Controller\InputEditor + + + Source Files\Controller + + + Source Files\Lib\Mercury + @@ -386,9 +398,6 @@ Source Files\Controller\Attachment - - Source Files\Config - Source Files\Resources @@ -659,5 +668,20 @@ Source Files\Lib\dr_libs + + Source Files\Controller\InputEditor + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Lib\nlohmann + + + Source Files\Lib\Mercury + \ No newline at end of file diff --git a/soh/.gitrepo b/soh/.gitrepo index 1186c7e01..06ac43f77 100644 --- a/soh/.gitrepo +++ b/soh/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/HarbourMasters/soh.git branch = master - commit = ba904bbd0d724784f8f37ff4bea378f6fe26151b - parent = 0bb0e7b53bd80bdc7f78e08c441691737e039b2b + commit = 75ccbade8ba26485266a8c8aa7d81e495d0ca4dd + parent = 8417db65c73cb3d117f2a0f9040105022a45480c method = rebase cmdver = 0.4.1 diff --git a/soh/Makefile b/soh/Makefile index 14bb46827..b05321a60 100644 --- a/soh/Makefile +++ b/soh/Makefile @@ -120,6 +120,7 @@ ifeq ($(UNAME), Darwin) #APPLE LDLIBS += \ $(addprefix -framework , \ OpenGL \ + Foundation \ ) \ $(shell sdl2-config --libs) $(shell pkg-config --libs glew) endif @@ -224,9 +225,6 @@ appbundle: macosx/$(APPNAME).icns cp macosx/PkgInfo $(APPBUNDLECONTENTS)/ cp macosx/$(APPNAME).icns $(APPBUNDLEICON)/ cp $(TARGET) $(APPBUNDLEEXE)/soh - cp macosx/launcher.sh $(APPBUNDLEEXE)/launcher.sh - clang -ObjC macosx/appsupport.m -arch arm64 -arch x86_64 -framework Foundation -o macosx/appsupport - cp macosx/appsupport $(APPBUNDLEEXE)/appsupport otool -l $(TARGET) | grep -A 2 LC_RPATH | tail -n 1 | awk '{print $2}' | dylibbundler -od -b -x $(APPBUNDLEEXE)/soh -d $(APPBUNDLECONTENTS)/libs macosx/$(APPNAME).icns: macosx/$(APPNAME)Icon.png @@ -244,7 +242,3 @@ macosx/$(APPNAME).icns: macosx/$(APPNAME)Icon.png cp macosx/$(APPNAME)Icon.png macosx/$(APPNAME).iconset/icon_512x512@2x.png iconutil -c icns -o macosx/$(APPNAME).icns macosx/$(APPNAME).iconset rm -r macosx/$(APPNAME).iconset - -filledappbundle: appbundle - cp ./oot.otr $(APPBUNDLEEXE)/oot.otr - diff --git a/soh/include/functions.h b/soh/include/functions.h index 73f366bb5..72fd6e98c 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -559,6 +559,7 @@ void ActorOverlayTable_Cleanup(void); u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*); void func_80038A28(CollisionPoly* poly, f32 tx, f32 ty, f32 tz, MtxF* dest); f32 CollisionPoly_GetPointDistanceFromPlane(CollisionPoly* poly, Vec3f* point); +CollisionHeader* BgCheck_GetCollisionHeader(CollisionContext* colCtx, s32 bgId); void CollisionPoly_GetVerticesByBgId(CollisionPoly* poly, s32 bgId, CollisionContext* colCtx, Vec3f* dest); s32 BgCheck_CheckStaticCeiling(StaticLookup* lookup, u16 xpFlags, CollisionContext* colCtx, f32* outY, Vec3f* pos, f32 checkHeight, CollisionPoly** outPoly); diff --git a/soh/include/z64.h b/soh/include/z64.h index 2d8a6f4a8..fdc634e58 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1203,6 +1203,9 @@ typedef struct GlobalContext { /* 0x00790 */ Camera* cameraPtrs[NUM_CAMS]; /* 0x007A0 */ s16 activeCamera; /* 0x007A2 */ s16 nextCamera; + /* 0x007A2 */ bool manualCamera; + /* 0x007A2 */ f32 camX; + /* 0x007A2 */ f32 camY; /* 0x007A4 */ SequenceContext sequenceCtx; /* 0x007A8 */ LightContext lightCtx; /* 0x007B8 */ FrameAdvanceContext frameAdvCtx; diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 86e962799..e58d7a925 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -3,7 +3,7 @@ #include "ultra64.h" #include "z64math.h" -#include +#include "soh/Enhancements/randomizer/randomizerTypes.h" typedef struct { /* 0x00 */ u8 buttonItems[8]; diff --git a/soh/macosx/Info.plist b/soh/macosx/Info.plist index af3ea4de5..d42198f02 100644 --- a/soh/macosx/Info.plist +++ b/soh/macosx/Info.plist @@ -7,9 +7,9 @@ CFBundleName Ship of Harkinian CFBundleExecutable - launcher.sh + soh CFBundleGetInfoString - 2.0.0 + 3.0.0 CFBundleIconFile soh.icns CFBundleIdentifier @@ -22,14 +22,14 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.0.0 + 3.0.0 CFBundleSignature ZOoT CFBundleVersion - 2.0.0 + 3.0.0 NSHumanReadableCopyright Copyright 2022 HarbourMasters. LSMinimumSystemVersion - 10.3 + 10.15 diff --git a/soh/macosx/appsupport.m b/soh/macosx/appsupport.m deleted file mode 100644 index a7df45e67..000000000 --- a/soh/macosx/appsupport.m +++ /dev/null @@ -1,26 +0,0 @@ -#import -int main(void) { - NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject]; - //If there isn't an App Support Directory yet ... - if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) { - NSError *error = nil; - //Create one - if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) { - NSLog(@"%@", error.localizedDescription); - } - else { - // *** OPTIONAL *** Mark the directory as excluded from iCloud backups - NSURL *url = [NSURL fileURLWithPath:appSupportDir]; - if (![url setResourceValue:@YES - forKey:NSURLIsExcludedFromBackupKey - error:&error]) - { - NSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription); - } - else { - NSLog(@"Yay"); - } - } - } - printf("%s\n", [appSupportDir UTF8String]); -} diff --git a/soh/macosx/launcher.sh b/soh/macosx/launcher.sh deleted file mode 100755 index ef22983de..000000000 --- a/soh/macosx/launcher.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -APPPATH="${0%/*}" -cd "${APPPATH}" -APPPATH=$(pwd) -APPSUPPORT=$(./appsupport) -mkdir -p "${APPSUPPORT}/com.shipofharkinian.soh" -cd "${APPSUPPORT}/com.shipofharkinian.soh" -cp "${APPPATH}/oot.otr" . -${APPPATH}/soh diff --git a/soh/randomizer_generation.cpp b/soh/randomizer_generation.cpp deleted file mode 100644 index a55d5fcf0..000000000 --- a/soh/randomizer_generation.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include - -void GenerateRandomizer() { - int ret = Playthrough::Playthrough_Init(std::hash{}(Settings::seed)); - - if (ret < 0) { - if (ret == -1) { // Failed to generate after 5 tries - SPDLOG_ERROR( - "\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be " - "successful."); - return; - } else { - SPDLOG_ERROR("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret); - return; - } - } - - const auto& randomizerHash = GetRandomizerHash(); -} \ No newline at end of file diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 5f7ea818f..6275e82fd 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -143,7 +143,7 @@ TurnOffAllWarnings false - INCLUDE_GAME_PRINTF;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;ENABLE_DX11;%(PreprocessorDefinitions)GLEW_STATIC + _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;ENABLE_DX11;%(PreprocessorDefinitions) true stdcpp20 MultiThreadedDebug @@ -941,6 +941,7 @@ + @@ -982,7 +983,7 @@ - + @@ -1038,7 +1039,6 @@ - diff --git a/soh/soh.vcxproj.filters b/soh/soh.vcxproj.filters index bbe6578f2..5f48ff042 100644 --- a/soh/soh.vcxproj.filters +++ b/soh/soh.vcxproj.filters @@ -82,12 +82,6 @@ {04fc1c52-49ff-48e2-ae23-2c00867374f8} - - {dbcf07c4-80b1-4c88-ac54-2bbdd8f53ee4} - - - {9c880c8e-492b-48f6-b230-1fd269ea74b1} - @@ -3947,9 +3941,6 @@ Source Files\soh - - Source Files\soh\Lib\nlohmann - Source Files\soh @@ -4061,7 +4052,7 @@ Header Files - + Header Files diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index 0b789b445..4f20155d4 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -20,7 +20,7 @@ extern BootCommandFunc BootCommands_Command_LoadFileSelect(char** argv, s32 argc static BootCommand sCommands[] = { { "--skiplogo", BootCommands_Command_SkipLogo }, { "--loadfileselect", BootCommands_Command_LoadFileSelect } }; -void BootCommands_Init() +void BootCommands_Init() { CVar_RegisterS32("gDisableLOD", 0); CVar_RegisterS32("gDebugEnabled", 0); @@ -30,7 +30,6 @@ void BootCommands_Init() CVar_RegisterS32("gHoverFishing", 0); CVar_RegisterS32("gN64WeirdFrames", 0); CVar_RegisterS32("gBombchusOOB", 0); - CVar_RegisterS32("gRumbleEnabled", 0); CVar_RegisterS32("gUniformLR", 0); CVar_RegisterS32("gTwoHandedIdle", 0); CVar_RegisterS32("gDekuNutUpgradeFix", 0); diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 969488569..9804d6c69 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -178,28 +178,28 @@ void Draw_Npcs(){ ImGui::TableSetupColumn("Outer colors##Navi", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort, TablesCellsWidth/2); Table_InitHeader(); Draw_HelpIcon("Inner color for Navi (idle flying around)"); - SohImGui::EnhancementColor("Navi Idle", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255, 255, 255, 255), false); + SohImGui::EnhancementColor("Navi Idle (Primary)", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255, 255, 255, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (idle flying around)"); - SohImGui::EnhancementColor("Navi Idle", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(0, 0, 255, 255), false); + SohImGui::EnhancementColor("Navi Idle (Secondary)", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(0, 0, 255, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around NPCs)"); - SohImGui::EnhancementColor("Navi NPC", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(150, 150, 255, 255), false); + SohImGui::EnhancementColor("Navi NPC (Primary)", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(150, 150, 255, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around NPCs)"); - SohImGui::EnhancementColor("Navi NPC", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(150, 150, 255, 255), false); + SohImGui::EnhancementColor("Navi NPC (Secondary)", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(150, 150, 255, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around Enemies or Bosses)"); - SohImGui::EnhancementColor("Navi Enemy", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Enemy (Primary)", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255, 255, 0, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around Enemies or Bosses)"); - SohImGui::EnhancementColor("Navi Enemy", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false); + SohImGui::EnhancementColor("Navi Enemy (Secondary)", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220, 155, 0, 255), false); Table_NextLine(); Draw_HelpIcon("Inner color for Navi (when Navi fly around props (signs etc))"); - SohImGui::EnhancementColor("Navi Prop", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Prop (Primary)", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0, 255, 0, 255), false); Table_NextCol(); Draw_HelpIcon("Outer color for Navi (when Navi fly around props (signs etc))"); - SohImGui::EnhancementColor("Navi Prop", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0, 255, 0, 255), false); + SohImGui::EnhancementColor("Navi Prop (Secondary)", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0, 255, 0, 255), false); ImGui::EndTable(); } SohImGui::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); @@ -212,10 +212,10 @@ void Draw_Npcs(){ SohImGui::EnhancementColor("Fire Primary color", "gKeese1_Ef_Prim", Keese1_primcol, ImVec4(255, 255, 100, 255)); Table_NextCol(); Draw_HelpIcon("Affects the primary color of the Ice itself of the Keese"); - SohImGui::EnhancementColor("Fire Primary color", "gKeese2_Ef_Prim", Keese2_primcol, ImVec4(100, 200, 255, 255)); + SohImGui::EnhancementColor("Ice Primary color", "gKeese2_Ef_Prim", Keese2_primcol, ImVec4(100, 200, 255, 255)); Table_NextLine(); Draw_HelpIcon("Affects the secondary color of the Fire itself of the Keese"); - SohImGui::EnhancementColor("Ice Secondary color", "gKeese1_Ef_Env", Keese1_envcol, ImVec4(255, 50, 0, 255)); + SohImGui::EnhancementColor("Fire Secondary color", "gKeese1_Ef_Env", Keese1_envcol, ImVec4(255, 50, 0, 255)); Table_NextCol(); Draw_HelpIcon("Affects the secondary color of the Ice itself of the Keese"); SohImGui::EnhancementColor("Ice Secondary color", "gKeese2_Ef_Env", Keese2_envcol, ImVec4(0, 0, 255, 255)); diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 445134f2a..eb2b02b11 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -16,6 +16,7 @@ #include #include +#include "Window.h" #include "Lib/ImGui/imgui_internal.h" #undef PATH_HACK #undef Path @@ -315,7 +316,7 @@ static bool SaveStateHandler(const std::vector& args) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE }); - switch (rtn) { + switch (rtn) { case SaveStateReturn::SUCCESS: INFO("[SOH] Saved state to slot %u", slot); return CMD_SUCCESS; @@ -329,7 +330,7 @@ static bool SaveStateHandler(const std::vector& args) { static bool LoadStateHandler(const std::vector& args) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD }); - + switch (rtn) { case SaveStateReturn::SUCCESS: INFO("[SOH] Loaded state from slot %u", slot); @@ -342,7 +343,7 @@ static bool LoadStateHandler(const std::vector& args) { return CMD_FAILED; case SaveStateReturn::FAIL_WRONG_GAMESTATE: ERROR("[SOH] Can not load a state outside of \"GamePlay\""); - return CMD_FAILED; + return CMD_FAILED; } } @@ -360,7 +361,7 @@ static bool StateSlotSelectHandler(const std::vector& args) { ERROR("[SOH] SaveState slot value must be a number."); return CMD_FAILED; } - + if (slot < 0) { ERROR("[SOH] Invalid slot passed. Slot must be between 0 and 2"); return CMD_FAILED; @@ -498,10 +499,10 @@ template bool is_number(const std::string& s) { return ((std::istringstream(s) >> n >> std::ws).eof()); } -void DebugConsole_LoadCVars() -{ - if (File::Exists("cvars.cfg")) { - const auto lines = File::ReadAllLines("cvars.cfg"); +void DebugConsole_LoadLegacyCVars() { + auto cvarsConfig = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("cvars.cfg"); + if (File::Exists(cvarsConfig)) { + const auto lines = File::ReadAllLines(cvarsConfig); for (const std::string& line : lines) { std::vector cfg = StringHelper::Split(line, " = "); @@ -519,21 +520,58 @@ void DebugConsole_LoadCVars() CVar_SetS32(cfg[0].c_str(), std::stoi(cfg[1])); } } + + fs::remove(cvarsConfig); } } +void DebugConsole_LoadCVars() { + + std::shared_ptr pConf = Ship::GlobalCtx2::GetInstance()->GetConfig(); + pConf->reload(); + + for (const auto& item : pConf->rjson["CVars"].items()) { + auto value = item.value(); + switch (value.type()) { + case nlohmann::detail::value_t::array: + break; + case nlohmann::detail::value_t::string: + CVar_SetString(item.key().c_str(), value.get().c_str()); + break; + case nlohmann::detail::value_t::boolean: + CVar_SetS32(item.key().c_str(), value.get()); + break; + case nlohmann::detail::value_t::number_unsigned: + case nlohmann::detail::value_t::number_integer: + CVar_SetS32(item.key().c_str(), value.get()); + break; + case nlohmann::detail::value_t::number_float: + CVar_SetFloat(item.key().c_str(), value.get()); + break; + default: ; + } + if (item.key() == "gOpenMenuBar") { + int bp = 0; + } + } + + DebugConsole_LoadLegacyCVars(); +} + void DebugConsole_SaveCVars() { - std::string output; + std::shared_ptr pConf = Ship::GlobalCtx2::GetInstance()->GetConfig(); for (const auto &cvar : cvars) { - if (cvar.second->type == CVAR_TYPE_STRING) - output += StringHelper::Sprintf("%s = \"%s\"\n", cvar.first.c_str(), cvar.second->value.valueStr); + const std::string key = StringHelper::Sprintf("CVars.%s", cvar.first.c_str()); + + if (cvar.second->type == CVAR_TYPE_STRING && cvar.second->value.valueStr != nullptr) + pConf->setString(key, std::string(cvar.second->value.valueStr)); else if (cvar.second->type == CVAR_TYPE_S32) - output += StringHelper::Sprintf("%s = %i\n", cvar.first.c_str(), cvar.second->value.valueS32); + pConf->setInt(key, cvar.second->value.valueS32); else if (cvar.second->type == CVAR_TYPE_FLOAT) - output += StringHelper::Sprintf("%s = %f\n", cvar.first.c_str(), cvar.second->value.valueFloat); + pConf->setFloat(key, cvar.second->value.valueFloat); } - File::WriteAllText("cvars.cfg", output); + pConf->save(); } diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index 1cab6ef64..e98ff0399 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -529,7 +529,7 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { Mtx m; MtxF mt; - SkinMatrix_SetTranslate(&mt, cyl->dim.pos.x, cyl->dim.pos.y, cyl->dim.pos.z); + SkinMatrix_SetTranslate(&mt, cyl->dim.pos.x, cyl->dim.pos.y + cyl->dim.yShift, cyl->dim.pos.z); MtxF ms; int32_t radius = cyl->dim.radius == 0 ? 1 : cyl->dim.radius; SkinMatrix_SetScale(&ms, radius / 128.0f, cyl->dim.height / 128.0f, radius / 128.0f); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 60c3e6c4e..f31a5e42a 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1561,6 +1561,18 @@ void DrawPlayerTab() { ImGui::InputScalar("C Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[2], &one, NULL); ImGui::SameLine(); ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL); + + if (CVar_GetS32("gDpadEquips", 0)) { + ImGui::NewLine(); + ImGui::Text("Current D-pad Equips"); + ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); // Two spaces at the end for aligning, not elegant but it's working + ImGui::SameLine(); + ImGui::InputScalar("D-pad Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[5], &one, NULL); + // Intentionnal to not put everything on the same line, else it's taking too much for lower resolution. + ImGui::InputScalar("D-pad Left", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[6], &one, NULL); + ImGui::SameLine(); + ImGui::InputScalar("D-pad Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[7], &one, NULL); + } }); } else { diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 80e5d63b2..7a0c16def 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -14,7 +14,7 @@ #include "location_access.hpp" #include "debug.hpp" #include -#include "randomizerTypes.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" namespace { bool seedChanged; diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.hpp b/soh/soh/Enhancements/randomizer/3drando/menu.hpp index 2f3933135..737c1d3cf 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.hpp @@ -2,7 +2,7 @@ #include #include -#include "randomizerTypes.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" #define MAIN_MENU 0 #define OPTION_SUB_MENU 1 diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 772cd4a5f..cfcbdfa91 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -6,7 +6,7 @@ #include "logic.hpp" #include "random.hpp" #include "spoiler_log.hpp" -#include "randomizerTypes.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" namespace Playthrough { diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index a936b6567..e14cf502d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -7,6 +7,9 @@ // #include #include #include +#define NOGDI +#define WIN32_LEAN_AND_MEAN +#include #define TICKS_PER_SEC 268123480.0 @@ -18,7 +21,7 @@ void RandoMain::GenerateRando(std::unordered_map cvarS // std::string settingsFileName = "./randomizer/latest_settings.json"; // CVar_SetString("gLoadedPreset", settingsFileName.c_str()); - std::string fileName = GenerateRandomizer(cvarSettings); + std::string fileName = Ship::GlobalCtx2::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings).c_str()); CVar_SetString("gSpoilerLog", fileName.c_str()); Game::SaveSettings(); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 3ed486a44..5deea4088 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -11,7 +11,7 @@ #include "utils.hpp" #include "shops.hpp" #include "hints.hpp" -#include "soh/Lib/nlohmann/json.hpp" +#include "Lib/nlohmann/json.hpp" #include #include @@ -26,6 +26,10 @@ #include #include +#define NOGDI +#define WIN32_LEAN_AND_MEAN +#include "GlobalCtx2.h" + using json = nlohmann::json; json jsonData; @@ -721,12 +725,13 @@ const char* SpoilerLog_Write(int language) { //WriteShuffledEntrances(spoilerLog); WriteAllLocations(language); - if (!std::filesystem::exists("./Randomizer")) { - std::filesystem::create_directory("./Randomizer"); + if (!std::filesystem::exists(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer"))) { + std::filesystem::create_directory(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Randomizer")); } std::string jsonString = jsonData.dump(4); - std::ofstream jsonFile("./Randomizer/" + Settings::seed + ".json"); + std::ofstream jsonFile(Ship::GlobalCtx2::GetPathRelativeToAppDirectory( + (std::string("Randomizer/") + std::string(Settings::seed) + std::string(".json")).c_str())); jsonFile << std::setw(4) << jsonString << std::endl; jsonFile.close(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 5fe2e0ae4..f4101e8fd 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -1,11 +1,10 @@ -#ifndef RANDOMIZER_H -#define RANDOMIZER_H +#pragma once #include #include #include "../../../include/ultra64.h" #include "../../../include/z64item.h" -#include +#include "soh/Enhancements/randomizer/randomizerTypes.h" class Randomizer { private: @@ -54,5 +53,3 @@ void Rando_Init(void); } #endif - -#endif diff --git a/soh/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h similarity index 100% rename from soh/randomizerTypes.h rename to soh/soh/Enhancements/randomizer/randomizerTypes.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 042a4b5e9..6a1ecc198 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -57,7 +57,6 @@ OTRGlobals* OTRGlobals::Instance; SaveManager* SaveManager::Instance; OTRGlobals::OTRGlobals() { - context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian"); gSaveStateMgr = std::make_shared(); gRandomizer = std::make_shared(); @@ -1154,34 +1153,27 @@ extern "C" s32* ResourceMgr_LoadCSByName(const char* path) return (s32*)res->commands.data(); } -std::filesystem::path GetSaveFile(Ship::ConfigFile& Conf) { - std::string fileName = Conf.get("SAVE").get("Save Filename"); - - if (fileName.empty()) { - Conf["SAVE"]["Save Filename"] = "oot_save.sav"; - Conf.Save(); - } +std::filesystem::path GetSaveFile(std::shared_ptr Conf) { + const std::string fileName = Conf->getString("Game.SaveName", Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.sav")); std::filesystem::path saveFile = std::filesystem::absolute(fileName); - if (!std::filesystem::exists(saveFile.parent_path())) { - std::filesystem::create_directories(saveFile.parent_path()); + if (!exists(saveFile.parent_path())) { + create_directories(saveFile.parent_path()); } return saveFile; } std::filesystem::path GetSaveFile() { - std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); + const std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - return GetSaveFile(Conf); + return GetSaveFile(pConf); } -void OTRGlobals::CheckSaveFile(size_t sramSize) { - std::shared_ptr pConf = context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); +void OTRGlobals::CheckSaveFile(size_t sramSize) const { + const std::shared_ptr pConf = Instance->context->GetConfig(); - std::filesystem::path savePath = GetSaveFile(Conf); + std::filesystem::path savePath = GetSaveFile(pConf); std::fstream saveFile(savePath, std::fstream::in | std::fstream::out | std::fstream::binary); if (saveFile.fail()) { saveFile.open(savePath, std::fstream::in | std::fstream::out | std::fstream::binary | std::fstream::app); @@ -1200,25 +1192,6 @@ extern "C" void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size) { OTRGlobals::Instance->context->WriteSaveFile(GetSaveFile(), addr, dramAddr, size); } -/* Remember to free after use of value */ -extern "C" char* Config_getValue(char* category, char* key) { - std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); - - std::string data = Conf.get(std::string(category)).get(std::string(key)); - char* retval = (char*)malloc(data.length()+1); - strcpy(retval, data.c_str()); - - return retval; -} - -extern "C" bool Config_setValue(char* category, char* key, char* value) { - std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); - Conf[std::string(category)][std::string(key)] = std::string(value); - return Conf.Save(); -} - std::wstring StringToU16(const std::string& s) { std::vector result; size_t i = 0; @@ -1320,11 +1293,10 @@ extern "C" uint32_t OTRGetCurrentHeight() { } extern "C" void OTRControllerCallback(ControllerCallback* controller) { - auto controllers = OTRGlobals::Instance->context->GetWindow()->Controllers; - for (size_t i = 0; i < controllers.size(); i++) { - for (int j = 0; j < controllers[i].size(); j++) { - OTRGlobals::Instance->context->GetWindow()->Controllers[i][j]->WriteToSource(controller); - } + const auto controllers = Ship::Window::ControllerApi->virtualDevices; + + for (int i = 0; i < controllers.size(); ++i) { + Ship::Window::ControllerApi->physicalDevices[controllers[i]]->WriteToSource(i, controller); } } @@ -1378,11 +1350,11 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) { } extern "C" int Controller_ShouldRumble(size_t i) { - for (const auto& controller : Ship::Window::Controllers.at(i)) - { - float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 1.0f); - if (controller->CanRumble() && rumble_strength > 0.001f) { + const auto controllers = Ship::Window::ControllerApi->virtualDevices; + + for (const auto virtual_entry : controllers) { + if (Ship::Window::ControllerApi->physicalDevices[virtual_entry]->CanRumble()) { return 1; } } @@ -1395,23 +1367,23 @@ extern "C" void* getN64WeirdFrame(s32 i) { return &weirdFrameBytes[i + sizeof(n64WeirdFrames)]; } -extern "C" s16 GetItemModelFromId(s16 itemId) { +extern "C" s16 Randomizer_GetItemModelFromId(s16 itemId) { return OTRGlobals::Instance->gRandomizer->GetItemModelFromId(itemId); } -extern "C" s32 GetItemIDFromGetItemID(s32 getItemId) { +extern "C" s32 Randomizer_GetItemIDFromGetItemID(s32 getItemId) { return OTRGlobals::Instance->gRandomizer->GetItemIDFromGetItemID(getItemId); } -extern "C" void LoadRandomizerSettings(const char* spoilerFileName) { +extern "C" void Randomizer_LoadSettings(const char* spoilerFileName) { OTRGlobals::Instance->gRandomizer->LoadRandomizerSettings(spoilerFileName); } -extern "C" void LoadHintLocations(const char* spoilerFileName) { +extern "C" void Randomizer_LoadHintLocations(const char* spoilerFileName) { OTRGlobals::Instance->gRandomizer->LoadHintLocations(spoilerFileName); } -extern "C" void LoadItemLocations(const char* spoilerFileName, bool silent) { +extern "C" void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent) { OTRGlobals::Instance->gRandomizer->LoadItemLocations(spoilerFileName, silent); } @@ -1419,11 +1391,11 @@ extern "C" bool SpoilerFileExists(const char* spoilerFileName) { return OTRGlobals::Instance->gRandomizer->SpoilerFileExists(spoilerFileName); } -extern "C" u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { +extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) { return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(randoSettingKey); } -extern "C" RandomizerCheck GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) { +extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) { return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams); } @@ -1499,33 +1471,33 @@ extern "C" int CopyScrubMessage(u16 scrubTextId, char* buffer, const int maxBuff return CopyStringToCharBuffer(scrubText, buffer, maxBufferSize); } -extern "C" int CopyAltarMessage(char* buffer, const int maxBufferSize) { +extern "C" int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize) { const std::string& altarText = (LINK_IS_ADULT) ? OTRGlobals::Instance->gRandomizer->GetAdultAltarText() : OTRGlobals::Instance->gRandomizer->GetChildAltarText(); return CopyStringToCharBuffer(altarText, buffer, maxBufferSize); } -extern "C" int CopyGanonText(char* buffer, const int maxBufferSize) { +extern "C" int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize) { const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonText(); return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize); } -extern "C" int CopyGanonHintText(char* buffer, const int maxBufferSize) { +extern "C" int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize) { const std::string& ganonText = OTRGlobals::Instance->gRandomizer->GetGanonHintText(); return CopyStringToCharBuffer(ganonText, buffer, maxBufferSize); } -extern "C" int CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) { +extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize) { // we don't want to make a copy of the std::string returned from GetHintFromCheck // so we're just going to let RVO take care of it const std::string& hintText = OTRGlobals::Instance->gRandomizer->GetHintFromCheck(check); return CopyStringToCharBuffer(hintText, buffer, maxBufferSize); } -extern "C" s32 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { +extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); } -extern "C" s32 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { +extern "C" s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { return OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 7c56e54c1..2bee6819d 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -23,7 +23,7 @@ public: ~OTRGlobals(); private: - void CheckSaveFile(size_t sramSize); + void CheckSaveFile(size_t sramSize) const; }; #endif @@ -61,8 +61,6 @@ SoundFontSample* ResourceMgr_LoadAudioSample(const char* path); CollisionHeader* ResourceMgr_LoadColByName(const char* path); void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); -char* Config_getValue(char* category, char* key); -bool Config_setValue(char* category, char* key, char* value); uint64_t GetPerfCounter(); struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path); @@ -86,19 +84,19 @@ void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples); int Controller_ShouldRumble(size_t i); void* getN64WeirdFrame(s32 i); Sprite* GetSeedTexture(uint8_t index); -void LoadRandomizerSettings(const char* spoilerFileName); -u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); -RandomizerCheck GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum); -int CopyAltarMessage(char* buffer, const int maxBufferSize); -int CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize); -int CopyGanonText(char* buffer, const int maxBufferSize); -int CopyGanonHintText(char* buffer, const int maxBufferSize); -void LoadHintLocations(const char* spoilerFileName); -void LoadItemLocations(const char* spoilerFileName, bool silent); -s16 GetItemModelFromId(s16 itemId); -s32 GetItemIDFromGetItemID(s32 getItemId); -s32 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); -s32 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); +void Randomizer_LoadSettings(const char* spoilerFileName); +u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); +RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum); +int Randomizer_CopyAltarMessage(char* buffer, const int maxBufferSize); +int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, const int maxBufferSize); +int Randomizer_CopyGanonText(char* buffer, const int maxBufferSize); +int Randomizer_CopyGanonHintText(char* buffer, const int maxBufferSize); +void Randomizer_LoadHintLocations(const char* spoilerFileName); +void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent); +s16 Randomizer_GetItemModelFromId(s16 itemId); +s32 Randomizer_GetItemIDFromGetItemID(s32 getItemId); +s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); +s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); #endif #endif diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 1bbbd3a1c..cbe4315d3 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1,4 +1,5 @@ #include "SaveManager.h" +#include "OTRGlobals.h" #include "z64.h" #include "functions.h" @@ -14,11 +15,9 @@ extern "C" SaveContext gSaveContext; -static const std::filesystem::path sSavePath("Save"); // TODO maybe let this be user-configurable? -static const std::filesystem::path sGlobalPath = sSavePath / "global.sav"; - std::filesystem::path SaveManager::GetFileName(int fileNum) { - return sSavePath / (std::string("file") + std::to_string(fileNum + 1) + ".sav"); + const std::filesystem::path sSavePath(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Save")); + return sSavePath / ("file" + std::to_string(fileNum + 1) + ".sav"); } SaveManager::SaveManager() { @@ -128,15 +127,20 @@ void SaveManager::SaveRandomizer() { } void SaveManager::Init() { + const std::filesystem::path sSavePath(Ship::GlobalCtx2::GetPathRelativeToAppDirectory("Save")); + const std::filesystem::path sGlobalPath = sSavePath / std::string("global.sav"); + auto sOldSavePath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.sav"); + auto sOldBackupSavePath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("oot_save.bak"); + // If the save directory does not exist, create it if (!std::filesystem::exists(sSavePath)) { std::filesystem::create_directory(sSavePath); } // If there is a lingering unversioned save, convert it - if (std::filesystem::exists("oot_save.sav")) { + if (std::filesystem::exists(sOldSavePath)) { ConvertFromUnversioned(); - std::filesystem::rename("oot_save.sav", "oot_save.bak"); + std::filesystem::rename(sOldSavePath, sOldBackupSavePath); } // If the global save file exist, load it. Otherwise, create it. diff --git a/soh/src/boot/build.c b/soh/src/boot/build.c index 94d142020..84a73076d 100644 --- a/soh/src/boot/build.c +++ b/soh/src/boot/build.c @@ -1,4 +1,4 @@ -const char gBuildVersion[] = "ROY ALFA (2.0.0)"; +const char gBuildVersion[] = "RACHAEL ALFA (3.0.0)"; const char gBuildTeam[] = "github.com/harbourmasters"; const char gBuildDate[] = __DATE__ " " __TIME__; const char gBuildMakeOption[] = ""; diff --git a/soh/src/code/audio_seqplayer.c b/soh/src/code/audio_seqplayer.c index 3ae70719c..b8fbd9e1f 100644 --- a/soh/src/code/audio_seqplayer.c +++ b/soh/src/code/audio_seqplayer.c @@ -1176,9 +1176,13 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { if (seqPlayer->defaultFont != 0xFF) { SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]); - int8_t idx = (sDat.numFonts - result - 1); - command = sDat.fonts[abs(idx)]; + // The game apparantely would sometimes do negative array lookups, the result of which would get rejected by AudioHeap_SearchCaches, never + // changing the actual fontid. + if (result > sDat.numFonts) + break; + + command = sDat.fonts[(sDat.numFonts - result - 1)]; } if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) diff --git a/soh/src/code/game.c b/soh/src/code/game.c index 9e0cfb50b..9089606e6 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -409,7 +409,9 @@ void GameState_Update(GameState* gameState) { // Unrestricted Items if (CVar_GetS32("gNoRestrictItems", 0) != 0) { if (gGlobalCtx) { + u8 sunsBackup = gGlobalCtx->interfaceCtx.restrictions.sunsSong; memset(&gGlobalCtx->interfaceCtx.restrictions, 0, sizeof(gGlobalCtx->interfaceCtx.restrictions)); + gGlobalCtx->interfaceCtx.restrictions.sunsSong = sunsBackup; } } diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index d89207e6f..9bd9d53e7 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -269,7 +269,7 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) { input->press.stick_y += (s8)(input->cur.stick_y - input->prev.stick_y); } - controllerCallback.rumble = CVar_GetS32("gRumbleEnabled", 0) && (padMgr->rumbleEnable[0] > 0); + controllerCallback.rumble = (padMgr->rumbleEnable[0] > 0); if (HealthMeter_IsCritical()) { controllerCallback.ledColor = 0; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 42ab8064c..70771880c 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -5983,7 +5983,7 @@ s32 func_80038290(GlobalContext* globalCtx, Actor* actor, Vec3s* arg2, Vec3s* ar } s32 GetChestGameRandoGetItemId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) { - if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { // RANDOTODO update this logic when we implement keysanity // because 3drando replaces the keys not the rupees if (ogDrawId == GID_RUPEE_GREEN || @@ -5993,27 +5993,27 @@ s32 GetChestGameRandoGetItemId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) switch(room) { case 1: if(!Flags_GetCollectible(globalCtx, 0x1B)) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, GI_RUPEE_GREEN); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, GI_RUPEE_GREEN); } break; case 2: if(!Flags_GetCollectible(globalCtx, 0x1C)) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, GI_RUPEE_GREEN); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, GI_RUPEE_GREEN); } break; case 3: if(!Flags_GetCollectible(globalCtx, 0x1D)) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, GI_RUPEE_BLUE); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, GI_RUPEE_BLUE); } break; case 4: if(!Flags_GetCollectible(globalCtx, 0x1E)) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, GI_RUPEE_BLUE); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, GI_RUPEE_BLUE); } break; case 5: if(!Flags_GetCollectible(globalCtx, 0x1F)) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, GI_RUPEE_RED); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, GI_RUPEE_RED); } break; } @@ -6021,7 +6021,7 @@ s32 GetChestGameRandoGetItemId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) } if(ogDrawId == GID_HEART_PIECE) { - return GetRandomizedItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_REWARD, GI_HEART_PIECE); + return Randomizer_GetItemIdFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_REWARD, GI_HEART_PIECE); } return GI_NONE; @@ -6031,7 +6031,7 @@ s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) { s32 randoGetItemId = GetChestGameRandoGetItemId(room, ogDrawId, globalCtx); if(randoGetItemId != GI_NONE) { - return GetItemModelFromId(randoGetItemId); + return Randomizer_GetItemModelFromId(randoGetItemId); } return ogDrawId; diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 7f4a5d704..10a89acdb 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1409,7 +1409,115 @@ s32 Camera_Noop(Camera* camera) { return true; } +s32 SetCameraManual(Camera* camera) { + f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x; + f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y; + + if ((fabsf(newCamX) >= 15.0f || fabsf(newCamY) >= 15.0f) && camera->globalCtx->manualCamera == false) { + camera->globalCtx->manualCamera = true; + + VecSph eyeAdjustment; + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment, &camera->at, &camera->eye); + + camera->globalCtx->camX = eyeAdjustment.yaw; + camera->globalCtx->camY = eyeAdjustment.pitch; + } + + if (camera->globalCtx->manualCamera) { + return 1; + } + + return 0; +} + +s32 Camera_Free(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + VecSph spA8; + CamColChk sp6C; + Parallel1* para1 = (Parallel1*)camera->paramData; + f32 playerHeight; + + at->x = Camera_LERPCeilF(camera->player->actor.world.pos.x, camera->at.x, 0.5f, 1.0f); + at->y = Camera_LERPCeilF(camera->player->actor.world.pos.y + (camera->player->rideActor != NULL + ? Player_GetHeight(camera->player) / 2 + : Player_GetHeight(camera->player)) / + 1.2f, + camera->at.y, 0.5f, 1.0f); + at->z = Camera_LERPCeilF(camera->player->actor.world.pos.z, camera->at.z, 0.5f, 1.0f); + + playerHeight = Player_GetHeight(camera->player); + + if (RELOAD_PARAMS) { + OLib_Vec3fDiffToVecSphGeo(&spA8, &camera->at, &camera->eye); + + camera->globalCtx->camX = spA8.yaw; + camera->globalCtx->camY = spA8.pitch; + + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + f32 yNormal = (1.0f + PCT(OREG(46))) - (PCT(OREG(46)) * (68.0f / playerHeight)); + + para1->yOffset = NEXTPCT * playerHeight * yNormal; + para1->distTarget = NEXTPCT * playerHeight * yNormal; + para1->pitchTarget = DEGF_TO_BINANG(NEXTSETTING); + para1->yawTarget = DEGF_TO_BINANG(NEXTSETTING); + para1->unk_08 = NEXTSETTING; + para1->unk_0C = NEXTSETTING; + para1->fovTarget = NEXTSETTING; + para1->unk_14 = NEXTPCT; + para1->interfaceFlags = NEXTSETTING; + para1->unk_18 = NEXTPCT * playerHeight * yNormal; + para1->unk_1C = NEXTPCT; + } + + if (R_RELOAD_CAM_PARAMS) { + Camera_CopyPREGToModeValues(camera); + } + + sCameraInterfaceFlags = 1; + + camera->animState = 1; + + f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x; + f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y; + + camera->globalCtx->camX += newCamX; + camera->globalCtx->camY += newCamY; + + if (camera->globalCtx->camY > 0x32A4) { + camera->globalCtx->camY = 0x32A4; + } + if (camera->globalCtx->camY < -0x228C) { + camera->globalCtx->camY = -0x228C; + } + + camera->dist = Camera_LERPCeilF(para1->distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, 0.0f); + OLib_Vec3fDiffToVecSphGeo(&spA8, at, eyeNext); + + spA8.r = camera->dist; + spA8.yaw = camera->globalCtx->camX; + spA8.pitch = camera->globalCtx->camY; + + Camera_Vec3fVecSphGeoAdd(eyeNext, at, &spA8); + if (camera->status == CAM_STAT_ACTIVE) { + sp6C.pos = *eyeNext; + Camera_BGCheckInfo(camera, at, &sp6C); + *eye = sp6C.pos; + } + + camera->fov = Camera_LERPCeilF(65.0f, camera->fov, camera->fovUpdateRate, 1.0f); + camera->roll = Camera_LERPCeilS(0, camera->roll, 0.5, 0xA); + + return 1; +} + s32 Camera_Normal1(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -1637,6 +1745,11 @@ s32 Camera_Normal1(Camera* camera) { } s32 Camera_Normal2(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -1803,6 +1916,11 @@ s32 Camera_Normal2(Camera* camera) { // riding epona s32 Camera_Normal3(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -1997,6 +2115,8 @@ s32 Camera_Parallel1(Camera* camera) { OLib_Vec3fDiffToVecSphGeo(&atToEyeDir, at, eye); OLib_Vec3fDiffToVecSphGeo(&atToEyeNextDir, at, eyeNext); + camera->globalCtx->manualCamera = false; + switch (camera->animState) { case 0: case 0xA: @@ -2162,6 +2282,11 @@ s32 Camera_Parallel0(Camera* camera) { * Generic jump, jumping off ledges */ s32 Camera_Jump1(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -2307,6 +2432,11 @@ s32 Camera_Jump1(Camera* camera) { // Climbing ladders/vines s32 Camera_Jump2(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -2489,6 +2619,11 @@ s32 Camera_Jump2(Camera* camera) { // swimming s32 Camera_Jump3(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -2946,6 +3081,11 @@ s32 Camera_Battle3(Camera* camera) { * setting value. */ s32 Camera_Battle4(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; @@ -4476,6 +4616,11 @@ s32 Camera_Data4(Camera* camera) { * Hanging off of a ledge */ s32 Camera_Unique1(Camera* camera) { + if (CVar_GetS32("gFreeCamera", 0) && SetCameraManual(camera) == 1) { + Camera_Free(camera); + return 1; + } + Vec3f* eye = &camera->eye; Vec3f* at = &camera->at; Vec3f* eyeNext = &camera->eyeNext; diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 7b55150ee..46b5fd9cf 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -2124,7 +2124,7 @@ void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx) { // If we are rando and tower escape skip is on, then set the flag to say we saw the towers fall // and exit. - if (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_SKIP_TOWER_ESCAPE)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE)) { return; } gSaveContext.cutsceneIndex = 0xFFF0; diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 0c26f8be9..51870bc17 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -509,7 +509,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { } if ((gSaveContext.n64ddFlag || getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) { - getItemId = GetRandomizedItemId(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItemId = Randomizer_GetRandomizedItemId(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); func_8002F554(&this->actor, globalCtx, getItemId); } @@ -548,7 +548,7 @@ void func_8001DFC8(EnItem00* this, GlobalContext* globalCtx) { } if (this->actor.params == ITEM00_HEART_PIECE) { - if ((CVar_GetS32("gNewDrops", 0) !=0) && !gSaveContext.n64ddFlag) { + if (CVar_GetS32("gNewDrops", 0) && !gSaveContext.n64ddFlag) { this->actor.shape.yOffset = Math_SinS(this->actor.shape.rot.y) * 20.0f + 50.0f; } else { this->actor.shape.yOffset = Math_SinS(this->actor.shape.rot.y) * 150.0f + 850.0f; @@ -881,7 +881,7 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) { if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) { if (gSaveContext.n64ddFlag) { - getItemId = GetRandomizedItemId(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItemId = Randomizer_GetRandomizedItemId(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); } func_8002F554(&this->actor, globalCtx, getItemId); } @@ -1297,14 +1297,14 @@ void EnItem00_DrawRupee(EnItem00* this, GlobalContext* globalCtx) { * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). */ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) { - if ((gSaveContext.n64ddFlag && this->getItemId != GI_NONE) || this->actor.params == ITEM00_SMALL_KEY) { + if (gSaveContext.n64ddFlag && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - s32 randoGetItemId = GetRandomizedItemId(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + s32 randoGetItemId = Randomizer_GetRandomizedItemId(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); if (randoGetItemId >= GI_MINUET_OF_FOREST && randoGetItemId <= GI_DOUBLE_DEFENSE) { EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemId); } - GetItem_Draw(globalCtx, GetItemModelFromId(randoGetItemId)); + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(randoGetItemId)); } else { s32 texIndex = this->actor.params - 3; @@ -1360,11 +1360,11 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) { if (gSaveContext.n64ddFlag) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - s32 randoGetItemId = GetRandomizedItemId(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum); + s32 randoGetItemId = Randomizer_GetRandomizedItemId(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum); if (randoGetItemId >= GI_MINUET_OF_FOREST && randoGetItemId <= GI_DOUBLE_DEFENSE) { EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemId); } - GetItem_Draw(globalCtx, GetItemModelFromId(randoGetItemId)); + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(randoGetItemId)); } else { s32 pad; diff --git a/soh/src/code/z_fbdemo_wipe1.c b/soh/src/code/z_fbdemo_wipe1.c index 1dfb0a501..d4502f8e7 100644 --- a/soh/src/code/z_fbdemo_wipe1.c +++ b/soh/src/code/z_fbdemo_wipe1.c @@ -89,6 +89,7 @@ void TransitionWipe_Draw(void* thisx, Gfx** gfxP) { TransitionWipe* this = (TransitionWipe*)thisx; s32 pad[4]; Gfx* tex; + Gfx* wipeDl = sWipeDList; modelView = this->modelView[this->frame]; diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 501a5b8cd..79326ee81 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1676,11 +1676,11 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { // if we're rando'd and talking to a gossip stone if (gSaveContext.n64ddFlag && textId == 0x2053 && - GetRandoSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 && - (GetRandoSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 || - (GetRandoSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 && + Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != 0 && + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 1 || + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 2 && Player_GetMask(globalCtx) == PLAYER_MASK_TRUTH) || - (GetRandoSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == 3 && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { s16 actorParams = msgCtx->talkActor->params; @@ -1700,14 +1700,14 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { } } - RandomizerCheck hintCheck = GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams); + RandomizerCheck hintCheck = Randomizer_GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams); // Pass the sizeof the message buffer so we don't hardcode any sizes and can rely on globals. // If no hint can be found, this just returns 0 size and doesn't modify the buffer, so no worries. - msgCtx->msgLength = font->msgLength = CopyHintFromCheck(hintCheck, font->msgBuf, sizeof(font->msgBuf)); + msgCtx->msgLength = font->msgLength = Randomizer_CopyHintFromCheck(hintCheck, font->msgBuf, sizeof(font->msgBuf)); } else if (gSaveContext.n64ddFlag && (textId == 0x7040 || textId == 0x7088)) { // rando hints at altar - msgCtx->msgLength = font->msgLength = CopyAltarMessage(font->msgBuf, sizeof(font->msgBuf)); + msgCtx->msgLength = font->msgLength = Randomizer_CopyAltarMessage(font->msgBuf, sizeof(font->msgBuf)); } else if (textId == 0x00b4 && CVar_GetS32("gInjectSkulltulaCount", 0) != 0) { switch (gSaveContext.language) { case LANGUAGE_FRA: @@ -1731,9 +1731,9 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { msgCtx->msgLength = font->msgLength = CopyScrubMessage(textId, font->msgBuf, sizeof(font->msgBuf)); } else if (gSaveContext.n64ddFlag && textId == 0x70CC) { if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { - msgCtx->msgLength = font->msgLength = CopyGanonText(font->msgBuf, sizeof(font->msgBuf)); + msgCtx->msgLength = font->msgLength = Randomizer_CopyGanonText(font->msgBuf, sizeof(font->msgBuf)); } else { - msgCtx->msgLength = font->msgLength = CopyGanonHintText(font->msgBuf, sizeof(font->msgBuf)); + msgCtx->msgLength = font->msgLength = Randomizer_CopyGanonHintText(font->msgBuf, sizeof(font->msgBuf)); } } else { msgCtx->msgLength = font->msgLength; @@ -2237,14 +2237,14 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) { } } else { osSyncPrintf("Na_StartOcarinaSinglePlayCheck2( message->ocarina_no );\n"); - func_800ECC04((1 << msgCtx->ocarinaAction) + 0x8000); + func_800ECC04((1 << (msgCtx->ocarinaAction % 32)) + 0x8000); } msgCtx->msgMode = MSGMODE_OCARINA_PLAYING; } else if (msgCtx->msgMode == MSGMODE_SONG_DEMONSTRATION_STARTING) { msgCtx->stateTimer = 20; msgCtx->msgMode = MSGMODE_SONG_DEMONSTRATION_SELECT_INSTRUMENT; } else { - func_800ECC04((1 << (msgCtx->ocarinaAction + 0x11)) + 0x8000); + func_800ECC04((1 << ((msgCtx->ocarinaAction + 0x11) % 32)) + 0x8000); // "Performance Check" osSyncPrintf("演奏チェック=%d\n", msgCtx->ocarinaAction - OCARINA_ACTION_PLAYBACK_MINUET); msgCtx->msgMode = MSGMODE_SONG_PLAYBACK; @@ -3228,6 +3228,8 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) { * the last value being saved in a static variable. */ void Message_DrawDebugVariableChanged(s16* var, GraphicsContext* gfxCtx) { + if (!CVar_GetS32("gDebugEnabled", 0)) { return; } + static s16 sVarLastValue = 0; static s16 sFillTimer = 0; s32 pad; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 08a9cf520..4a79bd3bc 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1710,6 +1710,8 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } else { gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS]; } + } else { + gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS]; } return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { @@ -1808,13 +1810,13 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if (item == ITEM_WALLET_ADULT) { Inventory_ChangeUpgrade(UPG_WALLET, 1); - if (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_FULL_WALLETS)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { Rupees_ChangeBy(200); } return ITEM_NONE; } else if (item == ITEM_WALLET_GIANT) { Inventory_ChangeUpgrade(UPG_WALLET, 2); - if (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_FULL_WALLETS)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { Rupees_ChangeBy(500); } return ITEM_NONE; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index d06f9ce4c..5656f4c07 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -198,7 +198,7 @@ void GivePlayerRandoRewardSongOfTime(GlobalContext* globalCtx, RandomizerCheck c if (gSaveContext.entranceIndex == 0x050F && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && !Flags_GetTreasure(globalCtx, 0x1F) && gSaveContext.nextTransition == 0xFF) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_SONG_OF_TIME); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_SONG_OF_TIME); GiveItemWithoutActor(globalCtx, getItemId); Flags_SetTreasure(globalCtx, 0x1F); } @@ -212,7 +212,7 @@ void GivePlayerRandoRewardNocturne(GlobalContext* globalCtx, RandomizerCheck che gSaveContext.entranceIndex == 0x0195) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && !Flags_GetEventChkInf(0xAA)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_NOCTURNE_OF_SHADOW); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_NOCTURNE_OF_SHADOW); GiveItemWithoutActor(globalCtx, getItemId); Flags_SetEventChkInf(0xAA); } @@ -224,7 +224,7 @@ void GivePlayerRandoRewardRequiem(GlobalContext* globalCtx, RandomizerCheck chec if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { if ((gSaveContext.entranceIndex == 0x01E1) && !Flags_GetEventChkInf(0xAC) && player != NULL && !Player_InBlockingCsMode(globalCtx, player)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_SONG_OF_TIME); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_SONG_OF_TIME); GiveItemWithoutActor(globalCtx, getItemId); Flags_SetEventChkInf(0xAC); } @@ -238,7 +238,7 @@ void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, Randomi (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TOKINOMA) && !Flags_GetTreasure(globalCtx, 0x1E) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && globalCtx->sceneLoadFlag == 0 && player->getItemId == GI_NONE) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_ARROW_LIGHT); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_ARROW_LIGHT); GiveItemWithoutActor(globalCtx, getItemId); Flags_SetTreasure(globalCtx, 0x1E); } @@ -247,7 +247,7 @@ void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, Randomi void GivePlayerRandoRewardSariaGift(GlobalContext* globalCtx, RandomizerCheck check) { Player* player = GET_PLAYER(globalCtx); if (gSaveContext.entranceIndex == 0x05E0) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_ZELDAS_LULLABY); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_ZELDAS_LULLABY); if ((!Flags_GetEventChkInf(0xC1) || (player->getItemId == getItemId && getItemId != GI_ICE_TRAP)) && player != NULL && !Player_InBlockingCsMode(globalCtx, player)) { @@ -271,7 +271,7 @@ void Gameplay_Init(GameState* thisx) { u8 tempSetupIndex; s32 pad[2]; - if (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_SKIP_CHILD_STEALTH)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH)) { if (gSaveContext.entranceIndex == 0x7A) { gSaveContext.entranceIndex = 0x400; } else if (gSaveContext.entranceIndex == 0x296) { @@ -530,6 +530,10 @@ void Gameplay_Update(GlobalContext* globalCtx) { ActorOverlayTable_LogPrint(); } + if (CVar_GetS32("gFreeCamera", 0) && Player_InCsMode(globalCtx)) { + globalCtx->manualCamera = false; + } + gSegments[4] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[globalCtx->objectCtx.mainKeepIndex].segment); gSegments[5] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[globalCtx->objectCtx.subKeepIndex].segment); gSegments[2] = VIRTUAL_TO_PHYSICAL(globalCtx->sceneSegment); diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 10daad055..7670762c5 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -416,7 +416,7 @@ void GiveLinkDungeonReward(GetItemID getItemId) { } void GiveLinksPocketMedallion() { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE); GiveLinkDungeonReward(getItemId); } @@ -644,7 +644,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { // Give Link's pocket item GiveLinksPocketMedallion(); - int openForest = GetRandoSettingValue(RSK_FOREST); + int openForest = Randomizer_GetSettingValue(RSK_FOREST); switch (openForest) { case 0: // closed break; @@ -657,28 +657,28 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { break; } - int doorOfTime = GetRandoSettingValue(RSK_DOOR_OF_TIME); + int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); switch (doorOfTime) { case 0: // open gSaveContext.eventChkInf[4] |= 0x800; break; } - int kakGate = GetRandoSettingValue(RSK_KAK_GATE); + int kakGate = Randomizer_GetSettingValue(RSK_KAK_GATE); switch (kakGate) { case 1: // open gSaveContext.infTable[7] |= 0x40; break; } - if(GetRandoSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword(); - if(GetRandoSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield(); + if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword(); + if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield(); - if(GetRandoSettingValue(RSK_STARTING_OCARINA)) { + if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if(GetRandoSettingValue(RSK_STARTING_MAPS_COMPASSES)) { + if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) { uint32_t mapBitMask = 1 << 1; uint32_t compassBitMask = 1 << 2; uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask; @@ -687,13 +687,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } } - if (GetRandoSettingValue(RSK_STARTING_CONSUMABLES)) { + if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) { GiveLinkDekuSticks(10); GiveLinkDekuNuts(20); } - if(GetRandoSettingValue(RSK_SKIP_CHILD_ZELDA)) { - s32 giid = GetRandomizedItemIdFromKnownCheck(RC_SONG_FROM_IMPA, GI_ZELDAS_LULLABY); + if(Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { + s32 giid = Randomizer_GetItemIdFromKnownCheck(RC_SONG_FROM_IMPA, GI_ZELDAS_LULLABY); if(giid >= GI_ZELDAS_LULLABY && giid <= GI_PRELUDE_OF_LIGHT) { GiveLinkSong(giid); @@ -780,7 +780,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } else if (giid == GI_DOUBLE_DEFENSE) { GiveLinkDoubleDefense(); } else { - s32 iid = GetItemIDFromGetItemID(giid); + s32 iid = Randomizer_GetItemIDFromGetItemID(giid); if (iid != -1) INV_CONTENT(iid) = iid; } @@ -801,18 +801,18 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA; } - if (GetRandoSettingValue(RSK_FULL_WALLETS)) { + if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { GiveLinkRupees(9001); } // For Ganon's boss key "Start With" is 0 - if(GetRandoSettingValue(RSK_GANONS_BOSS_KEY) == 0) { + if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) { gSaveContext.inventory.dungeonItems[10] |= 1; } - HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * GetRandoSettingValue(RSK_BIG_POE_COUNT)); + HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); - if(GetRandoSettingValue(RSK_SKIP_EPONA_RACE)) { + if(Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) { gSaveContext.eventChkInf[1] |= (1 << 8); } @@ -826,6 +826,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { // Go away ruto (water temple first cutscene) gSaveContext.sceneFlags[05].swch |= (1 << 0x10); + // Opens locked Water Temple door to prevent softlocks + // West door on the middle level that leads to the water raising thing + // Happens in 3DS rando and N64 rando as well + gSaveContext.sceneFlags[05].swch |= (1 << 0x15); + // Skip intro cutscene when bombing mud wall in Dodongo's cavern // this also makes the lower jaw render, and the eyes react to explosives Flags_SetEventChkInf(0xB0); @@ -834,7 +839,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.infTable[25] |= 0x20; // fast gerudo fortress - if (GetRandoSettingValue(RSK_GERUDO_FORTRESS) == 1 || GetRandoSettingValue(RSK_GERUDO_FORTRESS) == 2) { + if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == 1 || Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == 2) { gSaveContext.eventChkInf[9] |= 2; gSaveContext.eventChkInf[9] |= 4; gSaveContext.eventChkInf[9] |= 8; @@ -853,14 +858,14 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } // open gerudo fortress - if (GetRandoSettingValue(RSK_GERUDO_FORTRESS) == 2) { + if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == 2) { gSaveContext.eventChkInf[9] |= 1; gSaveContext.sceneFlags[12].swch |= (1 << 0x01); gSaveContext.sceneFlags[12].swch |= (1 << 0x05); gSaveContext.sceneFlags[12].swch |= (1 << 0x11); gSaveContext.sceneFlags[12].collect |= (1 << 0x0C); - if (!GetRandoSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { + if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { GiveLinkGerudoCard(); } } diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index a31d48855..7be483bd9 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -69,7 +69,7 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = { void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - GetItemID getItemId = GetRandomizedItemId(GI_NONE, this->actor.id, this->fountainType + 1, globalCtx->sceneNum); + GetItemID getItemId = Randomizer_GetRandomizedItemId(GI_NONE, this->actor.id, this->fountainType + 1, globalCtx->sceneNum); if (this->actor.parent == GET_PLAYER(globalCtx) && !Flags_GetTreasure(globalCtx, this->fountainType + 1) && !Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { diff --git a/soh/src/overlays/actors/ovl_Bg_Gate_Shutter/z_bg_gate_shutter.c b/soh/src/overlays/actors/ovl_Bg_Gate_Shutter/z_bg_gate_shutter.c index b2d8367f5..ec4dc030e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gate_Shutter/z_bg_gate_shutter.c +++ b/soh/src/overlays/actors/ovl_Bg_Gate_Shutter/z_bg_gate_shutter.c @@ -46,7 +46,7 @@ void BgGateShutter_Init(Actor* thisx, GlobalContext* globalCtx) { this->somePos.z = thisx->world.pos.z; if (((gSaveContext.infTable[7] & 0x40) || (!gSaveContext.n64ddFlag && (gSaveContext.eventChkInf[4] & 0x20)) || - (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_KAK_GATE))) && + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_KAK_GATE))) && (globalCtx->sceneNum == SCENE_SPOT01)) { thisx->world.pos.x = -89.0f; thisx->world.pos.z = -1375.0f; diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index ddb3f99cf..9e46c39ef 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -50,7 +50,7 @@ void BgGjyoBridge_Init(Actor* thisx, GlobalContext* globalCtx) { this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, thisx, colHeader); - int bridge = GetRandoSettingValue(RSK_RAINBOW_BRIDGE); + int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); if (gSaveContext.eventChkInf[4] & 0x2000 || (gSaveContext.n64ddFlag && bridge == 0)) { this->actionFunc = func_808787A4; } else { @@ -176,12 +176,12 @@ void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, GlobalContext* globalCtx) LaunchBridgeCutscene(this, globalCtx); } } else { - int bridge = GetRandoSettingValue(RSK_RAINBOW_BRIDGE); - int bridgeStoneCount = GetRandoSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); - int bridgeMedallionCount = GetRandoSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); - int bridgeRewardCount = GetRandoSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); - int bridgeDungeonCount = GetRandoSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); - int bridgeTokenCount = GetRandoSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); + int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); + int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); + int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); + int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); + int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); + int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); if (CheckPlayerPosition(player, globalCtx)) { switch (bridge) { diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index db5755436..f7a85fc26 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -1504,7 +1504,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx) if (this->csTimer == 180) { globalCtx->sceneLoadFlag = 0x14; - if (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_SKIP_TOWER_ESCAPE)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE)) { Flags_SetEventChkInf(0xC7); globalCtx->nextEntranceIndex = 0x517; } diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index a59e8fa68..cd49f7558 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -899,12 +899,12 @@ void func_80986BF8(DemoIm* this, GlobalContext* globalCtx) { } void GivePlayerRandoRewardImpa(Actor* impa, GlobalContext* globalCtx, RandomizerCheck check) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_ZELDAS_LULLABY); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_ZELDAS_LULLABY); if (impa->parent != NULL && impa->parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1F)) { Flags_SetTreasure(globalCtx, 0x1F); - } else if (!Flags_GetTreasure(globalCtx, 0x1F) && !GetRandoSettingValue(RSK_SKIP_CHILD_ZELDA)) { + } else if (!Flags_GetTreasure(globalCtx, 0x1F) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { func_8002F434(impa, globalCtx, getItemId, 75.0f, 50.0f); } else if (!Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { gSaveContext.eventChkInf[5] |= 0x200; diff --git a/soh/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c b/soh/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c index 32eab2b64..b365b3038 100644 --- a/soh/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c +++ b/soh/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c @@ -788,7 +788,14 @@ void DemoKankyo_DrawWarpSparkles(Actor* thisx, GlobalContext* globalCtx) { this->unk_150[i].unk_0.y = (s16)((Rand_ZeroOne() - 0.5f) * 16.0f * temp_f22); this->unk_150[i].unk_0.z = (s16)((Rand_ZeroOne() - 0.5f) * 16.0f * temp_f22); this->unk_150[i].unk_23 = 0; - this->unk_150[i].unk_22++; + + // Skip the first part of warp song cutscenes in rando + if (gSaveContext.n64ddFlag && this->actor.params == DEMOKANKYO_WARP_OUT) { + this->unk_150[i].unk_22 = 2; + } else { + this->unk_150[i].unk_22++; + } + case 1: if (this->actor.params == DEMOKANKYO_WARP_OUT) { if (func_800BB2B4(&camPos, &sWarpRoll, &sWarpFoV, sWarpOutCameraPoints, &this->unk_150[i].unk_20, diff --git a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c index 04b5b7247..46ecf5979 100644 --- a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c +++ b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c @@ -128,7 +128,7 @@ void DemoKekkai_Init(Actor* thisx, GlobalContext* globalCtx) { this->collider2.dim.yShift = 300; if (gSaveContext.n64ddFlag) { - int trialsToComplete = GetRandoSettingValue(RSK_TRIAL_COUNT); + int trialsToComplete = Randomizer_GetSettingValue(RSK_TRIAL_COUNT); if (trialsToComplete <= TrialsDoneCount()) { Actor_Kill(thisx); return; diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 20fc6355d..291208752 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -462,7 +462,7 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, GlobalContext* globalCtx) { } void GivePlayerRandoReward(DoorWarp1* this, Player* player, GlobalContext* globalCtx, u8 ruto, u8 adult) { - GetItemID getItemId = GetRandomizedItemId(GI_NONE, this->actor.id, this->actor.params, globalCtx->sceneNum); + GetItemID getItemId = Randomizer_GetRandomizedItemId(GI_NONE, this->actor.id, this->actor.params, globalCtx->sceneNum); if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1F)) { diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index ed6eef1a9..b5c7d8a4a 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -127,7 +127,7 @@ void func_809B0558(EnAni* this, GlobalContext* globalCtx) { gSaveContext.itemGetInf[1] |= 0x20; } else { if (gSaveContext.n64ddFlag) { - s32 getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); + s32 getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); func_8002F434(&this->actor, globalCtx, getItemId, 10000.0f, 200.0f); } else { func_8002F434(&this->actor, globalCtx, GI_HEART_PIECE, 10000.0f, 200.0f); @@ -141,7 +141,7 @@ void func_809B05F0(EnAni* this, GlobalContext* globalCtx) { } if (gSaveContext.n64ddFlag) { - s32 getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); + s32 getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); func_8002F434(&this->actor, globalCtx, getItemId, 10000.0f, 200.0f); } else { func_8002F434(&this->actor, globalCtx, GI_HEART_PIECE, 10000.0f, 200.0f); diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 5d86e72fb..ee9ce1329 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -186,14 +186,14 @@ void EnBomBowlPit_GivePrize(EnBomBowlPit* this, GlobalContext* globalCtx) { switch (this->prizeIndex) { case EXITEM_BOMB_BAG_BOWLING: this->getItemId = - GetRandomizedItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); + Randomizer_GetItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); break; case EXITEM_HEART_PIECE_BOWLING: this->getItemId = - GetRandomizedItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); + Randomizer_GetItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); break; case EXITEM_BOMBCHUS_BOWLING: - this->getItemId = GetRandomizedItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); + this->getItemId = Randomizer_GetItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); break; } } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 617e7ff00..533ba593a 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -421,7 +421,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) { Flags_SetTreasure(globalCtx, this->dyna.actor.params & 0x1F); // treasure chest game rando - if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { if (gSaveContext.n64ddFlag && globalCtx->sceneNum == 16 && (this->dyna.actor.params & 0x60) != 0x20) { if((this->dyna.actor.params & 0xF) < 2) { Flags_SetCollectible(globalCtx, 0x1B); @@ -445,10 +445,10 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) { func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { - int32_t item = GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum); + int32_t item = Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum); // RANDOTODO treasure chest game rando - if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { if (gSaveContext.n64ddFlag && globalCtx->sceneNum == 16 && (this->dyna.actor.params & 0x60) != 0x20) { if((this->dyna.actor.params & 0xF) < 2) { if(Flags_GetCollectible(globalCtx, 0x1B)) { @@ -590,7 +590,7 @@ void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) { } if (((!gSaveContext.n64ddFlag && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) || - (gSaveContext.n64ddFlag && GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, + (gSaveContext.n64ddFlag && Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum) == GI_ICE_TRAP)) && this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && diff --git a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c index 6760542cf..9f43a5f54 100644 --- a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c +++ b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c @@ -453,7 +453,7 @@ void func_809EEA00(EnDivingGame* this, GlobalContext* globalCtx) { if ((this->unk_292 == Message_GetState(&globalCtx->msgCtx) && Message_ShouldAdvance(globalCtx))) { Message_CloseTextbox(globalCtx); this->actor.parent = NULL; - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER) : GI_SCALE_SILVER, 90.0f, 10.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER) : GI_SCALE_SILVER, 90.0f, 10.0f); this->actionFunc = func_809EEA90; } } @@ -463,7 +463,7 @@ void func_809EEA90(EnDivingGame* this, GlobalContext* globalCtx) { if (Actor_HasParent(&this->actor, globalCtx)) { this->actionFunc = func_809EEAF8; } else { - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER) : GI_SCALE_SILVER, 90.0f, 10.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER) : GI_SCALE_SILVER, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 0d0a31f52..a89d583ae 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -371,7 +371,7 @@ void EnDns_Talk(EnDns* this, GlobalContext* globalCtx) { void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) { if (this->actor.params == 0x9) { if (gSaveContext.n64ddFlag) { - func_8002F434(&this->actor, globalCtx, GetRandomizedItemId(GI_STICK_UPGRADE_30, this->actor.id, this->actor.params, globalCtx->sceneNum), 130.0f, 100.0f); + func_8002F434(&this->actor, globalCtx, Randomizer_GetRandomizedItemId(GI_STICK_UPGRADE_30, this->actor.id, this->actor.params, globalCtx->sceneNum), 130.0f, 100.0f); } else if (CUR_UPG_VALUE(UPG_STICKS) < 2) { func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f); } else { @@ -379,14 +379,14 @@ void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) { } } else if (this->actor.params == 0xA) { if (gSaveContext.n64ddFlag) { - func_8002F434(&this->actor, globalCtx, GetRandomizedItemId(GI_NUT_UPGRADE_40, this->actor.id, this->actor.params, globalCtx->sceneNum), 130.0f, 100.0f); + func_8002F434(&this->actor, globalCtx, Randomizer_GetRandomizedItemId(GI_NUT_UPGRADE_40, this->actor.id, this->actor.params, globalCtx->sceneNum), 130.0f, 100.0f); } else if (CUR_UPG_VALUE(UPG_NUTS) < 2) { func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_30, 130.0f, 100.0f); } else { func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_40, 130.0f, 100.0f); } } else { - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemId(this->dnsItemEntry->getItemId, this->actor.id, this->actor.params, globalCtx->sceneNum) : this->dnsItemEntry->getItemId, 130.0f, 100.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetRandomizedItemId(this->dnsItemEntry->getItemId, this->actor.id, this->actor.params, globalCtx->sceneNum) : this->dnsItemEntry->getItemId, 130.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c index b500efea5..6d3a4accd 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c @@ -139,13 +139,13 @@ void EnDntDemo_Judge(EnDntDemo* this, GlobalContext* globalCtx) { switch (Player_GetMask(globalCtx)) { case PLAYER_MASK_SKULL: if (!Flags_GetTreasure(globalCtx, 0x1F)) { - GiveItemWithoutActor(globalCtx, GetRandomizedItemIdFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30)); + GiveItemWithoutActor(globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30)); Flags_SetTreasure(globalCtx, 0x1F); } break; case PLAYER_MASK_TRUTH: if (!Flags_GetTreasure(globalCtx, 0x1E)) { - GiveItemWithoutActor(globalCtx, GetRandomizedItemIdFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40)); + GiveItemWithoutActor(globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40)); Flags_SetTreasure(globalCtx, 0x1E); } break; diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index f90092d2f..e7f9b51aa 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -548,7 +548,7 @@ void func_809FEC70(EnDu* this, GlobalContext* globalCtx) { EnDu_SetupAction(this, func_809FECE4); } else { f32 xzRange = this->actor.xzDistToPlayer + 1.0f; - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_GC_DARUNIAS_JOY, GI_BRACELET) : GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_GC_DARUNIAS_JOY, GI_BRACELET) : GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 1b76ceaa9..b42ad6cbf 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -138,8 +138,8 @@ void EnExItem_WaitForObject(EnExItem* this, GlobalContext* globalCtx) { case EXITEM_BOMB_BAG_BOWLING: this->unk_17C = func_8002EBCC; if (gSaveContext.n64ddFlag) { - this->giDrawId = GetItemModelFromId( - GetRandomizedItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20)); + this->giDrawId = Randomizer_GetItemModelFromId( + Randomizer_GetItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20)); } else { this->giDrawId = GID_BOMB_BAG_30; } @@ -173,8 +173,8 @@ void EnExItem_WaitForObject(EnExItem* this, GlobalContext* globalCtx) { case EXITEM_BOMBCHUS_BOWLING: this->unk_17C = func_8002EBCC; if (gSaveContext.n64ddFlag) { - this->giDrawId = GetItemModelFromId( - GetRandomizedItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10)); + this->giDrawId = Randomizer_GetItemModelFromId( + Randomizer_GetItemIdFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10)); } else { this->giDrawId = GID_BOMBCHU; } @@ -229,7 +229,7 @@ void EnExItem_WaitForObject(EnExItem* this, GlobalContext* globalCtx) { this->scale = 0.5f; this->unkFloat = 0.5f; this->actor.velocity.y = 10.0f; - if (!gSaveContext.n64ddFlag || !GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { + if (!gSaveContext.n64ddFlag || !Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { switch (this->type) { case EXITEM_GREEN_RUPEE_CHEST: this->giDrawId = GID_RUPEE_GREEN; @@ -404,7 +404,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (gSaveContext.n64ddFlag) { GET_PLAYER(globalCtx)->stateFlags1 &= ~(PLAYER_STATE1_10 | PLAYER_STATE1_11); - getItemId = GetRandomizedItemIdFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); } else { if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { getItemId = GI_BULLET_BAG_40; @@ -424,7 +424,7 @@ void EnExItem_TargetPrizeGive(EnExItem* this, GlobalContext* globalCtx) { this->actionFunc = EnExItem_TargetPrizeFinish; } else { if (gSaveContext.n64ddFlag) { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); } else { getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; } @@ -510,12 +510,12 @@ void EnExItem_DrawItems(EnExItem* this, GlobalContext* globalCtx) { switch (this->type) { case EXITEM_BOMB_BAG_BOWLING: case EXITEM_BOMB_BAG_COUNTER: - randoGetItemId = GetRandomizedItemIdFromKnownCheck( + randoGetItemId = Randomizer_GetItemIdFromKnownCheck( RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); break; case EXITEM_BOMBCHUS_BOWLING: case EXITEM_BOMBCHUS_COUNTER: - randoGetItemId = GetRandomizedItemIdFromKnownCheck( + randoGetItemId = Randomizer_GetItemIdFromKnownCheck( RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); break; } @@ -532,12 +532,12 @@ void EnExItem_DrawHeartPiece(EnExItem* this, GlobalContext* globalCtx) { func_8002ED80(&this->actor, globalCtx, 0); if (gSaveContext.n64ddFlag) { - s32 randoGetItemId = GetRandomizedItemIdFromKnownCheck( + s32 randoGetItemId = Randomizer_GetItemIdFromKnownCheck( RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); if (randoGetItemId >= GI_MINUET_OF_FOREST && randoGetItemId <= GI_DOUBLE_DEFENSE) { EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemId); } - GetItem_Draw(globalCtx, GetItemModelFromId(randoGetItemId)); + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(randoGetItemId)); } else { GetItem_Draw(globalCtx, GID_HEART_PIECE); } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index e31f316a6..e6a85b331 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -940,7 +940,7 @@ void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { this->reward = GI_HEART_PIECE; } else { - this->reward = GetRandomizedItemIdFromKnownCheck(RC_ZR_FROGS_IN_THE_RAIN, GI_HEART_PIECE); + this->reward = Randomizer_GetItemIdFromKnownCheck(RC_ZR_FROGS_IN_THE_RAIN, GI_HEART_PIECE); } } else { this->reward = GI_RUPEE_BLUE; @@ -951,7 +951,7 @@ void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { this->reward = GI_HEART_PIECE; } else { - this->reward = GetRandomizedItemIdFromKnownCheck(RC_ZR_FROGS_OCARINA_GAME, GI_HEART_PIECE); + this->reward = Randomizer_GetItemIdFromKnownCheck(RC_ZR_FROGS_OCARINA_GAME, GI_HEART_PIECE); } } else { this->reward = GI_RUPEE_PURPLE; diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c index e08424d38..24676a577 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -154,7 +154,7 @@ void GivePlayerRandoRewardSongOfStorms(EnFu* windmillGuy, GlobalContext* globalC Flags_SetTreasure(globalCtx, 0x1F); windmillGuy->actionFunc = func_80A1DBD4; } else if (!Flags_GetTreasure(globalCtx, 0x1F)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_SONG_OF_STORMS); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_SONG_OF_STORMS); func_8002F434(&windmillGuy->actor, globalCtx, getItemId, 10000.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c index c41c067c2..a92ef3d6d 100644 --- a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c +++ b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c @@ -351,7 +351,7 @@ void func_80A2FA50(EnGb* this, GlobalContext* globalCtx) { void func_80A2FB40(EnGb* this, GlobalContext* globalCtx) { if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(globalCtx)) { - func_8002F434(&this->dyna.actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE) : GI_BOTTLE, 100.0f, 10.0f); + func_8002F434(&this->dyna.actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE) : GI_BOTTLE, 100.0f, 10.0f); this->actionFunc = func_80A2FBB0; } } @@ -361,7 +361,7 @@ void func_80A2FBB0(EnGb* this, GlobalContext* globalCtx) { this->dyna.actor.parent = NULL; this->actionFunc = func_80A2FC0C; } else { - func_8002F434(&this->dyna.actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE) : GI_BOTTLE, 100.0f, 10.0f); + func_8002F434(&this->dyna.actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE) : GI_BOTTLE, 100.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index e9cae8032..d34fb977b 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -533,14 +533,14 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, GlobalContext* globalCtx) { break; } } else { - getItemId = GetRandomizedItemIdFromKnownCheck( + getItemId = Randomizer_GetItemIdFromKnownCheck( RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); } } else { if (!gSaveContext.n64ddFlag) { getItemId = GI_HEART_PIECE; } else { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); } } func_8002F434(&this->actor, globalCtx, getItemId, 10000.0f, 50.0f); @@ -567,14 +567,14 @@ void EnGe1_BeginGiveItem_Archery(EnGe1* this, GlobalContext* globalCtx) { break; } } else { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_GF_HBA_1500_POINTS, + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); } } else { if (!gSaveContext.n64ddFlag) { getItemId = GI_HEART_PIECE; } else { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); } } diff --git a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 2fc6ef1df..5310fc65e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -457,7 +457,7 @@ void EnGe2_WaitTillCardGiven(EnGe2* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->actionFunc = EnGe2_SetActionAfterTalk; } else { - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -466,7 +466,7 @@ void EnGe2_GiveCard(EnGe2* this, GlobalContext* globalCtx) { Message_CloseTextbox(globalCtx); this->actor.flags &= ~ACTOR_FLAG_16; this->actionFunc = EnGe2_WaitTillCardGiven; - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index 3a2c50fab..556e7c203 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -142,7 +142,7 @@ void EnGe3_WaitTillCardGiven(EnGe3* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->actionFunc = EnGe3_Wait; } else { - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -151,7 +151,7 @@ void EnGe3_GiveCard(EnGe3* this, GlobalContext* globalCtx) { Message_CloseTextbox(globalCtx); this->actor.flags &= ~ACTOR_FLAG_16; this->actionFunc = EnGe3_WaitTillCardGiven; - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD) : GI_GERUDO_CARD, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index c1e6bd290..050bfc4d1 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -955,7 +955,7 @@ void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) { this->unk_20C = 0; if ((this->actor.params & 0xF0) == 0x90) { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { - getItemId = gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS) : GI_SWORD_BGS; + getItemId = gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS) : GI_SWORD_BGS; this->unk_20C = 1; } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 21d375d38..97f8fb5e0 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -342,7 +342,7 @@ s16 EnGo2_GetStateGoronCityRollingBig(GlobalContext* globalCtx, EnGo2* this) { if(!gSaveContext.n64ddFlag) { bombBagUpgrade = CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30; } else { - bombBagUpgrade = GetRandomizedItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40); + bombBagUpgrade = Randomizer_GetItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40); } EnGo2_GetItem(this, globalCtx, bombBagUpgrade); Message_CloseTextbox(globalCtx); @@ -538,7 +538,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) { } gSaveContext.infTable[16] |= 0x200; - EnGo2_GetItem(this, globalCtx, GetRandomizedItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON)); + EnGo2_GetItem(this, globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON)); this->actionFunc = EnGo2_SetupGetItem; Flags_SetTreasure(globalCtx, 0x1F); return 2; @@ -617,7 +617,7 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { return 0; } - EnGo2_GetItem(this, globalCtx, GetRandomizedItemIdFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); + EnGo2_GetItem(this, globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); Flags_SetTreasure(globalCtx, 0x1F); } else { EnGo2_GetItem(this, globalCtx, GI_SWORD_BGS); diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index 92fc1f022..af4eb8ef4 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -659,7 +659,7 @@ s16 func_80A70058(GlobalContext* globalCtx, Actor* thisx) { gSaveContext.dogParams = 0; break; case 0x709F: - func_80A6F7CC(this, globalCtx, (gSaveContext.infTable[25] & 2) ? GI_RUPEE_BLUE : gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_MARKET_LOST_DOG, GI_HEART_PIECE) : GI_HEART_PIECE); + func_80A6F7CC(this, globalCtx, (gSaveContext.infTable[25] & 2) ? GI_RUPEE_BLUE : gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_MARKET_LOST_DOG, GI_HEART_PIECE) : GI_HEART_PIECE); this->actionFunc = func_80A714C4; break; } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index 97544bce6..cda6e476d 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -344,7 +344,7 @@ void EnKz_Init(Actor* thisx, GlobalContext* globalCtx) { EnKz_SetMovedPos(this, globalCtx); } } else { - int zorasFountain = GetRandoSettingValue(RSK_ZORAS_FOUNTAIN); + int zorasFountain = Randomizer_GetSettingValue(RSK_ZORAS_FOUNTAIN); switch (zorasFountain) { case 0: if (gSaveContext.eventChkInf[3] & 8) { @@ -464,10 +464,10 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) { } else { if (gSaveContext.n64ddFlag) { if (this->isTrading) { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); Flags_SetTreasure(globalCtx, 0x1F); } else { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); } } else { getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index d69e54e65..15b0b8455 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -25,6 +25,7 @@ void func_80AA106C(EnMa1* this, GlobalContext* globalCtx); void func_80AA10EC(EnMa1* this, GlobalContext* globalCtx); void func_80AA1150(EnMa1* this, GlobalContext* globalCtx); void EnMa1_DoNothing(EnMa1* this, GlobalContext* globalCtx); +void EnMa1_WaitForSongGive(EnMa1* this, GlobalContext* globalCtx); const ActorInit En_Ma1_InitVars = { ACTOR_EN_MA1, @@ -337,7 +338,7 @@ void func_80AA0EA0(EnMa1* this, GlobalContext* globalCtx) { this->actionFunc = func_80AA0EFC; } else { if (gSaveContext.n64ddFlag) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(RC_HC_MALON_EGG, GI_WEIRD_EGG); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_HC_MALON_EGG, GI_WEIRD_EGG); func_8002F434(&this->actor, globalCtx, getItemId, 120.0f, 10.0f); } else { func_8002F434(&this->actor, globalCtx, GI_WEIRD_EGG, 120.0f, 10.0f); @@ -355,17 +356,21 @@ void func_80AA0EFC(EnMa1* this, GlobalContext* globalCtx) { } void GivePlayerRandoRewardMalon(EnMa1* malon, GlobalContext* globalCtx, RandomizerCheck check) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_EPONAS_SONG); - + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_EPONAS_SONG); + // Prevents flag from getting set if we weren't able to get the item (i.e. Player is holding shield + // when closing the textbox). if (malon->actor.parent != NULL && malon->actor.parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1F)) { Flags_SetTreasure(globalCtx, 0x1F); - } else if (!Flags_GetTreasure(globalCtx, 0x1F) && - (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE) && - Actor_TextboxIsClosing(&malon->actor, globalCtx) && - (globalCtx->msgCtx.textId == 0x2049 || globalCtx->msgCtx.textId == 0x204A)) { + // puts malon in the action that vanilla has her in after learning the song + // (confirmed via breakpoints in a vanilla save). + malon->actionFunc = func_80AA0D88; + } else if (!Flags_GetTreasure(globalCtx, 0x1F)) { func_8002F434(&malon->actor, globalCtx, getItemId, 10000.0f, 100.0f); } + // make malon sing again after giving the item. + malon->unk_1E8.unk_00 = 0; + malon->unk_1E0 = 1; } void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) { @@ -381,12 +386,8 @@ void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) { } } - if (gSaveContext.n64ddFlag) { - GivePlayerRandoRewardMalon(this, globalCtx, RC_SONG_FROM_MALON); - return; - } - if (gSaveContext.eventChkInf[1] & 0x40) { + // When the player pulls out the Ocarina while close to Malon if (player->stateFlags2 & 0x1000000) { player->stateFlags2 |= 0x2000000; player->unk_6A8 = &this->actor; @@ -394,10 +395,19 @@ void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) { Message_StartTextbox(globalCtx, this->actor.textId, NULL); this->unk_1E8.unk_00 = 1; this->actor.flags |= ACTOR_FLAG_16; - this->actionFunc = func_80AA106C; + // when rando'ed, skip to the Item Giving. Otherwise go to the song teaching code. + this->actionFunc = gSaveContext.n64ddFlag ? func_80AA1150 : func_80AA106C; } else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) { + // somehow flags that the player is close to malon so that pulling out the Ocarina + // triggers the code above this. player->stateFlags2 |= 0x800000; } + // If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina + // in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory. + if (gSaveContext.n64ddFlag && (Actor_TextboxIsClosing(&this->actor, globalCtx) && globalCtx->msgCtx.textId == 0x2049) && + (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE)) { + this->actionFunc = EnMa1_WaitForSongGive; + } } } @@ -419,14 +429,48 @@ void func_80AA10EC(EnMa1* this, GlobalContext* globalCtx) { } } +void EnMa1_WaitForSongGive(EnMa1* this, GlobalContext* globalCtx) { + // Actually give the song check. + GivePlayerRandoRewardMalon(this, globalCtx, RC_SONG_FROM_MALON); +} + +// Sets an Ocarina State necessary to not softlock in rando. +// This function should only be called in rando. +void EnMa1_EndTeachSong(EnMa1* this, GlobalContext* globalCtx) { + if (globalCtx->csCtx.state == CS_STATE_IDLE) { + this->actionFunc = func_80AA0F44; + globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_04; + } + + if (gSaveContext.n64ddFlag) { + // Transition to the giving the song check on the next update run. + this->actionFunc = EnMa1_WaitForSongGive; + } +} + void func_80AA1150(EnMa1* this, GlobalContext* globalCtx) { GET_PLAYER(globalCtx)->stateFlags2 |= 0x800000; + + // When rando'ed, trigger the "song learned" Ocarina mode. + if (gSaveContext.n64ddFlag && (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING)) { + globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_03; + } + if (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_03) { - globalCtx->nextEntranceIndex = 0x157; - gSaveContext.nextCutsceneIndex = 0xFFF1; - globalCtx->fadeTransition = 42; - globalCtx->sceneLoadFlag = 0x14; - this->actionFunc = EnMa1_DoNothing; + if (!gSaveContext.n64ddFlag) { + globalCtx->nextEntranceIndex = 0x157; + gSaveContext.nextCutsceneIndex = 0xFFF1; + globalCtx->fadeTransition = 42; + globalCtx->sceneLoadFlag = 0x14; + this->actionFunc = EnMa1_DoNothing; + } else { + // When rando'ed, skip the cutscene, play the chime, reset some flags, + // and give the song on next update. + func_80078884(NA_SE_SY_CORRECT_CHIME); + this->actionFunc = EnMa1_EndTeachSong; + this->actor.flags &= ~ACTOR_FLAG_16; + globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_00; + } } } diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index 86f07884a..ffb02e8d2 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -485,7 +485,10 @@ u8 EnMd_ShouldSpawn(EnMd* this, GlobalContext* globalCtx) { if (globalCtx->sceneNum == SCENE_SPOT04) { if (gSaveContext.n64ddFlag) { // if we have beaten deku tree or have open forest turned on - if (gSaveContext.dungeonsDone[1] || GetRandoSettingValue(RSK_FOREST) == 1) { + // or have already shown mido we have an equipped sword/shield + if (gSaveContext.dungeonsDone[1] || + Randomizer_GetSettingValue(RSK_FOREST) == 1 || + gSaveContext.eventChkInf[0] & 0x10) { return 0; } return 1; diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index 8f4c512e3..f42e09522 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -198,14 +198,14 @@ void func_80AACFA0(EnMk* this, GlobalContext* globalCtx) { gSaveContext.itemGetInf[1] |= 1; } else { // not sure when/how/if this is getting called - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE) : GI_HEART_PIECE, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE) : GI_HEART_PIECE, 10000.0f, 50.0f); } } void func_80AAD014(EnMk* this, GlobalContext* globalCtx) { if (Actor_TextboxIsClosing(&this->actor, globalCtx)) { this->actionFunc = func_80AACFA0; - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE) : GI_HEART_PIECE, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE) : GI_HEART_PIECE, 10000.0f, 50.0f); } this->flags |= 1; diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 47a1e5e0d..c31f2b923 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -200,7 +200,7 @@ void func_80ABA244(EnNiwLady* this, GlobalContext* globalCtx) { EnNiw* currentCucco; s32 phi_s1; - this->cuccosInPen = gSaveContext.n64ddFlag ? (7 - GetRandoSettingValue(RSK_CUCCO_COUNT)) : 0; + this->cuccosInPen = gSaveContext.n64ddFlag ? (7 - Randomizer_GetSettingValue(RSK_CUCCO_COUNT)) : 0; currentCucco = (EnNiw*)globalCtx->actorCtx.actorLists[ACTORCAT_PROP].head; while (currentCucco != NULL) { if (currentCucco->actor.id == ACTOR_EN_NIW) { @@ -305,7 +305,7 @@ void func_80ABA654(EnNiwLady* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (gSaveContext.n64ddFlag) { - s32 itemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_ANJU_AS_CHILD, GI_BOTTLE); + s32 itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_CHILD, GI_BOTTLE); func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 50.0f); } else { this->getItemId = GI_BOTTLE; @@ -395,7 +395,7 @@ void func_80ABA9B8(EnNiwLady* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (gSaveContext.n64ddFlag) { - s32 itemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + s32 itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); func_8002F434(&this->actor, globalCtx, itemId, 200.0f, 100.0f); } else { func_8002F434(&this->actor, globalCtx, GI_POCKET_EGG, 200.0f, 100.0f); @@ -455,7 +455,7 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) { getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO; if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) { - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); } } func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f); diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index b36a07dd5..cc7360c0a 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -234,7 +234,7 @@ void func_80ABF4C8(EnOkarinaTag* this, GlobalContext* globalCtx) { if (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_04) { this->actionFunc = func_80ABF28C; } else if (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (!gSaveContext.n64ddFlag || (gSaveContext.n64ddFlag && GetRandoSettingValue(RSK_DOOR_OF_TIME) != 2)) { + if (!gSaveContext.n64ddFlag || (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) != 2)) { func_80078884(NA_SE_SY_CORRECT_CHIME); } if (this->switchFlag >= 0) { @@ -257,7 +257,7 @@ void func_80ABF4C8(EnOkarinaTag* this, GlobalContext* globalCtx) { break; case 4: if (gSaveContext.n64ddFlag) { - int doorOfTime = GetRandoSettingValue(RSK_DOOR_OF_TIME); + int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); if (doorOfTime == 2 && (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_OCARINA_TIME || !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || !CHECK_QUEST_ITEM(QUEST_GORON_RUBY) || @@ -327,7 +327,7 @@ void GivePlayerRandoRewardSunSong(EnOkarinaTag* song, GlobalContext* globalCtx, !Flags_GetTreasure(globalCtx, 0x1F)) { Flags_SetTreasure(globalCtx, 0x1F); } else if (!Flags_GetTreasure(globalCtx, 0x1F)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_LETTER_ZELDA); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_LETTER_ZELDA); func_8002F434(&song->actor, globalCtx, getItemId, 10000.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index 15cae19d0..c6dd38acc 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -619,7 +619,7 @@ void func_80AF67D0(EnSa* this, GlobalContext* globalCtx) { void GivePlayerRandoRewardSaria(EnSa* saria, GlobalContext* globalCtx, RandomizerCheck check) { GetItemID getItemId = - GetRandomizedItemIdFromKnownCheck(check, GI_SARIAS_SONG); + Randomizer_GetItemIdFromKnownCheck(check, GI_SARIAS_SONG); if (saria->actor.parent != NULL && saria->actor.parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1F)) { diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 332aefc0b..859afb406 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1035,7 +1035,7 @@ void EnSkj_SariaSongTalk(EnSkj* this, GlobalContext* globalCtx) { EnSkj_SetupWaitInRange(this); } else { func_80AFFE24(this); - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE) : GI_HEART_PIECE, EnSkj_GetItemXzRange(this), + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE) : GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } @@ -1050,7 +1050,7 @@ void func_80AFFE44(EnSkj* this, GlobalContext* globalCtx) { this->actor.parent = NULL; EnSkj_SetupPostSariasSong(this); } else { - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE) : GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE) : GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } @@ -1529,7 +1529,7 @@ void EnSkj_WaitToGiveReward(EnSkj* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) { func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag && gSaveContext.ocarinaGameRoundNum != 3 - ? GetRandomizedItemIdFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE) + ? Randomizer_GetItemIdFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE) : sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); @@ -1544,7 +1544,7 @@ void EnSkj_GiveOcarinaGameReward(EnSkj* this, GlobalContext* globalCtx) { } else { func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag && gSaveContext.ocarinaGameRoundNum != 3 - ? GetRandomizedItemIdFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE) + ? Randomizer_GetItemIdFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE) : sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); } diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index d48aedc77..b01c6b8c4 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -245,19 +245,19 @@ void EnSth_GivePlayerItem(EnSth* this, GlobalContext* globalCtx) { case GI_RUPEE_GOLD: break; case GI_WALLET_ADULT: - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_10_GOLD_SKULLTULA_REWARD, GI_WALLET_ADULT); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_10_GOLD_SKULLTULA_REWARD, GI_WALLET_ADULT); break; case GI_STONE_OF_AGONY: - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_20_GOLD_SKULLTULA_REWARD, GI_STONE_OF_AGONY); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_20_GOLD_SKULLTULA_REWARD, GI_STONE_OF_AGONY); break; case GI_WALLET_GIANT: - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_30_GOLD_SKULLTULA_REWARD, GI_WALLET_GIANT); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_30_GOLD_SKULLTULA_REWARD, GI_WALLET_GIANT); break; case GI_BOMBCHUS_10: - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_40_GOLD_SKULLTULA_REWARD, GI_BOMBCHUS_10); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_40_GOLD_SKULLTULA_REWARD, GI_BOMBCHUS_10); break; case GI_HEART_PIECE: - getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_50_GOLD_SKULLTULA_REWARD, GI_HEART_PIECE); + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_50_GOLD_SKULLTULA_REWARD, GI_HEART_PIECE); break; } } else { diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 4f779cd0a..7b57bea89 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -336,7 +336,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (!LINK_IS_ADULT) { if(gSaveContext.n64ddFlag && !Flags_GetTreasure(globalCtx, 0x1E)) { - this->getItemId = GetRandomizedItemIdFromKnownCheck(RC_MARKET_SHOOTING_GALLERY_REWARD, GI_BULLET_BAG_50); + this->getItemId = Randomizer_GetItemIdFromKnownCheck(RC_MARKET_SHOOTING_GALLERY_REWARD, GI_BULLET_BAG_50); Flags_SetTreasure(globalCtx, 0x1E); } else if (!gSaveContext.n64ddFlag && !(gSaveContext.itemGetInf[0] & 0x2000)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Pachinko ☆☆☆☆☆ %d\n" VT_RST, @@ -351,7 +351,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, GlobalContext* globalCtx) { } } else { if(gSaveContext.n64ddFlag && !Flags_GetTreasure(globalCtx, 0x1F)) { - this->getItemId = GetRandomizedItemIdFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50); + this->getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50); Flags_SetTreasure(globalCtx, 0x1F); } else if (!gSaveContext.n64ddFlag && !(gSaveContext.itemGetInf[0] & 0x4000)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Bow ☆☆☆☆☆ %d\n" VT_RST, diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index e9f23176c..dad7d25e5 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -883,7 +883,7 @@ void func_80B15F54(EnTa* this, GlobalContext* globalCtx) { Message_CloseTextbox(globalCtx); this->unk_2E0 &= ~0x2; func_80B13AA0(this, func_80B15E80, func_80B16938); - func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? GetRandomizedItemIdFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE) : GI_MILK_BOTTLE, 10000.0f, 50.0f); + func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag ? Randomizer_GetItemIdFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE) : GI_MILK_BOTTLE, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index 2aff2225c..314092d49 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -252,12 +252,18 @@ void func_80B3A4F8(EnWonderTalk2* this, GlobalContext* globalCtx) { } this->unk_158 = 0; if (!this->unk_156) { - // whether or not to skip the text in rando + // Whether or not to skip the text in rando bool randoSkipText = false; if (gSaveContext.n64ddFlag) { - // scenes for which all of this type of wonder talk should be skipped. - switch (globalCtx->sceneNum) { - case 0x0007: //shadow temple + // Scenes for which all of this type of wonder talk should be skipped. + switch (globalCtx->sceneNum) { + case 0x0007: // Shadow Temple + randoSkipText = true; + break; + case 0x000B: // Gerudo Training Grounds + randoSkipText = true; + break; + case 0x000C: // Inside Gerudo Fortress randoSkipText = true; break; default: diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index e4ccbf4a3..88ce05819 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -292,7 +292,7 @@ void GivePlayerRandoRewardSheikSong(EnXc* sheik, GlobalContext* globalCtx, Rando !(gSaveContext.eventChkInf[5] & sheikType)) { gSaveContext.eventChkInf[5] |= sheikType; } else if (!(gSaveContext.eventChkInf[5] & sheikType)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, ogSongId); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, ogSongId); if (check == RC_SHEIK_AT_TEMPLE && !Flags_GetTreasure(globalCtx, 0x1F)) { if (func_8002F434(&sheik->actor, globalCtx, getItemId, 10000.0f, 100.0f)) { Flags_SetTreasure(globalCtx, 0x1F); diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index 87574aa56..d4250fca2 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -231,9 +231,9 @@ void GivePlayerRandoRewardZeldaChild(EnZl4* zelda, GlobalContext* globalCtx, Ran if (zelda->actor.parent != NULL && zelda->actor.parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1E)) { Flags_SetTreasure(globalCtx, 0x1E); - } else if (!Flags_GetTreasure(globalCtx, 0x1E) && !GetRandoSettingValue(RSK_SKIP_CHILD_ZELDA) && Actor_TextboxIsClosing(&zelda->actor, globalCtx) && + } else if (!Flags_GetTreasure(globalCtx, 0x1E) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA) && Actor_TextboxIsClosing(&zelda->actor, globalCtx) && (globalCtx->msgCtx.textId == 0x703C || globalCtx->msgCtx.textId == 0x703D)) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_LETTER_ZELDA); + GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_LETTER_ZELDA); func_8002F434(&zelda->actor, globalCtx, getItemId, 10000.0f, 100.0f); } else if (Flags_GetTreasure(globalCtx, 0x1E) && !Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { gSaveContext.unk_13EE = 0x32; diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 8666ca302..eb7c0a20a 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -5044,7 +5044,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, GlobalContext* globalCtx) { HIGH_SCORE(HS_FISHING) |= 0x400; sSinkingLureLocation = (u8)Rand_ZeroFloat(3.999f) + 1; getItemId = gSaveContext.n64ddFlag ? - GetRandomizedItemIdFromKnownCheck(RC_LH_CHILD_FISHING, GI_HEART_PIECE) : + Randomizer_GetItemIdFromKnownCheck(RC_LH_CHILD_FISHING, GI_HEART_PIECE) : GI_HEART_PIECE; } } @@ -5054,7 +5054,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, GlobalContext* globalCtx) { HIGH_SCORE(HS_FISHING) |= 0x800; sSinkingLureLocation = (u8)Rand_ZeroFloat(3.999f) + 1; getItemId = gSaveContext.n64ddFlag ? - GetRandomizedItemIdFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD) : + Randomizer_GetItemIdFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD) : GI_SCALE_GOLD; } } @@ -5130,7 +5130,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, GlobalContext* globalCtx) { func_8002F434(&this->actor, globalCtx, GI_SCALE_GOLD, 2000.0f, 1000.0f); } else { func_8002F434(&this->actor, globalCtx, - GetRandomizedItemIdFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD), 2000.0f, + Randomizer_GetItemIdFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD), 2000.0f, 1000.0f); } } diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index 17404ab77..e32ab216f 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -60,7 +60,7 @@ void ItemBHeart_Update(Actor* thisx, GlobalContext* globalCtx) { Actor_Kill(&this->actor); } else { if (gSaveContext.n64ddFlag) { - s32 getItemId = GetRandomizedItemId(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum); + s32 getItemId = Randomizer_GetRandomizedItemId(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum); func_8002F434(&this->actor, globalCtx, getItemId, 30.0f, 40.0f); } else { func_8002F434(&this->actor, globalCtx, GI_HEART_CONTAINER_2, 30.0f, 40.0f); @@ -100,7 +100,7 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) { if (gSaveContext.n64ddFlag) { GetItem_Draw(globalCtx, - GetItemModelFromId(GetRandomizedItemId(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum))); + Randomizer_GetItemModelFromId(Randomizer_GetRandomizedItemId(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum))); } else { if (flag) { func_80093D84(globalCtx->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index f1575306b..cfa115daf 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -133,7 +133,7 @@ void func_80B85824(ItemEtcetera* this, GlobalContext* globalCtx) { Actor_Kill(&this->actor); } else { if (gSaveContext.n64ddFlag) { - s32 getItemId = GetRandomizedItemIdFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); + s32 getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); func_8002F434(&this->actor, globalCtx, getItemId, 30.0f, 50.0f); } else { func_8002F434(&this->actor, globalCtx, this->getItemId, 30.0f, 50.0f); @@ -156,7 +156,7 @@ void func_80B858B4(ItemEtcetera* this, GlobalContext* globalCtx) { if (0) {} // Necessary to match if (gSaveContext.n64ddFlag) { - s32 getItemId = GetRandomizedItemIdFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + s32 getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); func_8002F434(&this->actor, globalCtx, getItemId, 30.0f, 50.0f); } else { func_8002F434(&this->actor, globalCtx, this->getItemId, 30.0f, 50.0f); @@ -234,7 +234,7 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, GlobalContext* globalCtx) { EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemId); } if (randoGetItemId != GI_NONE) { - GetItem_Draw(globalCtx, GetItemModelFromId(randoGetItemId)); + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(randoGetItemId)); return; } } @@ -250,9 +250,9 @@ void ItemEtcetera_Draw(Actor* thisx, GlobalContext* globalCtx) { if (gSaveContext.n64ddFlag) { s32 randoGetItemId = GI_NONE; if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItemId = GetRandomizedItemIdFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); + randoGetItemId = Randomizer_GetItemIdFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); } else if (type == ITEM_ETC_LETTER) { - randoGetItemId = GetRandomizedItemIdFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + randoGetItemId = Randomizer_GetItemIdFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); } if (randoGetItemId >= GI_MINUET_OF_FOREST && randoGetItemId <= GI_DOUBLE_DEFENSE) { @@ -260,7 +260,7 @@ void ItemEtcetera_Draw(Actor* thisx, GlobalContext* globalCtx) { } if (randoGetItemId != GI_NONE) { - this->giDrawId = GetItemModelFromId(randoGetItemId); + this->giDrawId = Randomizer_GetItemModelFromId(randoGetItemId); } } diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index 0b3d9382c..9992d08b3 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -191,7 +191,7 @@ void ItemOcarina_WaitInWater(ItemOcarina* this, GlobalContext* globalCtx) { } else { func_8002F434(&this->actor, globalCtx, gSaveContext.n64ddFlag - ? GetRandomizedItemIdFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT) + ? Randomizer_GetItemIdFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT) : GI_OCARINA_OOT, 30.0f, 50.0f); @@ -214,11 +214,11 @@ void ItemOcarina_Draw(Actor* thisx, GlobalContext* globalCtx) { func_8002ED80(thisx, globalCtx, 0); if (gSaveContext.n64ddFlag) { - s32 randoGetItemId = GetRandomizedItemIdFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); + s32 randoGetItemId = Randomizer_GetItemIdFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); if (randoGetItemId >= GI_MINUET_OF_FOREST && randoGetItemId <= GI_DOUBLE_DEFENSE) { EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemId); } - GetItem_Draw(globalCtx, GetItemModelFromId(randoGetItemId)); + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(randoGetItemId)); return; } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 70cf3ebb7..1f1d09a8d 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -620,7 +620,7 @@ static GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT), GET_ITEM(ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT), GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG), - GET_ITEM(ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x3C, 0x80, CHEST_ANIM_LONG), // Ice Traps + GET_ITEM(ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x3C, 0x80, CHEST_ANIM_SHORT), // Ice Traps GET_ITEM_NONE, GET_ITEM(ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG), @@ -3603,7 +3603,7 @@ s32 func_80837B18_modified(GlobalContext* globalCtx, Player* this, s32 damage, u s32 modifiedDamage = damage; if (modified) { - modifiedDamage *= CVar_GetS32("gDamageMul", 1); + modifiedDamage *= (1 << CVar_GetS32("gDamageMul", 0)); } return Health_ChangeBy(globalCtx, modifiedDamage); @@ -3836,7 +3836,7 @@ s32 func_808382DC(Player* this, GlobalContext* globalCtx) { if (this->unk_A86 != 0) { if (!Player_InBlockingCsMode(globalCtx, this)) { - Player_InflictDamageModified(globalCtx, -16 * CVar_GetS32("gVoidDamageMul", 1), false); + Player_InflictDamageModified(globalCtx, -16 * (1 << CVar_GetS32("gVoidDamageMul", 0)), false); this->unk_A86 = 0; } } @@ -8407,7 +8407,7 @@ s32 func_80843E64(GlobalContext* globalCtx, Player* this) { impactInfo = &D_80854600[impactIndex]; - if (Player_InflictDamageModified(globalCtx, impactInfo->damage * CVar_GetS32("gFallDamageMul", 1), false)) { + if (Player_InflictDamageModified(globalCtx, impactInfo->damage * (1 << CVar_GetS32("gFallDamageMul", 0)), false)) { return -1; } diff --git a/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h b/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h index 0a510eba2..93f4efb76 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h +++ b/soh/src/overlays/gamestates/ovl_file_choose/file_choose.h @@ -203,6 +203,11 @@ void FileChoose_DrawOptions(GameState* thisx); void FileChoose_DrawNameEntry(GameState* thisx); void FileChoose_DrawCharacter(GraphicsContext* gfxCtx, void* texture, s16 vtx); +void HandleMouseInput(Input* input); +u8 HandleMouseCursor(FileChooseContext* this, Input* input, int minx, int miny, int maxx, int maxy); +Vec2f HandleMouseCursorSplit(FileChooseContext* this, Input* input, int minx, int miny, int maxx, int maxy, int countx, + int county); + extern s16 D_808123F0[]; #endif diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 08d0c855b..2aef4bc64 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -415,15 +415,15 @@ void FileChoose_UpdateMainMenu(GameState* thisx) { } if ((CVar_GetS32("gNewFileDropped", 0) != 0) || - (CVar_GetS32("gNewSeedGenerated", 0) != 0) || + (CVar_GetS32("gNewSeedGenerated", 0) != 0) || (!fileSelectSpoilerFileLoaded && - SpoilerFileExists(CVar_GetString("gSpoilerLog", "")))) { + SpoilerFileExists(CVar_GetString("gSpoilerLog", "")))) { if (CVar_GetS32("gNewFileDropped", 0) != 0) { - CVar_SetString("gSpoilerLog", CVar_GetString("gDroppedFile", "")); + CVar_SetString("gSpoilerLog", CVar_GetString("gDroppedFile", "None")); } bool silent = true; - if((CVar_GetS32("gNewFileDropped", 0) != 0) || - (CVar_GetS32("gNewSeedGenerated", 0) != 0)) { + if ((CVar_GetS32("gNewFileDropped", 0) != 0) || + (CVar_GetS32("gNewSeedGenerated", 0) != 0)) { silent = false; } CVar_SetS32("gNewSeedGenerated", 0); @@ -431,9 +431,9 @@ void FileChoose_UpdateMainMenu(GameState* thisx) { CVar_SetString("gDroppedFile", ""); fileSelectSpoilerFileLoaded = false; const char* fileLoc = CVar_GetString("gSpoilerLog", ""); - LoadRandomizerSettings(fileLoc); - LoadHintLocations(fileLoc); - LoadItemLocations(fileLoc, silent); + Randomizer_LoadSettings(fileLoc); + Randomizer_LoadHintLocations(fileLoc); + Randomizer_LoadItemLocations(fileLoc, silent); fileSelectSpoilerFileLoaded = true; } @@ -1740,9 +1740,9 @@ void FileChoose_LoadGame(GameState* thisx) { this->state.running = false; } - LoadRandomizerSettings(""); - LoadHintLocations(""); - LoadItemLocations("", true); + Randomizer_LoadSettings(""); + Randomizer_LoadHintLocations(""); + Randomizer_LoadItemLocations("", true); gSaveContext.respawn[0].entranceIndex = -1; gSaveContext.respawnFlag = 0; @@ -1894,7 +1894,7 @@ void FileChoose_Main(GameState* thisx) { }; FileChooseContext* this = (FileChooseContext*)thisx; Input* input = &this->state.input[0]; - + if (CVar_GetS32("gTimeFlowFileSelect", 0) != 0) { gSaveContext.skyboxTime += 0x10; }