Add AI enemies time dilation fix

This commit is contained in:
2025-12-28 19:11:32 +01:00
parent 8a0dad9b39
commit f93c85534b

View File

@@ -18,6 +18,7 @@ const std::string PLUGIN_NAME = "TheCallistoProtocol";
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
constexpr float INVENTORY_CAM_OFFSET = 59.16f;
constexpr float FORGE_CAM_OFFSET = 46.f;
constexpr ULONGLONG DEFAULT_ACTORS_SCAN_BETWEEN_TICKS = 300; // Used for enemies time dilation
// 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_Vignetting_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_CameraOffset = 0;
static float g_WorldTimeDilationValue = 1.f;
static float g_AITimeDilationValue = 1.f;
static float g_CameraSmoothnessValue = 3.5f;
static float g_TransitionCameraOffset = 0.f;
static float g_NativeCameraDistance = 80.f;
@@ -53,6 +55,7 @@ static bool bIsInPrinterMode = false;
static bool bIsAiming = false;
static double LastCineCallTime = 0.0;
static bool user_inputs_logged = false;
static ULONGLONG lastScanTick = 0; // Last time Actors were scanned for enemies time dilation
// Shared values
static float g_FOV_In = 75.f;
@@ -93,7 +96,7 @@ static void DOFFixEnabled();
static void CAFixEnabled();
static void VignettingFixEnabled();
static void FogFixEnabled();
static void WorldTimeDilation();
static void TimeDilation();
static void EnableConsole();
// Unreal Engine camera struct
@@ -253,7 +256,7 @@ extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled, bool init)
if (!init && CAaddress) CAFixEnabled();
if (!init && Vignettingaddress) VignettingFixEnabled();
if (!init && Fogaddress) FogFixEnabled();
if (!init && WorldTimedilationaddress) WorldTimeDilation();
if (!init && WorldTimedilationaddress) TimeDilation();
if (!init && GObjectsaddress && AppendStringaddress && ProcessEventaddress) EnableConsole();
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::Vignetting) { g_Vignetting_fix_enabled = enabled; VignettingFixEnabled(); }
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)
@@ -289,10 +292,63 @@ extern "C" __declspec(dllexport) void SetWorldTimeDilation(float timeDilation) {
g_WorldTimeDilationValue = timeDilation;
}
extern "C" __declspec(dllexport) void SetAITimeDilation(float timeDilation) {
g_AITimeDilationValue = timeDilation;
}
extern "C" __declspec(dllexport) void SetCameraSmoothness(float 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
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() {
if (g_fix_enabled && g_camera_fix_enabled && ProcessEventaddress) {
if (!PEHook) {
@@ -384,13 +421,7 @@ static void CameraFixEnabled() {
// --- World to Pawn (player) ---
UWorld* world = UWorld::GetWorld();
if (!world) return;
UGameInstance* gameInstance = world->OwningGameInstance;
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;
APawn* pawn = GetPawnFromWorld(world);
if (!pawn) return;
// Retrieve Character class
@@ -486,7 +517,6 @@ static void CameraFixEnabled() {
cameraParams->NewViewRotation = cameraParams->ViewRotation;
cameraParams->NewFOV = cameraParams->FOV;
}
}
});
}
@@ -552,21 +582,44 @@ static void HUDFixEnabled() {
}
}
static void WorldTimeDilation() {
if (g_fix_enabled && g_WorldTimeDilation_fix_enabled) {
static void TimeDilation() {
if (g_fix_enabled && g_TimeDilation_fix_enabled && WorldTimedilationaddress) {
if (!WorldTimeDilationHook) {
WorldTimeDilationHook = safetyhook::create_mid(WorldTimedilationaddress + 0x20,
[](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("World time dilation fix enabled");
}
if (!(g_fix_enabled && g_WorldTimeDilation_fix_enabled)) {
if (WorldTimeDilationHook) WorldTimeDilationHook.disable();
logger->info("World time dilation fix disabled");
logger->info("Time dilation fix enabled");
}
if (!(g_fix_enabled && g_TimeDilation_fix_enabled) && WorldTimedilationaddress)
logger->info("Time dilation fix disabled");
}
// Memory patch fixes