diff --git a/OTRGui/src/game/game.cpp b/OTRGui/src/game/game.cpp index 3fc6438a8..ff7e7a22b 100644 --- a/OTRGui/src/game/game.cpp +++ b/OTRGui/src/game/game.cpp @@ -18,6 +18,7 @@ Shader shader = { 0 }; Light light = { 0 }; Vector3 lightPos = { -5.0f, 10.0f, 10.0f }; Vector2 dragOffset; +bool isDragging = false; std::string sohFolder = NULLSTR; bool extracting = false; bool rom_ready = false; @@ -95,69 +96,101 @@ void OTRGame::update(){ } void OTRGame::draw() { + Vector2 windowSize(GetScreenWidth(), GetScreenHeight()); + Rectangle titlebar = Rectangle(0, 0, windowSize.x - 50, 35); + Vector2 mousePos = GetMousePosition(); + Vector2 mouseDelta = GetMouseDelta(); + + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && !isDragging && + mousePos.x >= titlebar.x && mousePos.y >= titlebar.y && mousePos.x <= titlebar.x + titlebar.width && mousePos.y <= titlebar.y + titlebar.height) { + isDragging = true; + dragOffset = mousePos; + } + else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && isDragging) { + isDragging = false; + dragOffset = Vector2(0, 0); + } + + if (isDragging && (mouseDelta.x != 0.0f || mouseDelta.y != 0.0f)) { + Vector2 wndPos = GetWindowPosition(); + wndPos = Vector2(wndPos.x + (mousePos.x - dragOffset.x), wndPos.y + (mousePos.y - dragOffset.y)); + + // Calculate virtual screen total size in case there are multiple monitors + + int vsX1 = 0, vsY1 = 0, vsX2 = 0, vsY2 = 0; + int monitorCount = GetMonitorCount(); + + for (int m = 0; m < monitorCount; m++) { + Vector2 monitorPos = GetMonitorPosition(m); + Vector2 monitorSize = Vector2(GetMonitorWidth(m), GetMonitorHeight(m)); + + if (monitorPos.x < vsX1) vsX1 = monitorPos.x; + if (monitorPos.y < vsY1) vsY1 = monitorPos.y; + if (monitorPos.x + monitorSize.x > vsX2) vsX2 = monitorPos.x + monitorSize.x; + if (monitorPos.y + monitorSize.y > vsY2) vsY2 = monitorPos.y + monitorSize.y; + } + + // Clamp the window to the borders of the monitors + + if (wndPos.x < vsX1) wndPos.x = vsX1; + if (wndPos.y < vsY1) wndPos.y = vsY1; + if (wndPos.x + windowSize.x > vsX2) wndPos.x = vsX2 - windowSize.x; + if (wndPos.y + windowSize.y > vsY2) wndPos.y = vsY2 - windowSize.y; + + SetWindowPosition(wndPos.x, wndPos.y); + } + BeginDrawing(); - ClearBackground(Color(40, 40, 40, 255)); - Vector3 windowSize(GetScreenWidth(), GetScreenHeight()); - Rectangle titlebar = Rectangle(0, 0, windowSize.x - 50, 35); - Vector2 mousePos = Vector2(GetMouseX(), GetMouseY()); - bool hoveredTitlebar = mousePos.x >= titlebar.x && mousePos.y >= titlebar.y && mousePos.x <= titlebar.x + titlebar.width && mousePos.y <= titlebar.y + titlebar.height; + ClearBackground(Color(40, 40, 40, 255)); - if (hoveredTitlebar && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { - if (dragOffset.x == 0 && dragOffset.y == 0) dragOffset = mousePos; - Vector2 wndPos = GetWindowPosition(); + DrawTexture(Textures["Frame"], 0, 0, WHITE); - SetWindowPosition(wndPos.x + (mousePos.x - dragOffset.x), wndPos.y + (mousePos.y - dragOffset.y)); - } - else dragOffset = Vector2(0, 0); + Texture2D titleTex = Textures["Title"]; + DrawTexture(titleTex, windowSize.x / 2 - titleTex.width / 2, titlebar.height / 2 - titleTex.height / 2, WHITE); - DrawTexture(Textures["Frame"], 0, 0, WHITE); + if (UIUtils::GuiIcon("Exit", windowSize.x - 36, titlebar.height / 2 - 10) && (extracting && currentStep.find("Done") != std::string::npos || !extracting)) { + closeRequested = true; + } - Texture2D titleTex = Textures["Title"]; - DrawTexture(titleTex, windowSize.x / 2 - titleTex.width / 2, titlebar.height / 2 - titleTex.height / 2, WHITE); + BeginMode3D(camera); + DrawModelEx(Models["Ship"], Vector3Zero(), Vector3(.0f, 1.0f, .0f), this->ModelRotation, SCALE(1.0f), WHITE); + EndMode3D(); - if (UIUtils::GuiIcon("Exit", windowSize.x - 36, titlebar.height / 2 - 10) && (extracting && currentStep.find("Done") != std::string::npos || !extracting)) { - CloseWindow(); - } + constexpr float text_y = 125.f; + UIUtils::GuiShadowText(("Rom Type: " + version.version).c_str(), 32, text_y, 10, WHITE, BLACK); + UIUtils::GuiShadowText("Tool Version: 1.0", 32, text_y + 15, 10, WHITE, BLACK); + UIUtils::GuiShadowText("OTR Version: 1.0", 32, text_y + 30, 10, WHITE, BLACK); + UIUtils::GuiToggle(&single_thread, "Single Thread", 32, text_y + 40, currentStep != NULLSTR); - BeginMode3D(camera); - DrawModelEx(Models["Ship"] ,Vector3Zero(), Vector3(.0f, 1.0f, .0f), this->ModelRotation, SCALE(1.0f), WHITE); - EndMode3D(); + if (!hide_second_btn && UIUtils::GuiIconButton("Folder", "Open\nShip Folder", 109, 50, currentStep != NULLSTR, "Select your Ship of Harkinian Folder\n\nYou could use another folder\nfor development purposes")) { + const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FOLDER); + sohFolder = path; + } - constexpr float text_y = 125.f; - UIUtils::GuiShadowText(("Rom Type: " + version.version).c_str(), 32, text_y, 10, WHITE, BLACK); - UIUtils::GuiShadowText("Tool Version: 1.0", 32, text_y + 15, 10, WHITE, BLACK); - UIUtils::GuiShadowText("OTR Version: 1.0", 32, text_y + 30, 10, WHITE, BLACK); - UIUtils::GuiToggle(&single_thread, "Single Thread", 32, text_y + 40, currentStep != NULLSTR); - - if(!hide_second_btn && UIUtils::GuiIconButton("Folder", "Open\nShip Folder", 109, 50, currentStep != NULLSTR, "Select your Ship of Harkinian Folder\n\nYou could use another folder\nfor development purposes")) { - const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FOLDER); - sohFolder = path; - } - - if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nMaster Quest or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) { - const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FILE); - if (path != NULLSTR) { - const std::string patched_n64 = std::string(patched_rom); - MoonUtils::rm(patched_n64); - version = GetVersion(fopen(path.c_str(), "r")); - if (version.version != NULLSTR) { - MoonUtils::copy(path, patched_n64); - rom_ready = true; - return; - } - fix_baserom(path.c_str(), patched_rom); - version = GetVersion(fopen(patched_rom, "r")); - if (version.version != NULLSTR) rom_ready = true; + if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nMaster Quest or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) { + const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FILE); + if (path != NULLSTR) { + const std::string patched_n64 = std::string(patched_rom); + MoonUtils::rm(patched_n64); + version = GetVersion(fopen(path.c_str(), "r")); + if (version.version != NULLSTR) { + MoonUtils::copy(path, patched_n64); + rom_ready = true; + return; } + fix_baserom(path.c_str(), patched_rom); + version = GetVersion(fopen(patched_rom, "r")); + if (version.version != NULLSTR) rom_ready = true; } + } - if(currentStep != NULLSTR) { - DrawRectangle(0, 0, windowSize.x, windowSize.y, Color(0, 0, 0, 160)); - DrawTexture(Textures["Modal"], windowSize.x / 2 - Textures["Modal"].width / 2, windowSize.y / 2 - Textures["Modal"].height / 2, WHITE); - UIUtils::GuiShadowText(currentStep.c_str(), 0, windowSize.y / 2, 10, WHITE, BLACK, windowSize.x, true); - } + if (currentStep != NULLSTR) { + DrawRectangle(0, 0, windowSize.x, windowSize.y, Color(0, 0, 0, 160)); + DrawTexture(Textures["Modal"], windowSize.x / 2 - Textures["Modal"].width / 2, windowSize.y / 2 - Textures["Modal"].height / 2, WHITE); + UIUtils::GuiShadowText(currentStep.c_str(), 0, windowSize.y / 2, 10, WHITE, BLACK, windowSize.x, true); + } - EndDrawing(); + EndDrawing(); } void setCurrentStep(const std::string& step) { diff --git a/OTRGui/src/game/game.h b/OTRGui/src/game/game.h index b284f857a..bd74b1c3f 100644 --- a/OTRGui/src/game/game.h +++ b/OTRGui/src/game/game.h @@ -19,6 +19,8 @@ public: void update(); void draw(); void exit(); + + inline bool CloseRequested() { return closeRequested; } protected: void LoadTexture(const std::string& name, const std::string& path) { const Image tmp = LoadImage(path.c_str()); @@ -32,6 +34,9 @@ protected: SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); Fonts[name] = font; } + +private: + bool closeRequested = false; }; extern OTRGame* Game; diff --git a/OTRGui/src/main.cpp b/OTRGui/src/main.cpp index 87c9d26ee..2b3e40a7c 100644 --- a/OTRGui/src/main.cpp +++ b/OTRGui/src/main.cpp @@ -17,8 +17,8 @@ void UpdateDrawFrame(void) { } int main() { - constexpr Vector2 windowSize = Vector2(400, 200); - SetTargetFPS(144); + constexpr Vector2 windowSize = Vector2(400, 200); + SetConfigFlags(FLAG_VSYNC_HINT); SetConfigFlags(FLAG_WINDOW_HIGHDPI); SetConfigFlags(FLAG_WINDOW_UNDECORATED); SetConfigFlags(FLAG_MSAA_4X_HINT); @@ -32,7 +32,7 @@ int main() { Game = new OTRGame(); Game->preload(); Game->init(); - while(!WindowShouldClose()) { + while(!WindowShouldClose() && !Game->CloseRequested()) { UpdateDrawFrame(); } CloseWindow(); diff --git a/ZAPDTR/ZAPD/Main.cpp b/ZAPDTR/ZAPD/Main.cpp index 440f6d504..250704993 100644 --- a/ZAPDTR/ZAPD/Main.cpp +++ b/ZAPDTR/ZAPD/Main.cpp @@ -188,14 +188,16 @@ int main(int argc, char* argv[]) } else if (arg == "-eh") // Enable Error Handler { -#if !defined(_MSC_VER) && !defined(__CYGWIN__) + #if !defined(_MSC_VER) && !defined(__CYGWIN__) signal(SIGSEGV, ErrorHandler); signal(SIGABRT, ErrorHandler); #else - HANDLE_WARNING(WarningType::Always, - "tried to set error handler, but this ZAPD build lacks support for one", - ""); + // HANDLE_WARNING(WarningType::Always, + // "tried to set error handler, but this ZAPD build lacks support for one", + // ""); #endif + + } else if (arg == "-v") // Verbose { diff --git a/libultraship/libultraship/GameSettings.cpp b/libultraship/libultraship/GameSettings.cpp index 8599367a7..c638468af 100644 --- a/libultraship/libultraship/GameSettings.cpp +++ b/libultraship/libultraship/GameSettings.cpp @@ -27,6 +27,7 @@ namespace Game { const std::string AudioSection = AUDIO_SECTION; const std::string ControllerSection = CONTROLLER_SECTION; const std::string EnhancementSection = ENHANCEMENTS_SECTION; + const std::string CheatSection = CHEATS_SECTION; void UpdateAudio() { Audio_SetGameVolume(SEQ_BGM_MAIN, Settings.audio.music_main); @@ -57,9 +58,7 @@ namespace Game { Settings.enhancements.animated_pause_menu = stob(Conf[EnhancementSection]["animated_pause_menu"]); CVar_SetS32(const_cast("gPauseLiveLink"), Settings.enhancements.animated_pause_menu); - Settings.enhancements.debug_mode = stob(Conf[EnhancementSection]["debug_mode"]); - CVar_SetS32(const_cast("gDebugEnabled"), Settings.enhancements.debug_mode); - + // Audio Settings.audio.master = Ship::stof(Conf[AudioSection]["master"]); CVar_SetFloat(const_cast("gGameMasterVolume"), Settings.audio.master); @@ -75,6 +74,7 @@ namespace Game { Settings.audio.fanfare = Ship::stof(Conf[AudioSection]["fanfare"]); CVar_SetFloat(const_cast("gFanfareVolume"), Settings.audio.fanfare); + // Controllers Settings.controller.gyro_sensitivity = Ship::stof(Conf[ControllerSection]["gyro_sensitivity"]); CVar_SetFloat(const_cast("gGyroSensitivity"), Settings.controller.gyro_sensitivity); @@ -86,6 +86,34 @@ namespace Game { Settings.controller.input_enabled = stob(Conf[ControllerSection]["input_enabled"]); CVar_SetS32(const_cast("gInputEnabled"), Settings.controller.input_enabled); + + // Cheats + Settings.cheats.debug_mode = stob(Conf[CheatSection]["debug_mode"]); + CVar_SetS32(const_cast("gDebugEnabled"), Settings.cheats.debug_mode); + + Settings.cheats.infinite_money = stob(Conf[CheatSection]["infinite_money"]); + CVar_SetS32(const_cast("gInfiniteMoney"), Settings.cheats.infinite_money); + + Settings.cheats.infinite_health = stob(Conf[CheatSection]["infinite_health"]); + CVar_SetS32(const_cast("gInfiniteHealth"), Settings.cheats.infinite_health); + + Settings.cheats.infinite_ammo = stob(Conf[CheatSection]["infinite_ammo"]); + CVar_SetS32(const_cast("gInfiniteAmmo"), Settings.cheats.infinite_ammo); + + Settings.cheats.infinite_magic = stob(Conf[CheatSection]["infinite_magic"]); + CVar_SetS32(const_cast("gInfiniteMagic"), Settings.cheats.infinite_magic); + + Settings.cheats.no_clip = stob(Conf[CheatSection]["no_clip"]); + CVar_SetS32(const_cast("gNoClip"), Settings.cheats.no_clip); + + Settings.cheats.climb_everything = stob(Conf[CheatSection]["climb_everything"]); + CVar_SetS32(const_cast("gClimbEverything"), Settings.cheats.climb_everything); + + Settings.cheats.moon_jump_on_l = stob(Conf[CheatSection]["moon_jump_on_l"]); + CVar_SetS32(const_cast("gMoonJumpOnL"), Settings.cheats.moon_jump_on_l); + + Settings.cheats.super_tunic = stob(Conf[CheatSection]["super_tunic"]); + CVar_SetS32(const_cast("gSuperTunic"), Settings.cheats.super_tunic); UpdateAudio(); } @@ -111,13 +139,25 @@ namespace Game { Conf[EnhancementSection]["fast_text"] = std::to_string(Settings.enhancements.fast_text); Conf[EnhancementSection]["disable_lod"] = std::to_string(Settings.enhancements.disable_lod); Conf[EnhancementSection]["animated_pause_menu"] = std::to_string(Settings.enhancements.animated_pause_menu); - Conf[EnhancementSection]["debug_mode"] = std::to_string(Settings.enhancements.debug_mode); + + // Controllers Conf[ControllerSection]["gyro_sensitivity"] = std::to_string(Settings.controller.gyro_sensitivity); Conf[ControllerSection]["rumble_strength"] = std::to_string(Settings.controller.rumble_strength); Conf[ControllerSection]["input_scale"] = std::to_string(Settings.controller.input_scale); Conf[ControllerSection]["input_enabled"] = std::to_string(Settings.controller.input_enabled); + // Cheats + Conf[CheatSection]["debug_mode"] = std::to_string(Settings.cheats.debug_mode); + Conf[CheatSection]["infinite_money"] = std::to_string(Settings.cheats.infinite_money); + Conf[CheatSection]["infinite_health"] = std::to_string(Settings.cheats.infinite_health); + Conf[CheatSection]["infinite_ammo"] = std::to_string(Settings.cheats.infinite_ammo); + Conf[CheatSection]["infinite_magic"] = std::to_string(Settings.cheats.infinite_magic); + Conf[CheatSection]["no_clip"] = std::to_string(Settings.cheats.no_clip); + Conf[CheatSection]["climb_everything"] = std::to_string(Settings.cheats.climb_everything); + Conf[CheatSection]["moon_jump_on_l"] = std::to_string(Settings.cheats.moon_jump_on_l); + Conf[CheatSection]["super_tunic"] = std::to_string(Settings.cheats.super_tunic); + Conf.Save(); } diff --git a/libultraship/libultraship/GameSettings.h b/libultraship/libultraship/GameSettings.h index 35d948d89..be974fd80 100644 --- a/libultraship/libultraship/GameSettings.h +++ b/libultraship/libultraship/GameSettings.h @@ -23,15 +23,30 @@ struct SoHConfigType { bool fast_text = false; bool disable_lod = false; bool animated_pause_menu = false; - bool debug_mode = false; } enhancements; + // Controller struct { float gyro_sensitivity = 1.0f; float rumble_strength = 1.0f; float input_scale = 1.0f; - bool input_enabled = false; + float gyroDriftX = 0.0f; + float gyroDriftY = 0.0f; + bool input_enabled = false; } controller; + + // Cheats + struct { + bool debug_mode = false; + bool infinite_money = false; + bool infinite_health = false; + bool infinite_ammo = false; + bool infinite_magic = false; + bool no_clip = false; + bool climb_everything = false; + bool moon_jump_on_l = false; + bool super_tunic = false; + } cheats; }; enum SeqPlayers { @@ -46,6 +61,7 @@ enum SeqPlayers { #define AUDIO_SECTION "AUDIO SETTINGS" #define CONTROLLER_SECTION "CONTROLLER SECTION" #define ENHANCEMENTS_SECTION "ENHANCEMENT SETTINGS" +#define CHEATS_SECTION "CHEATS SETTINGS" namespace Game { extern SoHConfigType Settings; diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp index 52815bc1c..16e750d14 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp @@ -673,7 +673,11 @@ static void gfx_opengl_resize_framebuffer(int fb, uint32_t width, uint32_t heigh void gfx_opengl_set_framebuffer(int fb) { - glClipControl(GL_UPPER_LEFT, GL_NEGATIVE_ONE_TO_ONE); // Set origin to upper left corner, to match N64 and DX11 + if (GLEW_ARB_clip_control || GLEW_VERSION_4_5) { + // Set origin to upper left corner, to match N64 and DX11 + // If this function is not supported, the texture will be upside down :( + glClipControl(GL_UPPER_LEFT, GL_NEGATIVE_ONE_TO_ONE); + } glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb); glDepthMask(GL_TRUE); @@ -687,7 +691,9 @@ void gfx_opengl_reset_framebuffer(void) glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer); - glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE); + if (GLEW_ARB_clip_control || GLEW_VERSION_4_5) { + glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE); + } } void gfx_opengl_select_texture_fb(int fbID) diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index 3d6d6800d..47fb57441 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -7,12 +7,8 @@ #include "Window.h" extern "C" uint8_t __osMaxControllers; -float gyroDriftX; -float gyroDriftY; namespace Ship { - - SDLController::SDLController(int32_t dwControllerNumber) : Controller(dwControllerNumber), Cont(nullptr), guid(INVALID_SDL_CONTROLLER_GUID) { } @@ -147,8 +143,8 @@ namespace Ship { //bound diagonals to an octagonal range {-68 ... +68} if (ax != 0.0 && ay != 0.0) { auto slope = ay / ax; - auto edgex = copysign(85.0 / (abs(slope) + wAxisThreshold / 69.0), ax); - auto edgey = copysign(std::min(abs(edgex * slope), 85.0 / (1.0 / abs(slope) + wAxisThreshold / 69.0)), ay); + auto edgex = copysign(85.0 / (abs(slope) + 16.0 / 69.0), ax); + auto edgey = copysign(std::min(abs(edgex * slope), 85.0 / (1.0 / abs(slope) + 16.0 / 69.0)), ay); edgex = edgey / slope; auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0; @@ -186,31 +182,31 @@ namespace Ship { SDL_GameControllerGetSensorData(Cont, SDL_SENSOR_GYRO, gyroData, 3); const char* contName = SDL_GameControllerName(Cont); - const int isSpecialController = strcmp("PS5 Controller", contName); + const int isSpecialController = !strcmp("PS5 Controller", contName); const float gyroSensitivity = Game::Settings.controller.gyro_sensitivity; - if (gyroDriftX == 0) { - if (isSpecialController == 0) { - gyroDriftX = gyroData[2]; + if (Game::Settings.controller.gyroDriftX == 0) { + Game::Settings.controller.gyroDriftX = gyroData[0]; + } + + if (Game::Settings.controller.gyroDriftY == 0) { + if (isSpecialController == 1) { + Game::Settings.controller.gyroDriftY = gyroData[2]; } else { - gyroDriftX = gyroData[0]; + Game::Settings.controller.gyroDriftY = gyroData[1]; } } - if (gyroDriftY == 0) { - gyroDriftY = gyroData[1]; - } - - if (isSpecialController == 0) { - wGyroX = gyroData[2] - gyroDriftX; + if (isSpecialController == 1) { + wGyroX = gyroData[0] - Game::Settings.controller.gyroDriftX; + wGyroY = -gyroData[2] - Game::Settings.controller.gyroDriftY; } else { - wGyroX = gyroData[0] - gyroDriftX; + wGyroX = gyroData[0] - Game::Settings.controller.gyroDriftX; + wGyroY = gyroData[1] - Game::Settings.controller.gyroDriftY; } - wGyroY = gyroData[1] - gyroDriftY; - wGyroX *= gyroSensitivity; wGyroY *= gyroSensitivity; } @@ -340,11 +336,19 @@ namespace Ship { } if (SDL_GameControllerHasLED(Cont)) { - if (controller->ledColor == 1) { + switch (controller->ledColor) { + case 0: SDL_JoystickSetLED(SDL_GameControllerGetJoystick(Cont), 255, 0, 0); - } - else { - SDL_JoystickSetLED(SDL_GameControllerGetJoystick(Cont), 0, 255, 0); + break; + case 1: + SDL_JoystickSetLED(SDL_GameControllerGetJoystick(Cont), 0x1E, 0x69, 0x1B); + break; + case 2: + SDL_JoystickSetLED(SDL_GameControllerGetJoystick(Cont), 0x64, 0x14, 0x00); + break; + case 3: + SDL_JoystickSetLED(SDL_GameControllerGetJoystick(Cont), 0x00, 0x3C, 0x64); + break; } } } @@ -406,4 +410,4 @@ namespace Ship { std::string SDLController::GetBindingConfSection() { return GetControllerType() + " CONTROLLER BINDING " + guid; } -} \ No newline at end of file +} diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 22b47f680..abc51a535 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -306,6 +306,14 @@ namespace SohImGui { if (ImGui::SliderFloat("##GYROSCOPE", &Game::Settings.controller.gyro_sensitivity, 0.0f, 1.0f, "")) { needs_save = true; } + + if (ImGui::Button("Recalibrate Gyro")) { + Game::Settings.controller.gyroDriftX = 0; + Game::Settings.controller.gyroDriftY = 0; + } + + ImGui::Separator(); + ImGui::Text("Rumble Strength: %d %%", static_cast(100 * Game::Settings.controller.rumble_strength)); if (ImGui::SliderFloat("##RUMBLE", &Game::Settings.controller.rumble_strength, 0.0f, 1.0f, "")) { needs_save = true; @@ -350,20 +358,65 @@ namespace SohImGui { needs_save = true; } - ImGui::Text("Debugging"); - ImGui::Separator(); - - if (ImGui::Checkbox("Debug Mode", &Game::Settings.enhancements.debug_mode)) { - CVar_SetS32(const_cast("gDebugEnabled"), Game::Settings.enhancements.debug_mode); - needs_save = true; - } - ImGui::EndMenu(); } if (ImGui::BeginMenu("Developer Tools")) { HOOK(ImGui::MenuItem("Stats", nullptr, &Game::Settings.debug.soh)); HOOK(ImGui::MenuItem("Console", nullptr, &console->opened)); + + ImGui::Text("Debug"); + ImGui::Separator(); + + if (ImGui::Checkbox("Debug Mode", &Game::Settings.cheats.debug_mode)) { + CVar_SetS32(const_cast("gDebugEnabled"), Game::Settings.cheats.debug_mode); + needs_save = true; + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Cheats")) { + if (ImGui::Checkbox("Infinite Money", &Game::Settings.cheats.infinite_money)) { + CVar_SetS32(const_cast("gInfiniteMoney"), Game::Settings.cheats.infinite_money); + needs_save = true; + } + + if (ImGui::Checkbox("Infinite Health", &Game::Settings.cheats.infinite_health)) { + CVar_SetS32(const_cast("gInfiniteHealth"), Game::Settings.cheats.infinite_health); + needs_save = true; + } + + if (ImGui::Checkbox("Infinite Ammo", &Game::Settings.cheats.infinite_ammo)) { + CVar_SetS32(const_cast("gInfiniteAmmo"), Game::Settings.cheats.infinite_ammo); + needs_save = true; + } + + if (ImGui::Checkbox("Infinite Magic", &Game::Settings.cheats.infinite_magic)) { + CVar_SetS32(const_cast("gInfiniteMagic"), Game::Settings.cheats.infinite_magic); + needs_save = true; + } + + if (ImGui::Checkbox("No Clip", &Game::Settings.cheats.no_clip)) { + CVar_SetS32(const_cast("gNoClip"), Game::Settings.cheats.no_clip); + needs_save = true; + } + + if (ImGui::Checkbox("Climb Everything", &Game::Settings.cheats.climb_everything)) { + CVar_SetS32(const_cast("gClimbEverything"), Game::Settings.cheats.climb_everything); + needs_save = true; + } + + if (ImGui::Checkbox("Moon Jump on L", &Game::Settings.cheats.moon_jump_on_l)) { + CVar_SetS32(const_cast("gMoonJumpOnL"), Game::Settings.cheats.moon_jump_on_l); + needs_save = true; + } + + if (ImGui::Checkbox("Super Tunic", &Game::Settings.cheats.super_tunic)) { + CVar_SetS32(const_cast("gSuperTunic"), Game::Settings.cheats.super_tunic); + needs_save = true; + } + ImGui::EndMenu(); } diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 24fda1ade..665483b35 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -39,6 +39,14 @@ extern "C" { exit(EXIT_FAILURE); } + const char* controllerDb = "gamecontrollerdb.txt"; + int mappingsAdded = SDL_GameControllerAddMappingsFromFile(controllerDb); + if (mappingsAdded >= 0) { + SPDLOG_INFO("Added SDL game controllers from \"{}\" ({})", controllerDb, mappingsAdded); + } else { + SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError()); + } + // TODO: This for loop is debug. Burn it with fire. for (size_t i = 0; i < SDL_NumJoysticks(); i++) { if (SDL_IsGameController(i)) { diff --git a/soh/assets/xml/objects/object_triforce_spot.xml b/soh/assets/xml/objects/object_triforce_spot.xml index a9d52dd96..87d449458 100644 --- a/soh/assets/xml/objects/object_triforce_spot.xml +++ b/soh/assets/xml/objects/object_triforce_spot.xml @@ -1,6 +1,6 @@ - + diff --git a/soh/src/code/game.c b/soh/src/code/game.c index ec8a0e9fa..9392cbc25 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -323,6 +323,75 @@ void GameState_Update(GameState* gameState) { GameState_Draw(gameState, gfxCtx); func_800C49F4(gfxCtx); } + + // ----------------------- + // Cheats hooks + // ----------------------- + + // Inf Money + if (CVar_GetS32("gInfiniteMoney", 0) != 0) { + if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) { + gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); + } + } + + // Inf Health + if (CVar_GetS32("gInfiniteHealth", 0) != 0) { + if (gSaveContext.health < gSaveContext.healthCapacity) { + gSaveContext.health = gSaveContext.healthCapacity; + } + } + + // Inf Ammo + if (CVar_GetS32("gInfiniteAmmo", 0) != 0) { + // Deku Sticks + if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) { + AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); + } + + // Deku Nuts + if (AMMO(ITEM_NUT) < CUR_CAPACITY(UPG_NUTS)) { + AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); + } + + // Bombs + if (AMMO(ITEM_BOMB) < CUR_CAPACITY(UPG_BOMB_BAG)) { + AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); + } + + // Fairy Bow (Ammo) + if (AMMO(ITEM_BOW) < CUR_CAPACITY(UPG_QUIVER)) { + AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); + } + + // Fairy Slingshot (Ammo) + if (AMMO(ITEM_SLINGSHOT) < CUR_CAPACITY(UPG_BULLET_BAG)) { + AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG); + } + + // Bombchus (max: 50, no upgrades) + if (AMMO(ITEM_BOMBCHU) < 50) { + AMMO(ITEM_BOMBCHU) = 50; + } + } + + // Inf Magic + if (CVar_GetS32("gInfiniteMagic", 0) != 0) { + if (gSaveContext.magicAcquired && gSaveContext.magic != (gSaveContext.doubleMagic + 1) * 0x30) { + gSaveContext.magic = (gSaveContext.doubleMagic + 1) * 0x30; + } + } + + // Moon Jump On L + if (CVar_GetS32("gMoonJumpOnL", 0) != 0) { + if (gGlobalCtx) { + Player* player = GET_PLAYER(gGlobalCtx); + + if (CHECK_BTN_ANY(gGlobalCtx->state.input[0].cur.button, BTN_L)) { + player->actor.velocity.y = 6.34375f; + } + } + } gameState->frames++; } diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index fb4ceb8e6..973c2b446 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -272,9 +272,19 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) { controllerCallback.rumble = padMgr->rumbleEnable[0] > 0 ? 1 : 0; if (HealthMeter_IsCritical()) { - controllerCallback.ledColor = 1; - } else { controllerCallback.ledColor = 0; + } else if (gGlobalCtx) { + switch (CUR_EQUIP_VALUE(EQUIP_TUNIC) - 1) { + case PLAYER_TUNIC_KOKIRI: + controllerCallback.ledColor = 1; + break; + case PLAYER_TUNIC_GORON: + controllerCallback.ledColor = 2; + break; + case PLAYER_TUNIC_ZORA: + controllerCallback.ledColor = 3; + break; + } } OTRControllerCallback(&controllerCallback); diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index b736d0cf0..9ce139eed 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -1874,6 +1874,10 @@ s32 BgCheck_CheckWallImpl(CollisionContext* colCtx, u16 xpFlags, Vec3f* posResul s32 bgId2; f32 nx, ny, nz; // unit normal of polygon + if (CVar_GetS32("gNoClip", 0) != 0) { + return false; + } + result = false; *outBgId = BGCHECK_SCENE; *outPoly = NULL; @@ -3996,7 +4000,11 @@ u32 func_80041D94(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { * SurfaceType Get Wall Flags */ s32 func_80041DB8(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { - return D_80119D90[func_80041D94(colCtx, poly, bgId)]; + if (CVar_GetS32("gClimbEverything", 0) != 0) { + return (1 << 3) | D_80119D90[func_80041D94(colCtx, poly, bgId)]; + } else { + return D_80119D90[func_80041D94(colCtx, poly, bgId)]; + } } /** diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 3219527a9..8bce65a7b 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -4078,11 +4078,11 @@ void Interface_Update(GlobalContext* globalCtx) { D_80125A58 = func_8008F2F8(globalCtx); if (D_80125A58 == 1) { - if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == 2) { + if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == 2 || CVar_GetS32("gSuperTunic", 0) != 0) { D_80125A58 = 0; } } else if ((func_8008F2F8(globalCtx) >= 2) && (func_8008F2F8(globalCtx) < 5)) { - if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == 3) { + if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == 3 || CVar_GetS32("gSuperTunic", 0) != 0) { D_80125A58 = 0; } } diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index e15cc81eb..d7344d7c3 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -631,9 +631,9 @@ s32 func_8008F2F8(GlobalContext* globalCtx) { if (0) {} if ((triggerEntry->flag != 0) && !(gSaveContext.textTriggerFlags & triggerEntry->flag) && - (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON)) || + (((var == 0) && (this->currentTunic != PLAYER_TUNIC_GORON && CVar_GetS32("gSuperTunic", 0) == 0)) || (((var == 1) || (var == 3)) && (this->currentBoots == PLAYER_BOOTS_IRON) && - (this->currentTunic != PLAYER_TUNIC_ZORA)))) { + (this->currentTunic != PLAYER_TUNIC_ZORA && CVar_GetS32("gSuperTunic", 0) == 0)))) { Message_StartTextbox(globalCtx, triggerEntry->textId, NULL); gSaveContext.textTriggerFlags |= triggerEntry->flag; } @@ -1590,7 +1590,7 @@ void func_80091A24(GlobalContext* globalCtx, void* seg04, void* seg06, SkelAnime sp12C[0] = sword; sp12C[1] = shield; - Matrix_SetTranslateRotateYXZ(pos->x - (LINK_AGE_IN_YEARS == YEARS_ADULT ? 25 : 0), + Matrix_SetTranslateRotateYXZ(pos->x - ((CVar_GetS32("gPauseLiveLink", 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0), pos->y - (CVar_GetS32("gPauseTriforce", 0) ? 16 : 0), pos->z, rot); Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c index 1b89b7b8d..620463b04 100644 --- a/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c +++ b/soh/src/overlays/actors/ovl_En_Kusa/z_en_kusa.c @@ -300,7 +300,7 @@ void EnKusa_Main(EnKusa* this, GlobalContext* globalCtx) { if (Actor_HasParent(&this->actor, globalCtx)) { EnKusa_SetupLiftedUp(this); SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_PL_PULL_UP_PLANT); - } else if (this->collider.base.acFlags & AC_HIT) { + } else if (this->collider.base.acFlags & AC_HIT && gGlobalCtx->csCtx.state == 0) { this->collider.base.acFlags &= ~AC_HIT; EnKusa_SpawnFragments(this, globalCtx); EnKusa_DropCollectible(this, globalCtx); 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 d02788a8e..37ab3ed74 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2321,9 +2321,7 @@ s32 func_8083501C(Player* this, GlobalContext* globalCtx) { if ((!Player_HoldsHookshot(this) || func_80834FBC(this)) && !func_80834758(globalCtx, this) && !func_80834F2C(this, globalCtx)) { return 0; - } - else - { + } else if (this->rideActor != NULL) { this->unk_6AD = 2; // OTRTODO: THIS IS A BAD IDEA BUT IT FIXES THE HORSE FIRST PERSON? } @@ -3842,12 +3840,12 @@ s32 func_808382DC(Player* this, GlobalContext* globalCtx) { s32 sp48 = func_80838144(D_808535E4); if (((this->actor.wallPoly != NULL) && - SurfaceType_IsWallDamage(&globalCtx->colCtx, this->actor.wallPoly, this->actor.wallBgId)) || + SurfaceType_IsWallDamage(&globalCtx->colCtx, this->actor.wallPoly, this->actor.wallBgId)) || ((sp48 >= 0) && SurfaceType_IsWallDamage(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId) && (this->unk_A79 >= D_808544F4[sp48])) || ((sp48 >= 0) && - ((this->currentTunic != PLAYER_TUNIC_GORON) || (this->unk_A79 >= D_808544F4[sp48])))) { + ((this->currentTunic != PLAYER_TUNIC_GORON && CVar_GetS32("gSuperTunic", 0) == 0) || (this->unk_A79 >= D_808544F4[sp48])))) { this->unk_A79 = 0; this->actor.colChkInfo.damage = 4; func_80837C0C(globalCtx, this, 0, 4.0f, 5.0f, this->actor.shape.rot.y, 20); @@ -4632,7 +4630,7 @@ s32 func_8083A6AC(Player* this, GlobalContext* globalCtx) { if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &this->actor.world.pos, &sp74, &sp68, &sp84, true, false, false, true, &sp80) && - (ABS(sp84->normal.y) < 600)) { + ((ABS(sp84->normal.y) < 600) || (CVar_GetS32("gClimbEverything", 0) != 0))) { f32 nx = COLPOLY_GET_NORMAL(sp84->normal.x); f32 ny = COLPOLY_GET_NORMAL(sp84->normal.y); f32 nz = COLPOLY_GET_NORMAL(sp84->normal.z); @@ -8152,7 +8150,7 @@ static struct_80832924 D_808545F0[] = { }; void func_80843CEC(Player* this, GlobalContext* globalCtx) { - if (this->currentTunic != PLAYER_TUNIC_GORON) { + if (this->currentTunic != PLAYER_TUNIC_GORON && CVar_GetS32("gSuperTunic", 0) == 0) { if ((globalCtx->roomCtx.curRoom.unk_02 == 3) || (D_808535E4 == 9) || ((func_80838144(D_808535E4) >= 0) && !SurfaceType_IsWallDamage(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId))) { @@ -9888,7 +9886,7 @@ void func_80847BA0(GlobalContext* globalCtx, Player* this) { if ((this->actor.bgCheckFlags & 0x200) && (D_80853608 < 0x3000)) { CollisionPoly* wallPoly = this->actor.wallPoly; - if (ABS(wallPoly->normal.y) < 600) { + if ((ABS(wallPoly->normal.y) < 600) || (CVar_GetS32("gClimbEverything", 0) != 0)) { f32 sp8C = COLPOLY_GET_NORMAL(wallPoly->normal.x); f32 sp88 = COLPOLY_GET_NORMAL(wallPoly->normal.y); f32 sp84 = COLPOLY_GET_NORMAL(wallPoly->normal.z); @@ -10188,7 +10186,7 @@ void func_80848C74(GlobalContext* globalCtx, Player* this) { s32 sp58; s32 sp54; - if (this->currentTunic == PLAYER_TUNIC_GORON) { + if (this->currentTunic == PLAYER_TUNIC_GORON || CVar_GetS32("gSuperTunic", 0) != 0) { sp54 = 20; } else { @@ -14806,4 +14804,4 @@ void func_80853148(GlobalContext* globalCtx, Actor* actor) { this->naviActor->flags |= ACTOR_FLAG_8; func_80835EA4(globalCtx, 0xB); } -} \ No newline at end of file +}