Merge branch 'develop' into pausedpadnav

This commit is contained in:
Josh Bodner 2022-03-30 21:08:21 -07:00
commit bc1861a569
18 changed files with 371 additions and 119 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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
{

View File

@ -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<char*>("gPauseLiveLink"), Settings.enhancements.animated_pause_menu);
Settings.enhancements.debug_mode = stob(Conf[EnhancementSection]["debug_mode"]);
CVar_SetS32(const_cast<char*>("gDebugEnabled"), Settings.enhancements.debug_mode);
// Audio
Settings.audio.master = Ship::stof(Conf[AudioSection]["master"]);
CVar_SetFloat(const_cast<char*>("gGameMasterVolume"), Settings.audio.master);
@ -75,6 +74,7 @@ namespace Game {
Settings.audio.fanfare = Ship::stof(Conf[AudioSection]["fanfare"]);
CVar_SetFloat(const_cast<char*>("gFanfareVolume"), Settings.audio.fanfare);
// Controllers
Settings.controller.gyro_sensitivity = Ship::stof(Conf[ControllerSection]["gyro_sensitivity"]);
CVar_SetFloat(const_cast<char*>("gGyroSensitivity"), Settings.controller.gyro_sensitivity);
@ -87,6 +87,34 @@ namespace Game {
Settings.controller.input_enabled = stob(Conf[ControllerSection]["input_enabled"]);
CVar_SetS32(const_cast<char*>("gInputEnabled"), Settings.controller.input_enabled);
// Cheats
Settings.cheats.debug_mode = stob(Conf[CheatSection]["debug_mode"]);
CVar_SetS32(const_cast<char*>("gDebugEnabled"), Settings.cheats.debug_mode);
Settings.cheats.infinite_money = stob(Conf[CheatSection]["infinite_money"]);
CVar_SetS32(const_cast<char*>("gInfiniteMoney"), Settings.cheats.infinite_money);
Settings.cheats.infinite_health = stob(Conf[CheatSection]["infinite_health"]);
CVar_SetS32(const_cast<char*>("gInfiniteHealth"), Settings.cheats.infinite_health);
Settings.cheats.infinite_ammo = stob(Conf[CheatSection]["infinite_ammo"]);
CVar_SetS32(const_cast<char*>("gInfiniteAmmo"), Settings.cheats.infinite_ammo);
Settings.cheats.infinite_magic = stob(Conf[CheatSection]["infinite_magic"]);
CVar_SetS32(const_cast<char*>("gInfiniteMagic"), Settings.cheats.infinite_magic);
Settings.cheats.no_clip = stob(Conf[CheatSection]["no_clip"]);
CVar_SetS32(const_cast<char*>("gNoClip"), Settings.cheats.no_clip);
Settings.cheats.climb_everything = stob(Conf[CheatSection]["climb_everything"]);
CVar_SetS32(const_cast<char*>("gClimbEverything"), Settings.cheats.climb_everything);
Settings.cheats.moon_jump_on_l = stob(Conf[CheatSection]["moon_jump_on_l"]);
CVar_SetS32(const_cast<char*>("gMoonJumpOnL"), Settings.cheats.moon_jump_on_l);
Settings.cheats.super_tunic = stob(Conf[CheatSection]["super_tunic"]);
CVar_SetS32(const_cast<char*>("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();
}

View File

@ -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;

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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<int>(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<char*>("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<char*>("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<char*>("gInfiniteMoney"), Game::Settings.cheats.infinite_money);
needs_save = true;
}
if (ImGui::Checkbox("Infinite Health", &Game::Settings.cheats.infinite_health)) {
CVar_SetS32(const_cast<char*>("gInfiniteHealth"), Game::Settings.cheats.infinite_health);
needs_save = true;
}
if (ImGui::Checkbox("Infinite Ammo", &Game::Settings.cheats.infinite_ammo)) {
CVar_SetS32(const_cast<char*>("gInfiniteAmmo"), Game::Settings.cheats.infinite_ammo);
needs_save = true;
}
if (ImGui::Checkbox("Infinite Magic", &Game::Settings.cheats.infinite_magic)) {
CVar_SetS32(const_cast<char*>("gInfiniteMagic"), Game::Settings.cheats.infinite_magic);
needs_save = true;
}
if (ImGui::Checkbox("No Clip", &Game::Settings.cheats.no_clip)) {
CVar_SetS32(const_cast<char*>("gNoClip"), Game::Settings.cheats.no_clip);
needs_save = true;
}
if (ImGui::Checkbox("Climb Everything", &Game::Settings.cheats.climb_everything)) {
CVar_SetS32(const_cast<char*>("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<char*>("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<char*>("gSuperTunic"), Game::Settings.cheats.super_tunic);
needs_save = true;
}
ImGui::EndMenu();
}

View File

@ -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)) {

View File

@ -1,6 +1,6 @@
<Root>
<File Name="object_triforce_spot" Segment="6">
<Array Name="gTriforceVtx" Count="32" Offset="0x0000">
<Array Name="gTriforceVtx" Count="96" Offset="0x0000">
<Vtx/>
</Array>

View File

@ -324,6 +324,75 @@ void GameState_Update(GameState* gameState) {
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++;
}

View File

@ -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);

View File

@ -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)];
}
}
/**

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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 {