#pragma semicolon 1 #pragma newdecls required #include public Plugin myinfo = { name = "Fix Player Gravity", author = "xen", description = "Enable prediction for gravity and fix ladders resetting it", version = "1.0", url = "" }; ConVar g_CVar_sv_gravity; float g_flClientGravity[MAXPLAYERS + 1]; float g_flClientActualGravity[MAXPLAYERS + 1]; bool g_bLadder[MAXPLAYERS + 1]; public void OnPluginStart() { g_CVar_sv_gravity = FindConVar("sv_gravity"); HookEvent("round_start", OnRoundStart); } public void OnPluginEnd() { ResetGravityAll(); } // If a player is on a ladder with modified gravity and the round restarts, // their gravity would be restored to what it was last round since they'd be no longer on a ladder public void OnRoundStart(Handle event, const char[] name, bool dontBroadcast) { ResetGravityAll(); } public void OnGameFrame() { float flSVGravity = GetConVarFloat(g_CVar_sv_gravity); for (int client = 1; client < MaxClients; client++) { if (!IsClientInGame(client) || !IsPlayerAlive(client) || IsFakeClient(client)) { g_flClientGravity[client] = 1.0; g_bLadder[client] = false; continue; } if (GetEntityMoveType(client) == MOVETYPE_LADDER) { // They're on a ladder, ignore current gravity modifier if (!g_bLadder[client]) g_bLadder[client] = true; continue; } // Now that they're off, restore it if (g_bLadder[client]) { RequestFrame(RestoreGravity, client); continue; } float flClientGravity = GetEntityGravity(client); // Gamemovement treats 0.0 gravity as 1.0 if (flClientGravity != 0.0) g_flClientGravity[client] = flClientGravity; else flClientGravity = 1.0; // Some maps change sv_gravity while clients already have modified gravity // So we store the actual calculated gravity to catch such cases float flClientActualGravity = flClientGravity * flSVGravity; if (flClientActualGravity != g_flClientActualGravity[client]) { char szGravity[8]; FloatToString(flClientActualGravity, szGravity, sizeof(szGravity)); g_CVar_sv_gravity.ReplicateToClient(client, szGravity); g_flClientActualGravity[client] = flClientActualGravity; } } } public void RestoreGravity(int client) { g_bLadder[client] = false; SetEntityGravity(client, g_flClientGravity[client]); } public void ResetGravityAll() { char szGravity[8]; g_CVar_sv_gravity.GetString(szGravity, sizeof(szGravity)); for (int client = 1; client < MaxClients; client++) { g_flClientGravity[client] = 1.0; g_bLadder[client] = false; if (IsClientInGame(client) && !IsFakeClient(client)) g_CVar_sv_gravity.ReplicateToClient(client, szGravity); } }