2025-08-08 10:55:54 +02:00
# define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
2025-07-30 14:26:54 +02:00
# define IMGUI_HAS_DOCK 1
# include <imgui.h>
# include <reshade.hpp>
# include <fstream>
# include <string>
# include <Windows.h>
# include <thread>
# include <chrono>
// Core game dll functions declarations
typedef void ( * SetBoolFn ) ( bool , bool ) ;
typedef void ( * SetIntFn ) ( int ) ;
typedef float ( * GetFloatFn ) ( ) ;
typedef void ( * InitDLL ) ( ) ;
static HMODULE fixLib = nullptr ;
static SetBoolFn SetFixEnabled = nullptr ;
2025-08-08 10:55:54 +02:00
static SetBoolFn SetARAxisConstrainFixEnabled = nullptr ;
2025-07-30 14:26:54 +02:00
static SetBoolFn SetDOFFixEnabled = nullptr ;
2025-08-08 10:55:54 +02:00
static SetBoolFn SetVignettingFixEnabled = nullptr ;
static SetBoolFn SetFogFixEnabled = nullptr ;
2025-07-30 14:26:54 +02:00
static InitDLL InitializeLogger = nullptr ;
// Plugin variables for checkboxes and sliders
static bool fov_fix_enabled = false ;
2025-08-08 10:55:54 +02:00
static bool AR_Axis_constrain_fix_enabled = false ;
2025-07-30 14:26:54 +02:00
static bool DOF_fix_enabled = false ;
2025-08-08 10:55:54 +02:00
static bool Vignetting_fix_enabled = false ;
static bool Fog_fix_enabled = false ;
2025-07-30 14:26:54 +02:00
static bool fix_enabled = false ;
static bool popup_Informations = false ;
// Plugin settings
const char * SETTINGS_FILE = " PluginSettings.ini " ;
const char * GENERAL_FIX_SETTING = " GeneralFIX= " ;
2025-08-08 10:55:54 +02:00
const char * AR_AXIS_CONSTRAIN_FIX_SETTING = " ARAxisConstrainFIX= " ;
2025-07-30 14:26:54 +02:00
const char * DOF_FIX_SETTING = " DOFFIX= " ;
2025-08-08 10:55:54 +02:00
const char * VIGNETTING_FIX_SETTING = " VignettingFIX= " ;
const char * FOG_FIX_SETTING = " FogFIX= " ;
2025-07-30 14:26:54 +02:00
const char * FIX_VERSION = " 1.0.1 " ;
2025-08-08 10:55:54 +02:00
const char * FIX_INFORMATIONS = " This fix allows to: \n - Enable HOR+. \n - Disable depth of field. \n - Disable vignetting. \n - Disbale FOG. \n \n Enabling HOR + may over compensate FOV in game. \n Disabling Fog will not entirely remove it. " ;
2025-07-30 14:26:54 +02:00
const char * DONATION_URL = " https://buymeacoffee.com/k4sh44 " ;
2025-08-08 10:55:54 +02:00
// Ensure that our Core DLL will be called only once
bool IsAlreadyInitialized ( )
{
// Declare a lock
HANDLE hMap = OpenFileMappingA ( FILE_MAP_ALL_ACCESS , FALSE , " Local \\ WuchangFixSharedSection " ) ;
// If lock is not yet initialized
if ( hMap = = nullptr )
{
// We create the lock only once
hMap = CreateFileMappingA ( INVALID_HANDLE_VALUE , nullptr , PAGE_READWRITE , 0 , 1 , " Local \\ WuchangFixSharedSection " ) ;
if ( hMap = = nullptr ) // We ensure the lock is valid
return true ;
return false ; // First time created we return false
}
// Otherwise we return true
CloseHandle ( hMap ) ;
return true ;
}
2025-07-30 14:26:54 +02:00
// Load and unload game core dll functions /!\ necessary
static void LoadFixDLL ( )
{
2025-08-08 10:55:54 +02:00
if ( IsAlreadyInitialized ( ) )
return ; // déjà lancé dans un autre chargement
2025-07-30 14:26:54 +02:00
std : : thread ( [ ] ( ) {
2025-08-08 10:55:54 +02:00
// Game process is not ready at launch and memory is not yet initialized
// We do want the core dll to be called and initialized a few seconds after game launch
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 6000 ) ) ;
2025-07-30 14:26:54 +02:00
if ( GetModuleHandleA ( " WuchangFFCore.dll " ) = = nullptr ) {
fixLib = LoadLibraryA ( " WuchangFFCore.dll " ) ;
if ( ! fixLib ) {
MessageBoxA ( nullptr , " Impossible to load game core dll " , " Erreur " , MB_OK ) ;
return ;
}
SetFixEnabled = ( SetBoolFn ) GetProcAddress ( fixLib , " SetFixEnabled " ) ;
2025-08-08 10:55:54 +02:00
SetARAxisConstrainFixEnabled = ( SetBoolFn ) GetProcAddress ( fixLib , " SetARAxisConstrainFixEnabled " ) ;
2025-07-30 14:26:54 +02:00
SetDOFFixEnabled = ( SetBoolFn ) GetProcAddress ( fixLib , " SetDOFFixEnabled " ) ;
2025-08-08 10:55:54 +02:00
SetVignettingFixEnabled = ( SetBoolFn ) GetProcAddress ( fixLib , " SetVignettingFixEnabled " ) ;
SetFogFixEnabled = ( SetBoolFn ) GetProcAddress ( fixLib , " SetFogFixEnabled " ) ;
2025-07-30 14:26:54 +02:00
// Apply initial values loaded from settings
2025-08-08 10:55:54 +02:00
if ( SetARAxisConstrainFixEnabled ) SetARAxisConstrainFixEnabled ( AR_Axis_constrain_fix_enabled , true ) ;
if ( SetDOFFixEnabled ) SetDOFFixEnabled ( DOF_fix_enabled , true ) ;
if ( SetVignettingFixEnabled ) SetVignettingFixEnabled ( Vignetting_fix_enabled , true ) ;
if ( SetFogFixEnabled ) SetFogFixEnabled ( Fog_fix_enabled , true ) ;
2025-07-30 14:26:54 +02:00
if ( SetFixEnabled ) SetFixEnabled ( fix_enabled , true ) ;
}
2025-08-08 10:55:54 +02:00
} ) . detach ( ) ; // This thread will not block others
2025-07-30 14:26:54 +02:00
}
// Addon functions
static void SaveSettings ( )
{
std : : ofstream file ( SETTINGS_FILE ) ;
if ( file . is_open ( ) )
{
file < < GENERAL_FIX_SETTING < < ( fix_enabled ? " 1 " : " 0 " ) < < " \n " ;
2025-08-08 10:55:54 +02:00
file < < AR_AXIS_CONSTRAIN_FIX_SETTING < < ( AR_Axis_constrain_fix_enabled ? " 1 " : " 0 " ) < < " \n " ;
2025-07-30 14:26:54 +02:00
file < < DOF_FIX_SETTING < < ( DOF_fix_enabled ? " 1 " : " 0 " ) < < " \n " ;
2025-08-08 10:55:54 +02:00
file < < VIGNETTING_FIX_SETTING < < ( Vignetting_fix_enabled ? " 1 " : " 0 " ) < < " \n " ;
file < < FOG_FIX_SETTING < < ( Fog_fix_enabled ? " 1 " : " 0 " ) < < " \n " ;
2025-07-30 14:26:54 +02:00
file . close ( ) ;
}
}
static void LoadSettings ( )
{
std : : ifstream file ( SETTINGS_FILE ) ;
if ( file . is_open ( ) )
{
std : : string line ;
while ( std : : getline ( file , line ) )
{
if ( line . find ( GENERAL_FIX_SETTING ) = = 0 )
{
std : : string val = line . substr ( strlen ( GENERAL_FIX_SETTING ) ) ;
fix_enabled = ( val = = " 1 " | | val = = " true " ) ;
}
2025-08-08 10:55:54 +02:00
else if ( line . find ( AR_AXIS_CONSTRAIN_FIX_SETTING ) = = 0 )
2025-07-30 14:26:54 +02:00
{
2025-08-08 10:55:54 +02:00
std : : string val = line . substr ( strlen ( AR_AXIS_CONSTRAIN_FIX_SETTING ) ) ;
AR_Axis_constrain_fix_enabled = ( val = = " 1 " | | val = = " true " ) ;
2025-07-30 14:26:54 +02:00
}
else if ( line . find ( DOF_FIX_SETTING ) = = 0 )
{
std : : string val = line . substr ( strlen ( DOF_FIX_SETTING ) ) ;
DOF_fix_enabled = ( val = = " 1 " | | val = = " true " ) ;
}
2025-08-08 10:55:54 +02:00
else if ( line . find ( VIGNETTING_FIX_SETTING ) = = 0 )
{
std : : string val = line . substr ( strlen ( VIGNETTING_FIX_SETTING ) ) ;
Vignetting_fix_enabled = ( val = = " 1 " | | val = = " true " ) ;
}
else if ( line . find ( FOG_FIX_SETTING ) = = 0 )
{
std : : string val = line . substr ( strlen ( FOG_FIX_SETTING ) ) ;
Fog_fix_enabled = ( val = = " 1 " | | val = = " true " ) ;
}
2025-07-30 14:26:54 +02:00
}
file . close ( ) ;
}
}
static void displayFixInformations ( ) {
// Fix version
ImGui : : Begin ( " Informations " , & popup_Informations ) ; //
ImGui : : SetCursorPos ( ImVec2 ( 10 , 36 ) ) ;
ImGui : : Text ( " Version : %s " , FIX_VERSION ) ;
ImGui : : SetCursorPos ( ImVec2 ( 10 , 76 ) ) ;
ImGui : : Text ( FIX_INFORMATIONS ) ;
ImGui : : End ( ) ;
}
// Initialize ImGui widgets for Reshade
static void on_overlay_draw ( reshade : : api : : effect_runtime * runtime )
{
ImGui : : SetNextWindowPos ( ImVec2 ( 100 , 200 ) , ImGuiCond_Once ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( 350 , 150 ) , ImGuiCond_Once ) ;
// Donation ?
ImGui : : SetCursorPos ( ImVec2 ( 10 , 36 ) ) ;
ImGui : : Text ( " Like my work ? " ) ;
ImGui : : SetCursorPos ( ImVec2 ( 130 , 33 ) ) ;
if ( ImGui : : Button ( " consider donation " ) )
{
ShellExecuteA ( NULL , " open " , DONATION_URL , NULL , NULL , SW_SHOWNORMAL ) ;
}
// Fix informations
ImGui : : SetCursorPos ( ImVec2 ( 270 , 33 ) ) ;
if ( ImGui : : Button ( " Fix informations " ) )
popup_Informations = true ;
if ( popup_Informations )
displayFixInformations ( ) ;
// Generic fix
ImGui : : SetCursorPos ( ImVec2 ( 10 , 60 ) ) ;
ImGui : : BeginChild ( " AllFixesHeader " , ImVec2 ( 220 , 0 ) , false ) ; // true = border
if ( ImGui : : CollapsingHeader ( " Enable fixes " , ImGuiTreeNodeFlags_DefaultOpen ) ) {
ImGui : : SetCursorPos ( ImVec2 ( 5 , 30 ) ) ;
if ( ImGui : : Checkbox ( " Fix enabled " , & fix_enabled ) ) {
if ( SetFixEnabled ) SetFixEnabled ( fix_enabled , false ) ;
SaveSettings ( ) ;
}
}
ImGui : : EndChild ( ) ;
// Individual fixes
ImGui : : SetCursorPos ( ImVec2 ( 240 , 60 ) ) ;
ImGui : : BeginChild ( " IndividualFixesHeader " , ImVec2 ( 250 , 0 ) , false ) ;
if ( ImGui : : CollapsingHeader ( " Individual fixes " , ImGuiTreeNodeFlags_DefaultOpen ) ) {
ImGui : : SetCursorPos ( ImVec2 ( 5 , 30 ) ) ;
2025-08-08 10:55:54 +02:00
if ( ImGui : : Checkbox ( " Enable HOR+ " , & AR_Axis_constrain_fix_enabled ) ) {
if ( SetARAxisConstrainFixEnabled ) SetARAxisConstrainFixEnabled ( AR_Axis_constrain_fix_enabled , false ) ;
2025-07-30 14:26:54 +02:00
SaveSettings ( ) ;
}
ImGui : : SetCursorPos ( ImVec2 ( 5 , 55 ) ) ;
2025-08-08 10:55:54 +02:00
if ( ImGui : : Checkbox ( " Depth of field Fix " , & DOF_fix_enabled ) ) {
if ( SetDOFFixEnabled ) SetDOFFixEnabled ( DOF_fix_enabled , false ) ;
2025-07-30 14:26:54 +02:00
SaveSettings ( ) ;
}
ImGui : : SetCursorPos ( ImVec2 ( 5 , 80 ) ) ;
2025-08-08 10:55:54 +02:00
if ( ImGui : : Checkbox ( " Vignetting Fix " , & Vignetting_fix_enabled ) ) {
if ( SetVignettingFixEnabled ) SetVignettingFixEnabled ( Vignetting_fix_enabled , false ) ;
2025-07-30 14:26:54 +02:00
SaveSettings ( ) ;
}
2025-08-08 10:55:54 +02:00
ImGui : : SetCursorPos ( ImVec2 ( 5 , 105 ) ) ;
if ( ImGui : : Checkbox ( " Fog Fix " , & Fog_fix_enabled ) ) {
if ( SetFogFixEnabled ) SetFogFixEnabled ( Fog_fix_enabled , false ) ;
SaveSettings ( ) ;
}
2025-07-30 14:26:54 +02:00
}
ImGui : : EndChild ( ) ;
}
// Main dll intrance
BOOL WINAPI DllMain ( HINSTANCE hinstDLL , DWORD ul_reason_for_call , LPVOID )
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH :
if ( ! reshade : : register_addon ( hinstDLL ) )
return FALSE ;
LoadSettings ( ) ;
reshade : : register_overlay ( " Wuchang Fallen Feathers " , & on_overlay_draw ) ;
2025-08-06 09:46:07 +02:00
reshade : : register_event < reshade : : addon_event : : init_effect_runtime > (
[ ] ( reshade : : api : : effect_runtime * runtime ) {
2025-07-30 14:26:54 +02:00
LoadFixDLL ( ) ;
} ) ;
break ;
case DLL_PROCESS_DETACH :
reshade : : unregister_addon ( hinstDLL ) ;
break ;
2025-08-08 10:55:54 +02:00
}
2025-07-30 14:26:54 +02:00
return TRUE ;
}