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";
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user