Add AI enemies time dilation fix
This commit is contained in:
@@ -18,6 +18,7 @@ const std::string PLUGIN_NAME = "TheCallistoProtocol";
|
|||||||
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
|
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
|
||||||
constexpr float INVENTORY_CAM_OFFSET = 59.16f;
|
constexpr float INVENTORY_CAM_OFFSET = 59.16f;
|
||||||
constexpr float FORGE_CAM_OFFSET = 46.f;
|
constexpr float FORGE_CAM_OFFSET = 46.f;
|
||||||
|
constexpr ULONGLONG DEFAULT_ACTORS_SCAN_BETWEEN_TICKS = 300; // Used for enemies time dilation
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
std::shared_ptr<spdlog::logger> logger;
|
std::shared_ptr<spdlog::logger> logger;
|
||||||
@@ -36,10 +37,11 @@ static bool g_fov_fix_enabled = false;
|
|||||||
static bool g_CA_fix_enabled = false;
|
static bool g_CA_fix_enabled = false;
|
||||||
static bool g_Vignetting_fix_enabled = false;
|
static bool g_Vignetting_fix_enabled = false;
|
||||||
static bool g_Fog_fix_enabled = false;
|
static bool g_Fog_fix_enabled = false;
|
||||||
static bool g_WorldTimeDilation_fix_enabled = false;
|
static bool g_TimeDilation_fix_enabled = false;
|
||||||
static int g_AdditionalFOVValue = 0;
|
static int g_AdditionalFOVValue = 0;
|
||||||
static int g_CameraOffset = 0;
|
static int g_CameraOffset = 0;
|
||||||
static float g_WorldTimeDilationValue = 1.f;
|
static float g_WorldTimeDilationValue = 1.f;
|
||||||
|
static float g_AITimeDilationValue = 1.f;
|
||||||
static float g_CameraSmoothnessValue = 3.5f;
|
static float g_CameraSmoothnessValue = 3.5f;
|
||||||
static float g_TransitionCameraOffset = 0.f;
|
static float g_TransitionCameraOffset = 0.f;
|
||||||
static float g_NativeCameraDistance = 80.f;
|
static float g_NativeCameraDistance = 80.f;
|
||||||
@@ -53,6 +55,7 @@ static bool bIsInPrinterMode = false;
|
|||||||
static bool bIsAiming = false;
|
static bool bIsAiming = false;
|
||||||
static double LastCineCallTime = 0.0;
|
static double LastCineCallTime = 0.0;
|
||||||
static bool user_inputs_logged = false;
|
static bool user_inputs_logged = false;
|
||||||
|
static ULONGLONG lastScanTick = 0; // Last time Actors were scanned for enemies time dilation
|
||||||
|
|
||||||
// Shared values
|
// Shared values
|
||||||
static float g_FOV_In = 75.f;
|
static float g_FOV_In = 75.f;
|
||||||
@@ -93,7 +96,7 @@ static void DOFFixEnabled();
|
|||||||
static void CAFixEnabled();
|
static void CAFixEnabled();
|
||||||
static void VignettingFixEnabled();
|
static void VignettingFixEnabled();
|
||||||
static void FogFixEnabled();
|
static void FogFixEnabled();
|
||||||
static void WorldTimeDilation();
|
static void TimeDilation();
|
||||||
static void EnableConsole();
|
static void EnableConsole();
|
||||||
|
|
||||||
// Unreal Engine camera struct
|
// Unreal Engine camera struct
|
||||||
@@ -253,7 +256,7 @@ extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled, bool init)
|
|||||||
if (!init && CAaddress) CAFixEnabled();
|
if (!init && CAaddress) CAFixEnabled();
|
||||||
if (!init && Vignettingaddress) VignettingFixEnabled();
|
if (!init && Vignettingaddress) VignettingFixEnabled();
|
||||||
if (!init && Fogaddress) FogFixEnabled();
|
if (!init && Fogaddress) FogFixEnabled();
|
||||||
if (!init && WorldTimedilationaddress) WorldTimeDilation();
|
if (!init && WorldTimedilationaddress) TimeDilation();
|
||||||
if (!init && GObjectsaddress && AppendStringaddress && ProcessEventaddress) EnableConsole();
|
if (!init && GObjectsaddress && AppendStringaddress && ProcessEventaddress) EnableConsole();
|
||||||
if (ConstrainAspectaddress) UltraWideFixEnabled();
|
if (ConstrainAspectaddress) UltraWideFixEnabled();
|
||||||
}
|
}
|
||||||
@@ -267,7 +270,7 @@ extern "C" __declspec(dllexport) void SetFixesEnabled(GameFixes fix, bool enable
|
|||||||
if (fix == GameFixes::ChromaticAberrations) { g_CA_fix_enabled = enabled; CAFixEnabled(); }
|
if (fix == GameFixes::ChromaticAberrations) { g_CA_fix_enabled = enabled; CAFixEnabled(); }
|
||||||
if (fix == GameFixes::Vignetting) { g_Vignetting_fix_enabled = enabled; VignettingFixEnabled(); }
|
if (fix == GameFixes::Vignetting) { g_Vignetting_fix_enabled = enabled; VignettingFixEnabled(); }
|
||||||
if (fix == GameFixes::Fog) { g_Fog_fix_enabled = enabled; FogFixEnabled(); }
|
if (fix == GameFixes::Fog) { g_Fog_fix_enabled = enabled; FogFixEnabled(); }
|
||||||
if (fix == GameFixes::WorldTimeDilation) { g_WorldTimeDilation_fix_enabled = enabled; WorldTimeDilation(); }
|
if (fix == GameFixes::WorldTimeDilation) { g_TimeDilation_fix_enabled = enabled; TimeDilation(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" __declspec(dllexport) void SetFOV(int fov)
|
extern "C" __declspec(dllexport) void SetFOV(int fov)
|
||||||
@@ -289,10 +292,63 @@ extern "C" __declspec(dllexport) void SetWorldTimeDilation(float timeDilation) {
|
|||||||
g_WorldTimeDilationValue = timeDilation;
|
g_WorldTimeDilationValue = timeDilation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) void SetAITimeDilation(float timeDilation) {
|
||||||
|
g_AITimeDilationValue = timeDilation;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" __declspec(dllexport) void SetCameraSmoothness(float smoothness) {
|
extern "C" __declspec(dllexport) void SetCameraSmoothness(float smoothness) {
|
||||||
g_CameraSmoothnessValue = smoothness;
|
g_CameraSmoothnessValue = smoothness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unreal Engine functions
|
||||||
|
/**
|
||||||
|
* @brief Converts a rotator (Pitch, Yaw) to a forward direction vector.
|
||||||
|
*
|
||||||
|
* Computes a normalized forward vector from the given FRotator,
|
||||||
|
* using Pitch and Yaw angles (in degrees).
|
||||||
|
*
|
||||||
|
* @param rotator Input rotation (degrees).
|
||||||
|
* @return Forward direction vector.
|
||||||
|
*/
|
||||||
|
static FVector RotatorToForwardVector(const FRotator& rotator)
|
||||||
|
{
|
||||||
|
const float DEG_TO_RAD = 3.1415926535f / 180.0f;
|
||||||
|
|
||||||
|
float cp = cosf(rotator.Pitch * DEG_TO_RAD);
|
||||||
|
float sp = sinf(rotator.Pitch * DEG_TO_RAD);
|
||||||
|
float cy = cosf(rotator.Yaw * DEG_TO_RAD);
|
||||||
|
float sy = sinf(rotator.Yaw * DEG_TO_RAD);
|
||||||
|
|
||||||
|
return FVector(cp * cy, cp * sy, sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current player Pawn from the world.
|
||||||
|
* @param world Optional UWorld pointer.
|
||||||
|
* @return Player Pawn or nullptr.
|
||||||
|
*/
|
||||||
|
static APawn* GetPawnFromWorld(UWorld* world = nullptr) {
|
||||||
|
if (!world) UWorld* world = UWorld::GetWorld();
|
||||||
|
if (!world) return nullptr;
|
||||||
|
|
||||||
|
UGameInstance* gameInstance = world->OwningGameInstance;
|
||||||
|
if (!gameInstance || gameInstance->LocalPlayers.Num() == 0) return nullptr;
|
||||||
|
ULocalPlayer* localPlayer = gameInstance->LocalPlayers[0];
|
||||||
|
if (!localPlayer) return nullptr;
|
||||||
|
APlayerController* pc = localPlayer->PlayerController;
|
||||||
|
if (!pc) return nullptr;
|
||||||
|
APawn* pawn = pc->AcknowledgedPawn;
|
||||||
|
|
||||||
|
return pawn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Miscellaneous functions
|
||||||
|
static inline double NowSeconds()
|
||||||
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
|
static steady_clock::time_point start = steady_clock::now();
|
||||||
|
return duration<double>(steady_clock::now() - start).count();
|
||||||
|
}
|
||||||
|
|
||||||
// Getters for Reshade addon call
|
// Getters for Reshade addon call
|
||||||
extern "C" __declspec(dllexport) void GetGameInfos(GameInfos* infos) {
|
extern "C" __declspec(dllexport) void GetGameInfos(GameInfos* infos) {
|
||||||
@@ -324,25 +380,6 @@ static void FOVFixEnabled() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FVector RotatorToForwardVector(const FRotator& rotator)
|
|
||||||
{
|
|
||||||
const float DEG_TO_RAD = 3.1415926535f / 180.0f;
|
|
||||||
|
|
||||||
float cp = cosf(rotator.Pitch * DEG_TO_RAD);
|
|
||||||
float sp = sinf(rotator.Pitch * DEG_TO_RAD);
|
|
||||||
float cy = cosf(rotator.Yaw * DEG_TO_RAD);
|
|
||||||
float sy = sinf(rotator.Yaw * DEG_TO_RAD);
|
|
||||||
|
|
||||||
return FVector(cp * cy, cp * sy, sp);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double NowSeconds()
|
|
||||||
{
|
|
||||||
using namespace std::chrono;
|
|
||||||
static steady_clock::time_point start = steady_clock::now();
|
|
||||||
return duration<double>(steady_clock::now() - start).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CameraFixEnabled() {
|
static void CameraFixEnabled() {
|
||||||
if (g_fix_enabled && g_camera_fix_enabled && ProcessEventaddress) {
|
if (g_fix_enabled && g_camera_fix_enabled && ProcessEventaddress) {
|
||||||
if (!PEHook) {
|
if (!PEHook) {
|
||||||
@@ -384,13 +421,7 @@ static void CameraFixEnabled() {
|
|||||||
// --- World to Pawn (player) ---
|
// --- World to Pawn (player) ---
|
||||||
UWorld* world = UWorld::GetWorld();
|
UWorld* world = UWorld::GetWorld();
|
||||||
if (!world) return;
|
if (!world) return;
|
||||||
UGameInstance* gameInstance = world->OwningGameInstance;
|
APawn* pawn = GetPawnFromWorld(world);
|
||||||
if (!gameInstance || gameInstance->LocalPlayers.Num() == 0) return;
|
|
||||||
ULocalPlayer* localPlayer = gameInstance->LocalPlayers[0];
|
|
||||||
if (!localPlayer) return;
|
|
||||||
APlayerController* pc = localPlayer->PlayerController;
|
|
||||||
if (!pc) return;
|
|
||||||
APawn* pawn = pc->AcknowledgedPawn;
|
|
||||||
if (!pawn) return;
|
if (!pawn) return;
|
||||||
|
|
||||||
// Retrieve Character class
|
// Retrieve Character class
|
||||||
@@ -486,7 +517,6 @@ static void CameraFixEnabled() {
|
|||||||
cameraParams->NewViewRotation = cameraParams->ViewRotation;
|
cameraParams->NewViewRotation = cameraParams->ViewRotation;
|
||||||
cameraParams->NewFOV = cameraParams->FOV;
|
cameraParams->NewFOV = cameraParams->FOV;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -552,21 +582,44 @@ static void HUDFixEnabled() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WorldTimeDilation() {
|
static void TimeDilation() {
|
||||||
if (g_fix_enabled && g_WorldTimeDilation_fix_enabled) {
|
if (g_fix_enabled && g_TimeDilation_fix_enabled && WorldTimedilationaddress) {
|
||||||
if (!WorldTimeDilationHook) {
|
if (!WorldTimeDilationHook) {
|
||||||
WorldTimeDilationHook = safetyhook::create_mid(WorldTimedilationaddress + 0x20,
|
WorldTimeDilationHook = safetyhook::create_mid(WorldTimedilationaddress + 0x20,
|
||||||
[](SafetyHookContext& ctx) {
|
[](SafetyHookContext& ctx) {
|
||||||
ctx.xmm0.f32[0] = g_WorldTimeDilationValue;
|
ctx.xmm0.f32[0] = g_TimeDilation_fix_enabled ? g_WorldTimeDilationValue : 1.f;
|
||||||
|
|
||||||
|
ULONGLONG now = GetTickCount64();
|
||||||
|
if (now - lastScanTick < DEFAULT_ACTORS_SCAN_BETWEEN_TICKS) return;
|
||||||
|
|
||||||
|
lastScanTick = now;
|
||||||
|
UWorld* world = UWorld::GetWorld();
|
||||||
|
if (!world) return;
|
||||||
|
APawn* pawn = GetPawnFromWorld(world);
|
||||||
|
if (!pawn) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < world->Levels.Num(); i++) // Loop through level to find actors
|
||||||
|
{
|
||||||
|
ULevel* Level = world->Levels[i];
|
||||||
|
if (!Level) continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < Level->Actors.Num(); j++) // Loop through actors
|
||||||
|
{
|
||||||
|
AActor* actor = Level->Actors[j];
|
||||||
|
if (!actor) continue;
|
||||||
|
if (actor == pawn) continue; // We don't want to affect Jacob
|
||||||
|
if (!actor->IsA(ACharacter::StaticClass()) && !actor->IsA(APawn::StaticClass()))
|
||||||
|
continue; // We want to affect only enemies
|
||||||
|
|
||||||
|
actor->CustomTimeDilation = g_TimeDilation_fix_enabled ? g_AITimeDilationValue : 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else WorldTimeDilationHook.enable();
|
logger->info("Time dilation fix enabled");
|
||||||
logger->info("World time dilation fix enabled");
|
|
||||||
}
|
|
||||||
if (!(g_fix_enabled && g_WorldTimeDilation_fix_enabled)) {
|
|
||||||
if (WorldTimeDilationHook) WorldTimeDilationHook.disable();
|
|
||||||
logger->info("World time dilation fix disabled");
|
|
||||||
}
|
}
|
||||||
|
if (!(g_fix_enabled && g_TimeDilation_fix_enabled) && WorldTimedilationaddress)
|
||||||
|
logger->info("Time dilation fix disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memory patch fixes
|
// Memory patch fixes
|
||||||
|
|||||||
Reference in New Issue
Block a user