Add fog fixes and skip intro fix. Update game name.

This commit is contained in:
2025-10-12 19:45:40 +02:00
parent d084b38032
commit 1c0f9146c6

View File

@@ -10,11 +10,12 @@
#include "UEngine.hpp";
#include "SDK/Basic.hpp"
#include "SDK/Engine_classes.hpp"
#include "SDK/LVL_SplashScreens_classes.hpp"
using namespace SDK;
// Constants
const std::string PLUGIN_NAME = "LittleNightmareIII";
const std::string PLUGIN_NAME = "LittleNightmaresIII";
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
const std::string gameExecutable = "LittleNightmaresIII.exe";
@@ -29,6 +30,8 @@ static bool g_ultrawide_fix_enabled = false;
static bool g_DOF_fix_enabled = false;
static bool g_CA_fix_enabled = false;
static bool g_Vignetting_fix_enabled = false;
static bool g_Fog_fix_enabled = false;
static bool g_VolumetricFog_fix_enabled = false;
static int g_AdditionalFOVValue = 0;
// Shared values
@@ -47,12 +50,16 @@ static uint8_t* FOVaddress = nullptr;
static uint8_t* DOFaddress = nullptr;
static uint8_t* CAaddress = nullptr;
static uint8_t* Vignettingaddress = nullptr;
static uint8_t* VolumetricFogaddress = nullptr;
static uint8_t* Fogaddress = nullptr;
static uint8_t* CameraComponentaddress = nullptr;
static uint8_t* ConstrainAspectRatioaddress = nullptr;
static uint8_t* AspectRatioAxisConstraintaddress = nullptr;
// Hooking
static SafetyHookMid FOVHook{};
static SafetyHookMid FogHook{};
static SafetyHookMid ProcessEventHook{};
// Prototypes
static void FOVFixEnabled();
@@ -60,7 +67,10 @@ static void UltraWideFixEnabled();
static void DOFFixEnabled();
static void CAFixEnabled();
static void VignettingFixEnabled();
static void FogFixEnabled();
static void VolumetricFogFixEnabled();
static void EnableConsole();
static void SkipIntro();
extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled)
{
@@ -130,8 +140,28 @@ extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled)
logger->info("Vignetting signature found at address: 0x{:X}.", reinterpret_cast<uintptr_t>(Vignettingaddress));
}
if (CameraComponentaddress && FOVaddress && DOFaddress && CAaddress && Vignettingaddress
&& ConstrainAspectRatioaddress && AspectRatioAxisConstraintaddress) {
if (!Fogaddress) {
constexpr auto FogStringObfuscated = make_obfuscated<0x4A>("83 ?? ?? ?? 75 ?? B3 ?? EB ?? 32 ?? 48 8B");
Fogaddress = Memory::AOBScan(gameExecutable, FogStringObfuscated.decrypt(), PAGE_EXECUTE_READ);
if (!Fogaddress)
logger->warn("Fog signature not found. Maybe your game has been updated and is no more compatible with this plugin.");
else
logger->info("Fog signature found at address: 0x{:X}.", reinterpret_cast<uintptr_t>(Fogaddress));
}
if (!VolumetricFogaddress){
constexpr auto VolumetricFogStringObfuscated = make_obfuscated<0x4A>("74 ?? F7 47 ?? ?? ?? ?? ?? 74 ?? 83 BB");
VolumetricFogaddress = Memory::AOBScan(gameExecutable, VolumetricFogStringObfuscated.decrypt(), PAGE_EXECUTE_READ);
if (!VolumetricFogaddress)
logger->warn("Volumetric fog signature not found. Maybe your game has been updated and is no more compatible with this plugin.");
else
logger->info("Volumetric fog signature found at address: 0x{:X}.", reinterpret_cast<uintptr_t>(VolumetricFogaddress));
}
if (CameraComponentaddress && FOVaddress && DOFaddress && CAaddress && Vignettingaddress &&
Fogaddress && VolumetricFogaddress && ConstrainAspectRatioaddress && AspectRatioAxisConstraintaddress) {
logger->info("All AOB signatures found. Ready to patch...");
AOBScanDone = true;
}
@@ -180,6 +210,8 @@ extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled)
if (DOFaddress) DOFFixEnabled();
if (CAaddress) CAFixEnabled();
if (Vignettingaddress) VignettingFixEnabled();
if (Fogaddress) FogFixEnabled();
if (VolumetricFogaddress) VolumetricFogFixEnabled();
if (AspectRatioAxisConstraintaddress && ConstrainAspectRatioaddress) UltraWideFixEnabled();
if (!g_Console_Enabled && GObjectsaddress && GNamesaddress && ProcessEventaddress)
EnableConsole();
@@ -216,6 +248,24 @@ extern "C" __declspec(dllexport) void SetVignettingFixEnabled(bool enabled, bool
if (!init) VignettingFixEnabled();
}
extern "C" __declspec(dllexport) void SetFogFixEnabled(bool enabled, bool init)
{
g_Fog_fix_enabled = enabled;
if (!init) FogFixEnabled();
}
extern "C" __declspec(dllexport) void SetVolumetricFogFixEnabled(bool enabled, bool init)
{
g_VolumetricFog_fix_enabled = enabled;
if (!init) VolumetricFogFixEnabled();
}
extern "C" __declspec(dllexport) void SetSkipIntroEnabled(bool enabled)
{
if (enabled) SkipIntro();
}
extern "C" __declspec(dllexport) void SetFOV(int fov)
{
g_AdditionalFOVValue = fov;
@@ -250,6 +300,45 @@ static void FOVFixEnabled() {
}
}
static void FogFixEnabled() {
if (g_fix_enabled && g_Fog_fix_enabled && Fogaddress) {
if (!FogHook) {
FogHook = safetyhook::create_mid(Fogaddress,
[](SafetyHookContext& ctx) {
if (!ctx.rax) return;
uintptr_t* rax = reinterpret_cast<uintptr_t*>(ctx.rax);
bool* bFog = reinterpret_cast<bool*>(reinterpret_cast<uint8_t*>(rax) + 0x04);
*bFog = g_fix_enabled && g_Fog_fix_enabled ? false : true;
});
}
logger->info("Fog fix enabled");
}
if (!(g_fix_enabled && g_Fog_fix_enabled) && Fogaddress)
logger->info("Fog fix disabled");
}
static void SkipIntro() {
if (!ProcessEventHook && ProcessEventaddress) {
ProcessEventHook = safetyhook::create_mid(ProcessEventaddress + 0xc,
[](SafetyHookContext& ctx) {
auto* object = reinterpret_cast<UObject*>(ctx.rcx);
auto* function = reinterpret_cast<UFunction*>(ctx.rdx);
// Hook ProcessEvent to skip intros
if (object && function) {
std::string className = object->GetName();
std::string functionName = function->GetName();
if (className.contains("LVL_SplashScreens_C_0") && functionName.contains("ReceiveBeginPlay")) {
if (object->IsA(ALVL_SplashScreens_C::StaticClass())) {
auto* SplashScreen = static_cast<ALVL_SplashScreens_C*>(object);
if (SplashScreen) SplashScreen->GoToMainMenuLevel(); // skip intros
}
}
}
});
}
}
// Memory patch fixes
static void UltraWideFixEnabled() {
if (g_fix_enabled && g_ultrawide_fix_enabled && AspectRatioAxisConstraintaddress && ConstrainAspectRatioaddress) {
@@ -297,6 +386,17 @@ static void VignettingFixEnabled() {
}
}
static void VolumetricFogFixEnabled() {
if (g_fix_enabled && g_VolumetricFog_fix_enabled && VolumetricFogaddress) {
Memory::PatchBytes(VolumetricFogaddress, "\xEB", 1); // je-> jmp r.Fog=0
logger->info("Volumetric fog fix enabled");
}
if (!(g_fix_enabled && g_VolumetricFog_fix_enabled) && VolumetricFogaddress) {
Memory::RestoreBytes(VolumetricFogaddress);
logger->info("Volumetric fog fix disabled");
}
}
// UE Console creation
static void EnableConsole()
{
@@ -356,7 +456,7 @@ static void InitializeLogger()
std::filesystem::path log_path = std::filesystem::absolute(PLUGIN_LOG);
if (std::filesystem::exists(log_path))
std::filesystem::remove(log_path);
logger = std::make_shared<spdlog::logger>("Little Nightmare III", std::make_shared<spdlog::sinks::rotating_file_sink_st>(PLUGIN_LOG, 10 * 1024 * 1024, 1));
logger = std::make_shared<spdlog::logger>("Little Nightmares III", std::make_shared<spdlog::sinks::rotating_file_sink_st>(PLUGIN_LOG, 10 * 1024 * 1024, 1));
logger->set_level(spdlog::level::debug);
logger->flush_on(spdlog::level::debug); // Flush automatically
}