Compare commits
5
Commits
07f9a6768e
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
789b8ebef9 | ||
|
|
1ccb5cc387 | ||
|
|
fbc8a56fe1 | ||
|
|
42ffd211e7 | ||
|
|
cfa37daeb0 |
@@ -18,7 +18,7 @@ public Plugin myinfo =
|
||||
name = "LagCompensation",
|
||||
author = "BotoX, Vauff, .Rushaway, maxime1907",
|
||||
description = "",
|
||||
version = "1.0.6",
|
||||
version = "1.1.0",
|
||||
url = ""
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ bool g_bHasOnEntitySpawned = false;
|
||||
bool g_bCheckPing = false;
|
||||
int g_iCompenseEntityClass;
|
||||
|
||||
// Dont change this.
|
||||
// Don't change this.
|
||||
#define MAX_EDICTS 2048
|
||||
#define FSOLID_FORCE_WORLD_ALIGNED 0x0040
|
||||
#define FSOLID_ROOT_PARENT_ALIGNED 0x0100
|
||||
@@ -104,6 +104,7 @@ enum struct EntityLagData
|
||||
int iNotMoving;
|
||||
bool bRestore;
|
||||
bool bLateKill;
|
||||
char sClassname[64];
|
||||
}
|
||||
|
||||
LagRecord g_aaLagRecords[MAX_ENTITIES][MAX_RECORDS];
|
||||
@@ -159,10 +160,11 @@ int g_aaFilterClientSolidTouch[((MAXPLAYERS + 1) * MAX_EDICTS) / 32];
|
||||
int g_aBlockTriggerMoved[MAX_EDICTS / 32];
|
||||
int g_aBlacklisted[MAX_EDICTS / 32];
|
||||
|
||||
Handle g_hCookie_EnableLagComp;
|
||||
Handle g_hCookie_LagCompMessages;
|
||||
bool g_bEnableLagComp[MAXPLAYERS + 1];
|
||||
Handle g_hCookie_LagCompSettings;
|
||||
bool g_bDisableLagComp[MAXPLAYERS + 1];
|
||||
bool g_bPlayerLaserCompensated[MAXPLAYERS + 1];
|
||||
bool g_bLagCompMessages[MAXPLAYERS + 1];
|
||||
bool g_bSettingsTouched[MAXPLAYERS + 1];
|
||||
int g_iDisableLagComp[MAXPLAYERS + 1];
|
||||
ConVar g_cvCompenseEntityClass;
|
||||
ConVar g_cvCheckUserPing;
|
||||
@@ -173,8 +175,8 @@ public void OnPluginStart()
|
||||
LoadTranslations("common.phrases");
|
||||
|
||||
g_cvCompenseEntityClass = CreateConVar("sm_lagcomp_entityclass", "0", "Only lagcompensate: [0 = All | 1 = func_physbox only]", _, true, 0.0, true, 1.0);
|
||||
g_cvCheckUserPing = CreateConVar("sm_lagcomp_checkuserping", "0", "Check users ping before lagcompensating them [0 = Disabled | 1 = Enabled]", _, true, 0.0, true, 1.0);
|
||||
g_cvMinimumPing = CreateConVar("sm_lagcomp_ping", "150", "Minimum ping threshold to apply lagcomp on a client", _, true, 0.0);
|
||||
g_cvCheckUserPing = CreateConVar("sm_lagcomp_checkuserping", "0", "Check user's ping before lagcompensating them [0 = Disabled | 1 = Enabled]", _, true, 0.0, true, 1.0);
|
||||
g_cvMinimumPing = CreateConVar("sm_lagcomp_ping", "180", "Minimum ping threshold to apply lagcomp on a client", _, true, 0.0);
|
||||
|
||||
AutoExecConfig(true);
|
||||
|
||||
@@ -347,16 +349,16 @@ public void OnPluginStart()
|
||||
HookConVarChange(g_cvMinimumPing, OnConVarChanged);
|
||||
|
||||
|
||||
g_hCookie_EnableLagComp = RegClientCookie("enable_lagcomp", "Client LagComp Status", CookieAccess_Private);
|
||||
g_hCookie_LagCompMessages = RegClientCookie("lagcomp_messages", "Print LagComp messages in chat", CookieAccess_Private);
|
||||
RegConsoleCmd("sm_lagcomp", OnToggleLagCompSettings);
|
||||
g_hCookie_LagCompSettings = RegClientCookie("lagcomp_settings", "LagCompensation Settings", CookieAccess_Private);
|
||||
RegConsoleCmd("sm_lagcomp", OnLagCompSettings);
|
||||
RegConsoleCmd("sm_0ping", OnToggleLagCompSettings);
|
||||
RegConsoleCmd("sm_0pinglasers", OnToggleLagCompLasersSettings);
|
||||
RegConsoleCmd("sm_checklag", CheckLagComp);
|
||||
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "LagCompensation");
|
||||
|
||||
CreateTimer(0.1, DisableLagCompTimer, _, TIMER_REPEAT);
|
||||
|
||||
RegAdminCmd("sm_unlag", Command_AddLagCompensation, ADMFLAG_ROOT, "sm_unlag <entidx>");
|
||||
RegAdminCmd("sm_unlag", Command_AddLagCompensation, ADMFLAG_ROOT, "sm_unlag <entidx> [late]");
|
||||
RegAdminCmd("sm_lagged", Command_CheckLagCompensated, ADMFLAG_ROOT, "sm_lagged");
|
||||
|
||||
FilterClientSolidTouch(g_aaFilterClientSolidTouch, true);
|
||||
@@ -486,18 +488,27 @@ public void OnMapEnd()
|
||||
|
||||
public void OnClientConnected(int client)
|
||||
{
|
||||
g_bEnableLagComp[client] = false;
|
||||
// Must match the defaults in ParseClientCookie() for clients whose cookies never cache.
|
||||
g_bDisableLagComp[client] = false;
|
||||
g_bPlayerLaserCompensated[client] = true;
|
||||
g_bLagCompMessages[client] = false;
|
||||
g_bSettingsTouched[client] = false;
|
||||
g_iDisableLagComp[client] = 0;
|
||||
g_aLerpTicks[client] = 0;
|
||||
}
|
||||
|
||||
public void OnClientCookiesCached(int client)
|
||||
{
|
||||
char sBuffer[16];
|
||||
GetClientCookie(client, g_hCookie_EnableLagComp, sBuffer, sizeof(sBuffer));
|
||||
g_bEnableLagComp[client] = StringToInt(sBuffer) != 0; //this wording should make more sense, if the cookie exists its true to enable it.
|
||||
GetClientCookie(client, g_hCookie_LagCompMessages, sBuffer, sizeof(sBuffer));
|
||||
g_bLagCompMessages[client] = StringToInt(sBuffer) != 0;
|
||||
// A toggle made before the cookies arrived wins, so flush it instead of
|
||||
// overwriting the client's choice with the stored value.
|
||||
if(g_bSettingsTouched[client])
|
||||
{
|
||||
SaveLagCompSettings(client);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load all settings from single cookie
|
||||
ParseClientCookie(client, g_bDisableLagComp[client], g_bPlayerLaserCompensated[client], g_bLagCompMessages[client]);
|
||||
}
|
||||
|
||||
public void OnClientSettingsChanged(int client)
|
||||
@@ -511,7 +522,10 @@ public void OnClientSettingsChanged(int client)
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
g_bEnableLagComp[client] = false;
|
||||
g_bDisableLagComp[client] = false;
|
||||
g_bPlayerLaserCompensated[client] = true;
|
||||
g_bLagCompMessages[client] = false;
|
||||
g_bSettingsTouched[client] = false;
|
||||
g_iDisableLagComp[client] = 0;
|
||||
}
|
||||
|
||||
@@ -529,8 +543,9 @@ public void OnEntityCreated(int entity, const char[] classname)
|
||||
DHookEntity(g_hAcceptInput, true, entity);
|
||||
}
|
||||
|
||||
if (!g_bHasOnEntitySpawned && (!strncmp(classname, "func_physbox", 12, false) || (g_iCompenseEntityClass == 0 && strcmp(classname, "trigger_hurt", false) == 0 ||
|
||||
strcmp(classname, "trigger_push", false) == 0 || strcmp(classname, "trigger_teleport", false) == 0)))
|
||||
if (!g_bHasOnEntitySpawned && (!strncmp(classname, "func_physbox", 12, false) ||
|
||||
(g_iCompenseEntityClass == 0 && (strcmp(classname, "trigger_hurt", false) == 0 ||
|
||||
strcmp(classname, "trigger_push", false) == 0 || strcmp(classname, "trigger_teleport", false) == 0))))
|
||||
{
|
||||
SDKHook(entity, SDKHook_SpawnPost, OnSDKHookEntitySpawnPost);
|
||||
}
|
||||
@@ -570,7 +585,7 @@ public MRESReturn Hook_AcceptInput(int entity, Handle hReturn, Handle hParams)
|
||||
if(iCaller <= 0 || iCaller >= MAX_EDICTS)
|
||||
return MRES_Ignored;
|
||||
|
||||
// Dont lagcompensate anything that has a game_ui button in their hierarchy.
|
||||
// Don't lagcompensate anything that has a game_ui button in their hierarchy.
|
||||
BlacklistFamily(iCaller);
|
||||
|
||||
return MRES_Ignored;
|
||||
@@ -623,7 +638,7 @@ void BlacklistChildren(int parent)
|
||||
|
||||
bool CheckEntityForLagComp(int entity, const char[] classname, bool bRecursive=false, bool bGoodParents=false)
|
||||
{
|
||||
if(entity < 0 || entity > MAX_EDICTS)
|
||||
if(entity < 0 || entity >= MAX_EDICTS)
|
||||
return false;
|
||||
|
||||
if(!IsValidEntity(entity))
|
||||
@@ -668,7 +683,7 @@ bool CheckEntityForLagComp(int entity, const char[] classname, bool bRecursive=f
|
||||
return false;
|
||||
}
|
||||
|
||||
if(CheckBit(g_aBlacklisted, entity))
|
||||
if(CheckBit(g_aBlacklisted, iParent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -736,7 +751,7 @@ public void OnEntityDestroyed(int entity)
|
||||
if(g_bCleaningUp)
|
||||
return;
|
||||
|
||||
if(entity < 0 || entity > MAX_EDICTS)
|
||||
if(entity < 0 || entity >= MAX_EDICTS)
|
||||
return;
|
||||
|
||||
ClearBit(g_aBlacklisted, entity);
|
||||
@@ -758,7 +773,7 @@ public MRESReturn Detour_OnUTIL_Remove(Handle hParams)
|
||||
return MRES_Ignored;
|
||||
|
||||
int entity = DHookGetParamObjectPtrVar(hParams, 1, g_iNetworkableOuter, ObjectValueType_CBaseEntityPtr);
|
||||
if(entity < 0 || entity > MAX_EDICTS)
|
||||
if(entity < 0 || entity >= MAX_EDICTS)
|
||||
return MRES_Ignored;
|
||||
|
||||
int iIndex = g_aLagCompensated[entity];
|
||||
@@ -858,8 +873,8 @@ public MRESReturn Detour_OnFrameUpdatePostEntityThink()
|
||||
for(int i = 0; i < g_iNumEntities; i++)
|
||||
{
|
||||
// Dont make the entity check untouch in FrameUpdatePostEntityThink.
|
||||
// If the player didnt get simulated in the current frame then
|
||||
// they didnt have a chance to touch this entity.
|
||||
// If the player didn't get simulated in the current frame then
|
||||
// they didn't have a chance to touch this entity.
|
||||
// Hence the touchlink could be broken and we only let the player check untouch.
|
||||
int EFlags = GetEntData(g_aEntityLagData[i].iEntity, g_iEFlags);
|
||||
EFlags &= ~EFL_CHECK_UNTOUCH;
|
||||
@@ -877,7 +892,7 @@ public void OnRunThinkFunctions(bool simulating)
|
||||
|
||||
public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
|
||||
{
|
||||
if(!IsPlayerAlive(client) || IsFakeClient(client))
|
||||
if(!IsClientInGame(client) || !IsPlayerAlive(client) || IsFakeClient(client))
|
||||
return Plugin_Continue;
|
||||
|
||||
int iTargetTick = tickcount - g_aLerpTicks[client];
|
||||
@@ -928,6 +943,13 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
|
||||
continue;
|
||||
|
||||
int iRecord = iDelta;
|
||||
|
||||
if(!g_bPlayerLaserCompensated[client] &&
|
||||
(strcmp(g_aEntityLagData[i].sClassname, "trigger_hurt", false) == 0 ||
|
||||
strcmp(g_aEntityLagData[i].sClassname, "trigger_push", false) == 0 ||
|
||||
strcmp(g_aEntityLagData[i].sClassname, "trigger_teleport", false) == 0))
|
||||
iRecord = 0;
|
||||
|
||||
if(iRecord >= g_aEntityLagData[i].iNumRecords)
|
||||
iRecord = g_aEntityLagData[i].iNumRecords - 1;
|
||||
|
||||
@@ -1112,6 +1134,10 @@ bool AddEntityForLagCompensation(int iEntity, bool bLateKill)
|
||||
if(g_bCleaningUp)
|
||||
return false;
|
||||
|
||||
// sm_unlag takes an arbitrary index from the console, so validate before indexing anything.
|
||||
if(iEntity < 0 || iEntity >= MAX_EDICTS || !IsValidEntity(iEntity))
|
||||
return false;
|
||||
|
||||
if(g_aLagCompensated[iEntity] != -1)
|
||||
return false;
|
||||
|
||||
@@ -1144,6 +1170,7 @@ bool AddEntityForLagCompensation(int iEntity, bool bLateKill)
|
||||
g_aEntityLagData[i].iNotMoving = MAX_RECORDS;
|
||||
g_aEntityLagData[i].bRestore = false;
|
||||
g_aEntityLagData[i].bLateKill = bLateKill;
|
||||
g_aEntityLagData[i].sClassname = sClassname;
|
||||
|
||||
if(bLateKill)
|
||||
{
|
||||
@@ -1226,6 +1253,7 @@ void EntityLagData_Copy(EntityLagData obj, const EntityLagData other)
|
||||
obj.iNotMoving = other.iNotMoving;
|
||||
obj.bRestore = other.bRestore;
|
||||
obj.bLateKill = other.bLateKill;
|
||||
obj.sClassname = other.sClassname;
|
||||
}
|
||||
|
||||
void LagRecord_Copy(LagRecord obj, const LagRecord other)
|
||||
@@ -1253,6 +1281,59 @@ bool CompareVectors(const float vec1[3], const float vec2[3])
|
||||
return vec1[0] == vec2[0] && vec1[1] == vec2[1] && vec1[2] == vec2[2];
|
||||
}
|
||||
|
||||
void SaveLagCompSettings(int client)
|
||||
{
|
||||
// Remember that this client chose something, so OnClientCookiesCached
|
||||
// flushes it rather than loading over the top of it.
|
||||
g_bSettingsTouched[client] = true;
|
||||
|
||||
// Cookie reads/writes are meaningless until the cookies arrive; we get called back then.
|
||||
if(!AreClientCookiesCached(client))
|
||||
return;
|
||||
|
||||
// Read current cookie values
|
||||
bool currentDisableLagComp, currentPlayerLaserCompensated, currentLagCompMessages;
|
||||
ParseClientCookie(client, currentDisableLagComp, currentPlayerLaserCompensated, currentLagCompMessages);
|
||||
|
||||
// Check if values have changed
|
||||
bool disableChanged = g_bDisableLagComp[client] != currentDisableLagComp;
|
||||
bool laserChanged = g_bPlayerLaserCompensated[client] != currentPlayerLaserCompensated;
|
||||
bool messagesChanged = g_bLagCompMessages[client] != currentLagCompMessages;
|
||||
|
||||
// If no values have changed, no need to save
|
||||
if (!disableChanged && !laserChanged && !messagesChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, save the chain format
|
||||
char sBuffer[8];
|
||||
Format(sBuffer, sizeof(sBuffer), "%d%d%d",
|
||||
g_bDisableLagComp[client] ? 1 : 0,
|
||||
g_bPlayerLaserCompensated[client] ? 1 : 0,
|
||||
g_bLagCompMessages[client] ? 1 : 0);
|
||||
SetClientCookie(client, g_hCookie_LagCompSettings, sBuffer);
|
||||
}
|
||||
|
||||
void ParseClientCookie(int client, bool &disableLagComp, bool &playerLaserCompensated, bool &lagCompMessages)
|
||||
{
|
||||
char buffer[16];
|
||||
GetClientCookie(client, g_hCookie_LagCompSettings, buffer, sizeof(buffer));
|
||||
|
||||
// Parse chain format: disable|laser|messages
|
||||
if (strlen(buffer) >= 3)
|
||||
{
|
||||
disableLagComp = (buffer[0] == '1');
|
||||
playerLaserCompensated = (buffer[1] == '1');
|
||||
lagCompMessages = (buffer[2] == '1');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default values
|
||||
disableLagComp = false;
|
||||
playerLaserCompensated = true;
|
||||
lagCompMessages = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_AddLagCompensation(int client, int argc)
|
||||
{
|
||||
@@ -1355,9 +1436,9 @@ stock void PrintToBoth(const char[] format, any ...)
|
||||
|
||||
for(int client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
if (IsClientInGame(client) && g_bLagCompMessages[client])
|
||||
if (IsClientInGame(client) && g_bLagCompMessages[client] && CheckCommandAccess(client, "sm_lagged", ADMFLAG_ROOT))
|
||||
{
|
||||
PrintToChat(client, "%s", buffer);
|
||||
PrintToConsole(client, "%s", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1370,22 +1451,25 @@ public Action DisableLagCompTimer(Handle timer)
|
||||
continue;
|
||||
|
||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/master/sp/src/game/server/util.cpp#L747
|
||||
// Lag compensation only kicks in above the ping threshold, so ramp it off below it.
|
||||
if (g_bCheckPing)
|
||||
{
|
||||
int iAvgPing = RoundFloat(GetClientAvgLatency(client, NetFlow_Outgoing) * 1000);
|
||||
|
||||
if (iAvgPing > g_iMinPing)
|
||||
if (iAvgPing <= g_iMinPing)
|
||||
{
|
||||
g_iDisableLagComp[client]++;
|
||||
return Plugin_Continue;
|
||||
if(g_iDisableLagComp[client] < MAX_RECORDS)
|
||||
g_iDisableLagComp[client]++;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!g_bEnableLagComp[client] && g_iDisableLagComp[client] < MAX_RECORDS)
|
||||
if(g_bDisableLagComp[client] && g_iDisableLagComp[client] < MAX_RECORDS)
|
||||
{
|
||||
g_iDisableLagComp[client]++;
|
||||
}
|
||||
else if(g_bEnableLagComp[client] && g_iDisableLagComp[client] > 0)
|
||||
else if(!g_bDisableLagComp[client] && g_iDisableLagComp[client] > 0)
|
||||
{
|
||||
g_iDisableLagComp[client]--;
|
||||
}
|
||||
@@ -1406,33 +1490,52 @@ public Action OnToggleLagCompSettings(int client, int args)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action OnToggleLagCompLasersSettings(int client, int args)
|
||||
{
|
||||
ToggleLagCompLasers(client);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void ToggleLagCompSettings(int client)
|
||||
{
|
||||
if(!client)
|
||||
if(!client || !IsClientInGame(client) || IsFakeClient(client))
|
||||
return;
|
||||
|
||||
g_bEnableLagComp[client] = !g_bEnableLagComp[client];
|
||||
SetClientCookie(client, g_hCookie_EnableLagComp, g_bEnableLagComp[client] ? "1" : "");
|
||||
g_bDisableLagComp[client] = !g_bDisableLagComp[client];
|
||||
SaveLagCompSettings(client);
|
||||
|
||||
CPrintToChat(client, "%s LagCompensation has been %s.", PREFIX, g_bEnableLagComp[client] ? "enabled" : "disabled");
|
||||
CPrintToChat(client, "%s LagCompensation has been %s.", PREFIX, g_bDisableLagComp[client] ? "disabled" : "enabled");
|
||||
}
|
||||
|
||||
public void ToggleLagCompLasers(int client)
|
||||
{
|
||||
if(!client || !IsClientInGame(client) || IsFakeClient(client))
|
||||
return;
|
||||
|
||||
g_bPlayerLaserCompensated[client] = !g_bPlayerLaserCompensated[client];
|
||||
SaveLagCompSettings(client);
|
||||
|
||||
CPrintToChat(client, "%s LagCompensation for Lasers has been %s.", PREFIX, g_bPlayerLaserCompensated[client] ? "enabled" : "disabled");
|
||||
if (g_bCheckPing && g_bPlayerLaserCompensated[client])
|
||||
CPrintToChat(client, "%s It will take effect if your real ping is higher than %dms.", PREFIX, g_iMinPing);
|
||||
}
|
||||
|
||||
public void ToggleLagCompMessages(int client)
|
||||
{
|
||||
if(!client)
|
||||
if(!client || !IsClientInGame(client) || IsFakeClient(client))
|
||||
return;
|
||||
|
||||
g_bLagCompMessages[client] = !g_bLagCompMessages[client];
|
||||
SetClientCookie(client, g_hCookie_LagCompMessages, g_bLagCompMessages[client] ? "1" : "");
|
||||
SaveLagCompSettings(client);
|
||||
|
||||
CPrintToChat(client, "%s LagCompensation messages have been %s.", PREFIX, g_bLagCompMessages[client] ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
public Action CheckLagComp(int client, int args)
|
||||
{
|
||||
if (args > 1)
|
||||
if (args > 1 || (args == 0 && !client))
|
||||
{
|
||||
CPrintToChat(client, "%s Usage sm_checklag <client>", PREFIX);
|
||||
CReplyToCommand(client, "%s Usage: sm_checklag <client>", PREFIX);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
@@ -1455,7 +1558,14 @@ public Action CheckLagComp(int client, int args)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
CPrintToChat(client, "%s LagCompensation is %s for {olive}%N", PREFIX, g_bEnableLagComp[target] ? sEnable : "disabled", target);
|
||||
CReplyToCommand(client, "%s LagCompensation is %s for {olive}%N", PREFIX, g_bDisableLagComp[target] ? "disabled" : sEnable, target);
|
||||
CReplyToCommand(client, "%s Laser compensation: %s", PREFIX, g_bPlayerLaserCompensated[target] ? "enabled" : "disabled");
|
||||
|
||||
// g_iDisableLagComp also ramps from the ping threshold, so report it when they haven't opted out.
|
||||
if(!g_bDisableLagComp[target] && g_iDisableLagComp[target] > 0)
|
||||
CReplyToCommand(client, "%s Currently reduced: %d of %d ticks skipped%s.", PREFIX,
|
||||
g_iDisableLagComp[target], MAX_RECORDS,
|
||||
g_bCheckPing ? " (ping at or below the threshold ramps this up)" : "");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
@@ -1463,15 +1573,17 @@ public Action CheckLagComp(int client, int args)
|
||||
public void ShowSettingsMenu(int client)
|
||||
{
|
||||
Menu menu = new Menu(MenuHandler_MainMenu);
|
||||
menu.SetTitle("LagCompensation Settings", client);
|
||||
menu.SetTitle("LagCompensation Settings");
|
||||
menu.ExitBackButton = true;
|
||||
|
||||
char buffer[128], msg_buffer[128];
|
||||
Format(buffer, sizeof(buffer), "LagCompensation: %s", g_bEnableLagComp[client] ? "Enabled" : "Disabled");
|
||||
char buffer[128], buffer_lasers[128], msg_buffer[128];
|
||||
Format(buffer, sizeof(buffer), "LagCompensation: %s", g_bDisableLagComp[client] ? "Disabled" : "Enabled");
|
||||
Format(buffer_lasers, sizeof(buffer_lasers), "LagCompensation for Lasers: %s", g_bPlayerLaserCompensated[client] ? "Enabled" : "Disabled");
|
||||
Format(msg_buffer, sizeof(msg_buffer), "LagCompensation Messages: %s", g_bLagCompMessages[client] ? "Enabled" : "Disabled");
|
||||
|
||||
menu.AddItem("0", buffer);
|
||||
menu.AddItem("1", msg_buffer);
|
||||
menu.AddItem("1", buffer_lasers);
|
||||
menu.AddItem("2", msg_buffer, CheckCommandAccess(client, "sm_lagged", ADMFLAG_ROOT) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED);
|
||||
|
||||
menu.Display(client, MENU_TIME_FOREVER);
|
||||
}
|
||||
@@ -1482,7 +1594,7 @@ public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info
|
||||
{
|
||||
case(CookieMenuAction_DisplayOption):
|
||||
{
|
||||
Format(buffer, maxlen, "LagCompensation", client);
|
||||
strcopy(buffer, maxlen, "LagCompensation");
|
||||
}
|
||||
case(CookieMenuAction_SelectOption):
|
||||
{
|
||||
@@ -1500,7 +1612,8 @@ public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int se
|
||||
switch(selection)
|
||||
{
|
||||
case(0): ToggleLagCompSettings(client);
|
||||
case(1): ToggleLagCompMessages(client);
|
||||
case(1): ToggleLagCompLasers(client);
|
||||
case(2): ToggleLagCompMessages(client);
|
||||
}
|
||||
|
||||
ShowSettingsMenu(client);
|
||||
|
||||
@@ -21,9 +21,16 @@ Menu g_NpcMenu = null;
|
||||
KeyValues g_Models;
|
||||
|
||||
ConVar g_cvNotifyShot;
|
||||
ConVar g_cvNotifyTimer;
|
||||
|
||||
ArrayList g_aSpawnedProps; // Tracks entity indices of props spawned by this plugin so we can unhook them
|
||||
ArrayList g_aNotifyList;
|
||||
|
||||
enum struct NotifyListData
|
||||
{
|
||||
int client;
|
||||
Handle timer;
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
@@ -49,9 +56,11 @@ public void OnPluginStart()
|
||||
RegAdminCmd("sm_propspawner", Command_MainMenu, ADMFLAG_CHANGEMAP); //g
|
||||
|
||||
g_cvNotifyShot = CreateConVar("sm_propspawner_notify_shot", "0", "If set to 1, announces in chat when a plugin-spawned prop is shot.", FCVAR_NOTIFY, true, 0.0, true, 1.0);
|
||||
g_cvNotifyTimer = CreateConVar("sm_propspawner_notify_shot_timer", "0.5", "How long a player stays in the \"shooting couch\" list.");
|
||||
AutoExecConfig(true, "PropSpawner");
|
||||
|
||||
g_aSpawnedProps = new ArrayList();
|
||||
g_aNotifyList = new ArrayList();
|
||||
|
||||
HookEvent("round_end", Event_RoundEnd);
|
||||
}
|
||||
@@ -226,7 +235,7 @@ public int MainMenuHandler(Menu menu, MenuAction action, int client, int param2)
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public RotationHandler(Menu menu, MenuAction action, int client, int param2)
|
||||
@@ -547,7 +556,7 @@ void prop_any_create(int client)
|
||||
// Hook the prop so we can detect when it gets shot/damaged, and track it so we can unhook later
|
||||
if (g_cvNotifyShot.BoolValue)
|
||||
{
|
||||
SetEntityFlags(prop, FL_CLIENT); //Now youre thinking with portals
|
||||
SetEntityFlags(prop, FL_CLIENT); //Now youre thinking with portals
|
||||
SDKHook(prop, SDKHook_OnTakeDamage, OnPropTakeDamage);
|
||||
g_aSpawnedProps.Push(prop);
|
||||
}
|
||||
@@ -566,14 +575,85 @@ public Action OnPropTakeDamage(int victim, int &attacker, int &inflictor, float
|
||||
if (attacker < 1 || attacker > MaxClients || !IsClientInGame(attacker))
|
||||
return Plugin_Continue;
|
||||
|
||||
char sPropName[64];
|
||||
GetEntPropString(victim, Prop_Data, "m_ModelName", sPropName, sizeof(sPropName));
|
||||
Handle timer = CreateTimer(g_cvNotifyTimer.FloatValue, OnNotifyTimer, attacker);
|
||||
int idx = FindInNotifyList(attacker);
|
||||
if (idx == -1)
|
||||
{
|
||||
NotifyListData data;
|
||||
data.client = attacker;
|
||||
data.timer = timer;
|
||||
g_aNotifyList.PushArray(data, sizeof(NotifyListData));
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyListData buf;
|
||||
g_aNotifyList.GetArray(idx, buf, sizeof(NotifyListData));
|
||||
if (buf.timer != INVALID_HANDLE)
|
||||
KillTimer(buf.timer);
|
||||
|
||||
char sAttackerName[MAX_NAME_LENGTH];
|
||||
GetClientName(attacker, sAttackerName, sizeof(sAttackerName));
|
||||
buf.timer = timer;
|
||||
g_aNotifyList.SetArray(idx, buf, sizeof(NotifyListData));
|
||||
}
|
||||
|
||||
PrintToChatAll("\x01[SM] \x04%s\x01 is shooting the couch.", sAttackerName);
|
||||
DisplayNotifyList();
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void DisplayNotifyList()
|
||||
{
|
||||
static int channel = -1;
|
||||
char text[255];
|
||||
strcopy(text, sizeof(text), "Shooting Couch:\n");
|
||||
|
||||
for (int i = g_aNotifyList.Length - 1; i >= 0; i--)
|
||||
{
|
||||
NotifyListData buf;
|
||||
g_aNotifyList.GetArray(i, buf, sizeof(NotifyListData));
|
||||
|
||||
if (!IsClientInGame(buf.client))
|
||||
{
|
||||
if (buf.timer != INVALID_HANDLE)
|
||||
KillTimer(buf.timer);
|
||||
|
||||
g_aNotifyList.Erase(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
char clientName[32];
|
||||
GetClientName(buf.client, clientName, sizeof(clientName));
|
||||
StrCat(text, sizeof(text), clientName);
|
||||
StrCat(text, sizeof(text), "\n");
|
||||
}
|
||||
|
||||
SetHudTextParams(0.8, -1.0, g_cvNotifyTimer.FloatValue, 255, 255, 255, 255, 0, 0.0, 0.0, 0.0);
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (IsClientInGame(i))
|
||||
channel = ShowHudText(i, channel, text);
|
||||
}
|
||||
}
|
||||
|
||||
void OnNotifyTimer(Handle timer, any data)
|
||||
{
|
||||
int client = view_as<int>(data);
|
||||
int idx = FindInNotifyList(client);
|
||||
if (idx != -1)
|
||||
g_aNotifyList.Erase(idx);
|
||||
|
||||
if (g_aNotifyList.Length)
|
||||
DisplayNotifyList();
|
||||
}
|
||||
|
||||
int FindInNotifyList(int client)
|
||||
{
|
||||
for (int i = 0; i < g_aNotifyList.Length; i++)
|
||||
{
|
||||
NotifyListData buf;
|
||||
g_aNotifyList.GetArray(i, buf, sizeof(NotifyListData));
|
||||
if (buf.client == client)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2310,6 +2310,16 @@ NominateResult InternalNominateMap(char[] map, int owner)
|
||||
return Nominate_Added;
|
||||
}
|
||||
|
||||
public void GetMapCategory(const char[] mapname, char[] output_category, int maxlen)
|
||||
{
|
||||
strcopy(output_category, maxlen, "Uncategorized");
|
||||
if (g_Config && g_Config.JumpToKey(mapname))
|
||||
{
|
||||
g_Config.GetString("MapCategory", output_category, maxlen, "Uncategorized");
|
||||
g_Config.Rewind();
|
||||
}
|
||||
}
|
||||
|
||||
/* Add natives to allow nominate and initiate vote to be call */
|
||||
|
||||
/* native bool NominateMap(const char[] map, bool force, &NominateError:error); */
|
||||
@@ -3054,7 +3064,17 @@ public int Native_SimulateMapEnd(Handle plugin, int numParams)
|
||||
|
||||
stock void AddMapItem(const char[] map)
|
||||
{
|
||||
AddMenuItem(g_VoteMenu, map, map);
|
||||
char map_with_category[1024];
|
||||
if (StrContains(map, "ze_") == 0)
|
||||
{
|
||||
GetMapCategory(map, map_with_category, sizeof(map_with_category));
|
||||
Format(map_with_category, sizeof(map_with_category), "%s (%s)", map, map_with_category);
|
||||
AddMenuItem(g_VoteMenu, map, map_with_category);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMenuItem(g_VoteMenu, map, map);
|
||||
}
|
||||
}
|
||||
|
||||
stock void GetMapItem(Handle menu, int position, char[] map, int mapLen)
|
||||
|
||||
Reference in New Issue
Block a user