From 1c927f68131369c2e3712605b0f4d3437eb3e76c Mon Sep 17 00:00:00 2001 From: A1mDev <33463136+A1mDev@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:05:58 +0700 Subject: [PATCH 1/2] Fixed 'lerpmonitor'. Fixed 'lerpmonitor'. 1) Removed unnecessary checks in native 'LM_GetLerpTime'. 'GetClientAuthId' - will abort the code on error (If the client is not connected or the index is invalid). 2) Removed unnecessary checks in native 'LM_GetCurrentLerpTime'. 'GetClientInfo' - will abort the code on error (If the client is not connected or the index is invalid). 3) Added native 'LM_GetChachedLerpTime'. Native returns the stored lerp time for the player. 4) Changed native 'LM_GetLerpTime'. Native now returns the player's saved interpolation time, if the interpolation value is not found in the array, then it gets and returns the player's current interpolation time. --- .../scripting/include/lerpmonitor.inc | 35 ++- addons/sourcemod/scripting/lerpmonitor.sp | 234 ++++++++++-------- 2 files changed, 157 insertions(+), 112 deletions(-) diff --git a/addons/sourcemod/scripting/include/lerpmonitor.inc b/addons/sourcemod/scripting/include/lerpmonitor.inc index 8efa6d661..4a043b35a 100644 --- a/addons/sourcemod/scripting/include/lerpmonitor.inc +++ b/addons/sourcemod/scripting/include/lerpmonitor.inc @@ -1,26 +1,36 @@ -#if defined _lerpmonitor +#if defined __lerpmonitor_included #endinput #endif -#define _lerpmonitor +#define __lerpmonitor_included - /** - * @brief Get the player's saved lerp value - * @param client Client index +/** + * @brief Get the player's stored lerp time, if the stored value is not found in the array, + * then the current lerp time will be returned. + * @param client Client index. * - * @return -1.0 if the current lerp time has not been saved, otherwise current lerp value + * @return The current lerp, if the value was not stored, otherwise the stored value from the array. * @error If the client is not connected or the index is invalid. - */ +**/ native float LM_GetLerpTime(int client); - /** - * @brief Get the player's current lerp - * @param client Client index +/** + * @brief Get the player's current lerp time. + * @param client Client index. * - * @return Current lerp value + * @return Current lerp time. * @error Invalid client index, or client not connected. - */ +**/ native float LM_GetCurrentLerpTime(int client); +/** + * @brief Get the player's lerp time stored in the array. + * @param client Client index. + * + * @return Return -1.0 if the lerp time has not been saved, otherwise the stored lerp time. + * @error Invalid client index, or client not connected. +**/ +native float LM_GetStoredLerpTime(int client); + public SharedPlugin __lerpmonitor = { name = "LerpMonitor++", @@ -37,5 +47,6 @@ public void __pl_lerpmonitor_SetNTVOptional() { MarkNativeAsOptional("LM_GetLerpTime"); MarkNativeAsOptional("LM_GetCurrentLerpTime"); + MarkNativeAsOptional("LM_GetStoredLerpTime"); } #endif diff --git a/addons/sourcemod/scripting/lerpmonitor.sp b/addons/sourcemod/scripting/lerpmonitor.sp index bf5a16dd5..a10eb6d22 100644 --- a/addons/sourcemod/scripting/lerpmonitor.sp +++ b/addons/sourcemod/scripting/lerpmonitor.sp @@ -12,12 +12,11 @@ StringMap ArrLerpsValue = null, ArrLerpsCountChanges = null; - -ConVar + +ConVar cVarReadyUpLerpChanges = null, cVarAllowedLerpChanges = null, cVarLerpChangeSpec = null, - cVarBadLerpAction = null, cVarMinLerp = null, cVarMaxLerp = null, cVarMinUpdateRate = null, @@ -32,98 +31,75 @@ bool isMatchLife = true, isTransfer = false; -public Plugin myinfo = +public Plugin myinfo = { name = "LerpMonitor++", author = "ProdigySim, Die Teetasse, vintik, A1m`", description = "Keep track of players' lerp settings", - version = "2.3", - url = "https://github.com/A1mDev/L4D2-Competitive-Plugins" + version = "2.4.1", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { IsLateLoad = late; + CreateNative("LM_GetLerpTime", LM_GetLerpTime); CreateNative("LM_GetCurrentLerpTime", LM_GetCurrentLerpTime); + CreateNative("LM_GetStoredLerpTime", LM_GetStoredLerpTime); + RegPluginLibrary("lerpmonitor"); return APLRes_Success; } -int LM_GetLerpTime(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - if (client < 1 || client > MaxClients) { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d!", client); - } - - if (!IsClientInGame(client)) { - return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game!", client); - } - - float fLerpValue = -1.0; - char sSteamID[STEAMID_SIZE]; - GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID)); - if (ArrLerpsValue.GetValue(sSteamID, fLerpValue)) { - return view_as(fLerpValue); - } - return view_as(-1.0); -} - -int LM_GetCurrentLerpTime(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - if (client < 1 || client > MaxClients) { - return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d!", client); - } - - if (!IsClientConnected(client)) { - return ThrowNativeError(SP_ERROR_NATIVE, "Client %d not connected!", client); - } - - return view_as(GetLerpTime(client)); -} - public void OnPluginStart() { cVarAllowedLerpChanges = CreateConVar("sm_allowed_lerp_changes", "4", "Allowed number of lerp changes for a half", _, true, 0.0, true, 20.0); cVarLerpChangeSpec = CreateConVar("sm_lerp_change_spec", "1", "Move to spectators on exceeding lerp changes count?", _, true, 0.0, true, 1.0); - cVarBadLerpAction = CreateConVar("sm_bad_lerp_action", "1", "What to do with a player if he is out of allowed lerp range? 1 - move to spectators, 0 - kick from server", _, true, 0.0, true, 1.0); cVarReadyUpLerpChanges = CreateConVar("sm_readyup_lerp_changes", "1", "Allow lerp changes during ready-up", _, true, 0.0, true, 1.0); cVarShowLerpTeamChange = CreateConVar("sm_show_lerp_team_changes", "1", "show a message about the player's lerp if he changes the team", _, true, 0.0, true, 1.0); cVarMinLerp = CreateConVar("sm_min_lerp", "0.000", "Minimum allowed lerp value", _, true, 0.000, true, 0.500); cVarMaxLerp = CreateConVar("sm_max_lerp", "0.067", "Maximum allowed lerp value", _, true, 0.000, true, 0.500); - + RegConsoleCmd("sm_lerps", Lerps_Cmd, "List the Lerps of all players in game"); - + cVarMinUpdateRate = FindConVar("sv_minupdaterate"); cVarMaxUpdateRate = FindConVar("sv_maxupdaterate"); cVarMinInterpRatio = FindConVar("sv_client_min_interp_ratio"); cVarMaxInterpRatio = FindConVar("sv_client_max_interp_ratio"); - + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy); HookEvent("player_team", OnTeamChange, EventHookMode_Post); HookEvent("player_disconnect", Event_PlayerDisconnect, EventHookMode_Post); HookEvent("player_left_start_area", Event_RoundGoesLive, EventHookMode_PostNoCopy); - + // create arrays ArrLerpsValue = new StringMap(); ArrLerpsCountChanges = new StringMap(); - - if (IsLateLoad) { - // process current players - for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i) && !IsFakeClient(i)) { - ProcessPlayerLerp(i, true); - } + + LateLoad(); +} + +void LateLoad() +{ + if (!IsLateLoad) { + return; + } + + // process current players + for (int i = 1; i <= MaxClients; i++) { + if (!IsClientInGame(i) || IsFakeClient(i)) { + continue; } + + ProcessPlayerLerp(i, true); } } public void OnClientPutInServer(int client) { - if (IsValidEntity(client) && !IsFakeClient(client)) { + if (!IsFakeClient(client)) { CreateTimer(1.0, Process, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); } } @@ -131,7 +107,7 @@ public void OnClientPutInServer(int client) Action Process(Handle hTimer, int userid) { int client = GetClientOfUserId(userid); - if (client > 0 && GetClientTeam(client) > L4D_TEAM_SPECTATE) { + if (client > 0) { ProcessPlayerLerp(client); } @@ -159,7 +135,7 @@ void Event_RoundGoesLive(Event hEvent, const char[] name, bool dontBroadcast) public void OnClientSettingsChanged(int client) { - if (IsValidEntity(client) && !IsFakeClient(client)) { + if (IsValidEdict(client) && !IsFakeClient(client)) { ProcessPlayerLerp(client); } } @@ -168,11 +144,11 @@ void Event_PlayerDisconnect(Event hEvent, const char[] name, bool dontBroadcast) { char SteamID[64]; hEvent.GetString("networkid", SteamID, sizeof(SteamID)); - + if (StrContains(SteamID, "STEAM") != 0) { return; } - + ArrLerpsValue.Remove(SteamID); //ArrLerpsCountChanges.Remove(SteamID); } @@ -196,6 +172,7 @@ Action OnTeamChangeDelay(Handle hTimer, int userid) if (client > 0) { ProcessPlayerLerp(client, false, true); } + return Plugin_Stop; } @@ -218,27 +195,28 @@ Action Timer_RoundEndDelay(Handle hTimer) Action Lerps_Cmd(int client, int args) { - bool isEmpty = true; + int iCount = 0; if (ArrLerpsValue.Size > 0) { ReplyToCommand(client, "[!] Lerp setting list:"); - + float fLerpValue; char sSteamID[STEAMID_SIZE]; for (int i = 1; i <= MaxClients; i++) { if (IsClientInGame(i) && !IsFakeClient(i)) { GetClientAuthId(i, AuthId_Steam2, sSteamID, sizeof(sSteamID)); - + if (ArrLerpsValue.GetValue(sSteamID, fLerpValue)) { ReplyToCommand(client, "%N [%s]: %.01f", i, sSteamID, fLerpValue * 1000); - isEmpty = false; + iCount++; } } } } - - if (isEmpty) { + + if (iCount == 0) { ReplyToCommand(client, "There is nothing here!"); } + return Plugin_Handled; } @@ -248,28 +226,29 @@ void Event_RoundStart(Event hEvent, const char[] name, bool dontBroadcast) if (!isFirstHalf) { ArrLerpsCountChanges.Clear(); } - + CreateTimer(0.5, OnTransfer, _, TIMER_FLAG_NO_MAPCHANGE); } Action OnTransfer(Handle hTimer) { isTransfer = false; + return Plugin_Stop; } -void ProcessPlayerLerp(int client, bool load = false, bool team = false) +void ProcessPlayerLerp(int client, bool load = false, bool team = false) { float newLerpTime = GetLerpTime(client); // get lerp - + // set lerp for fixing differences between server and client with cl_interp_ratio 0 SetEntPropFloat(client, Prop_Data, "m_fLerpTime", newLerpTime); - + // check lerp first if (GetClientTeam(client) < L4D_TEAM_SURVIVORS) { return; } - + // Get steamid char steamID[STEAMID_SIZE]; GetClientAuthId(client, AuthId_Steam2, steamID, sizeof(steamID)); @@ -280,29 +259,20 @@ void ProcessPlayerLerp(int client, bool load = false, bool team = false) float currentLerpTime = 0.0; if (ArrLerpsValue.GetValue(steamID, currentLerpTime)) { if (currentLerpTime == newLerpTime) { // no change? - if (cVarBadLerpAction.IntValue == 1) { - ChangeClientTeam(client, L4D_TEAM_SPECTATE); - } else { - KickClient(client, "Illegal lerp value (min: %.01f, max: %.01f)", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); - } + ChangeClientTeam(client, L4D_TEAM_SPECTATE); return; } } - - if (cVarBadLerpAction.IntValue == 1) { - CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was moved to spectators for lerp {teamcolor}%.01f", client, newLerpTime * 1000); - CPrintToChatEx(client, client, "{default}<{olive}Lerp{default}> Illegal lerp value (min: {teamcolor}%.01f{default}, max: {teamcolor}%.01f{default})", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); - ChangeClientTeam(client, L4D_TEAM_SPECTATE); - } else { - CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was kicked for lerp {teamcolor}%.01f", client, newLerpTime * 1000); - KickClient(client, "Illegal lerp value (min: %.01f, max: %.01f)", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); - } + + CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was moved to spectators for lerp {teamcolor}%.01f", client, newLerpTime * 1000); + ChangeClientTeam(client, L4D_TEAM_SPECTATE); + CPrintToChatEx(client, client, "{default}<{olive}Lerp{default}> Illegal lerp value (min: {teamcolor}%.01f{default}, max: {teamcolor}%.01f{default})", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); } - + // nothing else to do return; } - + float currentLerpTime = 0.0; if (!ArrLerpsValue.GetValue(steamID, currentLerpTime)) { // add to array @@ -311,13 +281,13 @@ void ProcessPlayerLerp(int client, bool load = false, bool team = false) } ArrLerpsValue.SetValue(steamID, newLerpTime, true); - //ArrLerpsCountChanges.SetValue(steamID, 0, true); + //ArrLerpsCountChanges.SetValue(steamID, 0, true); return; } - + if (currentLerpTime == newLerpTime) { // no change? if (team && cVarShowLerpTeamChange.BoolValue) { - CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}@ {teamcolor}%.01f", client, newLerpTime * 1000); + CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}@ {teamcolor}%.01f", client, newLerpTime * 1000); } return; } @@ -326,10 +296,10 @@ void ProcessPlayerLerp(int client, bool load = false, bool team = false) int count = 0; ArrLerpsCountChanges.GetValue(steamID, count); count++; - + int max = cVarAllowedLerpChanges.IntValue; CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}@ {teamcolor}%.01f {default}<== {green}%.01f {default}[%s%d{default}/%d {olive}changes]", client, newLerpTime * 1000, currentLerpTime * 1000, ((count > max) ? "{teamcolor} ": ""), count, max); - + if (cVarLerpChangeSpec.BoolValue && (count > max)) { CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was moved to spectators (illegal lerp change)!", client); ChangeClientTeam(client, L4D_TEAM_SPECTATE); @@ -337,43 +307,43 @@ void ProcessPlayerLerp(int client, bool load = false, bool team = false) // no lerp update return; } - + ArrLerpsCountChanges.SetValue(steamID, count); // update changes } else { CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}@ {teamcolor}%.01f {default}<== {green}%.01f", client, newLerpTime * 1000, currentLerpTime * 1000); } - + ArrLerpsValue.SetValue(steamID, newLerpTime); // update lerp - //ArrLerpsCountChanges.SetValue(steamID, 0, true); + //ArrLerpsCountChanges.SetValue(steamID, 0, true); } float GetLerpTime(int client) { char buffer[64]; - + if (!GetClientInfo(client, "cl_updaterate", buffer, sizeof(buffer))) { buffer = ""; } - + int updateRate = StringToInt(buffer); updateRate = RoundFloat(clamp(float(updateRate), cVarMinUpdateRate.FloatValue, cVarMaxUpdateRate.FloatValue)); - + if (!GetClientInfo(client, "cl_interp_ratio", buffer, sizeof(buffer))) { buffer = ""; } - + float flLerpRatio = StringToFloat(buffer); - + if (!GetClientInfo(client, "cl_interp", buffer, sizeof(buffer))) { buffer = ""; } - + float flLerpAmount = StringToFloat(buffer); - + if (cVarMinInterpRatio != null && cVarMaxInterpRatio != null && cVarMinInterpRatio.FloatValue != -1.0) { flLerpRatio = clamp(flLerpRatio, cVarMinInterpRatio.FloatValue, cVarMaxInterpRatio.FloatValue); } - + return maximum(flLerpAmount, flLerpRatio / updateRate); } @@ -386,3 +356,67 @@ float clamp(float inc, float low, float high) { return (inc > high) ? high : ((inc < low) ? low : inc); } + +int LM_GetLerpTime(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + //'GetClientAuthId' - will abort the code on error (If the client is not connected or the index is invalid). + /*if (client < 1 || client > MaxClients) { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d!", client); + } + + if (!IsClientConnected(client)) { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d not connected!", client); + }*/ + + char sSteamID[STEAMID_SIZE]; + GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID)); + + float fLerpValue = -1.0; + if (ArrLerpsValue.GetValue(sSteamID, fLerpValue)) { + return view_as(fLerpValue); + } + + return view_as(GetLerpTime(client)); +} + +int LM_GetCurrentLerpTime(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + //'GetClientInfo' - will abort the code on error (If the client is not connected or the index is invalid). + /*if (client < 1 || client > MaxClients) { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d!", client); + } + + if (!IsClientConnected(client)) { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d not connected!", client); + }*/ + + return view_as(GetLerpTime(client)); +} + +int LM_GetStoredLerpTime(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + //'GetClientAuthId' - will abort the code on error (If the client is not connected or the index is invalid). + /*if (client < 1 || client > MaxClients) { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d!", client); + } + + if (!IsClientConnected(client)) { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d not connected!", client); + }*/ + + char sSteamID[STEAMID_SIZE]; + GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID)); + + float fLerpValue = -1.0; + if (ArrLerpsValue.GetValue(sSteamID, fLerpValue)) { + return view_as(fLerpValue); + } + + return view_as(-1.0); +} From 0c5ac62564c0205629028fdcd0b5d47debe081a3 Mon Sep 17 00:00:00 2001 From: A1mDev <33463136+A1mDev@users.noreply.github.com> Date: Mon, 27 Jan 2025 11:13:47 +0700 Subject: [PATCH 2/2] Add sm_bad_lerp_action cvar --- addons/sourcemod/scripting/lerpmonitor.sp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/addons/sourcemod/scripting/lerpmonitor.sp b/addons/sourcemod/scripting/lerpmonitor.sp index a10eb6d22..6c6bf9e3c 100644 --- a/addons/sourcemod/scripting/lerpmonitor.sp +++ b/addons/sourcemod/scripting/lerpmonitor.sp @@ -17,6 +17,7 @@ ConVar cVarReadyUpLerpChanges = null, cVarAllowedLerpChanges = null, cVarLerpChangeSpec = null, + cVarBadLerpAction = null, cVarMinLerp = null, cVarMaxLerp = null, cVarMinUpdateRate = null, @@ -36,7 +37,7 @@ public Plugin myinfo = name = "LerpMonitor++", author = "ProdigySim, Die Teetasse, vintik, A1m`", description = "Keep track of players' lerp settings", - version = "2.4.1", + version = "2.4.2", url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; @@ -56,6 +57,7 @@ public void OnPluginStart() { cVarAllowedLerpChanges = CreateConVar("sm_allowed_lerp_changes", "4", "Allowed number of lerp changes for a half", _, true, 0.0, true, 20.0); cVarLerpChangeSpec = CreateConVar("sm_lerp_change_spec", "1", "Move to spectators on exceeding lerp changes count?", _, true, 0.0, true, 1.0); + cVarBadLerpAction = CreateConVar("sm_bad_lerp_action", "1", "What to do with a player if he is out of allowed lerp range? 1 - move to spectators, 0 - kick from server", _, true, 0.0, true, 1.0); cVarReadyUpLerpChanges = CreateConVar("sm_readyup_lerp_changes", "1", "Allow lerp changes during ready-up", _, true, 0.0, true, 1.0); cVarShowLerpTeamChange = CreateConVar("sm_show_lerp_team_changes", "1", "show a message about the player's lerp if he changes the team", _, true, 0.0, true, 1.0); cVarMinLerp = CreateConVar("sm_min_lerp", "0.000", "Minimum allowed lerp value", _, true, 0.000, true, 0.500); @@ -259,14 +261,23 @@ void ProcessPlayerLerp(int client, bool load = false, bool team = false) float currentLerpTime = 0.0; if (ArrLerpsValue.GetValue(steamID, currentLerpTime)) { if (currentLerpTime == newLerpTime) { // no change? - ChangeClientTeam(client, L4D_TEAM_SPECTATE); + if (cVarBadLerpAction.IntValue == 1) { + ChangeClientTeam(client, L4D_TEAM_SPECTATE); + } else { + KickClient(client, "Illegal lerp value (min: %.01f, max: %.01f)", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); + } return; } } - CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was moved to spectators for lerp {teamcolor}%.01f", client, newLerpTime * 1000); - ChangeClientTeam(client, L4D_TEAM_SPECTATE); - CPrintToChatEx(client, client, "{default}<{olive}Lerp{default}> Illegal lerp value (min: {teamcolor}%.01f{default}, max: {teamcolor}%.01f{default})", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); + if (cVarBadLerpAction.IntValue == 1) { + CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was moved to spectators for lerp {teamcolor}%.01f", client, newLerpTime * 1000); + CPrintToChatEx(client, client, "{default}<{olive}Lerp{default}> Illegal lerp value (min: {teamcolor}%.01f{default}, max: {teamcolor}%.01f{default})", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); + ChangeClientTeam(client, L4D_TEAM_SPECTATE); + } else { + CPrintToChatAllEx(client, "{default}<{olive}Lerp{default}> {teamcolor}%N {default}was kicked for lerp {teamcolor}%.01f", client, newLerpTime * 1000); + KickClient(client, "Illegal lerp value (min: %.01f, max: %.01f)", cVarMinLerp.FloatValue * 1000, cVarMaxLerp.FloatValue * 1000); + } } // nothing else to do