113 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| #pragma semicolon 1
 | |
| #pragma newdecls required
 | |
| 
 | |
| #include <sourcemod>
 | |
| 
 | |
| 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);
 | |
| 	}
 | |
| }
 |