From 0f811969e2146360bdc3fa5dee4dcd6911ce73f3 Mon Sep 17 00:00:00 2001 From: CosmosXIII Date: Sun, 29 Aug 2021 19:02:36 +0900 Subject: [PATCH] FF7: Implemented analogue controls in fields --- misc/FFNx.toml | 9 ++++ src/cfg.cpp | 2 + src/cfg.h | 1 + src/ff7/misc.cpp | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) diff --git a/misc/FFNx.toml b/misc/FFNx.toml index be8e333f..adb7d5c1 100644 --- a/misc/FFNx.toml +++ b/misc/FFNx.toml @@ -208,6 +208,15 @@ enable_ffmpeg_videos = -1 #~~~~~~~~~~~~~~~~~~~~~~~~~~~ ffmpeg_video_ext = "avi" +########################### +# Controller Options +########################### + +#[ANALOGUE CONTROLS] +# This flag will enable analogue joystick input for controlling the player. +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +enable_analogue_controls = false + ############################### # MUST SET FOR VERSIONS BELOW # FF7 2012 FF7 STEAM diff --git a/src/cfg.cpp b/src/cfg.cpp index 04d9c7f1..99c11bc9 100644 --- a/src/cfg.cpp +++ b/src/cfg.cpp @@ -99,6 +99,7 @@ double speedhack_min; bool enable_animated_textures; long ff7_fps_limiter; bool ff7_footsteps; +bool enable_analogue_controls; std::vector get_string_or_array_of_strings(const toml::node_view &node) { @@ -212,6 +213,7 @@ void read_cfg() enable_animated_textures = config["enable_animated_textures"].value_or(false); ff7_fps_limiter = config["ff7_fps_limiter"].value_or(FF7_LIMITER_DEFAULT); ff7_footsteps = config["ff7_footsteps"].value_or(false); + enable_analogue_controls = config["enable_analogue_controls"].value_or(false); // Windows x or y size can't be less then 0 if (window_size_x < 0) window_size_x = 0; diff --git a/src/cfg.h b/src/cfg.h index f788b0cc..cf823e67 100644 --- a/src/cfg.h +++ b/src/cfg.h @@ -112,5 +112,6 @@ extern double speedhack_min; extern bool enable_animated_textures; extern long ff7_fps_limiter; extern bool ff7_footsteps; +extern bool enable_analogue_controls; void read_cfg(); diff --git a/src/ff7/misc.cpp b/src/ff7/misc.cpp index 2304138c..e2275b31 100644 --- a/src/ff7/misc.cpp +++ b/src/ff7/misc.cpp @@ -94,6 +94,107 @@ void ff7_wm_activateapp(bool hasFocus) } +int ff7_get_control_direction() +{ + byte* level_data = *ff7_externals.field_level_data_pointer; + + if (level_data != nullptr) + { + uint32_t triggers_offset = *(uint32_t*)(level_data + 0x22); + signed short* control_direction_data = (signed short*)(level_data + triggers_offset + 4 + 9); + + return static_cast(*control_direction_data); + } + + return 0; +} + +void ff7_set_control_direction(int x) +{ + byte* level_data = *ff7_externals.field_level_data_pointer; + + if (level_data != nullptr) + { + uint32_t triggers_offset = *(uint32_t*)(level_data + 0x22); + signed short* control_direction_data = (signed short*)(level_data + triggers_offset + 4 + 9); + + *control_direction_data = static_cast(x); + } +} + +void ff7_use_analogue_controls() +{ + static WORD last_field_id = 0; + static int base_control_direction = 0; + if (last_field_id != *ff7_externals.field_id) + { + last_field_id = *ff7_externals.field_id; + base_control_direction = ff7_get_control_direction(); + } + + point3d joyDir = {0.0f, 0.0f, 0.0f}; + point3d inputDir = {0.0f, 0.0f, 0.0f}; + if(xinput_connected) + { + joyDir = {gamepad.leftStickX, gamepad.leftStickY, 0.0f}; + + if(gamepad.leftStickY > 0.5f && !(gamepad.leftStickX < -0.5f || gamepad.leftStickX > 0.5f)) + inputDir = {0.0f, 1.0f, 0.0f}; + else if(gamepad.leftStickY > 0.5f && gamepad.leftStickX < -0.5f) + inputDir = {-0.707f, 0.707f, 0.0f}; + else if(gamepad.leftStickY > 0.5f && gamepad.leftStickX > 0.5f) + inputDir = {0.707f, 0.707f, 0.0f}; + else if(gamepad.leftStickX < -0.5f &&!(gamepad.leftStickY > 0.5f || gamepad.leftStickY < -0.5f)) + inputDir = {-1.0f, 0.0f, 0.0f}; + else if(gamepad.leftStickX > 0.5f && !(gamepad.leftStickY > 0.5f || gamepad.leftStickY < -0.5f)) + inputDir = {1.0f, 0.0f, 0.0f}; + else if(gamepad.leftStickY < -0.5f && gamepad.leftStickX < -0.5f) + inputDir = {-0.707f, -0.707f, 0.0f}; + else if(gamepad.leftStickY < -0.5f && gamepad.leftStickX > 0.5f) + inputDir = {0.707f, -0.707f, 0.0f}; + else if(gamepad.leftStickY < -0.5f && !(gamepad.leftStickX < -0.5f || gamepad.leftStickX > 0.5f)) + inputDir = {0.0f, -1.0f, 0.0f}; + } + else + { + joyDir = {static_cast(joystick.GetState()->lX), -static_cast(joystick.GetState()->lY), 0.0f}; + + if(joystick.GetState()->lY < joystick.GetDeadZone(-0.5f) && + !(joystick.GetState()->lX < joystick.GetDeadZone(-0.5f) || joystick.GetState()->lX > joystick.GetDeadZone(0.5f))) + inputDir = {0.0f, 1.0f, 0.0f}; + else if(joystick.GetState()->lY < joystick.GetDeadZone(-0.5f) && joystick.GetState()->lX < joystick.GetDeadZone(-0.5f)) + inputDir = {-0.707f, 0.707f, 0.0f}; + else if(joystick.GetState()->lY < joystick.GetDeadZone(-0.5f) && joystick.GetState()->lX > joystick.GetDeadZone(0.5f)) + inputDir = {0.707f, 0.707f, 0.0f}; + else if(joystick.GetState()->lX < joystick.GetDeadZone(-0.5f) && + !(joystick.GetState()->lY < joystick.GetDeadZone(-0.5f) || joystick.GetState()->lY > joystick.GetDeadZone(0.5f))) + inputDir = {-1.0f, 0.0f, 0.0f}; + else if(joystick.GetState()->lX > joystick.GetDeadZone(0.5f) && + !(joystick.GetState()->lY < joystick.GetDeadZone(-0.5f) || joystick.GetState()->lY > joystick.GetDeadZone(0.5f))) + inputDir = {1.0f, 0.0f, 0.0f}; + else if(joystick.GetState()->lY > joystick.GetDeadZone(0.5f) && joystick.GetState()->lX < joystick.GetDeadZone(-0.5f)) + inputDir = {-0.707f, -0.707f, 0.0f}; + else if(joystick.GetState()->lY > joystick.GetDeadZone(0.5f) && joystick.GetState()->lX > joystick.GetDeadZone(0.5f)) + inputDir = {0.707f, -0.707f, 0.0f}; + else if(joystick.GetState()->lY > joystick.GetDeadZone(0.5f) && + !(joystick.GetState()->lX < joystick.GetDeadZone(-0.5f) || joystick.GetState()->lX > joystick.GetDeadZone(0.5f))) + inputDir = {0.0f, -1.0f, 0.0f}; + } + + float inputDirLength = vector_length(&inputDir); + if(inputDirLength > 0.0f) + { + normalize_vector(&joyDir); + float angle = atan2( inputDir.x*joyDir.y - inputDir.y*joyDir.x, inputDir.x*joyDir.x + inputDir.y*joyDir.y ); + int offset = std::max(-128, std::min(128, static_cast(128.0f * angle / M_PI))); + ff7_set_control_direction(base_control_direction + offset); + } + else + { + ff7_set_control_direction(base_control_direction); + } +} + int ff7_get_gamepad() { if (simulate_OK_button) @@ -148,6 +249,8 @@ struct ff7_gamepad_status* ff7_update_gamepad_status() { if (gamepad.Refresh()) { + if(enable_analogue_controls) ff7_use_analogue_controls(); + ff7_externals.gamepad_status->pos_x = gamepad.leftStickX; ff7_externals.gamepad_status->pos_y = gamepad.leftStickY; ff7_externals.gamepad_status->dpad_up = (gamepad.leftStickY > 0.5f) || gamepad.IsPressed(XINPUT_GAMEPAD_DPAD_UP); // UP @@ -173,6 +276,8 @@ struct ff7_gamepad_status* ff7_update_gamepad_status() { if (joystick.Refresh()) { + if(enable_analogue_controls) ff7_use_analogue_controls(); + ff7_externals.gamepad_status->pos_x = joystick.GetState()->lX; ff7_externals.gamepad_status->pos_y = joystick.GetState()->lY; ff7_externals.gamepad_status->dpad_up = (joystick.GetState()->lY < joystick.GetDeadZone(-0.5f)) || joystick.GetState()->rgdwPOV[0] == 0; // UP