Add HUD scaling fix. Remove stealth cheat for boss

This commit is contained in:
2026-03-13 16:03:06 +01:00
parent c169118a5c
commit 69f879331a

View File

@@ -1,6 +1,7 @@
#include "CommonHeaders.h"
#include "UEngine.hpp"
#include "UETools.hpp"
#include "UEWidgets.hpp"
#include "UEvars.hpp"
#include "Logger.hpp"
#include "SDK/Basic.hpp"
@@ -8,15 +9,21 @@
#include "SDK/BP_CombatCharacter_Player_Final_classes.hpp"
#include "SDK/ExtendedStatComponent_Stamina_classes.hpp"
#include "SDK/Impl_BaseAIController_classes.hpp"
#include "SDK/WB_MainUI_classes.hpp"
#include "SDK/WB_ShowAddItemMain_New_classes.hpp"
#include "SDK/WB_NewHelpBlock_classes.hpp"
#include "SDK/WB_GameSaving_classes.hpp"
#include "SDK/WB_PoseMain_classes.hpp"
#include "SDK/WB_PlayerCoins_classes.hpp"
#include "SDK/WB_NewPlayerGuidelines_classes.hpp"
using namespace SDK;
// Constants
const std::string PLUGIN_NAME = "WuchangFF";
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
constexpr ULONGLONG DEFAULT_DELAY_BETWEEN_TICK = 500; // Used ProcessEvent tick
constexpr ULONGLONG DEFAULT_DELAY_BETWEEN_TICK = 1000; // Used ProcessEvent tick
constexpr ULONGLONG DEFAULT_DELAY_BETWEEN_ACTOR_TICK = 30; // Used for enemies tick
// Logger
std::shared_ptr<spdlog::logger> logger;
@@ -44,6 +51,7 @@ static std::atomic<bool> g_Stamina_fix_enabled = false;
static std::atomic<bool> g_Stealth_fix_enabled = false;
static int g_AdditionalFOVValue = 0;
static float g_CameraMultiplier = 1.f;
static int g_HUDOffsets = 0;
static float g_WorldTimeDilationValue = 1.f;
static float g_AITimeDilationValue = 1.f;
static bool user_inputs_logged = false;
@@ -77,6 +85,7 @@ static SafetyHookMid TimeDilationHook{};
// Prototypes
static void FOVFixEnabled();
static void UltraWideFixEnabled(GameFixes fix);
static void HUDUpdate(bool writeLog);
static void CameraDistanceFixEnabled();
static void DOFFixEnabled();
static void CAFixEnabled();
@@ -146,6 +155,7 @@ extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled, bool init) {
}
if (!init && CameraDistanceaddress) CameraDistanceFixEnabled();
if (!init && DOFaddress) DOFFixEnabled();
if (!init) HUDUpdate(true);
if (!init && Vignettingaddress) VignettingFixEnabled();
if (!init && Fogaddress) FogFixEnabled();
if (!init && WorldTimedilationaddress) {
@@ -163,6 +173,7 @@ extern "C" __declspec(dllexport) void SetFixesEnabled(GameFixes fix, bool enable
if (fix == GameFixes::FOV) { g_fov_fix_enabled = enabled; FOVFixEnabled(); }
if (fix == GameFixes::UltraWide) { g_ultrawide_fix_enabled = enabled; UltraWideFixEnabled(GameFixes::UltraWide); }
if (fix == GameFixes::Camera) { g_Camera_fix_enabled = enabled; CameraDistanceFixEnabled(); }
if (fix == GameFixes::HUD) { g_HUD_fix_enabled = enabled; HUDUpdate(true); }
if (fix == GameFixes::DOF) { g_DOF_fix_enabled = enabled; DOFFixEnabled(); }
if (fix == GameFixes::Vignetting) { g_Vignetting_fix_enabled = enabled; VignettingFixEnabled(); }
if (fix == GameFixes::Fog) { g_Fog_fix_enabled = enabled; FogFixEnabled(); }
@@ -177,6 +188,10 @@ extern "C" __declspec(dllexport) void SetValues(GameSetting setting, float value
if (setting == GameSetting::CameraDistance) g_CameraMultiplier = value;
if (setting == GameSetting::WorldTimeDilation) g_WorldTimeDilationValue = value;
if (setting == GameSetting::AITimeDilation) g_AITimeDilationValue = value;
if (setting == GameSetting::HUD) {
g_HUDOffsets = ((int)value * screenWidth) / 100;
HUDUpdate(false);
}
}
// Getters for Reshade addon call
extern "C" __declspec(dllexport) void GetGameInfos(GameInfos* infos) {
@@ -196,6 +211,16 @@ extern "C" __declspec(dllexport) void GetGameInfos(GameInfos* infos) {
}
// Code injection functions
static float g_UIScale = 1.f;
static UWidget* playerState = nullptr;
static UWidget* tipPanel = nullptr;
static UWidget* activeSlots = nullptr;
static UWidget* showItems = nullptr;
static UWidget* playerGuideLines = nullptr;
static UWidget* newHelpblock = nullptr;
static UWidget* coins = nullptr;
static UWidget* pose = nullptr;
static UWidget* gameSaving = nullptr;
static ULONGLONG lastScanResolutionTick = 0; // Last time Actors were scanned for enemies time dilation
static void ProcessEvent() {
if (!PEHook && ProcessEventaddress) {
@@ -211,12 +236,68 @@ static void ProcessEvent() {
}
if (object && func) {
std::string funcName = func->GetName();
std::string objectName = object->GetName();
if (funcName == "Construct") TrackWidgetConstruct((UUserWidget*)object);
if (funcName == "Destruct") TrackWidgetDestruct((UUserWidget*)object);
if (funcName == "Construct" || funcName == "Destruct") {
// Right HUD elements
auto HandleWidget = [&](auto* typedWidget, auto*& gWidgetPtr) { // Lambda to initialize pointers on Construct and nullify them on Destruct
if (funcName == "Construct") {
gWidgetPtr = typedWidget;
HUDUpdate(false);
}
else if (funcName == "Destruct") gWidgetPtr = nullptr;
};
if (object->IsA(UWB_NewPlayerGuidelines_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), playerGuideLines);
else if (object->IsA(UWB_GameSaving_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), gameSaving);
else if (object->IsA(UWB_ShowAddItemMain_New_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), showItems);
else if (object->IsA(UWB_NewHelpBlock_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), newHelpblock);
else if (object->IsA(UWB_PoseMain_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), pose);
else if (object->IsA(UWB_PlayerCoins_C::StaticClass())) // valid
HandleWidget(static_cast<UWidget*>(object), coins);
// Left HUD elements (player state, key tips, active slots)
else if (object->IsA(UWB_MainUI_C::StaticClass())) {
auto* HUDWidget = static_cast<UWB_MainUI_C*>(object);
if (funcName == "Construct") {
g_UIScale = SDK::UWidgetLayoutLibrary::GetViewportScale(HUDWidget);
//SetLogger(logger);
if (HUDWidget->WB_PlayerState) playerState = reinterpret_cast<UWidget*>(HUDWidget->WB_PlayerState);
if (HUDWidget->WB_KeyTipPanel_47) tipPanel = reinterpret_cast<UWidget*>(HUDWidget->WB_KeyTipPanel_47);
if (HUDWidget->WB_ActiveSlots) activeSlots = reinterpret_cast<UWidget*>(HUDWidget->WB_ActiveSlots);
HUDUpdate(false);
}
if (funcName == "Destruct") {
playerState = nullptr;
tipPanel = nullptr;
activeSlots = nullptr;
}
}
}
}
});
}
}
static void HUDUpdate(bool writeLog) {
if (writeLog) logger->info("HUD & UI scaling fix {}", g_fix_enabled && g_HUD_fix_enabled ? "enabled" : "disabled");
float HUDoffset = (g_fix_enabled && g_HUD_fix_enabled) ? g_HUDOffsets : 0.f;
ApplyTransformOffset(playerState, HUDoffset / g_UIScale);
ApplyTransformOffset(tipPanel, HUDoffset / g_UIScale);
ApplyTransformOffset(pose, HUDoffset / g_UIScale);
ApplyTransformOffset(activeSlots, -(HUDoffset / g_UIScale));
ApplyTransformOffset(showItems, -(HUDoffset / g_UIScale));
ApplyTransformOffset(playerGuideLines, -(HUDoffset / g_UIScale));
ApplyTransformOffset(newHelpblock, -(HUDoffset / g_UIScale));
ApplyTransformOffset(gameSaving, -(HUDoffset / g_UIScale));
ApplyTransformOffset(coins, -(HUDoffset / g_UIScale));
}
static bool bHastoCompensateFOV = false;
static float currentAspect = 0.f;
static void FOVFixEnabled() {
@@ -308,13 +389,15 @@ static void EnableCheats(Cheat cheat) {
if (controller && controller->IsA(AImpl_BaseAIController_C::StaticClass())) { // enemy spotted
auto* aiController = static_cast<AImpl_BaseAIController_C*>(controller);
if (aiController && aiController->Perception) {
if (g_Stealth_fix_enabled) aiController->EnableAlertPerception(false);
else {
aiController->EnableAlertPerception(true);
aiController->FlushEnableSense();
aiController->UpdateSenseTarget();
if (!aiController->IsBoss) { // Won't apply to bosses to avoid breaking the fight
if (g_Stealth_fix_enabled) aiController->EnableAlertPerception(false);
else {
aiController->EnableAlertPerception(true);
aiController->FlushEnableSense();
aiController->UpdateSenseTarget();
}
}
}
}
character->CustomTimeDilation = g_TimeDilation_fix_enabled ? g_AITimeDilationValue : 1.f;
}
}
@@ -407,6 +490,7 @@ static void EnableConsole() {
logger->info("-------------- Console re-enabling --------------");
ReactivateDevConsole(logger);
}
// Standard dll entry
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID) {
if (reason == DLL_PROCESS_ATTACH) {