Compare commits
121
Commits
9d3a9e6b89
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
789b8ebef9 | ||
|
|
1ccb5cc387 | ||
|
|
fbc8a56fe1 | ||
|
|
42ffd211e7 | ||
|
|
cfa37daeb0 | ||
|
|
07f9a6768e | ||
|
|
6b7803d46e | ||
|
|
ac67f2e27e | ||
|
|
ef4bc91712 | ||
|
|
e3e70fcb12 | ||
|
|
4fd3017e5f | ||
|
|
b791b050fc | ||
|
|
48ff38522b | ||
|
|
5a8c97e082 | ||
|
|
d697faa470 | ||
|
|
cb8d244030 | ||
|
|
2e21de0c47 | ||
|
|
80642cb0f0 | ||
|
|
06d0b43b9c | ||
|
|
b6c0cb232d | ||
|
|
a02fea8cc8 | ||
|
|
a4e2d541a9 | ||
|
|
1cb0905d78 | ||
|
|
14e83ec9a3 | ||
|
|
a72b0d9a8d | ||
|
|
4cf475c109 | ||
|
|
ef5ba318c1 | ||
|
|
2bde95afcc | ||
|
|
1fa8a916d6 | ||
|
|
52a452708e | ||
|
|
8ef2f2f2cc | ||
|
|
b527ce5473 | ||
|
|
921ae4e136 | ||
|
|
fd32ddc101 | ||
|
|
2b9224f11a | ||
|
|
ef15dfc71c | ||
|
|
2d91202469 | ||
|
|
622bc8da4e | ||
|
|
295c92f49f | ||
|
|
47460a2db4 | ||
|
|
a23be2483f | ||
|
|
b6e7443448 | ||
|
|
e3e5945e77 | ||
|
|
a8dbd00f89 | ||
|
|
f6536fd3c5 | ||
|
|
8ca6ecae97 | ||
|
|
02a990a29f | ||
|
|
1139fd89d0 | ||
|
|
5986bedc42 | ||
|
|
ee18f49be0 | ||
|
|
5a1ca4959d | ||
|
|
4a9a8e06cf | ||
|
|
6b625bc7ea | ||
|
|
bf6ed6e4e1 | ||
|
|
4469d07602 | ||
|
|
ce78793029 | ||
|
|
509bd521fb | ||
|
|
71d8773767 | ||
|
|
111cc27521 | ||
|
|
c03f450e8e | ||
|
|
e2b3ead9c3 | ||
|
|
c379458632 | ||
|
|
9e59258ab0 | ||
|
|
e2659d79a6 | ||
|
|
e74db611c4 | ||
|
|
fefad5ce8a | ||
|
|
3d7e279cc7 | ||
|
|
e86e90838a | ||
|
|
7ec6fed775 | ||
|
|
e5974b7478 | ||
|
|
429a2d1b0f | ||
|
|
07c8d450b3 | ||
|
|
a460fbeaeb | ||
|
|
4b89862452 | ||
|
|
8be8ced61a | ||
|
|
88b153ea3c | ||
|
|
e0672ab09b | ||
|
|
56c97b7d29 | ||
|
|
bf4c76a17c | ||
|
|
06e5c325ac | ||
|
|
4914461539 | ||
|
|
e3a85e1b65 | ||
|
|
5cce927ced | ||
|
|
b8ac8cc571 | ||
|
|
723525f8c5 | ||
|
|
890e2e1418 | ||
|
|
61568dc032 | ||
|
|
8b6f2e0d96 | ||
|
|
9ff0faf337 | ||
|
|
b6a1c15b7e | ||
|
|
0866d58b59 | ||
|
|
6acdc80767 | ||
|
|
80d0b85367 | ||
|
|
1df4cdf8dc | ||
|
|
c819974dd6 | ||
|
|
d48a5b14c1 | ||
|
|
45258da9e1 | ||
|
|
8e46053c0b | ||
|
|
2b67f52368 | ||
|
|
f5804eed72 | ||
|
|
c57aa5bcc2 | ||
|
|
4a1ac398d0 | ||
|
|
f590dcc7d1 | ||
|
|
01816792ae | ||
|
|
f37711fbdf | ||
|
|
7d5e56540a | ||
|
|
8e33a8bd87 | ||
|
|
208d084024 | ||
|
|
b4c4b11c3d | ||
|
|
778fdd2f7a | ||
|
|
d396e006b9 | ||
|
|
d12aff14ac | ||
|
|
7e3ad44699 | ||
|
|
13f4727826 | ||
|
|
06734d1b6e | ||
|
|
ff012d2df5 | ||
|
|
ef537b8826 | ||
|
|
6790e463fc | ||
|
|
6a5cbf74f1 | ||
|
|
a5a856073e | ||
|
|
3122ed0210 |
@@ -0,0 +1,76 @@
|
|||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <cstrike>
|
||||||
|
#include <AFKManager>
|
||||||
|
|
||||||
|
int g_iPlayer_move_spec_count;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "spectator_handler",
|
||||||
|
author = "jenz",
|
||||||
|
description = "moves afk spectators to team",
|
||||||
|
version = "1.3",
|
||||||
|
url = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
CreateTimer(60.0, CheckAfks, _, TIMER_REPEAT);
|
||||||
|
|
||||||
|
ConVar cvar;
|
||||||
|
HookConVarChange((cvar = CreateConVar("sm_move_spec_to_team_count", "30", "Move real players from spec to teams until this many real players are connected")), Cvar_move_spec_team);
|
||||||
|
g_iPlayer_move_spec_count = cvar.IntValue;
|
||||||
|
delete cvar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_move_spec_team(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iPlayer_move_spec_count = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CheckAfks(Handle timer)
|
||||||
|
{
|
||||||
|
int real_players = 0;
|
||||||
|
for (int i = 0; i < MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i) && !IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
real_players++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (real_players < g_iPlayer_move_spec_count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && GetClientTeam(i) <= CS_TEAM_SPECTATOR && GetClientIdleTime(i) > 60)
|
||||||
|
{
|
||||||
|
ChangeClientTeam(i, CS_TEAM_T);
|
||||||
|
CreateTimer(1.0, zspawn, GetClientSerial(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action zspawn(Handle hTimer, int Serial)
|
||||||
|
{
|
||||||
|
int client;
|
||||||
|
if ((client = GetClientFromSerial(Serial)) == 0)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
if (IsValidClient(client))
|
||||||
|
{
|
||||||
|
FakeClientCommandEx(client, "joinclass");
|
||||||
|
FakeClientCommandEx(client, "say /zspawn");
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client)
|
||||||
|
{
|
||||||
|
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -1,65 +1,140 @@
|
|||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <BotTargeting>
|
|
||||||
#include <cstrike>
|
#include <cstrike>
|
||||||
|
#include <mapchooser_extended>
|
||||||
|
|
||||||
|
int g_iDoingMapTouristMode;
|
||||||
|
int g_iActivePlayerCount;
|
||||||
|
bool g_bMapended;
|
||||||
|
|
||||||
public Plugin myinfo =
|
public Plugin myinfo =
|
||||||
{
|
{
|
||||||
name = "knockback low pop modifier",
|
name = "knockback low pop modifier and helper",
|
||||||
author = "jenz",
|
author = "jenz",
|
||||||
description = "balances knockback for low population",
|
description = "balances knockback and human settings for low population",
|
||||||
version = "1.0.0",
|
version = "2.1.0",
|
||||||
url = ""
|
url = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPluginStart()
|
public void OnPluginStart()
|
||||||
{
|
{
|
||||||
HookEvent("round_start", OnRoundStart);
|
HookEvent("round_start", OnRoundStart);
|
||||||
|
RegAdminCmd("sm_helpon", Cmd_enableHelp, ADMFLAG_GENERIC);
|
||||||
|
RegAdminCmd("sm_helpoff", Cmd_disableHelp, ADMFLAG_GENERIC);
|
||||||
|
CreateTimer(80.0, CheckPopulation, _, TIMER_REPEAT);
|
||||||
|
g_iDoingMapTouristMode = 0;
|
||||||
|
g_iActivePlayerCount = 0;
|
||||||
|
g_bMapended = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Cmd_enableHelp(int client, int args)
|
||||||
|
{
|
||||||
|
PrintToChatAll("ADMIN ENABLED LOW POP HELP");
|
||||||
|
CreateTimer(1.0, SetHealthOnCT);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Cmd_disableHelp(int client, int args)
|
||||||
|
{
|
||||||
|
PrintToChatAll("ADMIN DISABLED LOW POP HELP");
|
||||||
|
ServerCommand("sm_iammo @all 0");
|
||||||
|
ServerCommand("sm_hp @ct 100");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CheckPopulation(Handle timer)
|
||||||
|
{
|
||||||
|
int TimeLeft;
|
||||||
|
if (GetMapTimeLeft(TimeLeft) && TimeLeft < 0)
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
if (g_bMapended)
|
||||||
|
{
|
||||||
|
g_bMapended = false;
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_iActivePlayerCount = 0;
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i))
|
||||||
|
{
|
||||||
|
g_iActivePlayerCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPluginEnd()
|
public void OnPluginEnd()
|
||||||
{
|
{
|
||||||
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
||||||
|
g_iDoingMapTouristMode = 0;
|
||||||
|
g_iActivePlayerCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnMapEnd()
|
public void OnMapEnd()
|
||||||
{
|
{
|
||||||
|
g_iDoingMapTouristMode = 0;
|
||||||
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
||||||
|
g_bMapended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
char map[PLATFORM_MAX_PATH];
|
||||||
|
GetCurrentMap(map, PLATFORM_MAX_PATH);
|
||||||
|
|
||||||
|
//skipping de_, cs_, zm_ maps
|
||||||
|
if (StrContains(map, "ze_") == 0)
|
||||||
|
{
|
||||||
|
//LowPopHelpCount
|
||||||
|
g_iDoingMapTouristMode = GetMapLowPopHelpCount(map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
int active_player_count = 0;
|
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
||||||
|
ServerCommand("sm_iammo @all 0");
|
||||||
|
|
||||||
for (int i = 1; i <= MaxClients; i++)
|
int choosen_number = 35;
|
||||||
{
|
if (g_iDoingMapTouristMode > g_iActivePlayerCount > 0)
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i) && !IsFakeClient(i) && !IsClientAutismBot(i) && !IsClientSourceTV(i) && GetClientTeam(i) > CS_TEAM_SPECTATOR)
|
{
|
||||||
{
|
CreateTimer(3.0, SetHealthOnCT);
|
||||||
active_player_count++;
|
}
|
||||||
}
|
else if (g_iActivePlayerCount < choosen_number)
|
||||||
}
|
{
|
||||||
|
|
||||||
if (active_player_count < 24)
|
|
||||||
{
|
|
||||||
int zombie_ratio = GetConVarInt(FindConVar("zr_infect_mzombie_ratio"));
|
int zombie_ratio = GetConVarInt(FindConVar("zr_infect_mzombie_ratio"));
|
||||||
|
int infectectable_players = 0;
|
||||||
float knockback_increase = float(zombie_ratio) / float(active_player_count);
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i) && GetClientTeam(i) > CS_TEAM_SPECTATOR)
|
||||||
|
{
|
||||||
|
infectectable_players++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float knockback_increase = float(zombie_ratio) / float(infectectable_players);
|
||||||
if (knockback_increase > 3.0)
|
if (knockback_increase > 3.0)
|
||||||
knockback_increase = 3.0;
|
knockback_increase = 3.0;
|
||||||
else if(knockback_increase < 1.0)
|
else if(knockback_increase < 1.0)
|
||||||
knockback_increase = 1.0
|
knockback_increase = 1.0
|
||||||
|
|
||||||
if (knockback_increase > 1.0)
|
if (knockback_increase > 1.0)
|
||||||
{
|
{
|
||||||
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
||||||
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
||||||
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
PrintToChatAll("LOW POP: increased zombie knockback to X%.2f to balance gameplay", knockback_increase);
|
||||||
}
|
ServerCommand("zr_class_set_multiplier zombies knockback %.2f", knockback_increase);
|
||||||
|
}
|
||||||
ServerCommand("zr_class_set_multiplier zombies knockback %.2f", knockback_increase);
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
public Action SetHealthOnCT(Handle timer)
|
||||||
ServerCommand("zr_class_set_multiplier zombies knockback 1.0");
|
{
|
||||||
}
|
PrintToChatAll("LOW POP ON DIFFICULT MAP: ENABLING INFINITE AMMO AND 500 HP FOR CT");
|
||||||
|
PrintToChatAll("LOW POP ON DIFFICULT MAP: ENABLING INFINITE AMMO AND 500 HP FOR CT");
|
||||||
|
PrintToChatAll("LOW POP ON DIFFICULT MAP: ENABLING INFINITE AMMO AND 500 HP FOR CT");
|
||||||
|
ServerCommand("sm_iammo @all 1");
|
||||||
|
ServerCommand("sm_hp @ct 500");
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-30
@@ -21,7 +21,7 @@ ConVar g_hCvar_DebugMode;
|
|||||||
|
|
||||||
char g_sHUDText[256];
|
char g_sHUDText[256];
|
||||||
|
|
||||||
Handle g_aHurtEntityToBoss[4096] = {INVALID_HANDLE, ...};
|
Handle g_aHurtEntityToBoss[8191] = {INVALID_HANDLE, ...};
|
||||||
|
|
||||||
public Plugin myinfo =
|
public Plugin myinfo =
|
||||||
{
|
{
|
||||||
@@ -495,7 +495,7 @@ public void OnEntitySpawned(int entity, const char[] classname)
|
|||||||
{
|
{
|
||||||
char sBoss[64];
|
char sBoss[64];
|
||||||
Config.GetName(sBoss, sizeof(sBoss));
|
Config.GetName(sBoss, sizeof(sBoss));
|
||||||
LogDebugMessage("Couldn't find boss \"%s\" for hurttrigger %s:%s", sBoss, sHurtTrigger, sHurtOutput);
|
LogDebugMessage("Couldnt find boss \"%s\" for hurttrigger %s:%s", sBoss, sHurtTrigger, sHurtOutput);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -931,33 +931,45 @@ public void OnGameFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!IsVoteInProgress())
|
bool voteInProgress = IsVoteInProgress();
|
||||||
{
|
if(g_sHUDText[0])
|
||||||
if(g_sHUDText[0])
|
{
|
||||||
{
|
for(int client = 1; client <= MaxClients; client++)
|
||||||
for(int client = 1; client <= MaxClients; client++)
|
{
|
||||||
{
|
if(IsClientInGame(client))
|
||||||
if(IsClientInGame(client))
|
{
|
||||||
{
|
if (voteInProgress)
|
||||||
PrintHintText(client, g_sHUDText);
|
{
|
||||||
StopSound(client, SNDCHAN_STATIC, "UI/hint.wav");
|
PrintCenterText(client, g_sHUDText);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
s_bLastHudPrinted = true;
|
{
|
||||||
}
|
PrintHintText(client, g_sHUDText);
|
||||||
else if(s_bLastHudPrinted)
|
}
|
||||||
{
|
StopSound(client, SNDCHAN_STATIC, "UI/hint.wav");
|
||||||
for(int client = 1; client <= MaxClients; client++)
|
}
|
||||||
{
|
}
|
||||||
if(IsClientInGame(client))
|
s_bLastHudPrinted = true;
|
||||||
{
|
}
|
||||||
PrintHintText(client, "");
|
else if(s_bLastHudPrinted)
|
||||||
StopSound(client, SNDCHAN_STATIC, "UI/hint.wav");
|
{
|
||||||
}
|
for(int client = 1; client <= MaxClients; client++)
|
||||||
}
|
{
|
||||||
s_bLastHudPrinted = false;
|
if(IsClientInGame(client))
|
||||||
}
|
{
|
||||||
}
|
if (voteInProgress)
|
||||||
|
{
|
||||||
|
PrintCenterText(client, g_sHUDText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintHintText(client, g_sHUDText);
|
||||||
|
}
|
||||||
|
StopSound(client, SNDCHAN_STATIC, "UI/hint.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_bLastHudPrinted = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BossInit(CBoss _Boss)
|
bool BossInit(CBoss _Boss)
|
||||||
@@ -1415,7 +1427,7 @@ bool BossProcess(CBoss _Boss)
|
|||||||
_Boss.iLastChange = iLastChange;
|
_Boss.iLastChange = iLastChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boss hasn't initialized HP yet.
|
// Boss hasnt initialized HP yet.
|
||||||
if(iHealth == 0 && iLastHealth == 0)
|
if(iHealth == 0 && iLastHealth == 0)
|
||||||
{
|
{
|
||||||
// Boss invalid: Delete boss
|
// Boss invalid: Delete boss
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <BossHP>
|
#include <BossHP>
|
||||||
#include <zombiereloaded>
|
#include <zombiereloaded>
|
||||||
#include <hlstatsx_loghelper>
|
|
||||||
|
|
||||||
ArrayList g_hStats[MAXPLAYERS+1];
|
ArrayList g_hStats[MAXPLAYERS+1];
|
||||||
|
|
||||||
@@ -208,19 +207,16 @@ public void OnBossKilled(CBoss Boss, CConfig Config, int reason)
|
|||||||
{
|
{
|
||||||
Format(sBuffer, sizeof(sBuffer), "%s\n1. %N - %d %s", sBuffer, iSortedList[0][0], iSortedList[0][1], sType);
|
Format(sBuffer, sizeof(sBuffer), "%s\n1. %N - %d %s", sBuffer, iSortedList[0][0], iSortedList[0][1], sType);
|
||||||
|
|
||||||
LH_LogPlayerEvent(iSortedList[0][0], "triggered", "ze_boss_damage_first", true);
|
|
||||||
}
|
}
|
||||||
if (iSortedList[1][0])
|
if (iSortedList[1][0])
|
||||||
{
|
{
|
||||||
Format(sBuffer, sizeof(sBuffer), "%s\n2. %N - %d %s", sBuffer, iSortedList[1][0], iSortedList[1][1], sType);
|
Format(sBuffer, sizeof(sBuffer), "%s\n2. %N - %d %s", sBuffer, iSortedList[1][0], iSortedList[1][1], sType);
|
||||||
|
|
||||||
LH_LogPlayerEvent(iSortedList[1][0], "triggered", "ze_boss_damage_second", true);
|
|
||||||
}
|
}
|
||||||
if (iSortedList[2][0])
|
if (iSortedList[2][0])
|
||||||
{
|
{
|
||||||
Format(sBuffer, sizeof(sBuffer), "%s\n3. %N - %d %s", sBuffer, iSortedList[2][0], iSortedList[2][1], sType);
|
Format(sBuffer, sizeof(sBuffer), "%s\n3. %N - %d %s", sBuffer, iSortedList[2][0], iSortedList[2][1], sType);
|
||||||
|
|
||||||
LH_LogPlayerEvent(iSortedList[2][0], "triggered", "ze_boss_damage_third", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer);
|
Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer);
|
||||||
@@ -280,6 +276,22 @@ public void OnBossKilled(CBoss Boss, CConfig Config, int reason)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
PrintToChatAll(sBuffer);
|
PrintToChatAll(sBuffer);
|
||||||
|
|
||||||
|
for (int i = 0; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (iSortedList[i][0])
|
||||||
|
{
|
||||||
|
char sBuffer_rest[512];
|
||||||
|
Format(sBuffer_rest, sizeof(sBuffer_rest), "%s\n%i. %N - %d %s", sBuffer_rest, i, iSortedList[i][0], iSortedList[i][1], sType);
|
||||||
|
PrintToConsoleAll(sBuffer_rest);
|
||||||
|
}
|
||||||
|
else if (IsValidClient(i))
|
||||||
|
{
|
||||||
|
char sBuffer_rest[512];
|
||||||
|
Format(sBuffer_rest, sizeof(sBuffer_rest), "%s\n-1. %N - Did not shoot.", sBuffer_rest, i);
|
||||||
|
PrintToConsoleAll(sBuffer_rest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,340 @@
|
|||||||
|
#include <sourcemod>
|
||||||
|
#include <BossHP>
|
||||||
|
#include <zombiereloaded>
|
||||||
|
|
||||||
|
ArrayList g_hStats[MAXPLAYERS+1];
|
||||||
|
|
||||||
|
bool g_bZRLoaded;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "BossHP - Ranking",
|
||||||
|
author = "Neon & zaCade",
|
||||||
|
description = "",
|
||||||
|
version = "1.0.0",
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
HookEvent("player_death", EventHook_PlayerDeath, EventHookMode_Pre);
|
||||||
|
|
||||||
|
for (int client = 1; client <= MaxClients; client++)
|
||||||
|
{
|
||||||
|
if (!IsClientInGame(client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
OnClientPutInServer(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnAllPluginsLoaded()
|
||||||
|
{
|
||||||
|
g_bZRLoaded = LibraryExists("zombiereloaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnLibraryAdded(const char[] sName)
|
||||||
|
{
|
||||||
|
if (strcmp(sName, "zombiereloaded", false) == 0)
|
||||||
|
g_bZRLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnLibraryRemoved(const char[] sName)
|
||||||
|
{
|
||||||
|
if (strcmp(sName, "zombiereloaded", false) == 0)
|
||||||
|
g_bZRLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnClientPutInServer(int client)
|
||||||
|
{
|
||||||
|
g_hStats[client] = new ArrayList(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
delete g_hStats[client];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnBossDamaged(CBoss Boss, CConfig Config, int client, float damage)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int iMaxCash = GetConVarInt(FindConVar("sm_maxcash"));
|
||||||
|
|
||||||
|
if(!(GetEntProp(client, Prop_Send, "m_iAccount") >= iMaxCash))
|
||||||
|
SetEntProp(client, Prop_Send, "m_iAccount", GetEntProp(client, Prop_Send, "m_iAccount") + 2);
|
||||||
|
|
||||||
|
bool bBreakable;
|
||||||
|
CConfig _Config = view_as<CConfig>(Config);
|
||||||
|
|
||||||
|
if (_Config.IsBreakable)
|
||||||
|
bBreakable = true;
|
||||||
|
else
|
||||||
|
bBreakable = false;
|
||||||
|
|
||||||
|
delete _Config;
|
||||||
|
|
||||||
|
for (int index = 0; index < g_hStats[client].Length; index++)
|
||||||
|
{
|
||||||
|
int BossDamage[2];
|
||||||
|
g_hStats[client].GetArray(index, BossDamage, sizeof(BossDamage));
|
||||||
|
|
||||||
|
if (BossDamage[0] == view_as<int>(Boss))
|
||||||
|
{
|
||||||
|
if (bBreakable)
|
||||||
|
BossDamage[1] += RoundToNearest(damage);
|
||||||
|
else
|
||||||
|
BossDamage[1] += 1;
|
||||||
|
|
||||||
|
g_hStats[client].SetArray(index, BossDamage, sizeof(BossDamage));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BossDamage[2];
|
||||||
|
BossDamage[0] = view_as<int>(Boss);
|
||||||
|
|
||||||
|
if (bBreakable)
|
||||||
|
BossDamage[1] = RoundToNearest(damage);
|
||||||
|
else
|
||||||
|
BossDamage[1] = 1;
|
||||||
|
|
||||||
|
g_hStats[client].PushArray(BossDamage, sizeof(BossDamage));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnBossKilled(CBoss Boss, CConfig Config, int reason)
|
||||||
|
{
|
||||||
|
if (reason == 0)
|
||||||
|
{
|
||||||
|
for (int client = 1; client <= MaxClients; client++)
|
||||||
|
{
|
||||||
|
if (!IsClientInGame(client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int index = 0; index < g_hStats[client].Length; index++)
|
||||||
|
{
|
||||||
|
int BossDamage[2];
|
||||||
|
g_hStats[client].GetArray(index, BossDamage, sizeof(BossDamage));
|
||||||
|
|
||||||
|
if (BossDamage[0] == view_as<int>(Boss))
|
||||||
|
{
|
||||||
|
g_hStats[client].Erase(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int iSortedList[MAXPLAYERS+1][2];
|
||||||
|
int iSortedCount;
|
||||||
|
|
||||||
|
for (int client = 1; client <= MaxClients; client++)
|
||||||
|
{
|
||||||
|
if (!IsClientInGame(client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int index = 0; index < g_hStats[client].Length; index++)
|
||||||
|
{
|
||||||
|
int BossDamage[2];
|
||||||
|
g_hStats[client].GetArray(index, BossDamage, sizeof(BossDamage));
|
||||||
|
|
||||||
|
if (BossDamage[0] == view_as<int>(Boss))
|
||||||
|
{
|
||||||
|
iSortedList[iSortedCount][0] = client;
|
||||||
|
iSortedList[iSortedCount][1] = BossDamage[1];
|
||||||
|
iSortedCount++;
|
||||||
|
|
||||||
|
g_hStats[client].Erase(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SortCustom2D(iSortedList, iSortedCount, SortBossHitsList);
|
||||||
|
|
||||||
|
if (iSortedCount)
|
||||||
|
{
|
||||||
|
CConfig _Config = view_as<CConfig>(Config);
|
||||||
|
|
||||||
|
char sBossName[64];
|
||||||
|
_Config.GetName(sBossName, sizeof(sBossName));
|
||||||
|
|
||||||
|
char sBuffer[512];
|
||||||
|
char sType[16];
|
||||||
|
if (_Config.IsBreakable)
|
||||||
|
{
|
||||||
|
sType = "damage"
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "BOSS DAMAGE [%s]:", sBossName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sType = "hits"
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "BOSS HITS [%s]:", sBossName);
|
||||||
|
}
|
||||||
|
delete _Config;
|
||||||
|
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer);
|
||||||
|
|
||||||
|
if (iSortedList[0][0])
|
||||||
|
{
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s\n1. %N - %d %s", sBuffer, iSortedList[0][0], iSortedList[0][1], sType);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (iSortedList[1][0])
|
||||||
|
{
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s\n2. %N - %d %s", sBuffer, iSortedList[1][0], iSortedList[1][1], sType);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (iSortedList[2][0])
|
||||||
|
{
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s\n3. %N - %d %s", sBuffer, iSortedList[2][0], iSortedList[2][1], sType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s\n*************************", sBuffer);
|
||||||
|
|
||||||
|
Handle hMessage = StartMessageAll("HudMsg");
|
||||||
|
if (hMessage)
|
||||||
|
{
|
||||||
|
if (GetUserMessageType() == UM_Protobuf)
|
||||||
|
{
|
||||||
|
PbSetInt(hMessage, "channel", 50);
|
||||||
|
PbSetInt(hMessage, "effect", 0);
|
||||||
|
PbSetColor(hMessage, "clr1", {255, 255, 255, 255});
|
||||||
|
PbSetColor(hMessage, "clr2", {255, 255, 255, 255});
|
||||||
|
PbSetVector2D(hMessage, "pos", Float:{0.02, 0.45});
|
||||||
|
PbSetFloat(hMessage, "fade_in_time", 0.1);
|
||||||
|
PbSetFloat(hMessage, "fade_out_time", 0.1);
|
||||||
|
PbSetFloat(hMessage, "hold_time", 7.0);
|
||||||
|
PbSetFloat(hMessage, "fx_time", 0.0);
|
||||||
|
PbSetString(hMessage, "text", sBuffer);
|
||||||
|
EndMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BfWriteByte(hMessage, 50);
|
||||||
|
BfWriteFloat(hMessage, 0.02);
|
||||||
|
BfWriteFloat(hMessage, 0.25);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 0);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 255);
|
||||||
|
BfWriteByte(hMessage, 0);
|
||||||
|
BfWriteFloat(hMessage, 0.1);
|
||||||
|
BfWriteFloat(hMessage, 0.1);
|
||||||
|
BfWriteFloat(hMessage, 7.0);
|
||||||
|
BfWriteFloat(hMessage, 0.0);
|
||||||
|
BfWriteString(hMessage, sBuffer);
|
||||||
|
EndMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetEngineVersion() == Engine_CSGO)
|
||||||
|
{
|
||||||
|
int iSplits
|
||||||
|
char sSplits[16][512];
|
||||||
|
|
||||||
|
if((iSplits = ExplodeString(sBuffer, "\n", sSplits, sizeof(sSplits), sizeof(sSplits[]))) != 0)
|
||||||
|
{
|
||||||
|
for (int iSplit; iSplit < iSplits; iSplit++)
|
||||||
|
{
|
||||||
|
PrintToChatAll(sSplits[iSplit]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PrintToChatAll(sBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Action EventHook_PlayerDeath(Event hEvent, const char[] sEventName, bool bDontBroadcast)
|
||||||
|
{
|
||||||
|
if (!g_bZRLoaded)
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
int iClient = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
|
if (!IsValidClient(iClient))
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
if (IsPlayerAlive(iClient) && !ZR_IsClientHuman(iClient))
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
int iPacked = (iClient<<16) | (GetEntProp(iClient, Prop_Send, "m_iAccount")&0xFFFF);
|
||||||
|
|
||||||
|
RequestFrame(RequestFrame_Callback, iPacked);
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
void RequestFrame_Callback(int iPacked)
|
||||||
|
{
|
||||||
|
int iOldCash = iPacked&0xFFFF;
|
||||||
|
int iClient = iPacked>>16;
|
||||||
|
|
||||||
|
if (!IsValidEntity(iClient) || !IsValidClient(iClient))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetEntProp(iClient, Prop_Send, "m_iAccount", iOldCash);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public int SortBossHitsList(int[] elem1, int[] elem2, const int[][] array, Handle hndl)
|
||||||
|
{
|
||||||
|
if (elem1[1] > elem2[1]) return -1;
|
||||||
|
if (elem1[1] < elem2[1]) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
stock int IsValidClient(int client, bool nobots = true)
|
||||||
|
{
|
||||||
|
if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return IsClientInGame(client);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
this is used for the voice extension:
|
||||||
|
https://git.unloze.com/UNLOZE/sm-ext-Voice/src/branch/CeltOpusTranscoder_2026
|
||||||
|
|
||||||
|
//the voice chat is now transcoded so both celt and opus work by sending each stream to the player that needs it.
|
||||||
|
|
||||||
|
the include belongs to the voice extension but is also put here extra
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#if defined _voice_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _voice_included
|
||||||
|
|
||||||
|
native bool IsClientTalking(int client);
|
||||||
|
native bool SetClientNoSteam(int client, bool isNosteam);
|
||||||
|
native bool SendCeltVoiceInit(int client);
|
||||||
|
native bool ClientMutedOtherClient(int client, int otherclient, bool muted);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not edit below this line!
|
||||||
|
*/
|
||||||
|
public Extension __ext_voice =
|
||||||
|
{
|
||||||
|
name = "Voice",
|
||||||
|
file = "Voice.ext",
|
||||||
|
#if defined AUTOLOAD_EXTENSIONS
|
||||||
|
autoload = 1,
|
||||||
|
#else
|
||||||
|
autoload = 0,
|
||||||
|
#endif
|
||||||
|
#if defined REQUIRE_EXTENSIONS
|
||||||
|
required = 1,
|
||||||
|
#else
|
||||||
|
required = 0,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined REQUIRE_EXTENSIONS
|
||||||
|
public __ext_voice_SetNTVOptional()
|
||||||
|
{
|
||||||
|
MarkNativeAsOptional("IsClientTalking");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,366 @@
|
|||||||
|
#include <sourcemod>
|
||||||
|
#include <PlayerManager>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <basecomm>
|
||||||
|
#include <ccc>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <SteamWorks>
|
||||||
|
#tryinclude <zombiereloaded>
|
||||||
|
#include <selfmute>
|
||||||
|
#include <connect>
|
||||||
|
#include <voice>
|
||||||
|
|
||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
Handle g_hCheckMutes = null;
|
||||||
|
Handle g_hCookieTorchMuted = null;
|
||||||
|
|
||||||
|
bool g_bWebclient[MAXPLAYERS + 1];
|
||||||
|
bool g_bReRunWebClientName;
|
||||||
|
bool g_bSkipInfection = false;
|
||||||
|
|
||||||
|
char g_sLastWebclientIp[64];
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "NoSteam CELT Voice override",
|
||||||
|
author = "jenz",
|
||||||
|
version = "1.5"
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
Format(g_sLastWebclientIp, sizeof(g_sLastWebclientIp), "");
|
||||||
|
g_hCheckMutes = CreateTimer(2.0, check_mutes, _, TIMER_REPEAT);
|
||||||
|
g_hCookieTorchMuted = RegClientCookie("torch_muted", "is torch muted", CookieAccess_Protected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginEnd()
|
||||||
|
{
|
||||||
|
if (g_hCheckMutes != null)
|
||||||
|
{
|
||||||
|
delete g_hCheckMutes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_nosteam_listen_override(int client)
|
||||||
|
{
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || client == j || IsFakeClient(j))
|
||||||
|
continue;
|
||||||
|
if (PM_IsPlayerSteam(j))
|
||||||
|
{
|
||||||
|
//the nosteam client is not allowed to hear the steam client because broadcastvoicedata would ear rape them.
|
||||||
|
//LogMessage("%N has muted %N", client, j);
|
||||||
|
SetListenOverride(client, j, Listen_No);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action check_mutes(Handle timer, any data)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(i) || IsFakeClient(i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!PM_IsPlayerSteam(i))
|
||||||
|
{
|
||||||
|
set_nosteam_listen_override(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//maybe this is a fix? maybe not.
|
||||||
|
clear_steam_listen_override(i);
|
||||||
|
}
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || i == j || IsFakeClient(j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool isMuted = BaseComm_IsClientMuted(j);
|
||||||
|
if (!isMuted)
|
||||||
|
{
|
||||||
|
isMuted = SelfMute_IsIgnoring(i, j);
|
||||||
|
}
|
||||||
|
//PrintToChatAll("i: %N. j: %N. isMuted: %i", i, j, isMuted);
|
||||||
|
ClientMutedOtherClient(i, j, isMuted);
|
||||||
|
}
|
||||||
|
if (g_bReRunWebClientName && g_bWebclient[i])
|
||||||
|
{
|
||||||
|
char dummy[64];
|
||||||
|
OnClientAuthorized(i, dummy);
|
||||||
|
g_bReRunWebClientName = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//sourceTV special case, index 0.
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || IsFakeClient(j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//yeah its monkey work but server can probably handle it fine.
|
||||||
|
char sBuffer[2];
|
||||||
|
GetClientCookie(j, g_hCookieTorchMuted, sBuffer, sizeof(sBuffer));
|
||||||
|
//PrintToChatAll("sBuffer: %s. j: %N", sBuffer, j);
|
||||||
|
if(sBuffer[0] != '\0')
|
||||||
|
{
|
||||||
|
ClientMutedOtherClient(j, 0, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClientMutedOtherClient(j, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if webclient has new IP every 2 seconds through endpoint.
|
||||||
|
PollWebclientCurrentIp();
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear_steam_listen_override(int client)
|
||||||
|
{
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || client == j || IsFakeClient(j))
|
||||||
|
continue;
|
||||||
|
if (PM_IsPlayerSteam(j) && !BaseComm_IsClientMuted(j) && !SelfMute_IsIgnoring(client, j))
|
||||||
|
{
|
||||||
|
SetListenOverride(client, j, Listen_Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//AI slop
|
||||||
|
public void SendWebclientNameToSignaling(const char[] webclientName)
|
||||||
|
{
|
||||||
|
char url[256];
|
||||||
|
// Adjust port/path to match your signaling servers actual endpoint
|
||||||
|
FormatEx(url, sizeof(url), "http://127.0.0.1:3000/webclient-name");
|
||||||
|
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, url);
|
||||||
|
if (hRequest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the name as a POST body parameter
|
||||||
|
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "name", webclientName);
|
||||||
|
|
||||||
|
if (!SteamWorks_SetHTTPCallbacks(hRequest, OnWebclientNamePosted) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnWebclientNamePosted(Handle hRequest, bool bFailure, bool bRequestSuccessful,
|
||||||
|
EHTTPStatusCode eStatusCode, any data)
|
||||||
|
{
|
||||||
|
// Fire-and-forget: we dont care about the response, just clean up.
|
||||||
|
delete hRequest;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
g_bReRunWebClientName = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientPostAdminCheck(int client)
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = false;
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sIP[32];
|
||||||
|
GetClientIP(client, sIP, sizeof(sIP));
|
||||||
|
|
||||||
|
char allowed_ips[128];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowed_ips, sizeof(allowed_ips));
|
||||||
|
if (StrEqual(sIP, allowed_ips))
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = true;
|
||||||
|
g_bSkipInfection = GetConVarInt(FindConVar("zr_infect_mzombie_ratio")) > 10 ? true : false;
|
||||||
|
|
||||||
|
//this works fine with one webclient only existing.
|
||||||
|
char webclientName[64];
|
||||||
|
GetConVarString(FindConVar("sv_webclient_name"), webclientName, sizeof(webclientName));
|
||||||
|
SetClientName(client, webclientName);
|
||||||
|
SendWebclientNameToSignaling(webclientName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientAuthorized(int client, const char[] auth)
|
||||||
|
{
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetClientNoSteam(client, false);
|
||||||
|
if (!PM_IsPlayerSteam(client))
|
||||||
|
{
|
||||||
|
SetClientNoSteam(client, true);
|
||||||
|
//LogMessage("here in onauthorized client: %N", client);
|
||||||
|
//setting it too early does not work, so some delay needed.
|
||||||
|
CreateTimer(10.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(20.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(30.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(40.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(50.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(60.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CCC_OnChatMessage(int client, int author, const char[] message)
|
||||||
|
{
|
||||||
|
if (!g_bWebclient[client])
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
int index = FindCharInString(message, '"', false);
|
||||||
|
int index1 = FindCharInString(message, ';', false);
|
||||||
|
if (index != -1 || index1 != -1)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined _zr_included
|
||||||
|
public Action ZR_OnClientMotherZombieEligible(int client)
|
||||||
|
{
|
||||||
|
if (g_bWebclient[client] && g_bSkipInfection)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public Action Timer_SendVoiceInit(Handle timer, int Serial)
|
||||||
|
{
|
||||||
|
int client;
|
||||||
|
if ((client = GetClientFromSerial(Serial)) == 0)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
if (IsValidClient(client) && !PM_IsPlayerSteam(client))
|
||||||
|
{
|
||||||
|
SendCeltVoiceInit(client);
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls the signaling server for the current webclient controller's real IP.
|
||||||
|
* If the IP has changed since the last
|
||||||
|
* check and a webclient player is currently connected, forces them to
|
||||||
|
* reconnect with the new password via ClientCommand.
|
||||||
|
**/
|
||||||
|
public void PollWebclientCurrentIp()
|
||||||
|
{
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, "http://127.0.0.1:3000/webclient-current-ip");
|
||||||
|
if (hRequest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SteamWorks_SetHTTPCallbacks(hRequest, OnWebclientCurrentIpReceived) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnWebclientCurrentIpReceived(Handle hRequest, bool bFailure, bool bRequestSuccessful,
|
||||||
|
EHTTPStatusCode eStatusCode, any data)
|
||||||
|
{
|
||||||
|
if (bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bodySize;
|
||||||
|
bool gotSize = SteamWorks_GetHTTPResponseBodySize(hRequest, bodySize);
|
||||||
|
|
||||||
|
char newIp[64];
|
||||||
|
newIp[0] = '\0';
|
||||||
|
|
||||||
|
if (gotSize && bodySize > 0 && bodySize < sizeof(newIp))
|
||||||
|
{
|
||||||
|
SteamWorks_GetHTTPResponseBodyData(hRequest, newIp, bodySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
if (newIp[0] == '\0')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrEqual(newIp, g_sLastWebclientIp))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i) && g_bWebclient[i])
|
||||||
|
{
|
||||||
|
strcopy(g_sLastWebclientIp, sizeof(g_sLastWebclientIp), newIp);
|
||||||
|
LogMessage("Forcing webclient reconnect for client %N with new IP: %s", i, newIp);
|
||||||
|
ClientCommand(i, "retry");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EConnect OnClientPreConnectEx(const char[] sName, char sPassword[255], const char[] sIP, const char[] sSteam32ID, char sRejectReason[255])
|
||||||
|
{
|
||||||
|
char allowedIp[64];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowedIp, sizeof(allowedIp));
|
||||||
|
//this is to handle that the connect extension receives the password parameter for the webclient as its real connecting IP.
|
||||||
|
//works both for the client command retry and for the case that somebody presses the connect button in the clients Menu as the same password
|
||||||
|
//is applied again.
|
||||||
|
if (StrEqual(sIP, allowedIp) && strlen(g_sLastWebclientIp) > 0)
|
||||||
|
{
|
||||||
|
strcopy(sPassword, 255, g_sLastWebclientIp);
|
||||||
|
LogMessage("Backfilled empty password for webclient with cached IP: %s", g_sLastWebclientIp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ET_LowEvent takes the LOWEST value returned across all plugins hooking this forward.
|
||||||
|
//this plugin returns 1 (Accept), meanwhile the reserved slot plugin still might return 0 (reject) or -1 (async) to overrule the decision from this return value.
|
||||||
|
return k_OnClientPreConnectEx_Accept;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client)
|
||||||
|
{
|
||||||
|
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,333 @@
|
|||||||
|
#include <sourcemod>
|
||||||
|
#include <PlayerManager>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <basecomm>
|
||||||
|
#include <ccc>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <SteamWorks>
|
||||||
|
#include <selfmute>
|
||||||
|
#include <connect>
|
||||||
|
#include <voice>
|
||||||
|
|
||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
Handle g_hCheckMutes = null;
|
||||||
|
Handle g_hCookieTorchMuted = null;
|
||||||
|
|
||||||
|
bool g_bWebclient[MAXPLAYERS + 1];
|
||||||
|
bool g_bReRunWebClientName;
|
||||||
|
|
||||||
|
char g_sLastWebclientIp[64];
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "NoSteam CELT Voice override",
|
||||||
|
author = "jenz",
|
||||||
|
version = "1.5"
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
Format(g_sLastWebclientIp, sizeof(g_sLastWebclientIp), "");
|
||||||
|
g_hCheckMutes = CreateTimer(2.0, check_mutes, _, TIMER_REPEAT);
|
||||||
|
g_hCookieTorchMuted = RegClientCookie("torch_muted", "is torch muted", CookieAccess_Protected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginEnd()
|
||||||
|
{
|
||||||
|
if (g_hCheckMutes != null)
|
||||||
|
{
|
||||||
|
delete g_hCheckMutes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set_nosteam_listen_override(int client)
|
||||||
|
{
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || client == j || IsFakeClient(j))
|
||||||
|
continue;
|
||||||
|
if (PM_IsPlayerSteam(j))
|
||||||
|
{
|
||||||
|
//the nosteam client is not allowed to hear the steam client because broadcastvoicedata would ear rape them.
|
||||||
|
//LogMessage("%N has muted %N", client, j);
|
||||||
|
SetListenOverride(client, j, Listen_No);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action check_mutes(Handle timer, any data)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(i) || IsFakeClient(i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!PM_IsPlayerSteam(i))
|
||||||
|
{
|
||||||
|
set_nosteam_listen_override(i);
|
||||||
|
}
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || i == j || IsFakeClient(j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool isMuted = BaseComm_IsClientMuted(j);
|
||||||
|
if (!isMuted)
|
||||||
|
{
|
||||||
|
isMuted = SelfMute_IsIgnoring(i, j);
|
||||||
|
}
|
||||||
|
//PrintToChatAll("i: %N. j: %N. isMuted: %i", i, j, isMuted);
|
||||||
|
ClientMutedOtherClient(i, j, isMuted);
|
||||||
|
}
|
||||||
|
if (g_bReRunWebClientName && g_bWebclient[i])
|
||||||
|
{
|
||||||
|
char dummy[64];
|
||||||
|
OnClientAuthorized(i, dummy);
|
||||||
|
g_bReRunWebClientName = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//sourceTV special case, index 0.
|
||||||
|
for (int j = 1; j <= MaxClients; j++)
|
||||||
|
{
|
||||||
|
if (!IsValidClient(j) || IsFakeClient(j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//yeah its monkey work but server can probably handle it fine.
|
||||||
|
char sBuffer[2];
|
||||||
|
GetClientCookie(j, g_hCookieTorchMuted, sBuffer, sizeof(sBuffer));
|
||||||
|
//PrintToChatAll("sBuffer: %s. j: %N", sBuffer, j);
|
||||||
|
if(sBuffer[0] != '\0')
|
||||||
|
{
|
||||||
|
ClientMutedOtherClient(j, 0, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClientMutedOtherClient(j, 0, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if webclient has new IP every 2 seconds through endpoint.
|
||||||
|
PollWebclientCurrentIp();
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//AI slop
|
||||||
|
public void SendWebclientNameToSignaling(const char[] webclientName)
|
||||||
|
{
|
||||||
|
char url[256];
|
||||||
|
// Adjust port/path to match your signaling servers actual endpoint
|
||||||
|
FormatEx(url, sizeof(url), "http://127.0.0.1:3000/webclient-name");
|
||||||
|
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, url);
|
||||||
|
if (hRequest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the name as a POST body parameter
|
||||||
|
SteamWorks_SetHTTPRequestGetOrPostParameter(hRequest, "name", webclientName);
|
||||||
|
|
||||||
|
if (!SteamWorks_SetHTTPCallbacks(hRequest, OnWebclientNamePosted) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnWebclientNamePosted(Handle hRequest, bool bFailure, bool bRequestSuccessful,
|
||||||
|
EHTTPStatusCode eStatusCode, any data)
|
||||||
|
{
|
||||||
|
// Fire-and-forget: we dont care about the response, just clean up.
|
||||||
|
delete hRequest;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
g_bReRunWebClientName = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientPostAdminCheck(int client)
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = false;
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sIP[32];
|
||||||
|
GetClientIP(client, sIP, sizeof(sIP));
|
||||||
|
|
||||||
|
char allowed_ips[128];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowed_ips, sizeof(allowed_ips));
|
||||||
|
if (StrEqual(sIP, allowed_ips))
|
||||||
|
{
|
||||||
|
g_bWebclient[client] = true;
|
||||||
|
//this works fine with one webclient only existing.
|
||||||
|
char webclientName[64];
|
||||||
|
GetConVarString(FindConVar("sv_webclient_name"), webclientName, sizeof(webclientName));
|
||||||
|
SetClientName(client, webclientName);
|
||||||
|
SendWebclientNameToSignaling(webclientName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientAuthorized(int client, const char[] auth)
|
||||||
|
{
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetClientNoSteam(client, false);
|
||||||
|
if (!PM_IsPlayerSteam(client))
|
||||||
|
{
|
||||||
|
SetClientNoSteam(client, true);
|
||||||
|
//LogMessage("here in onauthorized client: %N", client);
|
||||||
|
//setting it too early does not work, so some delay needed.
|
||||||
|
CreateTimer(10.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(20.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(30.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(40.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(50.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
CreateTimer(60.0, Timer_SendVoiceInit, GetClientSerial(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CCC_OnChatMessage(int client, int author, const char[] message)
|
||||||
|
{
|
||||||
|
if (!g_bWebclient[client])
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
int index = FindCharInString(message, '"', false);
|
||||||
|
int index1 = FindCharInString(message, ';', false);
|
||||||
|
if (index != -1 || index1 != -1)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Timer_SendVoiceInit(Handle timer, int Serial)
|
||||||
|
{
|
||||||
|
int client;
|
||||||
|
if ((client = GetClientFromSerial(Serial)) == 0)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
if (IsValidClient(client))
|
||||||
|
{
|
||||||
|
SendCeltVoiceInit(client);
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls the signaling server for the current webclient controller's real IP.
|
||||||
|
* If the IP has changed since the last
|
||||||
|
* check and a webclient player is currently connected, forces them to
|
||||||
|
* reconnect with the new password via ClientCommand.
|
||||||
|
**/
|
||||||
|
public void PollWebclientCurrentIp()
|
||||||
|
{
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, "http://127.0.0.1:3000/webclient-current-ip");
|
||||||
|
if (hRequest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SteamWorks_SetHTTPCallbacks(hRequest, OnWebclientCurrentIpReceived) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnWebclientCurrentIpReceived(Handle hRequest, bool bFailure, bool bRequestSuccessful,
|
||||||
|
EHTTPStatusCode eStatusCode, any data)
|
||||||
|
{
|
||||||
|
if (bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bodySize;
|
||||||
|
bool gotSize = SteamWorks_GetHTTPResponseBodySize(hRequest, bodySize);
|
||||||
|
|
||||||
|
char newIp[64];
|
||||||
|
newIp[0] = '\0';
|
||||||
|
|
||||||
|
if (gotSize && bodySize > 0 && bodySize < sizeof(newIp))
|
||||||
|
{
|
||||||
|
SteamWorks_GetHTTPResponseBodyData(hRequest, newIp, bodySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
if (newIp[0] == '\0')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrEqual(newIp, g_sLastWebclientIp))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i) && g_bWebclient[i])
|
||||||
|
{
|
||||||
|
strcopy(g_sLastWebclientIp, sizeof(g_sLastWebclientIp), newIp);
|
||||||
|
LogMessage("Forcing webclient reconnect for client %N with new IP: %s", i, newIp);
|
||||||
|
ClientCommand(i, "retry");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EConnect OnClientPreConnectEx(const char[] sName, char sPassword[255], const char[] sIP, const char[] sSteam32ID, char sRejectReason[255])
|
||||||
|
{
|
||||||
|
char allowedIp[64];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowedIp, sizeof(allowedIp));
|
||||||
|
//this is to handle that the connect extension receives the password parameter for the webclient as its real connecting IP.
|
||||||
|
//works both for the client command retry and for the case that somebody presses the connect button in the clients Menu as the same password
|
||||||
|
//is applied again.
|
||||||
|
if (StrEqual(sIP, allowedIp) && strlen(g_sLastWebclientIp) > 0)
|
||||||
|
{
|
||||||
|
strcopy(sPassword, 255, g_sLastWebclientIp);
|
||||||
|
LogMessage("Backfilled empty password for webclient with cached IP: %s", g_sLastWebclientIp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ET_LowEvent takes the LOWEST value returned across all plugins hooking this forward.
|
||||||
|
//this plugin returns 1 (Accept), meanwhile the reserved slot plugin still might return 0 (reject) or -1 (async) to overrule the decision from this return value.
|
||||||
|
return k_OnClientPreConnectEx_Accept;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client)
|
||||||
|
{
|
||||||
|
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{BLUE}{PLAYERTIER} {WHITE}{PLAYERTYPE} {GREEN}{NAME} {green}[{lightgreen}{STEAMID}{NOSTEAM}{green}] connected{COUNTRY}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <multicolors>
|
#include <multicolors>
|
||||||
#include <clientprefs>
|
#include <clientprefs>
|
||||||
#include <PlayerManager>
|
#include <PlayerManager>
|
||||||
|
#include <unloze_playtime>
|
||||||
|
|
||||||
#pragma newdecls required
|
#pragma newdecls required
|
||||||
|
|
||||||
@@ -16,6 +17,8 @@ Database g_hDatabase;
|
|||||||
Handle g_hCustomMessageFile;
|
Handle g_hCustomMessageFile;
|
||||||
Handle g_hCustomMessageFile2;
|
Handle g_hCustomMessageFile2;
|
||||||
|
|
||||||
|
static Handle g_hForwardConnectMessage;
|
||||||
|
|
||||||
bool g_bHideCsays[MAXPLAYERS + 1] = { false, ... };
|
bool g_bHideCsays[MAXPLAYERS + 1] = { false, ... };
|
||||||
Handle g_hCookieHideCsays = null;
|
Handle g_hCookieHideCsays = null;
|
||||||
|
|
||||||
@@ -71,6 +74,17 @@ public void OnDatabaseConnect(Database db, const char[] error, any data)
|
|||||||
g_hDatabase = db;
|
g_hDatabase = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public APLRes AskPluginLoad2(Handle myself, bool late, char [] error, int err_max)
|
||||||
|
{
|
||||||
|
g_hForwardConnectMessage = CreateGlobalForward("GetPlayerConnectMessage", ET_Ignore, Param_String);
|
||||||
|
return APLRes_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginEnd()
|
||||||
|
{
|
||||||
|
CloseHandle(g_hForwardConnectMessage);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -175,6 +189,7 @@ public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int se
|
|||||||
delete menu;
|
delete menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -290,6 +305,189 @@ public Action Command_ResetJoinMsg(int client, int args)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void GetPlayerTier(int client, int tier)
|
||||||
|
{
|
||||||
|
Handle hFile = OpenFile(g_sDataFile, "r");
|
||||||
|
static char sRawMsg[301];
|
||||||
|
|
||||||
|
if(hFile != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
ReadFileLine(hFile, sRawMsg, sizeof(sRawMsg));
|
||||||
|
TrimString(sRawMsg);
|
||||||
|
delete hFile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogError("[SM] File not found! (configs/ConnectAnnounce/settings.txt)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char sIP[16];
|
||||||
|
static char sAuth[32];
|
||||||
|
static char sCountry[32];
|
||||||
|
static char sName[128];
|
||||||
|
|
||||||
|
GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));
|
||||||
|
GetClientName(client, sName, sizeof(sName));
|
||||||
|
AdminId aid;
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{PLAYERTIER}"))
|
||||||
|
{
|
||||||
|
char s_tier[64];
|
||||||
|
Format(s_tier, sizeof(s_tier), "Tier %i", tier);
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTIER}", s_tier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{PLAYERTYPE}"))
|
||||||
|
{
|
||||||
|
aid = GetUserAdmin(client);
|
||||||
|
|
||||||
|
if(GetAdminFlag(aid, Admin_Cheats) || GetAdminFlag(aid, Admin_Root))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Root-Admin");
|
||||||
|
}
|
||||||
|
else if(GetAdminFlag(aid, Admin_Generic))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Admin");
|
||||||
|
}
|
||||||
|
else if(GetAdminFlag(aid, Admin_Custom1))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "VIP");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else if(GetAdminFlag(aid, Admin_Custom6))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Member");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{PLAYERTYPE}", "Player");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{NOSTEAM}"))
|
||||||
|
{
|
||||||
|
if(!PM_IsPlayerSteam(client))
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{NOSTEAM}", " <NoSteam>");
|
||||||
|
else
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{NOSTEAM}", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{STEAMID}"))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{STEAMID}", sAuth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{NAME}"))
|
||||||
|
{
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{NAME}", sName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StrContains(sRawMsg, "{COUNTRY}"))
|
||||||
|
{
|
||||||
|
if(GetClientIP(client, sIP, sizeof(sIP)) && GeoipCountry(sIP, sCountry, sizeof(sCountry)))
|
||||||
|
{
|
||||||
|
char sBuffer[128];
|
||||||
|
Format(sBuffer, sizeof(sBuffer), " from %s", sCountry);
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{COUNTRY}", sBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ReplaceString(sRawMsg, sizeof(sRawMsg), "{COUNTRY}", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
if (!CheckCommandAccess(client, "sm_joinmsg", ADMFLAG_CUSTOM1))
|
||||||
|
{
|
||||||
|
CPrintToChatAll(sRawMsg);
|
||||||
|
Call_StartForward(g_hForwardConnectMessage);
|
||||||
|
Call_PushString(sRawMsg);
|
||||||
|
Call_Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete g_hCustomMessageFile2;
|
||||||
|
|
||||||
|
g_hCustomMessageFile2 = CreateKeyValues("custom_messages");
|
||||||
|
|
||||||
|
if (!FileToKeyValues(g_hCustomMessageFile2, g_sCustomMessageFile))
|
||||||
|
{
|
||||||
|
SetFailState("[ConnectAnnounce] Config file missing!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KvRewind(g_hCustomMessageFile2);
|
||||||
|
|
||||||
|
char sBanned[16];
|
||||||
|
char sFinalMessage[512];
|
||||||
|
char sCustomMessage[256];
|
||||||
|
|
||||||
|
if (KvJumpToKey(g_hCustomMessageFile2, sAuth))
|
||||||
|
{
|
||||||
|
KvGetString(g_hCustomMessageFile2, "banned", sBanned, sizeof(sBanned), "");
|
||||||
|
KvGetString(g_hCustomMessageFile2, "message", sCustomMessage, sizeof(sCustomMessage), "");
|
||||||
|
if(StrEqual(sCustomMessage, "reset") || StrEqual(sBanned, "true"))
|
||||||
|
{
|
||||||
|
CPrintToChatAll(sRawMsg);
|
||||||
|
Call_StartForward(g_hForwardConnectMessage);
|
||||||
|
Call_PushString(sRawMsg);
|
||||||
|
Call_Finish();
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i))
|
||||||
|
{
|
||||||
|
if(g_bHideCsays[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PrintCenterText(i, "%s %s %s", "[VIP]", sName, "connected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Format(sFinalMessage, sizeof(sFinalMessage), "%s %s", sRawMsg, sCustomMessage);
|
||||||
|
CPrintToChatAll(sFinalMessage);
|
||||||
|
Call_StartForward(g_hForwardConnectMessage);
|
||||||
|
Call_PushString(sRawMsg);
|
||||||
|
Call_Finish();
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i))
|
||||||
|
{
|
||||||
|
if(g_bHideCsays[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CRemoveTags(sCustomMessage, 256);
|
||||||
|
PrintCenterText(i, "%s %s %s %s", "[VIP]", sName, "connected", sCustomMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CPrintToChatAll(sRawMsg);
|
||||||
|
Call_StartForward(g_hForwardConnectMessage);
|
||||||
|
Call_PushString(sRawMsg);
|
||||||
|
Call_Finish();
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i))
|
||||||
|
{
|
||||||
|
if(g_bHideCsays[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PrintCenterText(i, "%s %s %s", "[VIP]", sName, "connected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void TQueryCB(Handle owner, Handle rs, const char[] error, any data)
|
public void TQueryCB(Handle owner, Handle rs, const char[] error, any data)
|
||||||
{
|
{
|
||||||
int client = 0;
|
int client = 0;
|
||||||
@@ -338,7 +536,6 @@ public void TQueryCB(Handle owner, Handle rs, const char[] error, any data)
|
|||||||
|
|
||||||
if(StrContains(sRawMsg, "{PLAYERTYPE}"))
|
if(StrContains(sRawMsg, "{PLAYERTYPE}"))
|
||||||
{
|
{
|
||||||
|
|
||||||
aid = GetUserAdmin(client);
|
aid = GetUserAdmin(client);
|
||||||
|
|
||||||
if(GetAdminFlag(aid, Admin_Generic))
|
if(GetAdminFlag(aid, Admin_Generic))
|
||||||
@@ -492,7 +689,9 @@ public void OnClientPostAdminCheck(int client)
|
|||||||
char sServer[16];
|
char sServer[16];
|
||||||
g_cvHlstatsServerName.GetString(sServer, sizeof(sServer));
|
g_cvHlstatsServerName.GetString(sServer, sizeof(sServer));
|
||||||
|
|
||||||
|
/*
|
||||||
char sQuery[512];
|
char sQuery[512];
|
||||||
Format(sQuery, sizeof(sQuery), "SELECT COUNT(*) AS 'rank' FROM hlstats_Players WHERE hlstats_Players.game = '%s' AND hideranking = 0 AND skill > (SELECT skill from hlstats_Players JOIN hlstats_PlayerUniqueIds ON hlstats_Players.playerId = hlstats_PlayerUniqueIds.playerId WHERE uniqueId = '%s' AND hlstats_PlayerUniqueIds.game = '%s')", sServer, sAuth, sServer);
|
Format(sQuery, sizeof(sQuery), "SELECT COUNT(*) AS 'rank' FROM hlstats_Players WHERE hlstats_Players.game = '%s' AND hideranking = 0 AND skill > (SELECT skill from hlstats_Players JOIN hlstats_PlayerUniqueIds ON hlstats_Players.playerId = hlstats_PlayerUniqueIds.playerId WHERE uniqueId = '%s' AND hlstats_PlayerUniqueIds.game = '%s')", sServer, sAuth, sServer);
|
||||||
g_hDatabase.Query(TQueryCB, sQuery, GetClientUserId(client), DBPrio_High);
|
g_hDatabase.Query(TQueryCB, sQuery, GetClientUserId(client), DBPrio_High);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#if defined _connect_announce_included_
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _connect_announce_included_
|
||||||
|
|
||||||
|
forward void GetPlayerConnectMessage(char[] message);
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <multicolors>
|
#include <multicolors>
|
||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <Discord_UNLOZE>
|
#include <Discord_UNLOZE>
|
||||||
|
#include <connect_announce>
|
||||||
|
|
||||||
#define API_URL ""
|
#define API_URL ""
|
||||||
#define BOT_TOKEN ""
|
#define BOT_TOKEN ""
|
||||||
@@ -17,7 +18,7 @@ public Plugin myinfo =
|
|||||||
name = "livechat stoat",
|
name = "livechat stoat",
|
||||||
author = "jenz",
|
author = "jenz",
|
||||||
description = "",
|
description = "",
|
||||||
version = "1.1.0",
|
version = "1.2.0",
|
||||||
url = "www.unloze.com"
|
url = "www.unloze.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +74,11 @@ public Action CommandListener_SmChat_stoat(int client, const char[] sCommand, in
|
|||||||
if (client <= 0)
|
if (client <= 0)
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
if (!IsValidClient(client))
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
char sText[256];
|
char sText[256];
|
||||||
char sUsername[32];
|
char sUsername[32];
|
||||||
|
|
||||||
@@ -192,6 +198,49 @@ public Action Command_PrintToAdminChat_stoat(int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ai SLOP
|
||||||
|
void StripColorTags(char[] buffer, int maxlen)
|
||||||
|
{
|
||||||
|
int len = strlen(buffer);
|
||||||
|
int writeIndex = 0;
|
||||||
|
bool inside = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (buffer[i] == '{')
|
||||||
|
{
|
||||||
|
inside = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (buffer[i] == '}')
|
||||||
|
{
|
||||||
|
inside = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inside && writeIndex < maxlen - 1)
|
||||||
|
{
|
||||||
|
buffer[writeIndex] = buffer[i];
|
||||||
|
writeIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[writeIndex] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetPlayerConnectMessage(char[] message)
|
||||||
|
{
|
||||||
|
StripColorTags(message, strlen(message));
|
||||||
|
if (i_port == 27015)
|
||||||
|
{
|
||||||
|
SendToStoat("", message, "");
|
||||||
|
}
|
||||||
|
else if (i_port == 27017)
|
||||||
|
{
|
||||||
|
SendToStoat("", message, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetDiscordToStoat(const char[] username, const char[] message, int type)
|
public void GetDiscordToStoat(const char[] username, const char[] message, int type)
|
||||||
{
|
{
|
||||||
//type = 1. ADMINLOGS
|
//type = 1. ADMINLOGS
|
||||||
|
|||||||
@@ -41,12 +41,21 @@ public void OnConVarQueryFinished(QueryCookie cookie, int client, ConVarQueryRes
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (result != ConVarQuery_Okay)
|
if (result != ConVarQuery_Okay)
|
||||||
LogError("Could not query ConVar \"cvarName\" for %N", client);
|
LogError("Could not query ConVar fps_max for %N", client);
|
||||||
|
|
||||||
|
int len = strlen(cvarValue);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (!IsCharNumeric(cvarValue[i]))
|
||||||
|
{
|
||||||
|
KickClient(client, "Invalid fps_max Format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//fps_max 0 is probably acceptable
|
//fps_max 0 is probably acceptable
|
||||||
if (StringToInt(cvarValue) == 0)
|
if (StringToInt(cvarValue) == 0)
|
||||||
return;
|
return;
|
||||||
if (StringToInt(cvarValue) < 58)
|
if (StringToInt(cvarValue) < 58)
|
||||||
KickClient(client, "Your fps_max is invalid, please set it to a higher value (>59)");
|
KickClient(client, "Your fps_max is invalid, please set it to a higher value (>59)");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
HAFL-LIFE_2
|
||||||
|
NoobDnoRaq
|
||||||
|
IMBA
|
||||||
|
ТАЩИР
|
||||||
|
ebaw-kak-t34
|
||||||
|
h4rdc0r3
|
||||||
|
omfg]wiz
|
||||||
|
GOdlikebAby
|
||||||
|
SHITSHITSHIT
|
||||||
|
-Impulse-
|
||||||
|
SLAVA_UKRAINE
|
||||||
|
4ik-pyk
|
||||||
|
BigBoss
|
||||||
|
lolkalalka
|
||||||
|
muhahahahaha
|
||||||
|
GFLClan.ru
|
||||||
|
nide.gg
|
||||||
|
vk.com/nide_css
|
||||||
|
alex481516
|
||||||
|
alahakbar
|
||||||
|
HeadShot
|
||||||
|
HolySHIT
|
||||||
|
CRAY_ZEE
|
||||||
|
mlpro
|
||||||
|
Deadmemories
|
||||||
|
MaGothic
|
||||||
|
ILoveYouBaby
|
||||||
|
nevazhno
|
||||||
|
Tauren
|
||||||
|
Calypso
|
||||||
|
Hawk
|
||||||
|
(1)HAFL-LIFE_2
|
||||||
|
(1)NoobDnoRaq
|
||||||
|
(1)Hawk
|
||||||
|
(1)Tauren
|
||||||
|
(1)mlpro
|
||||||
|
(1)CRAY_ZEE
|
||||||
|
(1)NF-CSS.RU
|
||||||
|
(1)Calypso
|
||||||
|
(1)BigBoss
|
||||||
|
HAFL-LIFE_2
|
||||||
|
NoobDnoRaq
|
||||||
|
IMBA
|
||||||
|
ТАЩИР
|
||||||
|
ebaw-kak-t34
|
||||||
|
h4rdc0r3
|
||||||
|
omfg]wiz
|
||||||
|
GOdlikebAby
|
||||||
|
SHITSHITSHIT
|
||||||
|
-Impulse-
|
||||||
|
SLAVA_UKRAINE
|
||||||
|
4ik-pyk
|
||||||
|
BigBoss
|
||||||
|
lolkalalka
|
||||||
|
muhahahahaha
|
||||||
|
cp.powerhub.ru
|
||||||
|
NiDE.GG
|
||||||
|
vk.com/nide_css
|
||||||
|
alex481516
|
||||||
|
alahakbar
|
||||||
|
HeadShot
|
||||||
|
HolySHIT
|
||||||
|
CRAY_ZEE
|
||||||
|
mlpro
|
||||||
|
Deadmemories
|
||||||
|
MaGothic
|
||||||
|
ILoveYouBaby
|
||||||
|
nevazhno
|
||||||
|
Tauren
|
||||||
|
Calypso
|
||||||
|
Hawk
|
||||||
|
(1)HAFL-LIFE_2
|
||||||
|
(1)NoobDnoRaq
|
||||||
|
(1)Hawk
|
||||||
|
(1)Tauren
|
||||||
|
(1)mlpro
|
||||||
|
(1)CRAY_ZEE
|
||||||
|
(1)NF-CSS.RU
|
||||||
|
(1)Calypso
|
||||||
|
(1)BigBoss
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
Dwelitram
|
|
||||||
Gwyri
|
|
||||||
Caredus
|
|
||||||
Arerawia
|
|
||||||
Vilali
|
|
||||||
Astiwiel
|
|
||||||
Vardonydd
|
|
||||||
Ybaossa
|
|
||||||
Umyk
|
|
||||||
Nico50Pax
|
|
||||||
Onand
|
|
||||||
Thelian
|
|
||||||
Nydaleth
|
|
||||||
Chomarin
|
|
||||||
Traedien
|
|
||||||
Miev
|
|
||||||
Kaaede
|
|
||||||
Koamond
|
|
||||||
TheRottenBenson
|
|
||||||
BigLegend2017
|
|
||||||
TRIGGEREDHarambexXx
|
|
||||||
InPepe2016
|
|
||||||
xXxMaster2012
|
|
||||||
InBoixXx
|
|
||||||
TheKopsing
|
|
||||||
Cornelius
|
|
||||||
Gustavo
|
|
||||||
Bryant
|
|
||||||
Winfred
|
|
||||||
Nicolas
|
|
||||||
Mitchel
|
|
||||||
Dana
|
|
||||||
Carrol
|
|
||||||
Darell
|
|
||||||
Ruben
|
|
||||||
Jeromy
|
|
||||||
Wade
|
|
||||||
Scotty
|
|
||||||
Salvatore
|
|
||||||
Kory
|
|
||||||
Don
|
|
||||||
Morgan
|
|
||||||
Kurtis
|
|
||||||
Federico
|
|
||||||
Darin
|
|
||||||
css-ru
|
|
||||||
aimbot
|
|
||||||
lastkraftwagenfahrzeug
|
|
||||||
edger
|
|
||||||
clownface
|
|
||||||
слово
|
|
||||||
счастливый
|
|
||||||
kara
|
|
||||||
puta
|
|
||||||
meow
|
|
||||||
uncle sam
|
|
||||||
FunBun
|
|
||||||
Counter-Strike.Com.Ua
|
|
||||||
For-css.Ru
|
|
||||||
BOBO
|
|
||||||
Z3r0
|
|
||||||
ZeTo
|
|
||||||
Sakharov
|
|
||||||
Sache11
|
|
||||||
Mr. Dogenberg
|
|
||||||
Maus
|
|
||||||
Magikarpet
|
|
||||||
Miles
|
|
||||||
magick
|
|
||||||
James Lebron
|
|
||||||
jiZZ
|
|
||||||
Dobel
|
|
||||||
THE POPE OF DOPE
|
|
||||||
The Joker
|
|
||||||
that guy over there
|
|
||||||
Be happy :)
|
|
||||||
KingKong
|
|
||||||
Figger Nucker
|
|
||||||
noname
|
|
||||||
alexdu63
|
|
||||||
I put babies in the microwave
|
|
||||||
Tango!!
|
|
||||||
faggot killer
|
|
||||||
admin pidaras
|
|
||||||
MESSI>RONALDO
|
|
||||||
Gabe Newell
|
|
||||||
acetylsalicylic acid
|
|
||||||
Country-Steak: Sauce
|
|
||||||
chlamydia harvester
|
|
||||||
kyle_69
|
|
||||||
Shaggy's dog
|
|
||||||
rEVERSE
|
|
||||||
Piment d'espelette
|
|
||||||
FireHawk
|
|
||||||
Sgt. Pepper
|
|
||||||
krix.
|
|
||||||
imPulse_^_
|
|
||||||
Lardon
|
|
||||||
CAPS LOCK
|
|
||||||
$pussymoneyweed$
|
|
||||||
Low5
|
|
||||||
Bonerfart
|
|
||||||
Shiny Thanos
|
|
||||||
MARK NUTT
|
|
||||||
Legless Runner
|
|
||||||
Banana is a berry
|
|
||||||
Gabriel
|
|
||||||
El Moustachio
|
|
||||||
James Bong
|
|
||||||
Disco Fever
|
|
||||||
Acacia
|
|
||||||
Sugared
|
|
||||||
ronald goddamn macdonald
|
|
||||||
pizza is life
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
"FakeClientsTiers"
|
||||||
|
{
|
||||||
|
"0" "23"
|
||||||
|
"3" "22"
|
||||||
|
"6" "21"
|
||||||
|
"9" "20"
|
||||||
|
"12" "19"
|
||||||
|
"15" "18"
|
||||||
|
"18" "17"
|
||||||
|
"21" "16"
|
||||||
|
"24" "15"
|
||||||
|
"27" "14"
|
||||||
|
"30" "13"
|
||||||
|
"33" "12"
|
||||||
|
"36" "11"
|
||||||
|
"39" "10"
|
||||||
|
"42" "9"
|
||||||
|
"45" "8"
|
||||||
|
"48" "7"
|
||||||
|
"51" "6"
|
||||||
|
"54" "5"
|
||||||
|
"55" "4"
|
||||||
|
"57" "3"
|
||||||
|
"60" "2"
|
||||||
|
"61" "1"
|
||||||
|
"62" "0"
|
||||||
|
}
|
||||||
@@ -1,27 +1,18 @@
|
|||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <sdktools>
|
#include <sdktools>
|
||||||
#include <zombiereloaded>
|
|
||||||
#include <BotTargeting>
|
|
||||||
#include <cstrike>
|
#include <cstrike>
|
||||||
|
|
||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
#pragma newdecls required
|
#pragma newdecls required
|
||||||
|
|
||||||
#define MAXNAMES 500
|
|
||||||
ArrayList g_hNames;
|
ArrayList g_hNames;
|
||||||
ArrayList g_hClanNames;
|
ArrayList g_hClanNames;
|
||||||
|
|
||||||
bool g_bMapEnded;
|
|
||||||
|
|
||||||
int g_iBaseLatency[MAXPLAYERS + 1];
|
int g_iBaseLatency[MAXPLAYERS + 1];
|
||||||
int g_iLatency[MAXPLAYERS + 1];
|
int g_iLatency[MAXPLAYERS + 1];
|
||||||
|
int g_iPlayerCount;
|
||||||
|
|
||||||
int g_iAdminFakes;
|
bool g_bMapended;
|
||||||
int g_iPopulation;
|
|
||||||
|
|
||||||
bool g_bCheckRequested;
|
|
||||||
|
|
||||||
bool g_bBlockInstantFakeConnects;
|
|
||||||
|
|
||||||
Database g_hDatabase;
|
Database g_hDatabase;
|
||||||
Database g_hDatabase_hlstats;
|
Database g_hDatabase_hlstats;
|
||||||
@@ -31,10 +22,10 @@ Database g_hDatabase_hlstats;
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Plugin myinfo =
|
public Plugin myinfo =
|
||||||
{
|
{
|
||||||
name = "ImprovedHitboxes", //camouflage
|
name = "fakes",
|
||||||
author = "Neon + Dogan + Botox",
|
author = "Neon + Dogan + Botox",
|
||||||
description = "Handle Hitboxes via Plugin",
|
description = "Handle Hitboxes via Plugin",
|
||||||
version = "5.3.1",
|
version = "5.4.1",
|
||||||
url = "https://steamcommunity.com/id/n3ontm"
|
url = "https://steamcommunity.com/id/n3ontm"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,28 +36,19 @@ public void OnPluginStart()
|
|||||||
{
|
{
|
||||||
RegAdminCmd("sm_debugfakes", Command_DebugFakes, ADMFLAG_GENERIC, "Shows the amount of fake-clients on server");
|
RegAdminCmd("sm_debugfakes", Command_DebugFakes, ADMFLAG_GENERIC, "Shows the amount of fake-clients on server");
|
||||||
RegAdminCmd("sm_fakes", Command_Fakes, ADMFLAG_GENERIC, "Shows the fake-clients on server");
|
RegAdminCmd("sm_fakes", Command_Fakes, ADMFLAG_GENERIC, "Shows the fake-clients on server");
|
||||||
RegAdminCmd("sm_setfakes", Command_SetFakes, ADMFLAG_RCON, "Manually sets the amount of fake-clients");
|
|
||||||
|
|
||||||
int arraySize = ByteCountToCells(MAX_NAME_LENGTH);
|
int arraySize = ByteCountToCells(MAX_NAME_LENGTH);
|
||||||
g_hNames = CreateArray(arraySize);
|
g_hNames = CreateArray(arraySize);
|
||||||
g_hClanNames = CreateArray(arraySize);
|
g_hClanNames = CreateArray(arraySize);
|
||||||
|
|
||||||
g_iAdminFakes = -1;
|
CreateTimer(GetRandomFloat(20.0, 40.0), RunPopulationCheck, _, TIMER_REPEAT);
|
||||||
g_iPopulation = GetClientCount(false);
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
g_iPopulation--;
|
|
||||||
}
|
|
||||||
g_bMapEnded = false;
|
|
||||||
g_bBlockInstantFakeConnects = false;
|
|
||||||
CreateTimer(10.0, BlockInstantFakeConnects, _, TIMER_REPEAT);
|
|
||||||
CreateTimer(3.0, RandomizePing, _, TIMER_REPEAT);
|
CreateTimer(3.0, RandomizePing, _, TIMER_REPEAT);
|
||||||
CreateTimer(150.0, RandomizeNames, _, TIMER_REPEAT);
|
CreateTimer(600.0, RandomizeNames, _, TIMER_REPEAT);
|
||||||
|
CreateTimer(80.0, CheckPopulation_interval, _, TIMER_REPEAT);
|
||||||
|
|
||||||
HookUserMessage(GetUserMessageId("SayText2"), UserMessage_SayText2, true);
|
HookUserMessage(GetUserMessageId("SayText2"), UserMessage_SayText2, true);
|
||||||
|
|
||||||
RequestFrame(CheckPopulation);
|
g_bMapended = false;
|
||||||
|
|
||||||
if (!g_hDatabase)
|
if (!g_hDatabase)
|
||||||
{
|
{
|
||||||
@@ -76,6 +58,7 @@ public void OnPluginStart()
|
|||||||
{
|
{
|
||||||
Database.Connect(SQL_OnDatabaseConnect_hlstats, "hlstatsx");
|
Database.Connect(SQL_OnDatabaseConnect_hlstats, "hlstatsx");
|
||||||
}
|
}
|
||||||
|
g_iPlayerCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SQL_OnDatabaseConnect_hlstats(Database db, const char[] error, any data)
|
public void SQL_OnDatabaseConnect_hlstats(Database db, const char[] error, any data)
|
||||||
@@ -92,7 +75,7 @@ public void SQL_OnDatabaseConnect_hlstats(Database db, const char[] error, any d
|
|||||||
public void randomize_clantags()
|
public void randomize_clantags()
|
||||||
{
|
{
|
||||||
char sQuery[512];
|
char sQuery[512];
|
||||||
Format(sQuery, sizeof(sQuery), "select DISTINCT tag from unloze_stats.hlstats_Clans ORDER BY RAND() limit 500");
|
Format(sQuery, sizeof(sQuery), "select DISTINCT tag from unloze_stats.hlstats_Clans ORDER BY RAND() limit 1000");
|
||||||
g_hDatabase_hlstats.Query(SQL_OnQueryCompleted_hlstats, sQuery, DBPrio_High);
|
g_hDatabase_hlstats.Query(SQL_OnQueryCompleted_hlstats, sQuery, DBPrio_High);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +93,7 @@ public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
|||||||
public void randomize_names()
|
public void randomize_names()
|
||||||
{
|
{
|
||||||
char sQuery[512];
|
char sQuery[512];
|
||||||
Format(sQuery, sizeof(sQuery), "select name from unloze_racetimer_css.random_names ORDER BY RAND() limit 500");
|
Format(sQuery, sizeof(sQuery), "select name from unloze_racetimer_css.random_names ORDER BY RAND() limit 1000");
|
||||||
g_hDatabase.Query(SQL_OnQueryCompleted, sQuery, DBPrio_High);
|
g_hDatabase.Query(SQL_OnQueryCompleted, sQuery, DBPrio_High);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,19 +141,9 @@ public void SQL_OnQueryCompleted(Database db, DBResultSet results, const char[]
|
|||||||
delete results;
|
delete results;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
public void OnMapEnd()
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public void OnPluginEnd()
|
|
||||||
{
|
{
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
g_bMapended = true;
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
{
|
|
||||||
g_iLatency[i] = 0;
|
|
||||||
KickClient(i, "Disconnect by user.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -178,80 +151,129 @@ public void OnPluginEnd()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnMapStart()
|
public void OnMapStart()
|
||||||
{
|
{
|
||||||
g_hNames.Clear();
|
KeyValues kv = CreateKeyValues("ints_used_already");
|
||||||
g_hClanNames.Clear();
|
int fakes_needed = getFakesNeeded();
|
||||||
if (!g_hDatabase)
|
for (float i = 0.0; i < fakes_needed;)
|
||||||
{
|
{
|
||||||
Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
|
int num = GetRandomInt(5, 45);
|
||||||
|
char strnum[16];
|
||||||
|
IntToString(num, strnum, sizeof(strnum));
|
||||||
|
int found = kv.GetNum(strnum, -1);
|
||||||
|
if (found != -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
kv.SetNum(strnum, num);
|
||||||
|
i += 1.0;
|
||||||
|
|
||||||
|
CreateTimer(float(num), addfakes);
|
||||||
}
|
}
|
||||||
else
|
delete kv;
|
||||||
{
|
|
||||||
randomize_names();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_hDatabase_hlstats)
|
|
||||||
{
|
|
||||||
Database.Connect(SQL_OnDatabaseConnect_hlstats, "hlstatsx");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
randomize_clantags();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
char sFile[PLATFORM_MAX_PATH];
|
|
||||||
char sLine[MAX_NAME_LENGTH];
|
|
||||||
BuildPath(Path_SM, sFile, sizeof(sFile), "configs/fakeclients_names.txt");
|
|
||||||
Handle hFile = OpenFile(sFile, "r");
|
|
||||||
|
|
||||||
if(hFile != INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
int iLine = 0;
|
|
||||||
g_hNames.Clear();
|
|
||||||
while (!IsEndOfFile(hFile))
|
|
||||||
{
|
|
||||||
if (!ReadFileLine(hFile, sLine, sizeof(sLine)) || iLine >= MAXNAMES)
|
|
||||||
break;
|
|
||||||
|
|
||||||
TrimString(sLine);
|
|
||||||
g_hNames.PushString(sLine);
|
|
||||||
iLine++;
|
|
||||||
}
|
|
||||||
delete hFile;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SetFailState("Could not open file: configs/fakeclients_names.txt");
|
|
||||||
*/
|
|
||||||
|
|
||||||
g_bMapEnded = false;
|
|
||||||
|
|
||||||
g_bBlockInstantFakeConnects = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
public int getFakesNeeded()
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public void OnMapEnd()
|
|
||||||
{
|
{
|
||||||
g_bMapEnded = true;
|
//copied from nide fakeclients plugin.
|
||||||
g_iAdminFakes = -1;
|
char sPath[PLATFORM_MAX_PATH];
|
||||||
g_iPopulation = GetClientCount(false);
|
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/fakeclients_tiers.cfg");
|
||||||
|
|
||||||
|
KeyValues kv = new KeyValues("FakeClientsTiers");
|
||||||
|
if (!kv.ImportFromFile(sPath))
|
||||||
|
{
|
||||||
|
LogError("configs/fakeclients_tiers.cfg not found — falling back to sm_fakeclients_players");
|
||||||
|
delete kv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kv.GotoFirstSubKey(false))
|
||||||
|
{
|
||||||
|
LogError("configs/fakeclients_tiers.cfg is empty or malformed");
|
||||||
|
delete kv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prev_bots = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char sKey[16], sVal[16];
|
||||||
|
kv.GetSectionName(sKey, sizeof(sKey));
|
||||||
|
kv.GetString(NULL_STRING, sVal, sizeof(sVal), "-1");
|
||||||
|
|
||||||
|
int bots = StringToInt(sVal);
|
||||||
|
int players = StringToInt(sKey);
|
||||||
|
if (players > g_iPlayerCount)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev_bots = bots;
|
||||||
|
|
||||||
|
} while (kv.GotoNextKey(false));
|
||||||
|
|
||||||
|
delete kv;
|
||||||
|
//LogMessage("prev_bots: %i", prev_bots);
|
||||||
|
return prev_bots;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action addfakes(Handle timer)
|
||||||
|
{
|
||||||
|
int limit = getFakesNeeded();
|
||||||
|
int fakes = 0;
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
{
|
{
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
if (IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i))
|
||||||
g_iPopulation--;
|
{
|
||||||
|
if (IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
fakes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (nightTime())
|
||||||
|
{
|
||||||
|
limit /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fakes < limit)
|
||||||
|
{
|
||||||
|
CreateFake();
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CheckPopulation_interval(Handle timer)
|
||||||
|
{
|
||||||
|
int TimeLeft;
|
||||||
|
if (GetMapTimeLeft(TimeLeft) && TimeLeft < 0)
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_bMapended)
|
||||||
|
{
|
||||||
|
g_bMapended = false;
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_iPlayerCount = 0;
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i))
|
||||||
|
{
|
||||||
|
if (!IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
g_iPlayerCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action BlockInstantFakeConnects(Handle timer)
|
public Action RunPopulationCheck(Handle timer)
|
||||||
{
|
{
|
||||||
g_bBlockInstantFakeConnects = false;
|
CheckPopulation();
|
||||||
RequestFrame(CheckPopulation);
|
|
||||||
|
|
||||||
return Plugin_Continue;
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,45 +381,17 @@ public Action Command_DebugFakes(int client, int argc)
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (IsFakeClient(i) || IsClientSourceTV(i))
|
if (IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
{
|
{
|
||||||
iFakes++;
|
iFakes++;
|
||||||
iPlayers--;
|
iPlayers--;
|
||||||
}
|
}
|
||||||
if (IsFakeClient(i) && GetClientTeam(i) > 0)
|
if (IsFakeClient(i) && GetClientTeam(i) > CS_TEAM_SPECTATOR)
|
||||||
iFakesInTeam++;
|
iFakesInTeam++;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplyToCommand(client, "[SM] There are currently %d Fake-Clients, from which %d are in Spectate.", iFakes, iFakes - iFakesInTeam);
|
ReplyToCommand(client, "[SM] There are currently %d Fake-Clients, from which %d are in Spectate. Real Clients %d", iFakes, iFakes - iFakesInTeam, iPlayers);
|
||||||
ReplyToCommand(client, "[SM] Server Population at the end of the previous Map: %d.", g_iPopulation);
|
|
||||||
ReplyToCommand(client, "[SM] Current Server Population: %d. Difference: %d.", iPlayers, iPlayers - g_iPopulation);
|
|
||||||
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public Action Command_SetFakes(int client, int argc)
|
|
||||||
{
|
|
||||||
if (argc < 1)
|
|
||||||
{
|
|
||||||
ReplyToCommand(client, "[SM] Usage: sm_setfakes <amount of fakes>");
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
char sArgs[16];
|
|
||||||
GetCmdArg(1, sArgs, sizeof(sArgs));
|
|
||||||
|
|
||||||
if (!StringToIntEx(sArgs, g_iAdminFakes))
|
|
||||||
{
|
|
||||||
ReplyToCommand(client, "[SM] Invalid value");
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReplyToCommand(client, "[SM] You set the amount of Fake-Clients to %d.", g_iAdminFakes);
|
|
||||||
CheckPopulation();
|
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,18 +427,6 @@ public Action Command_Fakes(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public void OnClientConnected(int client)
|
|
||||||
{
|
|
||||||
if (!g_bCheckRequested && !IsFakeClient(client) && !IsClientSourceTV(client))
|
|
||||||
{
|
|
||||||
RequestFrame(CheckPopulation);
|
|
||||||
g_bCheckRequested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -456,182 +438,131 @@ public void OnClientDisconnect(int client)
|
|||||||
{
|
{
|
||||||
g_iLatency[client] = 0;
|
g_iLatency[client] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_bCheckRequested && !IsFakeClient(client) && !IsClientSourceTV(client))
|
|
||||||
{
|
|
||||||
RequestFrame(CheckPopulation);
|
|
||||||
g_bCheckRequested = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action repeatCheckPopulation(Handle timer)
|
|
||||||
{
|
|
||||||
CheckPopulation();
|
|
||||||
return Plugin_Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void CheckPopulation()
|
public void CheckPopulation()
|
||||||
|
{
|
||||||
|
int fakes = 0;
|
||||||
|
int last_fake = 0;
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i))
|
||||||
|
{
|
||||||
|
if (IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
fakes++;
|
||||||
|
last_fake = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int fakes_needed = getFakesNeeded();
|
||||||
|
if (nightTime())
|
||||||
|
{
|
||||||
|
fakes_needed /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fakes > fakes_needed && last_fake != 0)
|
||||||
|
{
|
||||||
|
g_iLatency[last_fake] = 0;
|
||||||
|
KickClient(last_fake, "Disconnect by user.");
|
||||||
|
}
|
||||||
|
else if (fakes < fakes_needed)
|
||||||
|
{
|
||||||
|
CreateFake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool nightTime()
|
||||||
|
{
|
||||||
|
char sTime[8];
|
||||||
|
FormatTime(sTime, sizeof(sTime), "%H%M");
|
||||||
|
|
||||||
|
int CurTime = StringToInt(sTime);
|
||||||
|
int MinTime = 2300;
|
||||||
|
int MaxTime = 400;
|
||||||
|
|
||||||
|
//Wrap around.
|
||||||
|
CurTime = (CurTime <= MinTime) ? CurTime + 2400 : CurTime;
|
||||||
|
MaxTime = (MaxTime <= MinTime) ? MaxTime + 2400 : MaxTime;
|
||||||
|
|
||||||
|
if ((MinTime <= CurTime <= MaxTime))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//not used anymore
|
||||||
|
public void SetFakeToTeam()
|
||||||
|
{
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i) && GetClientTeam(i) <= CS_TEAM_SPECTATOR)
|
||||||
|
{
|
||||||
|
ChangeClientTeam(i, CS_TEAM_CT);
|
||||||
|
FakeClientCommandEx(i, "joinclass");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFake()
|
||||||
{
|
{
|
||||||
if (g_hNames.Length == 0 || g_hClanNames.Length == 0)
|
if (g_hNames.Length == 0 || g_hClanNames.Length == 0)
|
||||||
{
|
{
|
||||||
CreateTimer(5.0, repeatCheckPopulation);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_bCheckRequested = false;
|
ArrayList hNames = g_hNames.Clone();
|
||||||
|
char sName[MAX_NAME_LENGTH];
|
||||||
if(g_bMapEnded)
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
return;
|
|
||||||
|
|
||||||
int iPlayers = GetClientCount(false);
|
|
||||||
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsClientInGame(i) && IsClientAuthorized(i) && (IsFakeClient(i) || IsClientAutismBot(i) || IsClientSourceTV(i) || GetClientTeam(i) == CS_TEAM_SPECTATOR))
|
|
||||||
iPlayers--;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iFakes = 0;
|
|
||||||
int iFakesInTeam = 0;
|
|
||||||
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if (IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
iFakes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int iFakesInTeamNeeded = iPlayers;
|
|
||||||
int iFakesNeeded = iPlayers;
|
|
||||||
|
|
||||||
int full_client_count = GetClientCount(false);
|
|
||||||
|
|
||||||
if (full_client_count > 50) //counting all clients in total.
|
|
||||||
{
|
|
||||||
iFakesInTeamNeeded = 0;
|
|
||||||
iFakesNeeded = 0;
|
|
||||||
}
|
|
||||||
else if (full_client_count >= 42)
|
|
||||||
{
|
{
|
||||||
|
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
GetClientName(i, sName, sizeof(sName));
|
||||||
|
int iPos = hNames.FindString(sName);
|
||||||
|
if (iPos > -1)
|
||||||
|
hNames.Erase(iPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iRand = GetRandomInt(0, hNames.Length - 1);
|
||||||
|
hNames.GetString(iRand, sName, sizeof(sName));
|
||||||
|
delete hNames;
|
||||||
|
|
||||||
|
int iIndex = CreateFakeClient(sName);
|
||||||
|
|
||||||
|
if(iIndex < 1 || iIndex > MaxClients)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SetEntityFlags(iIndex, FL_CLIENT);
|
||||||
|
DispatchKeyValue(iIndex, "classname", "player");
|
||||||
|
DispatchSpawn(iIndex);
|
||||||
|
|
||||||
|
g_iBaseLatency[iIndex] = GetRandomInt(20, 110);
|
||||||
|
g_iLatency[iIndex] = g_iBaseLatency[iIndex];
|
||||||
|
|
||||||
|
AdminId FakeAdmin = CreateAdmin();
|
||||||
|
SetAdminFlag(FakeAdmin, Admin_Custom6, true);
|
||||||
|
SetUserAdmin(iIndex, FakeAdmin, true);
|
||||||
|
|
||||||
|
if (GetRandomInt(0, 5) >= 3)
|
||||||
|
{
|
||||||
|
ArrayList hClanNames = g_hClanNames.Clone();
|
||||||
|
iRand = GetRandomInt(0, hClanNames.Length - 1);
|
||||||
|
hClanNames.GetString(iRand, sName, sizeof(sName));
|
||||||
|
delete hClanNames;
|
||||||
|
CS_SetClientClanTag(iIndex, sName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
iFakesInTeamNeeded = (iFakesNeeded / 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iFakesInTeamNeeded < 0)
|
|
||||||
{
|
{
|
||||||
iFakesInTeamNeeded = 0;
|
CS_SetClientClanTag(iIndex, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (iFakes != iFakesNeeded)
|
|
||||||
{
|
|
||||||
while (iFakes < iFakesNeeded && !g_bBlockInstantFakeConnects)
|
|
||||||
{
|
|
||||||
ArrayList hNames = g_hNames.Clone();
|
|
||||||
char sName[MAX_NAME_LENGTH];
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
{
|
|
||||||
GetClientName(i, sName, sizeof(sName));
|
|
||||||
int iPos = hNames.FindString(sName);
|
|
||||||
if (iPos > -1)
|
|
||||||
hNames.Erase(iPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int iRand = GetRandomInt(0, hNames.Length - 1);
|
|
||||||
hNames.GetString(iRand, sName, sizeof(sName));
|
|
||||||
delete hNames;
|
|
||||||
|
|
||||||
int iIndex = CreateFakeClient(sName);
|
|
||||||
|
|
||||||
if(iIndex < 1 || iIndex > MaxClients)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetEntityFlags(iIndex, FL_CLIENT);
|
|
||||||
DispatchKeyValue(iIndex, "classname", "player");
|
|
||||||
DispatchSpawn(iIndex);
|
|
||||||
|
|
||||||
g_iBaseLatency[iIndex] = GetRandomInt(20, 110);
|
|
||||||
g_iLatency[iIndex] = g_iBaseLatency[iIndex];
|
|
||||||
|
|
||||||
AdminId FakeAdmin = CreateAdmin();
|
|
||||||
SetAdminFlag(FakeAdmin, Admin_Custom6, true);
|
|
||||||
SetUserAdmin(iIndex, FakeAdmin, true);
|
|
||||||
|
|
||||||
if (GetRandomInt(0, 5) >= 3)
|
|
||||||
{
|
|
||||||
ArrayList hClanNames = g_hClanNames.Clone();
|
|
||||||
iRand = GetRandomInt(0, hClanNames.Length - 1);
|
|
||||||
hClanNames.GetString(iRand, sName, sizeof(sName));
|
|
||||||
delete hClanNames;
|
|
||||||
CS_SetClientClanTag(iIndex, sName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CS_SetClientClanTag(iIndex, "");
|
|
||||||
}
|
|
||||||
iFakes++;
|
|
||||||
|
|
||||||
g_bBlockInstantFakeConnects = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iFakes > iFakesNeeded)
|
|
||||||
{
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
{
|
|
||||||
g_iLatency[i] = 0;
|
|
||||||
KickClient(i, "Disconnect by user.");
|
|
||||||
iFakes--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if (IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i) && GetClientTeam(i) >= CS_TEAM_T)
|
|
||||||
iFakesInTeam++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iFakesInTeam != iFakesInTeamNeeded && g_iAdminFakes == -1)
|
|
||||||
{
|
|
||||||
if (iFakesInTeam < iFakesInTeamNeeded)
|
|
||||||
{
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i) && GetClientTeam(i) <= CS_TEAM_SPECTATOR)
|
|
||||||
{
|
|
||||||
ChangeClientTeam(i, CS_TEAM_CT);
|
|
||||||
FakeClientCommandEx(i, "joinclass");
|
|
||||||
iFakesInTeam++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iFakesInTeam > iFakesInTeamNeeded)
|
|
||||||
{
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
{
|
|
||||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i) && GetClientTeam(i) >= CS_TEAM_T)
|
|
||||||
{
|
|
||||||
ChangeClientTeam(i, CS_TEAM_SPECTATOR);
|
|
||||||
iFakesInTeam--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -652,13 +583,3 @@ public void OnGameFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public Action ZR_OnClientMotherZombieEligible(int client)
|
|
||||||
{
|
|
||||||
if (IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
|
||||||
return Plugin_Handled;
|
|
||||||
|
|
||||||
return Plugin_Continue;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -0,0 +1,480 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#pragma newdecls required
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <cstrike>
|
||||||
|
|
||||||
|
#define MAX_TIERS 32
|
||||||
|
|
||||||
|
ConVar g_hCount;
|
||||||
|
ConVar g_hDelay;
|
||||||
|
ConVar g_hUseTiers;
|
||||||
|
ArrayList g_hNames;
|
||||||
|
|
||||||
|
int g_iTierThreshold[MAX_TIERS]; // real player count that triggers this tier
|
||||||
|
int g_iTierMaxBots[MAX_TIERS]; // max bots allowed for this tier
|
||||||
|
int g_iTierCount = 0;
|
||||||
|
int g_iPendingBots = 0;
|
||||||
|
|
||||||
|
bool g_bUseTiers = false;
|
||||||
|
|
||||||
|
public Plugin myinfo = {
|
||||||
|
name = "FakeClients",
|
||||||
|
author = "Tsunami, .Rushaway",
|
||||||
|
description = "Put fake clients in server with tier system",
|
||||||
|
version = "3.0.0",
|
||||||
|
url = "https://github.com/srcdslab/sm-plugin-FakeClients"
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
g_hCount = CreateConVar("sm_fakeclients_players", "8", "Fallback: number of bots when tier system is disabled", _, true, 0.0, true, 64.0);
|
||||||
|
g_hDelay = CreateConVar("sm_fakeclients_delay", "120", "Delay after map change before fake clients join (seconds)", _, true, 0.0, true, 10000.0);
|
||||||
|
g_hUseTiers = CreateConVar("sm_fakeclients_tiers", "0", "Use tier system from fakeclients_tiers.cfg (1 = enabled, 0 = disabled)", _, true, 0.0, true, 1.0);
|
||||||
|
|
||||||
|
g_bUseTiers = g_hUseTiers.BoolValue;
|
||||||
|
g_hUseTiers.AddChangeHook(OnConVarChanged);
|
||||||
|
|
||||||
|
RegAdminCmd("sm_debugfakes", Command_DebugFakes, ADMFLAG_GENERIC, "Shows the amount of fake-clients on server");
|
||||||
|
RegAdminCmd("sm_fakes", Command_Fakes, ADMFLAG_GENERIC, "Shows the fake-clients on server");
|
||||||
|
|
||||||
|
AutoExecConfig(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_DebugFakes(int client, int argc)
|
||||||
|
{
|
||||||
|
int iFakes = 0;
|
||||||
|
int iFakesInTeam = 0;
|
||||||
|
int iPlayers = GetClientCount(false);
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsClientConnected(i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (IsFakeClient(i) || IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
iFakes++;
|
||||||
|
iPlayers--;
|
||||||
|
}
|
||||||
|
if (IsFakeClient(i) && GetClientTeam(i) > CS_TEAM_SPECTATOR)
|
||||||
|
iFakesInTeam++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplyToCommand(client, "[SM] There are currently %d Fake-Clients, from which %d are in Spectate. Real Clients %d", iFakes, iFakes - iFakesInTeam, iPlayers);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Action Command_Fakes(int client, int args)
|
||||||
|
{
|
||||||
|
char aBuf[1024];
|
||||||
|
char aBuf2[MAX_NAME_LENGTH];
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i))
|
||||||
|
{
|
||||||
|
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
GetClientName(i, aBuf2, sizeof(aBuf2));
|
||||||
|
StrCat(aBuf, sizeof(aBuf), aBuf2);
|
||||||
|
StrCat(aBuf, sizeof(aBuf), ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen(aBuf))
|
||||||
|
{
|
||||||
|
aBuf[strlen(aBuf) - 2] = 0;
|
||||||
|
ReplyToCommand(client, "[SM] Fake-Clients online: %s", aBuf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ReplyToCommand(client, "[SM] Fake-Clients online: none");
|
||||||
|
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
ParseNames();
|
||||||
|
ParseTiers();
|
||||||
|
CreateTimer(g_hDelay.FloatValue, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnConVarChanged(ConVar hConVar, const char[] sOldValue, const char[] sNewValue)
|
||||||
|
{
|
||||||
|
if (hConVar == g_hUseTiers)
|
||||||
|
{
|
||||||
|
g_bUseTiers = g_hUseTiers.BoolValue;
|
||||||
|
LogMessage("Tier system %s", g_bUseTiers ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
if (g_bUseTiers)
|
||||||
|
{
|
||||||
|
g_iPendingBots = 0;
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsClientConnected(i) || !IsClientInGame(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!IsFakeClient(i) || IsClientSourceTV(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
KickClient(i, "Client Disconnect");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait a moment for all bots to be kicked before trying to add new ones according to tiers.
|
||||||
|
CreateTimer(1.0, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AdjustFakeClientsToTier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the target bot count based on the current number of real players.
|
||||||
|
* Falls back to sm_fakeclients_players if tiers are disabled or not loaded.
|
||||||
|
*/
|
||||||
|
int GetTargetBotCount(int iRealPlayers)
|
||||||
|
{
|
||||||
|
if (!g_bUseTiers || g_iTierCount == 0)
|
||||||
|
return g_hCount.IntValue;
|
||||||
|
|
||||||
|
// Walk tiers from highest threshold down, pick the first one that applies
|
||||||
|
for (int t = g_iTierCount - 1; t >= 0; t--)
|
||||||
|
{
|
||||||
|
if (iRealPlayers >= g_iTierThreshold[t])
|
||||||
|
return g_iTierMaxBots[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
// No tier matched (e.g. config missing threshold "0")
|
||||||
|
LogMessage("Warning: no tier matched for %d real players, defaulting to 0 bots", iRealPlayers);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the clamped target bot count, accounting for available slots and
|
||||||
|
* server over-capacity. Shared by AdjustFakeClientsToTier and OnClientPutInServer.
|
||||||
|
*/
|
||||||
|
int ComputeTarget(int iBots, int iRealPlayers, int iReservedSlots)
|
||||||
|
{
|
||||||
|
int iTarget = GetTargetBotCount(iRealPlayers);
|
||||||
|
if (iTarget < 0)
|
||||||
|
iTarget = 0;
|
||||||
|
|
||||||
|
// Bots currently being added already count as occupied slots
|
||||||
|
int iEffectiveBots = iBots + g_iPendingBots;
|
||||||
|
int iFreeSlots = MaxClients - (iRealPlayers + iEffectiveBots + iReservedSlots);
|
||||||
|
|
||||||
|
if (iFreeSlots < 0)
|
||||||
|
{
|
||||||
|
iTarget = iEffectiveBots + iFreeSlots;
|
||||||
|
if (iTarget < 0)
|
||||||
|
iTarget = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int iMaxBotsBySlots = iEffectiveBots + iFreeSlots;
|
||||||
|
if (iTarget > iMaxBotsBySlots)
|
||||||
|
iTarget = iMaxBotsBySlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks excess bots until the bot count reaches iTarget.
|
||||||
|
* Never kicks real players or SourceTV.
|
||||||
|
*/
|
||||||
|
void KickExcessBots(int iBots, int iRealPlayers, int iTarget)
|
||||||
|
{
|
||||||
|
int iToKick = iBots - iTarget;
|
||||||
|
int iKicked = 0;
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients && iKicked < iToKick; i++)
|
||||||
|
{
|
||||||
|
if (!IsClientConnected(i) || !IsClientInGame(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Safety: never kick real players or SourceTV
|
||||||
|
if (!IsFakeClient(i) || IsClientSourceTV(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LogMessage("Kicking fake client '%N' (slot %d) — bots:%d target:%d", i, i, iBots, iTarget);
|
||||||
|
|
||||||
|
KickClient(i, "Client Disconnect");
|
||||||
|
iKicked++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iKicked > 0)
|
||||||
|
LogMessage("Kicked %d bot(s) — real:%d bots:%d target:%d slots:%d", iKicked, iRealPlayers, iBots, iTarget, MaxClients);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules staggered timers to add bots up to iToAdd, respecting free slots.
|
||||||
|
*/
|
||||||
|
void ScheduleBotsToAdd(int iToAdd, int iFreeSlots)
|
||||||
|
{
|
||||||
|
if (iFreeSlots <= 0 || iToAdd <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (iToAdd > iFreeSlots)
|
||||||
|
iToAdd = iFreeSlots;
|
||||||
|
|
||||||
|
// Keep a staggered cadence but add jitter so joins look less scripted.
|
||||||
|
float fNextDelay = GetRandomFloat(0.4, 1.2);
|
||||||
|
|
||||||
|
for (int j = 0; j < iToAdd; j++)
|
||||||
|
{
|
||||||
|
g_iPendingBots++;
|
||||||
|
CreateTimer(fNextDelay, Timer_CreateFakeClient, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
fNextDelay += GetRandomFloat(0.7, 1.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares current bot count against the target and either kicks excess bots
|
||||||
|
* or schedules new ones to fill the gap.
|
||||||
|
*/
|
||||||
|
void AdjustFakeClientsToTier()
|
||||||
|
{
|
||||||
|
int iBots, iRealPlayers, iReservedSlots;
|
||||||
|
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
|
||||||
|
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
int iFreeSlots = MaxClients - (iRealPlayers + iBots + iReservedSlots);
|
||||||
|
|
||||||
|
// Too many active bots -> kick extras
|
||||||
|
if (iBots > iTarget)
|
||||||
|
{
|
||||||
|
g_iPendingBots = 0;
|
||||||
|
KickExcessBots(iBots, iRealPlayers, iTarget);
|
||||||
|
}
|
||||||
|
// Active + pending bots are below target -> add missing bots
|
||||||
|
else if ((iBots + g_iPendingBots) < iTarget)
|
||||||
|
ScheduleBotsToAdd(iTarget - iBots - g_iPendingBots, iFreeSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects fake bots, real players and reserved slots in a single client loop.
|
||||||
|
*/
|
||||||
|
void CollectClientCounts(int &iBots, int &iRealPlayers, int &iReservedSlots)
|
||||||
|
{
|
||||||
|
iBots = 0;
|
||||||
|
iRealPlayers = 0;
|
||||||
|
bool bHasSourceTV = false;
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsClientConnected(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (IsClientSourceTV(i))
|
||||||
|
{
|
||||||
|
bHasSourceTV = true;
|
||||||
|
continue; // SourceTV occupies its own slot in MaxClients — do not count it as a bot
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsFakeClient(i))
|
||||||
|
iBots++;
|
||||||
|
else
|
||||||
|
iRealPlayers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve 1 free slot so a real player can always connect.
|
||||||
|
// When SourceTV is active, reserve 1 extra (SourceTV's slot is already in MaxClients).
|
||||||
|
iReservedSlots = bHasSourceTV ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientPutInServer(int client)
|
||||||
|
{
|
||||||
|
// Skip fake clients: bot additions are managed via timers.
|
||||||
|
// Calling AdjustFakeClientsToTier on every bot join would cause cascading timers.
|
||||||
|
if (!client || IsFakeClient(client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// A real player joined: only kick excess bots, never schedule additions.
|
||||||
|
// Scheduling here would race with the staggered timers already in flight.
|
||||||
|
int iBots, iRealPlayers, iReservedSlots;
|
||||||
|
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
|
||||||
|
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
if (iBots > iTarget)
|
||||||
|
KickExcessBots(iBots, iRealPlayers, iTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
// Ignore bot disconnects (caused by our own kicks) to avoid cascading timers.
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CreateTimer(0.5, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Timer_CreateFakeClient(Handle timer)
|
||||||
|
{
|
||||||
|
g_iPendingBots--;
|
||||||
|
if (g_iPendingBots < 0)
|
||||||
|
g_iPendingBots = 0;
|
||||||
|
|
||||||
|
int iBots, iRealPlayers, iReservedSlots;
|
||||||
|
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
|
||||||
|
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||||
|
int iFreeSlots = MaxClients - (iRealPlayers + iBots + iReservedSlots);
|
||||||
|
|
||||||
|
// Recheck: tier may have changed since this timer was scheduled
|
||||||
|
if (iFreeSlots <= 0 || iBots >= iTarget)
|
||||||
|
return Plugin_Handled;
|
||||||
|
|
||||||
|
char sName[MAX_NAME_LENGTH];
|
||||||
|
char sTarget[MAX_TARGET_LENGTH];
|
||||||
|
int iTargets[MAXPLAYERS];
|
||||||
|
bool bTN_Is_ML;
|
||||||
|
|
||||||
|
// Pick a random name, re-roll if it's already taken by a fake client.
|
||||||
|
// Stop after trying all available names to prevent an infinite loop when
|
||||||
|
// the name list is smaller than the number of bots (duplicates are allowed).
|
||||||
|
// If no names are configured, CreateFakeClient will assign a default name based on the engine.
|
||||||
|
int iNameCount = g_hNames.Length;
|
||||||
|
if (iNameCount > 0)
|
||||||
|
{
|
||||||
|
g_hNames.GetString(GetRandomInt(0, iNameCount - 1), sName, sizeof(sName));
|
||||||
|
|
||||||
|
for (int iAttempt = 1; iAttempt < iNameCount; iAttempt++)
|
||||||
|
{
|
||||||
|
if (ProcessTargetString(sName, 0, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sTarget, MAX_TARGET_LENGTH, bTN_Is_ML) != 1 || !IsFakeClient(iTargets[0]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
g_hNames.GetString(GetRandomInt(0, iNameCount - 1), sName, sizeof(sName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateFakeClient(sName);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Timer_CreateFakeClients(Handle timer)
|
||||||
|
{
|
||||||
|
AdjustFakeClientsToTier();
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads tier thresholds from configs/fakeclients_tiers.cfg. Max 32 tiers.
|
||||||
|
* Format (KeyValues):
|
||||||
|
*
|
||||||
|
* "FakeClientsTiers"
|
||||||
|
* {
|
||||||
|
* "0" "12" // 0 real players → up to 12 bots
|
||||||
|
* "5" "10" // 5+ real players → up to 10 bots
|
||||||
|
* "15" "8" // And so on...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Entries are sorted by threshold automatically, so order in the file
|
||||||
|
* does not matter.
|
||||||
|
*/
|
||||||
|
stock void ParseTiers()
|
||||||
|
{
|
||||||
|
if (!g_bUseTiers)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_iTierCount = 0;
|
||||||
|
|
||||||
|
char sPath[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/fakeclients_tiers.cfg");
|
||||||
|
|
||||||
|
KeyValues kv = new KeyValues("FakeClientsTiers");
|
||||||
|
|
||||||
|
if (!kv.ImportFromFile(sPath))
|
||||||
|
{
|
||||||
|
LogError("configs/fakeclients_tiers.cfg not found — falling back to sm_fakeclients_players");
|
||||||
|
g_hUseTiers.BoolValue = false;
|
||||||
|
delete kv;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kv.GotoFirstSubKey(false))
|
||||||
|
{
|
||||||
|
LogError("configs/fakeclients_tiers.cfg is empty or malformed");
|
||||||
|
g_hUseTiers.BoolValue = false;
|
||||||
|
delete kv;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (g_iTierCount >= MAX_TIERS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
char sKey[16], sVal[16];
|
||||||
|
kv.GetSectionName(sKey, sizeof(sKey));
|
||||||
|
kv.GetString(NULL_STRING, sVal, sizeof(sVal), "-1");
|
||||||
|
|
||||||
|
int iMaxBots = StringToInt(sVal);
|
||||||
|
if (iMaxBots < 0)
|
||||||
|
continue; // skip malformed lines
|
||||||
|
|
||||||
|
g_iTierThreshold[g_iTierCount] = StringToInt(sKey);
|
||||||
|
g_iTierMaxBots[g_iTierCount] = iMaxBots;
|
||||||
|
g_iTierCount++;
|
||||||
|
|
||||||
|
} while (kv.GotoNextKey(false));
|
||||||
|
|
||||||
|
delete kv;
|
||||||
|
|
||||||
|
// Bubble sort tiers by threshold (ascending) so GetTargetBotCount() works correctly
|
||||||
|
for (int i = 0; i < g_iTierCount - 1; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < g_iTierCount - 1 - i; j++)
|
||||||
|
{
|
||||||
|
if (g_iTierThreshold[j] > g_iTierThreshold[j + 1])
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
tmp = g_iTierThreshold[j]; g_iTierThreshold[j] = g_iTierThreshold[j + 1]; g_iTierThreshold[j + 1] = tmp;
|
||||||
|
tmp = g_iTierMaxBots[j]; g_iTierMaxBots[j] = g_iTierMaxBots[j + 1]; g_iTierMaxBots[j + 1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage("Loaded %d tier(s) from fakeclients_tiers.cfg", g_iTierCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads bot display names from configs/fakeclients.txt (one name per line).
|
||||||
|
*/
|
||||||
|
stock void ParseNames()
|
||||||
|
{
|
||||||
|
delete g_hNames;
|
||||||
|
g_hNames = new ArrayList(MAX_NAME_LENGTH);
|
||||||
|
|
||||||
|
char sBuffer[256];
|
||||||
|
BuildPath(Path_SM, sBuffer, sizeof(sBuffer), "configs/fakeclients.txt");
|
||||||
|
|
||||||
|
File hConfig = OpenFile(sBuffer, "r");
|
||||||
|
if (!hConfig)
|
||||||
|
{
|
||||||
|
LogError("configs/fakeclients.txt not found — using default engine name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (hConfig.ReadLine(sBuffer, sizeof(sBuffer)))
|
||||||
|
{
|
||||||
|
TrimString(sBuffer);
|
||||||
|
if (strlen(sBuffer) > 0)
|
||||||
|
g_hNames.PushString(sBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete hConfig;
|
||||||
|
|
||||||
|
if (!g_hNames.Length)
|
||||||
|
LogError("configs/fakeclients.txt is empty — using default engine name");
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
// Angery nut
|
||||||
|
materials/models/unloze/william/back.vmt
|
||||||
|
materials/models/unloze/william/back.vtf
|
||||||
|
materials/models/unloze/william/front.vmt
|
||||||
|
materials/models/unloze/william/front.vtf
|
||||||
|
models/unloze/william/angerynut.dx80.vtx
|
||||||
|
models/unloze/william/angerynut.dx90.vtx
|
||||||
|
models/unloze/william/angerynut.mdl
|
||||||
|
models/unloze/william/angerynut.sw.vtx
|
||||||
|
models/unloze/william/angerynut.vvd
|
||||||
|
//
|
||||||
|
//// Eevee
|
||||||
|
models\unloze\grenades\eevee.dx80.vtx
|
||||||
|
models\unloze\grenades\eevee.dx90.vtx
|
||||||
|
models\unloze\grenades\eevee.mdl
|
||||||
|
models\unloze\grenades\eevee.sw.vtx
|
||||||
|
models\unloze\grenades\eevee.vvd
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_body.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_body_shiny.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_eye.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_eye_shiny.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_mouth.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eevee_mouth_shiny.vtf
|
||||||
|
materials\models\unloze\grenades\eevee\eievui.vmt
|
||||||
|
materials\models\unloze\grenades\eevee\eievuieye.vmt
|
||||||
|
materials\models\unloze\grenades\eevee\eievuieye_shiny.vmt
|
||||||
|
materials\models\unloze\grenades\eevee\eievuimouth.vmt
|
||||||
|
materials\models\unloze\grenades\eevee\eievuimouth_shiny.vmt
|
||||||
|
materials\models\unloze\grenades\eevee\eievui_shiny.vmt
|
||||||
|
//
|
||||||
|
//// Holy Grenade
|
||||||
|
models\unloze\grenades\holy_grenade.dx80.vtx
|
||||||
|
models\unloze\grenades\holy_grenade.dx90.vtx
|
||||||
|
models\unloze\grenades\holy_grenade.mdl
|
||||||
|
models\unloze\grenades\holy_grenade.phy
|
||||||
|
models\unloze\grenades\holy_grenade.sw.vtx
|
||||||
|
models\unloze\grenades\holy_grenade.vvd
|
||||||
|
materials\models\unloze\grenades\holy_grenade\holy_grenade.vmt
|
||||||
|
materials\models\unloze\grenades\holy_grenade\holy_grenade.vtf
|
||||||
|
//
|
||||||
|
//// Lenny
|
||||||
|
models\unloze\grenades\lenny.dx80.vtx
|
||||||
|
models\unloze\grenades\lenny.dx90.vtx
|
||||||
|
models\unloze\grenades\lenny.mdl
|
||||||
|
models\unloze\grenades\lenny.sw.vtx
|
||||||
|
models\unloze\grenades\lenny.vvd
|
||||||
|
models\unloze\grenades\lennysad.dx80.vtx
|
||||||
|
models\unloze\grenades\lennysad.dx90.vtx
|
||||||
|
models\unloze\grenades\lennysad.mdl
|
||||||
|
models\unloze\grenades\lennysad.sw.vtx
|
||||||
|
models\unloze\grenades\lennysad.vvd
|
||||||
|
materials\models\unloze\grenades\lenny\black.vmt
|
||||||
|
//
|
||||||
|
//// Pokeball
|
||||||
|
models\unloze\grenades\pokeball.dx80.vtx
|
||||||
|
models\unloze\grenades\pokeball.dx90.vtx
|
||||||
|
models\unloze\grenades\pokeball.mdl
|
||||||
|
models\unloze\grenades\pokeball.phy
|
||||||
|
models\unloze\grenades\pokeball.sw.vtx
|
||||||
|
models\unloze\grenades\pokeball.vvd
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball.vmt
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball.vtf
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_great.vmt
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_great.vtf
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_gs.vmt
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_gs.vtf
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_master.vmt
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_master.vtf
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_ultra.vmt
|
||||||
|
materials\models\unloze\grenades\pokeball\pokeball_ultra.vtf
|
||||||
|
//
|
||||||
|
//// Soccer Ball
|
||||||
|
materials/models/unloze/soccer/soccerball.vmt
|
||||||
|
materials/models/unloze/soccer/soccerball_unloze.vtf
|
||||||
|
models/unloze/soccer/soccerball.dx80.vtx
|
||||||
|
models/unloze/soccer/soccerball.dx90.vtx
|
||||||
|
models/unloze/soccer/soccerball.mdl
|
||||||
|
models/unloze/soccer/soccerball.phy
|
||||||
|
models/unloze/soccer/soccerball.sw.vtx
|
||||||
|
models/unloze/soccer/soccerball.vvd
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
"Skins"
|
||||||
|
{
|
||||||
|
"0"
|
||||||
|
{
|
||||||
|
"Name" "Hula Doll"
|
||||||
|
"ModelPath" "models/props_lab/huladoll.mdl"
|
||||||
|
"Scale" "1.7"
|
||||||
|
"Tier" "1"
|
||||||
|
}
|
||||||
|
"1"
|
||||||
|
{
|
||||||
|
"Name" "Banana"
|
||||||
|
"ModelPath" "models/props/cs_italy/bananna.mdl"
|
||||||
|
"Tier" "2"
|
||||||
|
}
|
||||||
|
"2"
|
||||||
|
{
|
||||||
|
"Name" "Melon"
|
||||||
|
"ModelPath" "models/props_junk/watermelon01.mdl"
|
||||||
|
"Scale" "0.7"
|
||||||
|
"Tier" "2"
|
||||||
|
}
|
||||||
|
"3"
|
||||||
|
{
|
||||||
|
"Name" "Orange"
|
||||||
|
"ModelPath" "models/props/cs_italy/orange.mdl"
|
||||||
|
"Scale" "1.5"
|
||||||
|
"Tier" "3"
|
||||||
|
}
|
||||||
|
"4"
|
||||||
|
{
|
||||||
|
"Name" "Creepy Doll"
|
||||||
|
"ModelPath" "models/props_c17/doll01.mdl"
|
||||||
|
"Scale" "0.8"
|
||||||
|
"Tier" "3"
|
||||||
|
}
|
||||||
|
"5"
|
||||||
|
{
|
||||||
|
"Name" "Turtle"
|
||||||
|
"ModelPath" "models/props/de_tides/vending_turtle.mdl"
|
||||||
|
"Tier" "4"
|
||||||
|
}
|
||||||
|
"6"
|
||||||
|
{
|
||||||
|
"Name" "Goldfish"
|
||||||
|
"ModelPath" "models/props/de_inferno/goldfish.mdl"
|
||||||
|
"Tier" "5"
|
||||||
|
}
|
||||||
|
"7"
|
||||||
|
{
|
||||||
|
"Name" "River Fish"
|
||||||
|
"ModelPath" "models/props/cs_militia/fishriver01.mdl"
|
||||||
|
"Tier" "5"
|
||||||
|
}
|
||||||
|
"8"
|
||||||
|
{
|
||||||
|
"Name" "Snowman Head"
|
||||||
|
"ModelPath" "models/props/cs_office/snowman_face.mdl"
|
||||||
|
"Scale" "0.7"
|
||||||
|
"Tier" "6"
|
||||||
|
}
|
||||||
|
"9"
|
||||||
|
{
|
||||||
|
"Name" "Glass Bottle"
|
||||||
|
"ModelPath" "models/props/cs_militia/bottle01.mdl"
|
||||||
|
"Tier" "7"
|
||||||
|
}
|
||||||
|
"10"
|
||||||
|
{
|
||||||
|
"Name" "Gift"
|
||||||
|
"ModelPath" "models/items/cs_gift.mdl"
|
||||||
|
"Scale" "0.6"
|
||||||
|
"Tier" "8"
|
||||||
|
}
|
||||||
|
"11"
|
||||||
|
{
|
||||||
|
"Name" "Rollermine"
|
||||||
|
"ModelPath" "models/roller_spikes.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.7"
|
||||||
|
}
|
||||||
|
"12"
|
||||||
|
{
|
||||||
|
"Name" "Helicopter Bomb"
|
||||||
|
"ModelPath" "models/combine_helicopter/helicopter_bomb01.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.35"
|
||||||
|
}
|
||||||
|
"13"
|
||||||
|
{
|
||||||
|
"Name" "Explosive Barrel"
|
||||||
|
"ModelPath" "models/props_c17/oildrum001_explosive.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.25"
|
||||||
|
}
|
||||||
|
"14"
|
||||||
|
{
|
||||||
|
"Name" "Skull"
|
||||||
|
"ModelPath" "models/gibs/agibs.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "1.3"
|
||||||
|
}
|
||||||
|
"15"
|
||||||
|
{
|
||||||
|
"Name" "Angery Nut"
|
||||||
|
"ModelPath" "models/unloze/william/angerynut.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.8"
|
||||||
|
}
|
||||||
|
"16"
|
||||||
|
{
|
||||||
|
"Name" "Holy Grenade"
|
||||||
|
"ModelPath" "models/unloze/grenades/holy_grenade.mdl"
|
||||||
|
"Scale" "0.6"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"17"
|
||||||
|
{
|
||||||
|
"Name" "Lenny Face"
|
||||||
|
"ModelPath" "models/unloze/grenades/lenny.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.8"
|
||||||
|
}
|
||||||
|
"18"
|
||||||
|
{
|
||||||
|
"Name" "Lenny Sad"
|
||||||
|
"ModelPath" "models/unloze/grenades/lennysad.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.8"
|
||||||
|
}
|
||||||
|
"19"
|
||||||
|
{
|
||||||
|
"Name" "Soccer Ball"
|
||||||
|
"ModelPath" "models/unloze/soccer/soccerball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.4"
|
||||||
|
}
|
||||||
|
"20"
|
||||||
|
{
|
||||||
|
"Name" "Eevee"
|
||||||
|
"ModelPath" "models/unloze/grenades/eevee.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "0.5"
|
||||||
|
}
|
||||||
|
"21"
|
||||||
|
{
|
||||||
|
"Name" "Shiny Eevee"
|
||||||
|
"ModelPath" "models/unloze/grenades/eevee.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Skin" "1"
|
||||||
|
"Scale" "0.5"
|
||||||
|
}
|
||||||
|
"22"
|
||||||
|
{
|
||||||
|
"Name" "Poke Ball"
|
||||||
|
"ModelPath" "models/unloze/grenades/pokeball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Scale" "1.5"
|
||||||
|
}
|
||||||
|
"23"
|
||||||
|
{
|
||||||
|
"Name" "Great Ball"
|
||||||
|
"ModelPath" "models/unloze/grenades/pokeball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Skin" "1"
|
||||||
|
"Scale" "1.5"
|
||||||
|
}
|
||||||
|
"24"
|
||||||
|
{
|
||||||
|
"Name" "Ultra Ball"
|
||||||
|
"ModelPath" "models/unloze/grenades/pokeball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Skin" "4"
|
||||||
|
"Scale" "1.5"
|
||||||
|
}
|
||||||
|
"25"
|
||||||
|
{
|
||||||
|
"Name" "Master Ball"
|
||||||
|
"ModelPath" "models/unloze/grenades/pokeball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Skin" "3"
|
||||||
|
"Scale" "1.5"
|
||||||
|
}
|
||||||
|
"26"
|
||||||
|
{
|
||||||
|
"Name" "GS Ball"
|
||||||
|
"ModelPath" "models/unloze/grenades/pokeball.mdl"
|
||||||
|
"VIP" "1"
|
||||||
|
"Skin" "2"
|
||||||
|
"Scale" "1.5"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,416 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <sdkhooks>
|
||||||
|
#include <unloze_playtime>
|
||||||
|
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
#define MAX_SKINS 64
|
||||||
|
|
||||||
|
enum struct GrenadeSkin
|
||||||
|
{
|
||||||
|
char ModelPath[128];
|
||||||
|
char Name[128];
|
||||||
|
int VIP;
|
||||||
|
int Tier;
|
||||||
|
float Scale;
|
||||||
|
int Skin;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrenadeSkin g_aGrenadeSkins[MAX_SKINS];
|
||||||
|
int g_iSkinCount = 0;
|
||||||
|
|
||||||
|
int g_iGrenadeSkin[MAXPLAYERS + 1] = { -1, ... };
|
||||||
|
bool g_bAdminChecked[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
Handle g_hCookie_GrenadeSkin;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "Grenade Skins",
|
||||||
|
description = "grenade skins but source code actually provided",
|
||||||
|
author = "redone by claude ai mostly, slight human adjustments",
|
||||||
|
version = "1.0",
|
||||||
|
url = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
RegConsoleCmd("sm_grenadeskin", Cmd_GrenadeSkinSettings);
|
||||||
|
RegConsoleCmd("sm_grenadeskins", Cmd_GrenadeSkinSettings);
|
||||||
|
|
||||||
|
g_hCookie_GrenadeSkin = RegClientCookie("grenade_skin", "Selected grenade skin", CookieAccess_Protected);
|
||||||
|
|
||||||
|
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Grenade Skin");
|
||||||
|
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i, true) && AreClientCookiesCached(i))
|
||||||
|
{
|
||||||
|
OnClientCookiesCached(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
LoadDownloads();
|
||||||
|
LoadSkinsConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadDownloads()
|
||||||
|
{
|
||||||
|
char sDownloadsFile[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sDownloadsFile, sizeof(sDownloadsFile), "configs/grenade_skins/downloads.txt");
|
||||||
|
|
||||||
|
File hFile = OpenFile(sDownloadsFile, "r");
|
||||||
|
if (!hFile)
|
||||||
|
{
|
||||||
|
SetFailState("Could not open file: configs/grenade_skins/downloads.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
char sLine[1024];
|
||||||
|
while (hFile.ReadLine(sLine, sizeof(sLine)))
|
||||||
|
{
|
||||||
|
TrimString(sLine);
|
||||||
|
|
||||||
|
// Skip empty lines and comment lines (lines starting with "//" with no file extension).
|
||||||
|
if (sLine[0] == '\0')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (StrContains(sLine, ".", false) == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (FileExists(sLine, false, "GAME"))
|
||||||
|
{
|
||||||
|
AddFileToDownloadsTable(sLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete hFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadSkinsConfig()
|
||||||
|
{
|
||||||
|
// Clear existing skins.
|
||||||
|
for (int i = 0; i < MAX_SKINS; i++)
|
||||||
|
{
|
||||||
|
g_aGrenadeSkins[i].ModelPath[0] = '\0';
|
||||||
|
g_aGrenadeSkins[i].Name[0] = '\0';
|
||||||
|
g_aGrenadeSkins[i].VIP = 0;
|
||||||
|
g_aGrenadeSkins[i].Tier = 0;
|
||||||
|
g_aGrenadeSkins[i].Scale = 1.0;
|
||||||
|
g_aGrenadeSkins[i].Skin = 0;
|
||||||
|
}
|
||||||
|
g_iSkinCount = 0;
|
||||||
|
|
||||||
|
char sConfigFile[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/grenade_skins/skins.cfg");
|
||||||
|
|
||||||
|
if (!FileExists(sConfigFile, false, "GAME"))
|
||||||
|
{
|
||||||
|
SetFailState("Could not find: \"%s\"", sConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyValues kv = new KeyValues("Skins");
|
||||||
|
if (!kv.ImportFromFile(sConfigFile))
|
||||||
|
{
|
||||||
|
delete kv;
|
||||||
|
SetFailState("ImportFromFile() failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kv.GotoFirstSubKey(true))
|
||||||
|
{
|
||||||
|
delete kv;
|
||||||
|
SetFailState("Unable to goto first sub key in: \"%s\"", sConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (i >= MAX_SKINS)
|
||||||
|
{
|
||||||
|
LogError("grenade_skins: skins.cfg has more than %d entries, ignoring the rest.", MAX_SKINS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv.GetString("ModelPath", g_aGrenadeSkins[i].ModelPath, sizeof(g_aGrenadeSkins[].ModelPath), "error");
|
||||||
|
if (StrEqual(g_aGrenadeSkins[i].ModelPath, "error", true))
|
||||||
|
{
|
||||||
|
SetFailState("Unable to read Path");
|
||||||
|
}
|
||||||
|
|
||||||
|
kv.GetString("Name", g_aGrenadeSkins[i].Name, sizeof(g_aGrenadeSkins[].Name), "error");
|
||||||
|
if (StrEqual(g_aGrenadeSkins[i].Name, "error", true))
|
||||||
|
{
|
||||||
|
SetFailState("Unable to read Name");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_aGrenadeSkins[i].VIP = kv.GetNum("VIP", 0);
|
||||||
|
g_aGrenadeSkins[i].Tier = kv.GetNum("tier", 0);
|
||||||
|
g_aGrenadeSkins[i].Scale = kv.GetFloat("Scale", 1.0);
|
||||||
|
g_aGrenadeSkins[i].Skin = kv.GetNum("Skin", 0);
|
||||||
|
|
||||||
|
PrecacheModel(g_aGrenadeSkins[i].ModelPath, false);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (kv.GotoNextKey(true));
|
||||||
|
|
||||||
|
g_iSkinCount = i;
|
||||||
|
|
||||||
|
delete kv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientCookiesCached(int client)
|
||||||
|
{
|
||||||
|
char sBuffer[256];
|
||||||
|
GetClientCookie(client, g_hCookie_GrenadeSkin, sBuffer, sizeof(sBuffer));
|
||||||
|
|
||||||
|
if (sBuffer[0])
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < g_iSkinCount; i++)
|
||||||
|
{
|
||||||
|
if (StrEqual(g_aGrenadeSkins[i].ModelPath, sBuffer, true))
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = i;
|
||||||
|
|
||||||
|
if (g_bAdminChecked[client] && !ClientHasSkinAccess(client, i))
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = -1;
|
||||||
|
g_bAdminChecked[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientPostAdminCheck(int client)
|
||||||
|
{
|
||||||
|
g_bAdminChecked[client] = true;
|
||||||
|
|
||||||
|
if (AreClientCookiesCached(client) && g_iGrenadeSkin[client] != -1)
|
||||||
|
{
|
||||||
|
if (!ClientHasSkinAccess(client, g_iGrenadeSkin[client]))
|
||||||
|
{
|
||||||
|
g_iGrenadeSkin[client] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a client has access to a given skin index,
|
||||||
|
* taking both the legacy VIP flag and the new tier requirement into account.
|
||||||
|
*/
|
||||||
|
bool ClientHasSkinAccess(int client, int skinIndex)
|
||||||
|
{
|
||||||
|
if (g_aGrenadeSkins[skinIndex].VIP && !CheckCommandAccess(client, "", ADMFLAG_RESERVATION, false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_aGrenadeSkins[skinIndex].Tier > 0 && GetPlayerTier_native(client) < g_aGrenadeSkins[skinIndex].Tier)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEntitySpawned(int entity, const char[] sClassname)
|
||||||
|
{
|
||||||
|
if (StrContains(sClassname, "_projectile", false) == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iOwner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity");
|
||||||
|
|
||||||
|
if (!IsValidClient(iOwner, true) || g_iGrenadeSkin[iOwner] == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skinIndex = g_iGrenadeSkin[iOwner];
|
||||||
|
|
||||||
|
SetEntityRenderMode(entity, RENDER_TRANSALPHA);
|
||||||
|
|
||||||
|
float fNadeOrigin[3];
|
||||||
|
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", fNadeOrigin);
|
||||||
|
|
||||||
|
int iNadeProp = CreateEntityAtOrigin("prop_dynamic_override", fNadeOrigin);
|
||||||
|
|
||||||
|
DispatchKeyValue(iNadeProp, "disableshadows", "1");
|
||||||
|
DispatchKeyValue(iNadeProp, "disablereceiveshadows", "1");
|
||||||
|
DispatchKeyValue(iNadeProp, "DisableBoneFollowers", "1");
|
||||||
|
DispatchKeyValue(iNadeProp, "solid", "0");
|
||||||
|
DispatchKeyValue(iNadeProp, "model", g_aGrenadeSkins[skinIndex].ModelPath);
|
||||||
|
|
||||||
|
char sScale[32];
|
||||||
|
FloatToString(g_aGrenadeSkins[skinIndex].Scale, sScale, sizeof(sScale));
|
||||||
|
DispatchKeyValue(iNadeProp, "modelscale", sScale);
|
||||||
|
|
||||||
|
SpawnAndActivate(iNadeProp);
|
||||||
|
ParentToEntity(iNadeProp, entity);
|
||||||
|
|
||||||
|
if (g_aGrenadeSkins[skinIndex].Skin > 0)
|
||||||
|
{
|
||||||
|
char sSkinBuf[16];
|
||||||
|
IntToString(g_aGrenadeSkins[skinIndex].Skin, sSkinBuf, sizeof(sSkinBuf));
|
||||||
|
SetVariantString(sSkinBuf);
|
||||||
|
AcceptEntityInput(iNadeProp, "Skin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Cmd_GrenadeSkinSettings(int client, int args)
|
||||||
|
{
|
||||||
|
ShowSettingsMenu(client);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case CookieMenuAction_DisplayOption:
|
||||||
|
{
|
||||||
|
Format(buffer, maxlen, "Grenade Skin");
|
||||||
|
}
|
||||||
|
case CookieMenuAction_SelectOption:
|
||||||
|
{
|
||||||
|
ShowSettingsMenu(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowSettingsMenu(int client)
|
||||||
|
{
|
||||||
|
Menu menu = new Menu(MenuHandler_MainMenu);
|
||||||
|
menu.SetTitle("Grenade Skin");
|
||||||
|
|
||||||
|
char sBuffer[128];
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "No Skin%s", (g_iGrenadeSkin[client] == -1) ? " (Selected)" : "");
|
||||||
|
menu.AddItem("-1", sBuffer, (g_iGrenadeSkin[client] == -1) ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
|
||||||
|
|
||||||
|
for (int i = 0; i < g_iSkinCount; i++)
|
||||||
|
{
|
||||||
|
bool bSelected = (i == g_iGrenadeSkin[client]);
|
||||||
|
bool bHasAccess = ClientHasSkinAccess(client, i);
|
||||||
|
bool bUnavailable = bSelected || !bHasAccess;
|
||||||
|
|
||||||
|
char sSuffix[32];
|
||||||
|
sSuffix[0] = '\0';
|
||||||
|
|
||||||
|
if (!bHasAccess)
|
||||||
|
{
|
||||||
|
if (g_aGrenadeSkins[i].VIP && !CheckCommandAccess(client, "", ADMFLAG_RESERVATION, false))
|
||||||
|
{
|
||||||
|
Format(sSuffix, sizeof(sSuffix), " [VIP]");
|
||||||
|
}
|
||||||
|
else if (g_aGrenadeSkins[i].Tier > 0 && GetPlayerTier_native(client) < g_aGrenadeSkins[i].Tier)
|
||||||
|
{
|
||||||
|
Format(sSuffix, sizeof(sSuffix), " [Tier %i]", g_aGrenadeSkins[i].Tier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bSelected)
|
||||||
|
{
|
||||||
|
Format(sSuffix, sizeof(sSuffix), " (Selected)");
|
||||||
|
}
|
||||||
|
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s%s", g_aGrenadeSkins[i].Name, sSuffix);
|
||||||
|
|
||||||
|
char sInfo[8];
|
||||||
|
IntToString(i, sInfo, sizeof(sInfo));
|
||||||
|
|
||||||
|
menu.AddItem(sInfo, sBuffer, bUnavailable ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.ExitBackButton = true;
|
||||||
|
menu.Display(client, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int selection)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case MenuAction_Select:
|
||||||
|
{
|
||||||
|
char sInfo[8];
|
||||||
|
menu.GetItem(selection, sInfo, sizeof(sInfo));
|
||||||
|
|
||||||
|
int chosen = StringToInt(sInfo);
|
||||||
|
g_iGrenadeSkin[client] = chosen;
|
||||||
|
|
||||||
|
if (chosen == -1)
|
||||||
|
{
|
||||||
|
SetClientCookie(client, g_hCookie_GrenadeSkin, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetClientCookie(client, g_hCookie_GrenadeSkin, g_aGrenadeSkins[chosen].ModelPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowSettingsMenu(client);
|
||||||
|
}
|
||||||
|
case MenuAction_Cancel:
|
||||||
|
{
|
||||||
|
if (selection == MenuCancel_ExitBack)
|
||||||
|
{
|
||||||
|
// Re-open the cookie/settings menu if desired; original plugin
|
||||||
|
// routed back into the cookie menu here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MenuAction_End:
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Helper stocks (ported from decompiled output)
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client, bool noBots)
|
||||||
|
{
|
||||||
|
if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (noBots && IsFakeClient(client)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return IsClientInGame(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
stock int CreateEntityAtOrigin(const char[] classname, const float origin[3])
|
||||||
|
{
|
||||||
|
int entity = CreateEntityByName(classname);
|
||||||
|
TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void SpawnAndActivate(int entity)
|
||||||
|
{
|
||||||
|
DispatchSpawn(entity);
|
||||||
|
ActivateEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void ParentToEntity(int entity, int parent)
|
||||||
|
{
|
||||||
|
SetVariantString("!activator");
|
||||||
|
AcceptEntityInput(entity, "SetParent", parent, parent);
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ bool g_bHitmarkerSound[MAXPLAYERS+1];
|
|||||||
int g_iHitmarkerSoundVolume[MAXPLAYERS+1] = {100,...};
|
int g_iHitmarkerSoundVolume[MAXPLAYERS+1] = {100,...};
|
||||||
int g_iHitmarkerSkin[MAXPLAYERS+1];
|
int g_iHitmarkerSkin[MAXPLAYERS+1];
|
||||||
|
|
||||||
#define MAXIMUMSKINS 6
|
#define MAXIMUMSKINS 12
|
||||||
char g_sHitmarkerSkins[MAXIMUMSKINS][PLATFORM_MAX_PATH];
|
char g_sHitmarkerSkins[MAXIMUMSKINS][PLATFORM_MAX_PATH];
|
||||||
char g_sHitmarkerSkinsNames[MAXIMUMSKINS][PLATFORM_MAX_PATH];
|
char g_sHitmarkerSkinsNames[MAXIMUMSKINS][PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ Handle g_hCookie_HitmarkerSoundVolume;
|
|||||||
Handle g_hCookie_HitmarkerSkin;
|
Handle g_hCookie_HitmarkerSkin;
|
||||||
|
|
||||||
ConVar g_hCVar_Debug;
|
ConVar g_hCVar_Debug;
|
||||||
|
ConVar g_hCVar_HitmarkerEnabled;
|
||||||
|
|
||||||
bool g_bLate;
|
bool g_bLate;
|
||||||
|
|
||||||
@@ -87,7 +88,9 @@ public void OnPluginStart()
|
|||||||
g_hCookie_HitmarkerSkin = RegClientCookie("hitmarker_skin", "", CookieAccess_Private);
|
g_hCookie_HitmarkerSkin = RegClientCookie("hitmarker_skin", "", CookieAccess_Private);
|
||||||
|
|
||||||
g_hCVar_Debug = CreateConVar("sm_hitmarker_debug", "0", "", FCVAR_NONE, true, 0.0, true, 1.0);
|
g_hCVar_Debug = CreateConVar("sm_hitmarker_debug", "0", "", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
AutoExecConfig();
|
g_hCVar_HitmarkerEnabled = CreateConVar("sm_hitmarker_enabled", "1", "", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
|
g_hCVar_HitmarkerEnabled.AddChangeHook(OnConVarChanged);
|
||||||
|
AutoExecConfig(true);
|
||||||
|
|
||||||
RegConsoleCmd("sm_hm", OnHitmarkerSettings);
|
RegConsoleCmd("sm_hm", OnHitmarkerSettings);
|
||||||
RegConsoleCmd("sm_hitmarker", OnHitmarkerSettings);
|
RegConsoleCmd("sm_hitmarker", OnHitmarkerSettings);
|
||||||
@@ -109,6 +112,14 @@ public void OnPluginStart()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
if(g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
CPrintToChatAll("{cyan}[Hitmarker] {white}has been allowed.");
|
||||||
|
else
|
||||||
|
CPrintToChatAll("{cyan}[Hitmarker] {white}has been disabled.");
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -120,6 +131,11 @@ public void OnMapStart()
|
|||||||
g_sHitmarkerSkinsNames[i] = "";
|
g_sHitmarkerSkinsNames[i] = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char sConfigFile[PLATFORM_MAX_PATH];
|
char sConfigFile[PLATFORM_MAX_PATH];
|
||||||
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/Hitmarkers.cfg");
|
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/Hitmarkers.cfg");
|
||||||
|
|
||||||
@@ -184,6 +200,11 @@ public void OnMapStart()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnClientCookiesCached(int client)
|
public void OnClientCookiesCached(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char sBuffer[PLATFORM_MAX_PATH];
|
char sBuffer[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
GetClientCookie(client, g_hCookie_ShowBossHitmarker, sBuffer, sizeof(sBuffer));
|
GetClientCookie(client, g_hCookie_ShowBossHitmarker, sBuffer, sizeof(sBuffer));
|
||||||
@@ -243,6 +264,10 @@ public void OnClientDisconnect(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action OnHitmarkerSettings(int client, int args)
|
public Action OnHitmarkerSettings(int client, int args)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
ShowSettingsMenu(client);
|
ShowSettingsMenu(client);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -252,6 +277,10 @@ public Action OnHitmarkerSettings(int client, int args)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action OnToggleBossHitmarker(int client, int args)
|
public Action OnToggleBossHitmarker(int client, int args)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
ToggleBossHitmarker(client);
|
ToggleBossHitmarker(client);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -275,6 +304,10 @@ public void ToggleBossHitmarker(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action OnToggleZombieHitmarker(int client, int args)
|
public Action OnToggleZombieHitmarker(int client, int args)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
ToggleZombieHitmarker(client);
|
ToggleZombieHitmarker(client);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -284,6 +317,10 @@ public Action OnToggleZombieHitmarker(int client, int args)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ToggleZombieHitmarker(int client)
|
public void ToggleZombieHitmarker(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_bShowZombieHitmarker[client] = !g_bShowZombieHitmarker[client];
|
g_bShowZombieHitmarker[client] = !g_bShowZombieHitmarker[client];
|
||||||
SetClientCookie(client, g_hCookie_ShowZombieHitmarker, g_bShowZombieHitmarker[client] ? "1" : "");
|
SetClientCookie(client, g_hCookie_ShowZombieHitmarker, g_bShowZombieHitmarker[client] ? "1" : "");
|
||||||
|
|
||||||
@@ -298,6 +335,10 @@ public void ToggleZombieHitmarker(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action OnToggleHitmarkerSound(int client, int args)
|
public Action OnToggleHitmarkerSound(int client, int args)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
ToggleHitmarkerSound(client);
|
ToggleHitmarkerSound(client);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -307,6 +348,10 @@ public Action OnToggleHitmarkerSound(int client, int args)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ToggleHitmarkerSound(int client)
|
public void ToggleHitmarkerSound(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_bHitmarkerSound[client] = !g_bHitmarkerSound[client];
|
g_bHitmarkerSound[client] = !g_bHitmarkerSound[client];
|
||||||
SetClientCookie(client, g_hCookie_HitmarkerSound, g_bHitmarkerSound[client] ? "1" : "");
|
SetClientCookie(client, g_hCookie_HitmarkerSound, g_bHitmarkerSound[client] ? "1" : "");
|
||||||
|
|
||||||
@@ -321,6 +366,10 @@ public void ToggleHitmarkerSound(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ToggleHitmarkerSoundVolume(int client)
|
public void ToggleHitmarkerSoundVolume(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_iHitmarkerSoundVolume[client] += 25;
|
g_iHitmarkerSoundVolume[client] += 25;
|
||||||
|
|
||||||
if(g_iHitmarkerSoundVolume[client] > 100)
|
if(g_iHitmarkerSoundVolume[client] > 100)
|
||||||
@@ -339,6 +388,10 @@ public void ToggleHitmarkerSoundVolume(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ToggleHitmarkerSkin(int client)
|
public void ToggleHitmarkerSkin(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_iHitmarkerSkin[client]++;
|
g_iHitmarkerSkin[client]++;
|
||||||
|
|
||||||
if (StrEqual(g_sHitmarkerSkins[g_iHitmarkerSkin[client]], ""))
|
if (StrEqual(g_sHitmarkerSkins[g_iHitmarkerSkin[client]], ""))
|
||||||
@@ -354,6 +407,10 @@ public void ToggleHitmarkerSkin(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ShowSettingsMenu(int client)
|
public void ShowSettingsMenu(int client)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
Menu menu = new Menu(MenuHandler_MainMenu);
|
Menu menu = new Menu(MenuHandler_MainMenu);
|
||||||
|
|
||||||
menu.SetTitle("Hitmarker Settings", client);
|
menu.SetTitle("Hitmarker Settings", client);
|
||||||
@@ -434,6 +491,10 @@ public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int se
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnEntitySpawned(int Entity, const char[] sClassname)
|
public void OnEntitySpawned(int Entity, const char[] sClassname)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int ent = EntRefToEntIndex(Entity);
|
int ent = EntRefToEntIndex(Entity);
|
||||||
|
|
||||||
if (0 < ent < MAX_EDICTS)
|
if (0 < ent < MAX_EDICTS)
|
||||||
@@ -451,6 +512,10 @@ public void OnEntitySpawned(int Entity, const char[] sClassname)
|
|||||||
/*
|
/*
|
||||||
public void OnBossDamaged(CBoss Boss, CConfig Config, int client, float damage)
|
public void OnBossDamaged(CBoss Boss, CConfig Config, int client, float damage)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!IsValidClient(client))
|
if (!IsValidClient(client))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -475,6 +540,10 @@ public void OnBossDamaged(CBoss Boss, CConfig Config, int client, float damage)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public MRESReturn Detour_OnTakeDamage(int entity, Handle hReturn, Handle hParams)
|
public MRESReturn Detour_OnTakeDamage(int entity, Handle hReturn, Handle hParams)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return MRES_Ignored;
|
||||||
|
}
|
||||||
//https://github.com/alliedmodders/hl2sdk/blob/css/game/shared/takedamageinfo.h#L115
|
//https://github.com/alliedmodders/hl2sdk/blob/css/game/shared/takedamageinfo.h#L115
|
||||||
int iHealth = GetEntProp(entity, Prop_Data, "m_iHealth");
|
int iHealth = GetEntProp(entity, Prop_Data, "m_iHealth");
|
||||||
int client = DHookGetParamObjectPtrVar(hParams, 1, 3*(3*4) + 0, ObjectValueType_Ehandle);
|
int client = DHookGetParamObjectPtrVar(hParams, 1, 3*(3*4) + 0, ObjectValueType_Ehandle);
|
||||||
@@ -514,6 +583,10 @@ public MRESReturn Detour_OnTakeDamage(int entity, Handle hReturn, Handle hParams
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int client = GetClientOfUserId(hEvent.GetInt("attacker"));
|
int client = GetClientOfUserId(hEvent.GetInt("attacker"));
|
||||||
int victim = GetClientOfUserId(hEvent.GetInt("userid"));
|
int victim = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
@@ -544,6 +617,10 @@ public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void ShowOverlay(int client, float fTime = 0.3)
|
void ShowOverlay(int client, float fTime = 0.3)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_HitmarkerEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (g_bHitmarkerSound[client])
|
if (g_bHitmarkerSound[client])
|
||||||
{
|
{
|
||||||
float fVolume = g_iHitmarkerSoundVolume[client] / 100.0;
|
float fVolume = g_iHitmarkerSoundVolume[client] / 100.0;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
char g_sBanListFilePath[256];
|
char g_sBanListFilePath[256];
|
||||||
|
|
||||||
|
Database g_hDatabase;
|
||||||
|
|
||||||
bool g_bKnifeBanned[MAXPLAYERS + 1];
|
bool g_bKnifeBanned[MAXPLAYERS + 1];
|
||||||
bool g_bKnifeBan;
|
bool g_bKnifeBan;
|
||||||
|
|
||||||
@@ -53,6 +55,7 @@ public void OnPluginStart()
|
|||||||
SetFailState("Couldnt find CBaseCombatCharacter::m_hActiveWeapon");
|
SetFailState("Couldnt find CBaseCombatCharacter::m_hActiveWeapon");
|
||||||
|
|
||||||
CreateTimer(5.0, CheckKnifeBans, _, TIMER_REPEAT);
|
CreateTimer(5.0, CheckKnifeBans, _, TIMER_REPEAT);
|
||||||
|
CreateTimer(300.0, CheckKnifeBansFromWeb, _, TIMER_REPEAT); //check every 5 minutes if something new was done on webpannel
|
||||||
|
|
||||||
g_TempBanned = new ArrayList();
|
g_TempBanned = new ArrayList();
|
||||||
|
|
||||||
@@ -68,6 +71,29 @@ public void OnPluginStart()
|
|||||||
if(IsClientInGame(i))
|
if(IsClientInGame(i))
|
||||||
OnClientPostAdminCheck(i);
|
OnClientPostAdminCheck(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_knifeban_web");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_knifeban_web");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if(!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Database error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hDatabase = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPluginEnd()
|
public void OnPluginEnd()
|
||||||
@@ -99,9 +125,6 @@ public void OnClientPostAdminCheck(int client)
|
|||||||
SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
|
SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_iClientHours[client] = 0;
|
|
||||||
g_iClientMinutes[client] = 0;
|
|
||||||
|
|
||||||
char sAuth[32];
|
char sAuth[32];
|
||||||
GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));
|
GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth));
|
||||||
|
|
||||||
@@ -141,6 +164,134 @@ public void OnMapEnd()
|
|||||||
g_TempBanned.Clear();
|
g_TempBanned.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Action CheckKnifeBansFromWeb(Handle timer)
|
||||||
|
{
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "select client_steamid, web_addban_required, web_unban_required, web_ban_delete, web_edit_required, time_played_start, length, krcb.admin_name from `KbRestrict_CurrentBans` krcb where krcb.web_addban_required = 1 or krcb.web_unban_required = 1 or krcb.web_ban_delete = 1 or krcb.web_edit_required = 1");
|
||||||
|
g_hDatabase.Query(SQL_OnQueryCompletedWebKbans, sQuery);
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_OnQueryCompletedWebKbans(Database db, DBResultSet results, const char[] error, int iSerial)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
LogError("Query error 3: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (results.RowCount && results.FetchRow())
|
||||||
|
{
|
||||||
|
char sSID[64];
|
||||||
|
results.FetchString(0, sSID, sizeof(sSID));
|
||||||
|
int web_addban_required = results.FetchInt(1);
|
||||||
|
int web_unban_required = results.FetchInt(2);
|
||||||
|
int web_ban_delete = results.FetchInt(3);
|
||||||
|
int web_edit_required = results.FetchInt(4);
|
||||||
|
int time_played_start = results.FetchInt(5);
|
||||||
|
int length = results.FetchInt(6);
|
||||||
|
char admin_name[255];
|
||||||
|
results.FetchString(7, admin_name, sizeof(admin_name));
|
||||||
|
|
||||||
|
char sQuery[512];
|
||||||
|
if (web_addban_required)
|
||||||
|
{
|
||||||
|
file_addban(sSID, time_played_start, length, admin_name);
|
||||||
|
Format(sQuery, sizeof(sQuery), "update `KbRestrict_CurrentBans` set web_addban_required = 0 where client_steamid = '%s' and web_addban_required = 1", sSID);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery);
|
||||||
|
}
|
||||||
|
else if (web_unban_required)
|
||||||
|
{
|
||||||
|
file_unban(sSID);
|
||||||
|
Format(sQuery, sizeof(sQuery), "update `KbRestrict_CurrentBans` set web_unban_required = 0 where client_steamid = '%s' and web_unban_required = 1", sSID);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery);
|
||||||
|
}
|
||||||
|
else if (web_ban_delete)
|
||||||
|
{
|
||||||
|
file_unban(sSID);
|
||||||
|
Format(sQuery, sizeof(sQuery), "delete from `KbRestrict_CurrentBans` where client_steamid = '%s' and web_ban_delete = 1", sSID);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery);
|
||||||
|
}
|
||||||
|
else if (web_edit_required)
|
||||||
|
{
|
||||||
|
file_edit_ban(sSID, length);
|
||||||
|
Format(sQuery, sizeof(sQuery), "update `KbRestrict_CurrentBans` set web_edit_required = 0 where client_steamid = '%s' and web_edit_required = 1", sSID);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void file_edit_ban(char sAuth[64], int length)
|
||||||
|
{
|
||||||
|
int length_hours = length / 60;
|
||||||
|
int length_minutes = length % 60;
|
||||||
|
|
||||||
|
if(Banlist.JumpToKey(sAuth))
|
||||||
|
{
|
||||||
|
Banlist.SetNum("duration", length_hours);
|
||||||
|
Banlist.SetNum("duration_minutes", length_minutes);
|
||||||
|
Banlist.Rewind();
|
||||||
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void file_unban(char sAuth[64])
|
||||||
|
{
|
||||||
|
if(Banlist.JumpToKey(sAuth))
|
||||||
|
{
|
||||||
|
int history = Banlist.GetNum("history");
|
||||||
|
Banlist.SetNum("history", history - 1);
|
||||||
|
Banlist.SetNum("time", 0);
|
||||||
|
Banlist.SetNum("time_minutes", 0);
|
||||||
|
Banlist.SetNum("duration", 0);
|
||||||
|
Banlist.SetNum("duration_minutes", 0);
|
||||||
|
Banlist.SetString("admin", "");
|
||||||
|
Banlist.Rewind();
|
||||||
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void file_addban(char sAuth[64], int time_played_start, int length, char sAdmin[255])
|
||||||
|
{
|
||||||
|
int time = time_played_start / 60;
|
||||||
|
int time_minutes = time_played_start & 60;
|
||||||
|
|
||||||
|
int length_hours = length / 60;
|
||||||
|
int length_minutes = length % 60;
|
||||||
|
|
||||||
|
if( length_hours || length_minutes)
|
||||||
|
{
|
||||||
|
if(Banlist.JumpToKey(sAuth, true))
|
||||||
|
{
|
||||||
|
int history = Banlist.GetNum("history");
|
||||||
|
Banlist.SetNum("history", history + 1);
|
||||||
|
Banlist.SetNum("time", time);
|
||||||
|
Banlist.SetNum("time_minutes", time_minutes);
|
||||||
|
Banlist.SetNum("duration", length_hours);
|
||||||
|
Banlist.SetNum("duration_minutes", length_minutes);
|
||||||
|
Banlist.SetString("admin", sAdmin);
|
||||||
|
Banlist.Rewind();
|
||||||
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Banlist.JumpToKey(sAuth, true))
|
||||||
|
{
|
||||||
|
int history = Banlist.GetNum("history");
|
||||||
|
Banlist.SetNum("history", history + 1);
|
||||||
|
Banlist.SetNum("time", time);
|
||||||
|
Banlist.SetNum("time_minutes", time_minutes);
|
||||||
|
Banlist.SetNum("duration", -1);
|
||||||
|
Banlist.SetNum("duration_minutes", -1);
|
||||||
|
Banlist.SetString("admin", sAdmin);
|
||||||
|
Banlist.Rewind();
|
||||||
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Action CheckKnifeBans(Handle timer)
|
public Action CheckKnifeBans(Handle timer)
|
||||||
{
|
{
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
@@ -208,6 +359,7 @@ public void CheckIfClientIsStillKnifeBanned(char sAuth[32], int client, int time
|
|||||||
Banlist.SetString("admin", "");
|
Banlist.SetString("admin", "");
|
||||||
Banlist.Rewind();
|
Banlist.Rewind();
|
||||||
Banlist.ExportToFile(g_sBanListFilePath);
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
update_knife_unban_mysql(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,6 +473,8 @@ public Action Command_Knifeban(int client, int args)
|
|||||||
Banlist.SetString("admin", sAdmin);
|
Banlist.SetString("admin", sAdmin);
|
||||||
Banlist.Rewind();
|
Banlist.Rewind();
|
||||||
Banlist.ExportToFile(g_sBanListFilePath);
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
|
||||||
|
insert_knifeban_mysql(client, target, length_hours, length_minutes, time, time_minutes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -338,6 +492,8 @@ public Action Command_Knifeban(int client, int args)
|
|||||||
Banlist.SetString("admin", sAdmin);
|
Banlist.SetString("admin", sAdmin);
|
||||||
Banlist.Rewind();
|
Banlist.Rewind();
|
||||||
Banlist.ExportToFile(g_sBanListFilePath);
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
|
||||||
|
insert_knifeban_mysql(client, target, -1, -1, time, time_minutes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,6 +518,60 @@ public Action Command_Knifeban(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insert_knifeban_mysql(int admin, int knife_banned_player, int length_hours, int length_minutes, int time_start_playertime_hours, int time_start_playertime_minutes)
|
||||||
|
{
|
||||||
|
char sNameAdmin[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(admin, sNameAdmin, sizeof(sNameAdmin));
|
||||||
|
int size2 = 2 * strlen(sNameAdmin) + 1;
|
||||||
|
char[] sEscapedNameAdmin = new char[size2 + 1];
|
||||||
|
g_hDatabase.Escape(sNameAdmin, sEscapedNameAdmin, size2 + 1);
|
||||||
|
char sSIDAdmin[64];
|
||||||
|
GetClientAuthId(admin, AuthId_Steam2, sSIDAdmin, sizeof(sSIDAdmin));
|
||||||
|
|
||||||
|
|
||||||
|
char sNameClient[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(knife_banned_player, sNameClient, sizeof(sNameClient));
|
||||||
|
size2 = 2 * strlen(sNameClient) + 1;
|
||||||
|
char[] sEscapedNameClient = new char[size2 + 1];
|
||||||
|
g_hDatabase.Escape(sNameClient, sEscapedNameClient, size2 + 1);
|
||||||
|
char sSIDClient[64];
|
||||||
|
GetClientAuthId(knife_banned_player, AuthId_Steam2, sSIDClient, sizeof(sSIDClient));
|
||||||
|
char sIP[32];
|
||||||
|
GetClientIP(knife_banned_player, sIP, sizeof(sIP));
|
||||||
|
|
||||||
|
char currentMap[64];
|
||||||
|
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||||
|
|
||||||
|
char sQuery[512];
|
||||||
|
//length is assumed to be minutes.
|
||||||
|
int length = (length_hours * 60) + length_minutes;
|
||||||
|
if (length_hours == -1)
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int playtime_start_client = (time_start_playertime_hours * 60) + time_start_playertime_minutes;
|
||||||
|
int playtime_end_client = playtime_start_client + length;
|
||||||
|
|
||||||
|
if (length_hours == -1)
|
||||||
|
{
|
||||||
|
playtime_end_client = -1;
|
||||||
|
playtime_start_client = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Format(sQuery, sizeof(sQuery), "INSERT INTO `KbRestrict_CurrentBans` (`client_name`, `client_steamid`, `client_ip`, `admin_name`, `admin_steamid`, `reason`, `map`, `length`, `time_played_start`, `time_played_end`, `is_expired`, `is_removed`, `admin_name_removed`, `admin_steamid_removed`, `time_stamp_removed`, `reason_removed`) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%i', '%i', '%i', 0, 0, ' ', ' ', 0, ' ')", sEscapedNameClient, sSIDClient, sIP, sEscapedNameAdmin, sSIDAdmin, "get fucked", currentMap, length, playtime_start_client, playtime_end_client);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error 3: %s", error);
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
}
|
||||||
|
|
||||||
public Action Command_Knifeunban(int client, int args)
|
public Action Command_Knifeunban(int client, int args)
|
||||||
{
|
{
|
||||||
if(!GetCmdArgs())
|
if(!GetCmdArgs())
|
||||||
@@ -400,6 +610,7 @@ public Action Command_Knifeunban(int client, int args)
|
|||||||
Banlist.SetString("admin", "");
|
Banlist.SetString("admin", "");
|
||||||
Banlist.Rewind();
|
Banlist.Rewind();
|
||||||
Banlist.ExportToFile(g_sBanListFilePath);
|
Banlist.ExportToFile(g_sBanListFilePath);
|
||||||
|
update_knife_unban_mysql(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
int accountid = GetSteamAccountID(target);
|
int accountid = GetSteamAccountID(target);
|
||||||
@@ -416,6 +627,16 @@ public Action Command_Knifeunban(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void update_knife_unban_mysql(int knife_unbanned_client)
|
||||||
|
{
|
||||||
|
char sSIDClient[64];
|
||||||
|
GetClientAuthId(knife_unbanned_client, AuthId_Steam2, sSIDClient, sizeof(sSIDClient));
|
||||||
|
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "update `KbRestrict_CurrentBans` set is_expired = 1 where client_steamid = '%s' and is_expired = 0", sSIDClient);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Normal);
|
||||||
|
}
|
||||||
|
|
||||||
public Action Command_Knifestatus(int client, int args)
|
public Action Command_Knifestatus(int client, int args)
|
||||||
{
|
{
|
||||||
if(CheckCommandAccess(client, "", ADMFLAG_BAN) && GetCmdArgs())
|
if(CheckCommandAccess(client, "", ADMFLAG_BAN) && GetCmdArgs())
|
||||||
@@ -477,6 +698,11 @@ public Action Command_Knifestatus(int client, int args)
|
|||||||
|
|
||||||
int iTimeRemaining = length_hours - timesinceknifeban;
|
int iTimeRemaining = length_hours - timesinceknifeban;
|
||||||
int iTimeRemaining_minutes = length_minutes - timesinceknifeban_minutes;
|
int iTimeRemaining_minutes = length_minutes - timesinceknifeban_minutes;
|
||||||
|
if (iTimeRemaining_minutes < 0)
|
||||||
|
{
|
||||||
|
iTimeRemaining_minutes += 60;
|
||||||
|
iTimeRemaining--;
|
||||||
|
}
|
||||||
|
|
||||||
Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours and %d minutes playtime", iTimeRemaining, iTimeRemaining_minutes);
|
Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours and %d minutes playtime", iTimeRemaining, iTimeRemaining_minutes);
|
||||||
CReplyToCommand(client, "\x07%s[KnifeBan] \x07%s%N\x07%s is currently knifebanned for another \x07%s%s\x07%s.", "E01B5D", "EDEDED", target, "F16767", "EDEDED", sTimeRemaining, "F16767");
|
CReplyToCommand(client, "\x07%s[KnifeBan] \x07%s%N\x07%s is currently knifebanned for another \x07%s%s\x07%s.", "E01B5D", "EDEDED", target, "F16767", "EDEDED", sTimeRemaining, "F16767");
|
||||||
@@ -534,6 +760,11 @@ public Action Command_Knifestatus(int client, int args)
|
|||||||
|
|
||||||
int iTimeRemaining = length_hours - timesinceknifeban;
|
int iTimeRemaining = length_hours - timesinceknifeban;
|
||||||
int iTimeRemaining_minutes = length_minutes - timesinceknifeban_minutes;
|
int iTimeRemaining_minutes = length_minutes - timesinceknifeban_minutes;
|
||||||
|
if (iTimeRemaining_minutes < 0)
|
||||||
|
{
|
||||||
|
iTimeRemaining_minutes += 60;
|
||||||
|
iTimeRemaining--;
|
||||||
|
}
|
||||||
|
|
||||||
Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours and %d minutes playtime", iTimeRemaining, iTimeRemaining_minutes);
|
Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours and %d minutes playtime", iTimeRemaining, iTimeRemaining_minutes);
|
||||||
CReplyToCommand(client, "\x07%s[KnifeBan] \x07%sYou are currently knifebanned for another \x07%s%s\x07%s.", "E01B5D", "F16767", "EDEDED", sTimeRemaining, "F16767");
|
CReplyToCommand(client, "\x07%s[KnifeBan] \x07%sYou are currently knifebanned for another \x07%s%s\x07%s.", "E01B5D", "F16767", "EDEDED", sTimeRemaining, "F16767");
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
-- knifeban_web.KbRestrict_CurrentBans definition
|
||||||
|
|
||||||
|
CREATE TABLE `KbRestrict_CurrentBans` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`client_name` varchar(64) NOT NULL,
|
||||||
|
`client_steamid` varchar(64) NOT NULL,
|
||||||
|
`client_ip` varchar(64) NOT NULL,
|
||||||
|
`admin_name` varchar(64) NOT NULL,
|
||||||
|
`admin_steamid` varchar(64) NOT NULL,
|
||||||
|
`reason` varchar(255) NOT NULL,
|
||||||
|
`map` varchar(64) NOT NULL,
|
||||||
|
`length` int(11) NOT NULL,
|
||||||
|
`time_stamp_start` datetime DEFAULT current_timestamp(),
|
||||||
|
`time_played_start` int(11) NOT NULL,
|
||||||
|
`time_played_end` int(11) NOT NULL,
|
||||||
|
`is_expired` int(11) NOT NULL,
|
||||||
|
`is_removed` int(11) NOT NULL,
|
||||||
|
`time_stamp_removed` int(20) NOT NULL,
|
||||||
|
`admin_name_removed` varchar(255) NOT NULL,
|
||||||
|
`admin_steamid_removed` varchar(255) NOT NULL,
|
||||||
|
`reason_removed` varchar(255) NOT NULL,
|
||||||
|
`web_unban_required` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
`web_addban_required` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
`web_ban_delete` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
`web_edit_required` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_steamid_search` (`client_steamid`),
|
||||||
|
KEY `idx_ip_search` (`client_ip`),
|
||||||
|
KEY `idx_admin_steamid` (`admin_steamid`),
|
||||||
|
KEY `idx_status` (`is_expired`,`is_removed`),
|
||||||
|
KEY `idx_steamid_ip_status` (`client_steamid`,`client_ip`,`is_expired`,`is_removed`),
|
||||||
|
KEY `idx_web_unban_required` (`web_unban_required`),
|
||||||
|
KEY `idx_web_addban_required` (`web_addban_required`),
|
||||||
|
KEY `idx_web_ban_delete` (`web_ban_delete`),
|
||||||
|
KEY `idx_web_edit_required` (`web_edit_required`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS knifeban_web.KbRestrict_weblogs (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`message` varchar(200) NOT NULL,
|
||||||
|
`admin_name` varchar(255) NOT NULL,
|
||||||
|
`admin_steamid` varchar(64) NOT NULL,
|
||||||
|
`client_name` varchar(255) NOT NULL,
|
||||||
|
`client_steamid` varchar(64) NOT NULL,
|
||||||
|
`time_stamp` int(20) NOT NULL,
|
||||||
|
PRIMARY KEY(`id`));
|
||||||
@@ -18,7 +18,7 @@ public Plugin myinfo =
|
|||||||
name = "LagCompensation",
|
name = "LagCompensation",
|
||||||
author = "BotoX, Vauff, .Rushaway, maxime1907",
|
author = "BotoX, Vauff, .Rushaway, maxime1907",
|
||||||
description = "",
|
description = "",
|
||||||
version = "1.0.6",
|
version = "1.1.0",
|
||||||
url = ""
|
url = ""
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ bool g_bHasOnEntitySpawned = false;
|
|||||||
bool g_bCheckPing = false;
|
bool g_bCheckPing = false;
|
||||||
int g_iCompenseEntityClass;
|
int g_iCompenseEntityClass;
|
||||||
|
|
||||||
// Dont change this.
|
// Don't change this.
|
||||||
#define MAX_EDICTS 2048
|
#define MAX_EDICTS 2048
|
||||||
#define FSOLID_FORCE_WORLD_ALIGNED 0x0040
|
#define FSOLID_FORCE_WORLD_ALIGNED 0x0040
|
||||||
#define FSOLID_ROOT_PARENT_ALIGNED 0x0100
|
#define FSOLID_ROOT_PARENT_ALIGNED 0x0100
|
||||||
@@ -104,6 +104,7 @@ enum struct EntityLagData
|
|||||||
int iNotMoving;
|
int iNotMoving;
|
||||||
bool bRestore;
|
bool bRestore;
|
||||||
bool bLateKill;
|
bool bLateKill;
|
||||||
|
char sClassname[64];
|
||||||
}
|
}
|
||||||
|
|
||||||
LagRecord g_aaLagRecords[MAX_ENTITIES][MAX_RECORDS];
|
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_aBlockTriggerMoved[MAX_EDICTS / 32];
|
||||||
int g_aBlacklisted[MAX_EDICTS / 32];
|
int g_aBlacklisted[MAX_EDICTS / 32];
|
||||||
|
|
||||||
Handle g_hCookie_EnableLagComp;
|
Handle g_hCookie_LagCompSettings;
|
||||||
Handle g_hCookie_LagCompMessages;
|
bool g_bDisableLagComp[MAXPLAYERS + 1];
|
||||||
bool g_bEnableLagComp[MAXPLAYERS + 1];
|
bool g_bPlayerLaserCompensated[MAXPLAYERS + 1];
|
||||||
bool g_bLagCompMessages[MAXPLAYERS + 1];
|
bool g_bLagCompMessages[MAXPLAYERS + 1];
|
||||||
|
bool g_bSettingsTouched[MAXPLAYERS + 1];
|
||||||
int g_iDisableLagComp[MAXPLAYERS + 1];
|
int g_iDisableLagComp[MAXPLAYERS + 1];
|
||||||
ConVar g_cvCompenseEntityClass;
|
ConVar g_cvCompenseEntityClass;
|
||||||
ConVar g_cvCheckUserPing;
|
ConVar g_cvCheckUserPing;
|
||||||
@@ -173,8 +175,8 @@ public void OnPluginStart()
|
|||||||
LoadTranslations("common.phrases");
|
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_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_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", "150", "Minimum ping threshold to apply lagcomp on a client", _, true, 0.0);
|
g_cvMinimumPing = CreateConVar("sm_lagcomp_ping", "180", "Minimum ping threshold to apply lagcomp on a client", _, true, 0.0);
|
||||||
|
|
||||||
AutoExecConfig(true);
|
AutoExecConfig(true);
|
||||||
|
|
||||||
@@ -347,16 +349,16 @@ public void OnPluginStart()
|
|||||||
HookConVarChange(g_cvMinimumPing, OnConVarChanged);
|
HookConVarChange(g_cvMinimumPing, OnConVarChanged);
|
||||||
|
|
||||||
|
|
||||||
g_hCookie_EnableLagComp = RegClientCookie("enable_lagcomp", "Client LagComp Status", CookieAccess_Private);
|
g_hCookie_LagCompSettings = RegClientCookie("lagcomp_settings", "LagCompensation Settings", CookieAccess_Private);
|
||||||
g_hCookie_LagCompMessages = RegClientCookie("lagcomp_messages", "Print LagComp messages in chat", CookieAccess_Private);
|
RegConsoleCmd("sm_lagcomp", OnLagCompSettings);
|
||||||
RegConsoleCmd("sm_lagcomp", OnToggleLagCompSettings);
|
|
||||||
RegConsoleCmd("sm_0ping", OnToggleLagCompSettings);
|
RegConsoleCmd("sm_0ping", OnToggleLagCompSettings);
|
||||||
|
RegConsoleCmd("sm_0pinglasers", OnToggleLagCompLasersSettings);
|
||||||
RegConsoleCmd("sm_checklag", CheckLagComp);
|
RegConsoleCmd("sm_checklag", CheckLagComp);
|
||||||
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "LagCompensation");
|
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "LagCompensation");
|
||||||
|
|
||||||
CreateTimer(0.1, DisableLagCompTimer, _, TIMER_REPEAT);
|
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");
|
RegAdminCmd("sm_lagged", Command_CheckLagCompensated, ADMFLAG_ROOT, "sm_lagged");
|
||||||
|
|
||||||
FilterClientSolidTouch(g_aaFilterClientSolidTouch, true);
|
FilterClientSolidTouch(g_aaFilterClientSolidTouch, true);
|
||||||
@@ -486,18 +488,27 @@ public void OnMapEnd()
|
|||||||
|
|
||||||
public void OnClientConnected(int client)
|
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_iDisableLagComp[client] = 0;
|
||||||
g_aLerpTicks[client] = 0;
|
g_aLerpTicks[client] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnClientCookiesCached(int client)
|
public void OnClientCookiesCached(int client)
|
||||||
{
|
{
|
||||||
char sBuffer[16];
|
// A toggle made before the cookies arrived wins, so flush it instead of
|
||||||
GetClientCookie(client, g_hCookie_EnableLagComp, sBuffer, sizeof(sBuffer));
|
// overwriting the client's choice with the stored value.
|
||||||
g_bEnableLagComp[client] = StringToInt(sBuffer) != 0; //this wording should make more sense, if the cookie exists its true to enable it.
|
if(g_bSettingsTouched[client])
|
||||||
GetClientCookie(client, g_hCookie_LagCompMessages, sBuffer, sizeof(sBuffer));
|
{
|
||||||
g_bLagCompMessages[client] = StringToInt(sBuffer) != 0;
|
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)
|
public void OnClientSettingsChanged(int client)
|
||||||
@@ -511,7 +522,10 @@ public void OnClientSettingsChanged(int client)
|
|||||||
|
|
||||||
public void OnClientDisconnect(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;
|
g_iDisableLagComp[client] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,8 +543,9 @@ public void OnEntityCreated(int entity, const char[] classname)
|
|||||||
DHookEntity(g_hAcceptInput, true, entity);
|
DHookEntity(g_hAcceptInput, true, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_bHasOnEntitySpawned && (!strncmp(classname, "func_physbox", 12, false) || (g_iCompenseEntityClass == 0 && strcmp(classname, "trigger_hurt", false) == 0 ||
|
if (!g_bHasOnEntitySpawned && (!strncmp(classname, "func_physbox", 12, false) ||
|
||||||
strcmp(classname, "trigger_push", false) == 0 || strcmp(classname, "trigger_teleport", false) == 0)))
|
(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);
|
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)
|
if(iCaller <= 0 || iCaller >= MAX_EDICTS)
|
||||||
return MRES_Ignored;
|
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);
|
BlacklistFamily(iCaller);
|
||||||
|
|
||||||
return MRES_Ignored;
|
return MRES_Ignored;
|
||||||
@@ -623,7 +638,7 @@ void BlacklistChildren(int parent)
|
|||||||
|
|
||||||
bool CheckEntityForLagComp(int entity, const char[] classname, bool bRecursive=false, bool bGoodParents=false)
|
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;
|
return false;
|
||||||
|
|
||||||
if(!IsValidEntity(entity))
|
if(!IsValidEntity(entity))
|
||||||
@@ -668,7 +683,7 @@ bool CheckEntityForLagComp(int entity, const char[] classname, bool bRecursive=f
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CheckBit(g_aBlacklisted, entity))
|
if(CheckBit(g_aBlacklisted, iParent))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -736,7 +751,7 @@ public void OnEntityDestroyed(int entity)
|
|||||||
if(g_bCleaningUp)
|
if(g_bCleaningUp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(entity < 0 || entity > MAX_EDICTS)
|
if(entity < 0 || entity >= MAX_EDICTS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ClearBit(g_aBlacklisted, entity);
|
ClearBit(g_aBlacklisted, entity);
|
||||||
@@ -758,7 +773,7 @@ public MRESReturn Detour_OnUTIL_Remove(Handle hParams)
|
|||||||
return MRES_Ignored;
|
return MRES_Ignored;
|
||||||
|
|
||||||
int entity = DHookGetParamObjectPtrVar(hParams, 1, g_iNetworkableOuter, ObjectValueType_CBaseEntityPtr);
|
int entity = DHookGetParamObjectPtrVar(hParams, 1, g_iNetworkableOuter, ObjectValueType_CBaseEntityPtr);
|
||||||
if(entity < 0 || entity > MAX_EDICTS)
|
if(entity < 0 || entity >= MAX_EDICTS)
|
||||||
return MRES_Ignored;
|
return MRES_Ignored;
|
||||||
|
|
||||||
int iIndex = g_aLagCompensated[entity];
|
int iIndex = g_aLagCompensated[entity];
|
||||||
@@ -858,8 +873,8 @@ public MRESReturn Detour_OnFrameUpdatePostEntityThink()
|
|||||||
for(int i = 0; i < g_iNumEntities; i++)
|
for(int i = 0; i < g_iNumEntities; i++)
|
||||||
{
|
{
|
||||||
// Dont make the entity check untouch in FrameUpdatePostEntityThink.
|
// Dont make the entity check untouch in FrameUpdatePostEntityThink.
|
||||||
// If the player didnt get simulated in the current frame then
|
// If the player didn't get simulated in the current frame then
|
||||||
// they didnt have a chance to touch this entity.
|
// they didn't have a chance to touch this entity.
|
||||||
// Hence the touchlink could be broken and we only let the player check untouch.
|
// Hence the touchlink could be broken and we only let the player check untouch.
|
||||||
int EFlags = GetEntData(g_aEntityLagData[i].iEntity, g_iEFlags);
|
int EFlags = GetEntData(g_aEntityLagData[i].iEntity, g_iEFlags);
|
||||||
EFlags &= ~EFL_CHECK_UNTOUCH;
|
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])
|
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;
|
return Plugin_Continue;
|
||||||
|
|
||||||
int iTargetTick = tickcount - g_aLerpTicks[client];
|
int iTargetTick = tickcount - g_aLerpTicks[client];
|
||||||
@@ -928,6 +943,13 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
int iRecord = iDelta;
|
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)
|
if(iRecord >= g_aEntityLagData[i].iNumRecords)
|
||||||
iRecord = g_aEntityLagData[i].iNumRecords - 1;
|
iRecord = g_aEntityLagData[i].iNumRecords - 1;
|
||||||
|
|
||||||
@@ -1112,6 +1134,10 @@ bool AddEntityForLagCompensation(int iEntity, bool bLateKill)
|
|||||||
if(g_bCleaningUp)
|
if(g_bCleaningUp)
|
||||||
return false;
|
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)
|
if(g_aLagCompensated[iEntity] != -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1144,6 +1170,7 @@ bool AddEntityForLagCompensation(int iEntity, bool bLateKill)
|
|||||||
g_aEntityLagData[i].iNotMoving = MAX_RECORDS;
|
g_aEntityLagData[i].iNotMoving = MAX_RECORDS;
|
||||||
g_aEntityLagData[i].bRestore = false;
|
g_aEntityLagData[i].bRestore = false;
|
||||||
g_aEntityLagData[i].bLateKill = bLateKill;
|
g_aEntityLagData[i].bLateKill = bLateKill;
|
||||||
|
g_aEntityLagData[i].sClassname = sClassname;
|
||||||
|
|
||||||
if(bLateKill)
|
if(bLateKill)
|
||||||
{
|
{
|
||||||
@@ -1226,6 +1253,7 @@ void EntityLagData_Copy(EntityLagData obj, const EntityLagData other)
|
|||||||
obj.iNotMoving = other.iNotMoving;
|
obj.iNotMoving = other.iNotMoving;
|
||||||
obj.bRestore = other.bRestore;
|
obj.bRestore = other.bRestore;
|
||||||
obj.bLateKill = other.bLateKill;
|
obj.bLateKill = other.bLateKill;
|
||||||
|
obj.sClassname = other.sClassname;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LagRecord_Copy(LagRecord obj, const LagRecord other)
|
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];
|
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)
|
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++)
|
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;
|
continue;
|
||||||
|
|
||||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/master/sp/src/game/server/util.cpp#L747
|
// 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)
|
if (g_bCheckPing)
|
||||||
{
|
{
|
||||||
int iAvgPing = RoundFloat(GetClientAvgLatency(client, NetFlow_Outgoing) * 1000);
|
int iAvgPing = RoundFloat(GetClientAvgLatency(client, NetFlow_Outgoing) * 1000);
|
||||||
|
|
||||||
if (iAvgPing > g_iMinPing)
|
if (iAvgPing <= g_iMinPing)
|
||||||
{
|
{
|
||||||
g_iDisableLagComp[client]++;
|
if(g_iDisableLagComp[client] < MAX_RECORDS)
|
||||||
return Plugin_Continue;
|
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]++;
|
g_iDisableLagComp[client]++;
|
||||||
}
|
}
|
||||||
else if(g_bEnableLagComp[client] && g_iDisableLagComp[client] > 0)
|
else if(!g_bDisableLagComp[client] && g_iDisableLagComp[client] > 0)
|
||||||
{
|
{
|
||||||
g_iDisableLagComp[client]--;
|
g_iDisableLagComp[client]--;
|
||||||
}
|
}
|
||||||
@@ -1406,33 +1490,52 @@ public Action OnToggleLagCompSettings(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Action OnToggleLagCompLasersSettings(int client, int args)
|
||||||
|
{
|
||||||
|
ToggleLagCompLasers(client);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
public void ToggleLagCompSettings(int client)
|
public void ToggleLagCompSettings(int client)
|
||||||
{
|
{
|
||||||
if(!client)
|
if(!client || !IsClientInGame(client) || IsFakeClient(client))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_bEnableLagComp[client] = !g_bEnableLagComp[client];
|
g_bDisableLagComp[client] = !g_bDisableLagComp[client];
|
||||||
SetClientCookie(client, g_hCookie_EnableLagComp, g_bEnableLagComp[client] ? "1" : "");
|
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)
|
public void ToggleLagCompMessages(int client)
|
||||||
{
|
{
|
||||||
if(!client)
|
if(!client || !IsClientInGame(client) || IsFakeClient(client))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_bLagCompMessages[client] = !g_bLagCompMessages[client];
|
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");
|
CPrintToChat(client, "%s LagCompensation messages have been %s.", PREFIX, g_bLagCompMessages[client] ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action CheckLagComp(int client, int args)
|
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;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1455,7 +1558,14 @@ public Action CheckLagComp(int client, int args)
|
|||||||
return Plugin_Handled;
|
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;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -1463,15 +1573,17 @@ public Action CheckLagComp(int client, int args)
|
|||||||
public void ShowSettingsMenu(int client)
|
public void ShowSettingsMenu(int client)
|
||||||
{
|
{
|
||||||
Menu menu = new Menu(MenuHandler_MainMenu);
|
Menu menu = new Menu(MenuHandler_MainMenu);
|
||||||
menu.SetTitle("LagCompensation Settings", client);
|
menu.SetTitle("LagCompensation Settings");
|
||||||
menu.ExitBackButton = true;
|
menu.ExitBackButton = true;
|
||||||
|
|
||||||
char buffer[128], msg_buffer[128];
|
char buffer[128], buffer_lasers[128], msg_buffer[128];
|
||||||
Format(buffer, sizeof(buffer), "LagCompensation: %s", g_bEnableLagComp[client] ? "Enabled" : "Disabled");
|
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");
|
Format(msg_buffer, sizeof(msg_buffer), "LagCompensation Messages: %s", g_bLagCompMessages[client] ? "Enabled" : "Disabled");
|
||||||
|
|
||||||
menu.AddItem("0", buffer);
|
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);
|
menu.Display(client, MENU_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
@@ -1482,7 +1594,7 @@ public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info
|
|||||||
{
|
{
|
||||||
case(CookieMenuAction_DisplayOption):
|
case(CookieMenuAction_DisplayOption):
|
||||||
{
|
{
|
||||||
Format(buffer, maxlen, "LagCompensation", client);
|
strcopy(buffer, maxlen, "LagCompensation");
|
||||||
}
|
}
|
||||||
case(CookieMenuAction_SelectOption):
|
case(CookieMenuAction_SelectOption):
|
||||||
{
|
{
|
||||||
@@ -1500,7 +1612,8 @@ public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int se
|
|||||||
switch(selection)
|
switch(selection)
|
||||||
{
|
{
|
||||||
case(0): ToggleLagCompSettings(client);
|
case(0): ToggleLagCompSettings(client);
|
||||||
case(1): ToggleLagCompMessages(client);
|
case(1): ToggleLagCompLasers(client);
|
||||||
|
case(2): ToggleLagCompMessages(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowSettingsMenu(client);
|
ShowSettingsMenu(client);
|
||||||
|
|||||||
@@ -1030,6 +1030,13 @@ public void LeaderMenu(int client)
|
|||||||
AddMenuItem(menu, "ping", "Ping Menu");
|
AddMenuItem(menu, "ping", "Ping Menu");
|
||||||
AddMenuItem(menu, "beacon", "Toggle Beacon");
|
AddMenuItem(menu, "beacon", "Toggle Beacon");
|
||||||
|
|
||||||
|
// RCON-only options
|
||||||
|
if (CheckCommandAccess(client, "", ADMFLAG_RCON, false))
|
||||||
|
{
|
||||||
|
AddMenuItem(menu, "addleader", "[RCON] Add Leader to File");
|
||||||
|
AddMenuItem(menu, "removeleader", "[RCON] Remove Leader from File");
|
||||||
|
}
|
||||||
|
|
||||||
SetMenuExitButton(menu, true);
|
SetMenuExitButton(menu, true);
|
||||||
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
@@ -1046,6 +1053,23 @@ public int LeaderMenu_Handler(Handle menu, MenuAction action, int client, int po
|
|||||||
char info[32];
|
char info[32];
|
||||||
GetMenuItem(menu, position, info, sizeof(info));
|
GetMenuItem(menu, position, info, sizeof(info));
|
||||||
|
|
||||||
|
if(StrEqual(info, "addleader"))
|
||||||
|
{
|
||||||
|
if(CheckCommandAccess(client, "", ADMFLAG_RCON, false))
|
||||||
|
{
|
||||||
|
AddLeaderMenu(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StrEqual(info, "removeleader"))
|
||||||
|
{
|
||||||
|
if(CheckCommandAccess(client, "", ADMFLAG_RCON, false))
|
||||||
|
{
|
||||||
|
RemoveLeaderMenu(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(StrEqual(info, "resign"))
|
if(StrEqual(info, "resign"))
|
||||||
{
|
{
|
||||||
RemoveLeader(client);
|
RemoveLeader(client);
|
||||||
@@ -1070,7 +1094,260 @@ public int LeaderMenu_Handler(Handle menu, MenuAction action, int client, int po
|
|||||||
delete menu;
|
delete menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: RCON - shows connected players to add to the leaders file
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void AddLeaderMenu(int client)
|
||||||
|
{
|
||||||
|
Handle menu = CreateMenu(AddLeaderMenu_Handler);
|
||||||
|
SetMenuTitle(menu, "Select a player to ADD as Leader");
|
||||||
|
|
||||||
|
char info[12], display[MAX_NAME_LENGTH];
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i) && !IsFakeClient(i))
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
IntToString(GetClientUserId(i), info, sizeof(info));
|
||||||
|
GetClientName(i, display, sizeof(display));
|
||||||
|
AddMenuItem(menu, info, display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!any)
|
||||||
|
{
|
||||||
|
AddMenuItem(menu, "", "No players connected", ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMenuExitBackButton(menu, true);
|
||||||
|
SetMenuExitButton(menu, true);
|
||||||
|
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public int AddLeaderMenu_Handler(Handle menu, MenuAction action, int client, int position)
|
||||||
|
{
|
||||||
|
if(action == MenuAction_Select)
|
||||||
|
{
|
||||||
|
if(!CheckCommandAccess(client, "", ADMFLAG_RCON, false))
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[SM] You no longer have access to this.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char info[12];
|
||||||
|
GetMenuItem(menu, position, info, sizeof(info));
|
||||||
|
|
||||||
|
int target = GetClientOfUserId(StringToInt(info));
|
||||||
|
if(target == 0)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[SM] That player is no longer available.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLeaderToFile(client, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaderMenu(client);
|
||||||
|
}
|
||||||
|
else if(action == MenuAction_End)
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
else if(action == MenuAction_Cancel && position == MenuCancel_ExitBack)
|
||||||
|
{
|
||||||
|
LeaderMenu(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//AI slop
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: RCON - shows connected players to remove from the leaders file
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void RemoveLeaderMenu(int client)
|
||||||
|
{
|
||||||
|
Handle menu = CreateMenu(RemoveLeaderMenu_Handler);
|
||||||
|
SetMenuTitle(menu, "Select a player to REMOVE as Leader");
|
||||||
|
|
||||||
|
char info[12], display[MAX_NAME_LENGTH];
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsClientInGame(i) && !IsFakeClient(i))
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
IntToString(GetClientUserId(i), info, sizeof(info));
|
||||||
|
GetClientName(i, display, sizeof(display));
|
||||||
|
AddMenuItem(menu, info, display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!any)
|
||||||
|
{
|
||||||
|
AddMenuItem(menu, "", "No players connected", ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMenuExitBackButton(menu, true);
|
||||||
|
SetMenuExitButton(menu, true);
|
||||||
|
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public int RemoveLeaderMenu_Handler(Handle menu, MenuAction action, int client, int position)
|
||||||
|
{
|
||||||
|
if(action == MenuAction_Select)
|
||||||
|
{
|
||||||
|
if(!CheckCommandAccess(client, "", ADMFLAG_RCON, false))
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[SM] You no longer have access to this.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char info[12];
|
||||||
|
GetMenuItem(menu, position, info, sizeof(info));
|
||||||
|
|
||||||
|
int target = GetClientOfUserId(StringToInt(info));
|
||||||
|
if(target == 0)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[SM] That player is no longer available.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveLeaderFromFile(client, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaderMenu(client);
|
||||||
|
}
|
||||||
|
else if(action == MenuAction_End)
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
else if(action == MenuAction_Cancel && position == MenuCancel_ExitBack)
|
||||||
|
{
|
||||||
|
LeaderMenu(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: Appends a targets SteamID2 to the leaders file with their name as a comment
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void AddLeaderToFile(int admin, int target)
|
||||||
|
{
|
||||||
|
char sAuth[64], sName[MAX_NAME_LENGTH];
|
||||||
|
if(!GetClientAuthId(target, AuthId_Steam2, sAuth, sizeof(sAuth)))
|
||||||
|
{
|
||||||
|
PrintToChat(admin, "[SM] Could not resolve a SteamID for that player yet, try again in a moment.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GetClientName(target, sName, sizeof(sName));
|
||||||
|
|
||||||
|
if(IsPossibleLeader(target))
|
||||||
|
{
|
||||||
|
PrintToChat(admin, "[SM] %N is already in the leaders file.", target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File fFile = OpenFile(g_sDataFile, "a");
|
||||||
|
if(!fFile)
|
||||||
|
{
|
||||||
|
PrintToChat(admin, "[SM] Failed to open the leaders file for writing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fFile.WriteLine("\"%s\" //%s", sAuth, sName);
|
||||||
|
fFile.Close();
|
||||||
|
|
||||||
|
UpdateLeaders();
|
||||||
|
|
||||||
|
PrintToChatAll("[SM] %N added %N to the leaders list.", admin, target);
|
||||||
|
LogAction(admin, target, "\"%L\" added \"%L\" to the leaders file", admin, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: Removes a targets SteamID2 line from the leaders file, if present
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void RemoveLeaderFromFile(int admin, int target)
|
||||||
|
{
|
||||||
|
char sAuth[64];
|
||||||
|
if(!GetClientAuthId(target, AuthId_Steam2, sAuth, sizeof(sAuth)))
|
||||||
|
{
|
||||||
|
PrintToChat(admin, "[SM] Could not resolve a SteamID for that player yet, try again in a moment.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File fRead = OpenFile(g_sDataFile, "rt");
|
||||||
|
if(!fRead)
|
||||||
|
{
|
||||||
|
PrintToChat(admin, "[SM] Failed to open the leaders file for reading.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList lines = new ArrayList(ByteCountToCells(255));
|
||||||
|
char line[255];
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
while(!fRead.EndOfFile() && fRead.ReadLine(line, sizeof(line)))
|
||||||
|
{
|
||||||
|
// Only skip the first line that actually contains this SteamID (inside the quotes)
|
||||||
|
if(!found && StrContains(line, sAuth) != -1)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lines.PushString(line);
|
||||||
|
}
|
||||||
|
fRead.Close();
|
||||||
|
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
delete lines;
|
||||||
|
PrintToChat(admin, "[SM] %N was not found in the leaders file.", target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File fWrite = OpenFile(g_sDataFile, "wt");
|
||||||
|
if(!fWrite)
|
||||||
|
{
|
||||||
|
delete lines;
|
||||||
|
PrintToChat(admin, "[SM] Failed to open the leaders file for writing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = lines.Length;
|
||||||
|
for(int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
lines.GetString(i, line, sizeof(line));
|
||||||
|
fWrite.WriteLine(line);
|
||||||
|
}
|
||||||
|
fWrite.Close();
|
||||||
|
delete lines;
|
||||||
|
|
||||||
|
UpdateLeaders();
|
||||||
|
|
||||||
|
PrintToChatAll("[SM] %N removed %N from the leaders list.", admin, target);
|
||||||
|
LogAction(admin, target, "\"%L\" removed \"%L\" from the leaders file", admin, target);
|
||||||
|
|
||||||
|
// If the person removed is the current leader, kick them out of the role too
|
||||||
|
if(target == leaderClient)
|
||||||
|
{
|
||||||
|
RemoveLeader(target);
|
||||||
|
PrintToChatAll("[SM] %N is no longer a valid leader and has been removed from the leader role.", target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -1191,6 +1468,7 @@ public int SpriteMenu_Handler(Handle menu, MenuAction action, int client, int po
|
|||||||
LeaderMenu(client);
|
LeaderMenu(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -1320,6 +1598,7 @@ public int PingMenu_Handler(Handle menu, MenuAction action, int client, int posi
|
|||||||
LeaderMenu(client);
|
LeaderMenu(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -1353,6 +1632,7 @@ public Action Event_PlayerDeath(Handle event, char[] name, bool dontBroadcast)
|
|||||||
PrintToChatAll("[SM] The leader has died!");
|
PrintToChatAll("[SM] The leader has died!");
|
||||||
RemoveLeader(client);
|
RemoveLeader(client);
|
||||||
}
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -1413,6 +1693,7 @@ public Action Event_RoundEnd(Handle event, char[] name, bool dontBroadcast)
|
|||||||
pingEntity1 = -1;
|
pingEntity1 = -1;
|
||||||
pingEntity2 = -1;
|
pingEntity2 = -1;
|
||||||
pingEntity3 = -1;
|
pingEntity3 = -1;
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -1463,6 +1744,7 @@ public int Native_CurrentLeader(Handle plugin, int numParams)
|
|||||||
public int Native_SetLeader(Handle plugin, int numParams)
|
public int Native_SetLeader(Handle plugin, int numParams)
|
||||||
{
|
{
|
||||||
SetLeader(GetNativeCell(1));
|
SetLeader(GetNativeCell(1));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
|
|||||||
+102
-16
@@ -7,16 +7,7 @@
|
|||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
#pragma newdecls required
|
#pragma newdecls required
|
||||||
|
|
||||||
public Plugin myinfo =
|
#define NUMBEROFSTAGES 7
|
||||||
{
|
|
||||||
name = "MakoVoteSystem",
|
|
||||||
author = "Neon",
|
|
||||||
description = "MakoVoteSystem",
|
|
||||||
version = "1.1",
|
|
||||||
url = "https://steamcommunity.com/id/n3ontm"
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUMBEROFSTAGES 6
|
|
||||||
|
|
||||||
bool g_bVoteFinished = true;
|
bool g_bVoteFinished = true;
|
||||||
bool g_bIsRevote = false;
|
bool g_bIsRevote = false;
|
||||||
@@ -24,13 +15,15 @@ bool g_bStartVoteNextRound = false;
|
|||||||
bool g_bPlayedZM = false;
|
bool g_bPlayedZM = false;
|
||||||
|
|
||||||
bool g_bOnCooldown[NUMBEROFSTAGES];
|
bool g_bOnCooldown[NUMBEROFSTAGES];
|
||||||
static char g_sStageName[NUMBEROFSTAGES][32] = {"Extreme 2", "Extreme 2 (Heal + Ultima)", "Extreme 3 (ZED)", "Extreme 3 (Hellz)", "Race Mode", "Zombie Mode"};
|
static char g_sStageName[NUMBEROFSTAGES][32] = {"Extreme 2 (Heal + Ultima)", "Extreme 3 (ZED)", "Extreme 3 (Hellz)", "Race Mode", "Zombie Mode", "Extreme 4 RMZS", "Ext2 Special Lasers"};
|
||||||
int g_Winnerstage;
|
int g_Winnerstage;
|
||||||
|
|
||||||
Handle g_VoteMenu = INVALID_HANDLE;
|
Handle g_VoteMenu = INVALID_HANDLE;
|
||||||
Handle g_StageList = INVALID_HANDLE;
|
Handle g_StageList = INVALID_HANDLE;
|
||||||
Handle g_CountdownTimer = INVALID_HANDLE;
|
Handle g_CountdownTimer = INVALID_HANDLE;
|
||||||
|
|
||||||
|
bool g_bCorrectMap = false;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -57,6 +50,7 @@ public void OnPluginStart()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnMapStart()
|
public void OnMapStart()
|
||||||
{
|
{
|
||||||
|
g_bCorrectMap = false;
|
||||||
VerifyMap();
|
VerifyMap();
|
||||||
|
|
||||||
g_bStartVoteNextRound = false;
|
g_bStartVoteNextRound = false;
|
||||||
@@ -76,17 +70,22 @@ public Action VerifyMap()
|
|||||||
|
|
||||||
if (!StrEqual(currentMap, "ze_ffvii_mako_reactor_v5_3", false))
|
if (!StrEqual(currentMap, "ze_ffvii_mako_reactor_v5_3", false))
|
||||||
{
|
{
|
||||||
|
//plugin unloading can make map switches very slow
|
||||||
|
/*
|
||||||
char sFilename[256];
|
char sFilename[256];
|
||||||
GetPluginFilename(INVALID_HANDLE, sFilename, sizeof(sFilename));
|
GetPluginFilename(INVALID_HANDLE, sFilename, sizeof(sFilename));
|
||||||
|
|
||||||
ServerCommand("sm plugins unload %s", sFilename);
|
ServerCommand("sm plugins unload %s", sFilename);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
g_bCorrectMap = true;
|
||||||
PrecacheSound("#unloze/Pendulum - Witchcraft.mp3", true);
|
PrecacheSound("#unloze/Pendulum - Witchcraft.mp3", true);
|
||||||
|
|
||||||
AddFileToDownloadsTable("sound/unloze/Pendulum - Witchcraft.mp3");
|
AddFileToDownloadsTable("sound/unloze/Pendulum - Witchcraft.mp3");
|
||||||
}
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -94,6 +93,10 @@ public Action VerifyMap()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnEntitySpawned(int iEntity, const char[] sClassname)
|
public void OnEntitySpawned(int iEntity, const char[] sClassname)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!IsValidEntity(iEntity) || g_bVoteFinished)
|
if (!IsValidEntity(iEntity) || g_bVoteFinished)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -109,6 +112,10 @@ public void OnEntitySpawned(int iEntity, const char[] sClassname)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (g_bStartVoteNextRound)
|
if (g_bStartVoteNextRound)
|
||||||
{
|
{
|
||||||
g_bVoteFinished = false;
|
g_bVoteFinished = false;
|
||||||
@@ -160,9 +167,12 @@ public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|||||||
if (iButton5 != INVALID_ENT_REFERENCE)
|
if (iButton5 != INVALID_ENT_REFERENCE)
|
||||||
AcceptEntityInput(iButton5, "Lock");
|
AcceptEntityInput(iButton5, "Lock");
|
||||||
|
|
||||||
int iCounter = FindEntityByTargetname(INVALID_ENT_REFERENCE, "LevelCounter", "math_counter");
|
//its now a permanent entity so really dont kill it.
|
||||||
|
/*
|
||||||
|
int iCounter = FindEntityByTargetname(INVALID_ENT_REFERENCE, "LevelCounter", "info_target");
|
||||||
if (iCounter != INVALID_ENT_REFERENCE)
|
if (iCounter != INVALID_ENT_REFERENCE)
|
||||||
AcceptEntityInput(iCounter, "Kill");
|
AcceptEntityInput(iCounter, "Kill");
|
||||||
|
*/
|
||||||
|
|
||||||
int iFilter = FindEntityByTargetname(INVALID_ENT_REFERENCE, "humanos", "filter_activator_team");
|
int iFilter = FindEntityByTargetname(INVALID_ENT_REFERENCE, "humanos", "filter_activator_team");
|
||||||
if (iFilter != INVALID_ENT_REFERENCE)
|
if (iFilter != INVALID_ENT_REFERENCE)
|
||||||
@@ -245,6 +255,10 @@ public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void GenerateArray()
|
public void GenerateArray()
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int iBlockSize = ByteCountToCells(PLATFORM_MAX_PATH);
|
int iBlockSize = ByteCountToCells(PLATFORM_MAX_PATH);
|
||||||
g_StageList = CreateArray(iBlockSize);
|
g_StageList = CreateArray(iBlockSize);
|
||||||
|
|
||||||
@@ -270,6 +284,11 @@ public void GenerateArray()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action Command_StartVote(int args)
|
public Action Command_StartVote(int args)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
int iCurrentStage = GetCurrentStage();
|
int iCurrentStage = GetCurrentStage();
|
||||||
|
|
||||||
if (iCurrentStage > 0)
|
if (iCurrentStage > 0)
|
||||||
@@ -302,6 +321,10 @@ public Action Command_StartVote(int args)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action StartVote(Handle timer)
|
public Action StartVote(Handle timer)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
static int iCountDown = 5;
|
static int iCountDown = 5;
|
||||||
PrintCenterTextAll("[MakoVote] Starting Vote in %ds", iCountDown);
|
PrintCenterTextAll("[MakoVote] Starting Vote in %ds", iCountDown);
|
||||||
|
|
||||||
@@ -312,6 +335,7 @@ public Action StartVote(Handle timer)
|
|||||||
g_CountdownTimer = INVALID_HANDLE;
|
g_CountdownTimer = INVALID_HANDLE;
|
||||||
InitiateVote();
|
InitiateVote();
|
||||||
}
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -319,6 +343,10 @@ public Action StartVote(Handle timer)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void InitiateVote()
|
public void InitiateVote()
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(IsVoteInProgress())
|
if(IsVoteInProgress())
|
||||||
{
|
{
|
||||||
CPrintToChatAll("{green}[Mako Vote] {white}Another vote is currently in progress, retrying again in 5s.");
|
CPrintToChatAll("{green}[Mako Vote] {white}Another vote is currently in progress, retrying again in 5s.");
|
||||||
@@ -347,7 +375,7 @@ public void InitiateVote()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetMenuOptionFlags(g_VoteMenu, MENUFLAG_BUTTON_NOVOTE);
|
//SetMenuOptionFlags(g_VoteMenu, MENUFLAG_BUTTON_NOVOTE);
|
||||||
SetMenuTitle(g_VoteMenu, "What stage to play next?");
|
SetMenuTitle(g_VoteMenu, "What stage to play next?");
|
||||||
SetVoteResultCallback(g_VoteMenu, Handler_SettingsVoteFinished);
|
SetVoteResultCallback(g_VoteMenu, Handler_SettingsVoteFinished);
|
||||||
VoteMenuToAll(g_VoteMenu, 20);
|
VoteMenuToAll(g_VoteMenu, 20);
|
||||||
@@ -358,6 +386,10 @@ public void InitiateVote()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public int Handler_MakoVoteMenu(Handle menu, MenuAction action, int param1, int param2)
|
public int Handler_MakoVoteMenu(Handle menu, MenuAction action, int param1, int param2)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
switch(action)
|
switch(action)
|
||||||
{
|
{
|
||||||
case MenuAction_End:
|
case MenuAction_End:
|
||||||
@@ -385,10 +417,15 @@ public int MenuHandler_NotifyPanel(Menu hMenu, MenuAction iAction, int iParam1,
|
|||||||
case MenuAction_Select, MenuAction_Cancel:
|
case MenuAction_Select, MenuAction_Cancel:
|
||||||
delete hMenu;
|
delete hMenu;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handler_SettingsVoteFinished(Handle menu, int num_votes, int num_clients, const int[][] client_info, int num_items, const int[][] item_info)
|
public void Handler_SettingsVoteFinished(Handle menu, int num_votes, int num_clients, const int[][] client_info, int num_items, const int[][] item_info)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int highest_votes = item_info[0][VOTEINFO_ITEM_VOTES];
|
int highest_votes = item_info[0][VOTEINFO_ITEM_VOTES];
|
||||||
int required_percent = 60;
|
int required_percent = 60;
|
||||||
int required_votes = RoundToCeil(float(num_votes) * float(required_percent) / 100);
|
int required_votes = RoundToCeil(float(num_votes) * float(required_percent) / 100);
|
||||||
@@ -416,6 +453,10 @@ public void Handler_SettingsVoteFinished(Handle menu, int num_votes, int num_cli
|
|||||||
|
|
||||||
public void Handler_VoteFinishedGeneric(Handle menu, int num_votes, int num_clients, const int[][] client_info, int num_items, const int[][] item_info)
|
public void Handler_VoteFinishedGeneric(Handle menu, int num_votes, int num_clients, const int[][] client_info, int num_items, const int[][] item_info)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_bVoteFinished = true;
|
g_bVoteFinished = true;
|
||||||
char sWinner[128];
|
char sWinner[128];
|
||||||
GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], sWinner, sizeof(sWinner));
|
GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], sWinner, sizeof(sWinner));
|
||||||
@@ -429,7 +470,42 @@ public void Handler_VoteFinishedGeneric(Handle menu, int num_votes, int num_clie
|
|||||||
g_Winnerstage = i;
|
g_Winnerstage = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerCommand("sm_stage %d", (g_Winnerstage + 4));
|
//ServerCommand("sm_stage %d", (g_Winnerstage + 4));
|
||||||
|
char winner_stage[64];
|
||||||
|
if (StrEqual(sWinner, "Extreme 3 (Hellz)"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "hellz");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Extreme 2"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "extreme2");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Extreme 2 (Heal + Ultima)"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "ultiheal");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Extreme 3 (ZED)"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "zombieden");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Race Mode"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "race");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Zombie Mode"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "zm");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Extreme 4 RMZS"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "rmzs");
|
||||||
|
}
|
||||||
|
else if (StrEqual(sWinner, "Ext2 Special Lasers"))
|
||||||
|
{
|
||||||
|
Format(winner_stage, sizeof(winner_stage), "laser");
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerCommand("sm_stage %s", winner_stage);
|
||||||
|
|
||||||
float fDelay = 3.0;
|
float fDelay = 3.0;
|
||||||
CS_TerminateRound(fDelay, CSRoundEnd_GameStart, false);
|
CS_TerminateRound(fDelay, CSRoundEnd_GameStart, false);
|
||||||
@@ -437,7 +513,13 @@ public void Handler_VoteFinishedGeneric(Handle menu, int num_votes, int num_clie
|
|||||||
|
|
||||||
public int GetCurrentStage()
|
public int GetCurrentStage()
|
||||||
{
|
{
|
||||||
int iLevelCounterEnt = FindEntityByTargetname(INVALID_ENT_REFERENCE, "LevelCounter", "math_counter");
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//int iLevelCounterEnt = FindEntityByTargetname(INVALID_ENT_REFERENCE, "LevelCounter", "math_counter");
|
||||||
|
//due to the stripper its now an info_target and not math_counter.
|
||||||
|
int iLevelCounterEnt = FindEntityByTargetname(INVALID_ENT_REFERENCE, "LevelCounter", "info_target");
|
||||||
|
|
||||||
int offset = FindDataMapInfo(iLevelCounterEnt, "m_OutValue");
|
int offset = FindDataMapInfo(iLevelCounterEnt, "m_OutValue");
|
||||||
int iCounterVal = RoundFloat(GetEntDataFloat(iLevelCounterEnt, offset));
|
int iCounterVal = RoundFloat(GetEntDataFloat(iLevelCounterEnt, offset));
|
||||||
@@ -463,6 +545,10 @@ public int GetCurrentStage()
|
|||||||
|
|
||||||
public int FindEntityByTargetname(int entity, const char[] sTargetname, const char[] sClassname)
|
public int FindEntityByTargetname(int entity, const char[] sTargetname, const char[] sClassname)
|
||||||
{
|
{
|
||||||
|
if (!g_bCorrectMap)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(sTargetname[0] == '#') // HammerID
|
if(sTargetname[0] == '#') // HammerID
|
||||||
{
|
{
|
||||||
int HammerID = StringToInt(sTargetname[1]);
|
int HammerID = StringToInt(sTargetname[1]);
|
||||||
@@ -488,4 +574,4 @@ public int FindEntityByTargetname(int entity, const char[] sTargetname, const ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return INVALID_ENT_REFERENCE;
|
return INVALID_ENT_REFERENCE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public void OnPluginStart()
|
|||||||
ConVar cvar;
|
ConVar cvar;
|
||||||
HookConVarChange((cvar = CreateConVar("sm_admin_afk_time", "30", "Time in seconds until an admin is considered as AFK.")), Cvar_AdminAFKTime);
|
HookConVarChange((cvar = CreateConVar("sm_admin_afk_time", "30", "Time in seconds until an admin is considered as AFK.")), Cvar_AdminAFKTime);
|
||||||
g_iAdminAFKTime = cvar.IntValue;
|
g_iAdminAFKTime = cvar.IntValue;
|
||||||
HookConVarChange((cvar = CreateConVar("sm_selfextend_amount", "2", "Amount of sm_selfextend's allowed.")), Cvar_SelfExtendsAmount);
|
HookConVarChange((cvar = CreateConVar("sm_selfextend_amount", "2", "Amount of sm_selfextends allowed.")), Cvar_SelfExtendsAmount);
|
||||||
g_iSelfMaxExtendsAmount = cvar.IntValue;
|
g_iSelfMaxExtendsAmount = cvar.IntValue;
|
||||||
HookConVarChange((cvar = CreateConVar("sm_selfextend_time", "10", "How long to extend in minutes when sm_selfextend passes through.")), Cvar_SelfExtendsTime);
|
HookConVarChange((cvar = CreateConVar("sm_selfextend_time", "10", "How long to extend in minutes when sm_selfextend passes through.")), Cvar_SelfExtendsTime);
|
||||||
g_iSelfExtendsTime = cvar.IntValue;
|
g_iSelfExtendsTime = cvar.IntValue;
|
||||||
@@ -175,24 +175,14 @@ public Action Command_DisplayActiveAdmins(int client, int args)
|
|||||||
|
|
||||||
public Action Command_SelfExtend(int client, int args)
|
public Action Command_SelfExtend(int client, int args)
|
||||||
{
|
{
|
||||||
int iAdminActivity = 0;
|
|
||||||
for(int i = 1; i <= MaxClients; i++)
|
|
||||||
if(g_bActiveAdmin[i])
|
|
||||||
iAdminActivity++;
|
|
||||||
|
|
||||||
if(GetExtendsLeft() > 0)
|
if(GetExtendsLeft() > 0)
|
||||||
{
|
{
|
||||||
ReplyToCommand(client, "[SM] Not available because not all regular extends have been depleted.");
|
ReplyToCommand(client, "[SM] Not available because not all regular extends have been depleted.");
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
if(iAdminActivity > 0)
|
|
||||||
{
|
|
||||||
ReplyToCommand(client, "[SM] Not available because there is atleast one active Admin who can extend. Please ask the Admins.");
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
if(!g_bSelfExtendsAllowed)
|
if(!g_bSelfExtendsAllowed)
|
||||||
{
|
{
|
||||||
ReplyToCommand(client, "[SM] Not available because it's still too early in the map.");
|
ReplyToCommand(client, "[SM] Not available because its still too early in the map.");
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
if(g_iSelfMaxExtendsAmount <= g_iSelfExtends)
|
if(g_iSelfMaxExtendsAmount <= g_iSelfExtends)
|
||||||
@@ -201,14 +191,34 @@ public Action Command_SelfExtend(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iPlayers;
|
||||||
|
int iSelfExtendsPlayers;
|
||||||
|
int iPlayersNeeded;
|
||||||
|
|
||||||
|
for(int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if(IsValidClient(i))
|
||||||
|
iPlayers++;
|
||||||
|
|
||||||
|
if(g_bSelfExtends[i])
|
||||||
|
iSelfExtendsPlayers++;
|
||||||
|
}
|
||||||
|
iPlayersNeeded = RoundToFloor(float(iPlayers) * g_fSelfExtendsRatio);
|
||||||
|
|
||||||
|
if (iPlayersNeeded == 0)
|
||||||
|
{
|
||||||
|
iPlayersNeeded = 1;
|
||||||
|
}
|
||||||
if(!g_bSelfExtends[client])
|
if(!g_bSelfExtends[client])
|
||||||
{
|
{
|
||||||
g_bSelfExtends[client] = true;
|
g_bSelfExtends[client] = true;
|
||||||
PrintToChatAll("[SM] %N wants to self-extend the map.", client);
|
PrintToChatAll("[SM] %N wants to self-extend the map. %i/%i", client, iSelfExtendsPlayers + 1, iPlayersNeeded);
|
||||||
CheckRatio();
|
CheckRatio();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReplyToCommand(client, "[SM] You have already voted to self-extend the map.");
|
{
|
||||||
|
ReplyToCommand(client, "[SM] You have already voted to self-extend the map. %i/%i", iSelfExtendsPlayers, iPlayersNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -233,7 +243,7 @@ public void CheckRatio()
|
|||||||
|
|
||||||
iPlayersNeeded = RoundToFloor(float(iPlayers) * g_fSelfExtendsRatio);
|
iPlayersNeeded = RoundToFloor(float(iPlayers) * g_fSelfExtendsRatio);
|
||||||
|
|
||||||
if(iSelfExtendsPlayers >= iPlayersNeeded && iPlayersNeeded != 0)
|
if(iSelfExtendsPlayers >= iPlayersNeeded && iSelfExtendsPlayers > 0)
|
||||||
{
|
{
|
||||||
PrintToChatAll("[SM] Enough Players voted to self-extend the map. Adding %d minutes to the timelimit.", g_iSelfExtendsTime);
|
PrintToChatAll("[SM] Enough Players voted to self-extend the map. Adding %d minutes to the timelimit.", g_iSelfExtendsTime);
|
||||||
LogMessage("Enough Players voted to self-extend the map. Adding %d minutes to the timelimit.", g_iSelfExtendsTime);
|
LogMessage("Enough Players voted to self-extend the map. Adding %d minutes to the timelimit.", g_iSelfExtendsTime);
|
||||||
@@ -243,7 +253,6 @@ public void CheckRatio()
|
|||||||
for(int j; j <= MaxClients; j++)
|
for(int j; j <= MaxClients; j++)
|
||||||
g_bSelfExtends[j] = false;
|
g_bSelfExtends[j] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,4 +266,4 @@ static stock bool IsValidClient(int client)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
ConVar g_hCvar_BlockSpoof;
|
ConVar g_hCvar_BlockSpoof;
|
||||||
ConVar g_hCvar_BlockAdmin;
|
ConVar g_hCvar_BlockAdmin;
|
||||||
ConVar g_hCvar_BlockVoice;
|
ConVar g_hCvar_BlockVoice;
|
||||||
ConVar g_hCvar_AuthenticationTime;
|
|
||||||
|
|
||||||
/* DATABASE */
|
/* DATABASE */
|
||||||
Database g_hDatabase;
|
Database g_hDatabase;
|
||||||
@@ -53,7 +52,6 @@ public void OnPluginStart()
|
|||||||
g_hCvar_BlockSpoof = CreateConVar("sm_manager_block_spoof", "1", "Kick unauthenticated people that join with known steamids.", FCVAR_NONE, true, 0.0, true, 1.0);
|
g_hCvar_BlockSpoof = CreateConVar("sm_manager_block_spoof", "1", "Kick unauthenticated people that join with known steamids.", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
g_hCvar_BlockAdmin = CreateConVar("sm_manager_block_admin", "1", "Should unauthenticated people be blocked from admin?", FCVAR_NONE, true, 0.0, true, 1.0);
|
g_hCvar_BlockAdmin = CreateConVar("sm_manager_block_admin", "1", "Should unauthenticated people be blocked from admin?", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
g_hCvar_BlockVoice = CreateConVar("sm_manager_block_voice", "1", "Should unauthenticated people be blocked from voice?", FCVAR_NONE, true, 0.0, true, 1.0);
|
g_hCvar_BlockVoice = CreateConVar("sm_manager_block_voice", "1", "Should unauthenticated people be blocked from voice?", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
g_hCvar_AuthenticationTime = CreateConVar("sm_manager_authentication_time", "15", "Time in seconds after which a client needs to be assigned to a SteamID", FCVAR_NONE, true, 1.0);
|
|
||||||
|
|
||||||
AddMultiTargetFilter("@steam", Filter_Steam, "Steam Players", false);
|
AddMultiTargetFilter("@steam", Filter_Steam, "Steam Players", false);
|
||||||
AddMultiTargetFilter("@nosteam", Filter_NoSteam, "No-Steam Players", false);
|
AddMultiTargetFilter("@nosteam", Filter_NoSteam, "No-Steam Players", false);
|
||||||
@@ -258,14 +256,6 @@ public EConnect OnClientPreConnectEx(const char[] sName, char sPassword[255], co
|
|||||||
return k_OnClientPreConnectEx_Accept;
|
return k_OnClientPreConnectEx_Accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public void OnClientPutInServer(int client)
|
|
||||||
{
|
|
||||||
//CreateTimer(g_hCvar_AuthenticationTime.FloatValue, CheckAuth, GetClientSerial(client), TIMER_FLAG_NO_MAPCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -273,9 +263,22 @@ public void OnClientAuthorized(int client, const char[] sAuthID)
|
|||||||
{
|
{
|
||||||
char sAddress[16];
|
char sAddress[16];
|
||||||
GetClientIP(client, sAddress, sizeof(sAddress));
|
GetClientIP(client, sAddress, sizeof(sAddress));
|
||||||
static char sCountry[32];
|
//if its the webclient its not a malicious steam ID steal, just pure coincidence if it were to hit a real steam players steamID.
|
||||||
|
char allowed_ips[128];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowed_ips, sizeof(allowed_ips));
|
||||||
|
if (StrEqual(sAddress, allowed_ips))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//just kicking all nosteamers from algeria. not very cool but so be it.
|
//just kicking all nosteamers from algeria. not very cool but so be it.
|
||||||
/*
|
/*
|
||||||
|
static char sCountry[32];
|
||||||
if (GeoipCountry(sAddress, sCountry, sizeof(sCountry)) && StrEqual(sCountry, "Algeria", false))
|
if (GeoipCountry(sAddress, sCountry, sizeof(sCountry)) && StrEqual(sCountry, "Algeria", false))
|
||||||
{
|
{
|
||||||
if (!SteamClientAuthenticatedEx(sAuthID))
|
if (!SteamClientAuthenticatedEx(sAuthID))
|
||||||
@@ -334,61 +337,6 @@ public void OnClientPostAdminCheck(int client)
|
|||||||
|
|
||||||
char sAuthID[32];
|
char sAuthID[32];
|
||||||
GetClientAuthId(client, AuthId_Steam2, sAuthID, sizeof(sAuthID), false);
|
GetClientAuthId(client, AuthId_Steam2, sAuthID, sizeof(sAuthID), false);
|
||||||
|
|
||||||
/*
|
|
||||||
if(!SteamClientAuthenticatedEx(sAuthID))
|
|
||||||
{
|
|
||||||
LogMessage("%L was not authenticated with steam, muting client.", client);
|
|
||||||
BaseComm_SetClientMute(client, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
// Purpose:
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
public Action CheckAuth(Handle timer, int data)
|
|
||||||
{
|
|
||||||
int client;
|
|
||||||
if ((client = GetClientFromSerial(data)) == 0)
|
|
||||||
return Plugin_Stop;
|
|
||||||
|
|
||||||
char sAuthID[32];
|
|
||||||
if(!GetClientAuthId(client, AuthId_Steam2, sAuthID, sizeof(sAuthID), true))
|
|
||||||
{
|
|
||||||
LogMessage("%L could not be assigned to a SteamID, kicking client.", client);
|
|
||||||
//KickClient(client, "Invalid STEAMID");
|
|
||||||
if (IsValidClient(client))
|
|
||||||
{
|
|
||||||
Panel hNotifyPanel = new Panel(GetMenuStyleHandle(MenuStyle_Radio));
|
|
||||||
hNotifyPanel.DrawItem("WARNING: Your SteamID is Invalid: Reconnecting you to the server in 8 Seconds.", ITEMDRAW_RAWLINE);
|
|
||||||
hNotifyPanel.DrawItem("", ITEMDRAW_SPACER);
|
|
||||||
hNotifyPanel.DrawItem("IMPORTANT: You may disconnect, reconnect if necessary!", ITEMDRAW_RAWLINE);
|
|
||||||
hNotifyPanel.Send(client, MenuHandler_NotifyPanel, 8);
|
|
||||||
delete hNotifyPanel;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
PrintToChat(client, "WARNING: Your SteamID is Invalid: Reconnecting you to the server in 8 Seconds.");
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateTimer(8.0, forceClientRetry, GetClientSerial(client));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Plugin_Stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action forceClientRetry(Handle timer, int data)
|
|
||||||
{
|
|
||||||
int client;
|
|
||||||
if ((client = GetClientFromSerial(data)) == 0)
|
|
||||||
return Plugin_Stop;
|
|
||||||
if (IsValidClient(client))
|
|
||||||
{
|
|
||||||
ClientCommand(client, "retry");
|
|
||||||
}
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stock bool IsValidClient(int client)
|
stock bool IsValidClient(int client)
|
||||||
@@ -398,16 +346,6 @@ stock bool IsValidClient(int client)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MenuHandler_NotifyPanel(Menu hMenu, MenuAction iAction, int iParam1, int iParam2)
|
|
||||||
{
|
|
||||||
switch (iAction)
|
|
||||||
{
|
|
||||||
case MenuAction_Select, MenuAction_Cancel:
|
|
||||||
delete hMenu;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -474,13 +412,12 @@ public void SQL_OnQueryCompleted(Database db, DBResultSet results, const char[]
|
|||||||
{
|
{
|
||||||
if(StrEqual(sAddress, sResultAddress, false))
|
if(StrEqual(sAddress, sResultAddress, false))
|
||||||
{
|
{
|
||||||
LogMessage("%L tried to join with a legitimate steamid while not authenticated with steam. Allowing connection, IPs match. (Known: %s)", client, sAddress);
|
LogMessage("%N tried to join with a legitimate steamid while not authenticated with steam. Allowing connection, IPs match. (Known: %s)", client, sAddress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogAction(client, -1, "\"%L\" tried to join with a legitimate steamid while not authenticated with steam. Refusing connection, IPs dont match. (Known: %s | Current: %s)", client, sResultAddress, sAddress);
|
LogMessage("%N tried to join with a legitimate steamid while not authenticated with steam. Refusing connection, IPs dont match. (Known: %s | Current: %s)", client, sResultAddress, sAddress);
|
||||||
static char sCountry[32];
|
|
||||||
KickClient(client, "Trying to join with a legitimate steamid while not authenticated with steam.");
|
KickClient(client, "Trying to join with a legitimate steamid while not authenticated with steam.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <sdktools>
|
#include <sdktools>
|
||||||
|
#include <sdkhooks>
|
||||||
|
|
||||||
public Plugin myinfo =
|
public Plugin myinfo =
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,17 @@ Menu g_NpcMenu = null;
|
|||||||
|
|
||||||
KeyValues g_Models;
|
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()
|
public void OnPluginStart()
|
||||||
{
|
{
|
||||||
@@ -42,6 +54,50 @@ public void OnPluginStart()
|
|||||||
g_Models.Rewind(); // Go back to the root node
|
g_Models.Rewind(); // Go back to the root node
|
||||||
|
|
||||||
RegAdminCmd("sm_propspawner", Command_MainMenu, ADMFLAG_CHANGEMAP); //g
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEntityDestroyed(int entity)
|
||||||
|
{
|
||||||
|
// Safety net: if a tracked prop is removed by any means other than DeleteProp()
|
||||||
|
// (e.g. an explosion, another plugin, map cleanup), stop tracking it here too.
|
||||||
|
if (entity <= 0 || g_aSpawnedProps == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int index = g_aSpawnedProps.FindValue(entity);
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
g_aSpawnedProps.Erase(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
|
||||||
|
{
|
||||||
|
UnhookAllSpawnedProps();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnhookAllSpawnedProps()
|
||||||
|
{
|
||||||
|
if (g_aSpawnedProps == null || !g_cvNotifyShot.BoolValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < g_aSpawnedProps.Length; i++)
|
||||||
|
{
|
||||||
|
int prop = g_aSpawnedProps.Get(i);
|
||||||
|
if (IsValidEntity(prop))
|
||||||
|
{
|
||||||
|
SDKUnhook(prop, SDKHook_OnTakeDamage, OnPropTakeDamage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_aSpawnedProps.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnMapStart()
|
public void OnMapStart()
|
||||||
@@ -82,6 +138,8 @@ public void OnMapEnd()
|
|||||||
delete(g_NpcMenu);
|
delete(g_NpcMenu);
|
||||||
g_NpcMenu = null;
|
g_NpcMenu = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnhookAllSpawnedProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------- */
|
/* ----------------------------------- */
|
||||||
@@ -177,6 +235,7 @@ public int MainMenuHandler(Menu menu, MenuAction action, int client, int param2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RotationHandler(Menu menu, MenuAction action, int client, int param2)
|
public RotationHandler(Menu menu, MenuAction action, int client, int param2)
|
||||||
@@ -320,6 +379,15 @@ void DeleteProp(int client){
|
|||||||
GetEdictClassname(DeleteIndex, classname, sizeof(classname));
|
GetEdictClassname(DeleteIndex, classname, sizeof(classname));
|
||||||
if(isAProp(classname))
|
if(isAProp(classname))
|
||||||
{
|
{
|
||||||
|
if (g_cvNotifyShot.BoolValue)
|
||||||
|
{
|
||||||
|
int propIndex = g_aSpawnedProps.FindValue(DeleteIndex);
|
||||||
|
if (propIndex != -1)
|
||||||
|
{
|
||||||
|
SDKUnhook(DeleteIndex, SDKHook_OnTakeDamage, OnPropTakeDamage);
|
||||||
|
g_aSpawnedProps.Erase(propIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
AcceptEntityInput(DeleteIndex, "Kill", -1, -1, 0);
|
AcceptEntityInput(DeleteIndex, "Kill", -1, -1, 0);
|
||||||
ShowActivity2(client, "\x01[SM] \x04", "deleted a prop.");
|
ShowActivity2(client, "\x01[SM] \x04", "deleted a prop.");
|
||||||
LogAction(client, -1, "\"%L\" deleted a prop.", client);
|
LogAction(client, -1, "\"%L\" deleted a prop.", client);
|
||||||
@@ -405,7 +473,7 @@ void prop_any_create(int client)
|
|||||||
char sModelExplodeRadius[11];
|
char sModelExplodeRadius[11];
|
||||||
int iModelExplode = g_Models.GetNum("explode",0); // if "explode" is not set, then it's 0
|
int iModelExplode = g_Models.GetNum("explode",0); // if "explode" is not set, then it's 0
|
||||||
|
|
||||||
g_Models.GetString("health", sModelHealth, sizeof(sModelHealth),"0"); // if "health" is not set, then it's 0
|
g_Models.GetString("health", sModelHealth, sizeof(sModelHealth),"0"); // if "health" is not set, then its 0
|
||||||
g_Models.GetString("explodedamage", sModelExplodeDamage, sizeof(sModelExplodeDamage),"1");
|
g_Models.GetString("explodedamage", sModelExplodeDamage, sizeof(sModelExplodeDamage),"1");
|
||||||
g_Models.GetString("exploderadius", sModelExplodeRadius, sizeof(sModelExplodeRadius),"1");
|
g_Models.GetString("exploderadius", sModelExplodeRadius, sizeof(sModelExplodeRadius),"1");
|
||||||
|
|
||||||
@@ -484,7 +552,108 @@ void prop_any_create(int client)
|
|||||||
DispatchSpawn(prop);
|
DispatchSpawn(prop);
|
||||||
AcceptEntityInput(prop, "TurnOn", prop, prop, 0);
|
AcceptEntityInput(prop, "TurnOn", prop, prop, 0);
|
||||||
AcceptEntityInput(prop, "EnableCollision");
|
AcceptEntityInput(prop, "EnableCollision");
|
||||||
|
|
||||||
|
// 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
|
||||||
|
SDKHook(prop, SDKHook_OnTakeDamage, OnPropTakeDamage);
|
||||||
|
g_aSpawnedProps.Push(prop);
|
||||||
|
}
|
||||||
|
|
||||||
ShowActivity2(client, "\x01[SM] \x04", "\x01Spawned \x04%s\x01.", sModelName);
|
ShowActivity2(client, "\x01[SM] \x04", "\x01Spawned \x04%s\x01.", sModelName);
|
||||||
LogAction(client, -1, "\"%L\" Spawned \"%s\".", client, sModelName);
|
LogAction(client, -1, "\"%L\" Spawned \"%s\".", client, sModelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
public Action OnPropTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom)
|
||||||
|
{
|
||||||
|
if (!g_cvNotifyShot.BoolValue)
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
if (attacker < 1 || attacker > MaxClients || !IsClientInGame(attacker))
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
buf.timer = timer;
|
||||||
|
g_aNotifyList.SetArray(idx, buf, sizeof(NotifyListData));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <sdkhooks>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <multicolors>
|
||||||
|
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
static const char entityList[][] = { "env_entity_igniter", "env_explosion", "env_fade", "env_fire", "env_hudhint", \
|
||||||
|
"env_physexplosion", "env_sprite", "env_sun", \
|
||||||
|
"func_breakable", "func_brush", "func_bomb_target", "func_button", "func_door", \
|
||||||
|
"func_dustmotes", "func_physbox_multiplayer", "info_overlay", "info_particle_system", \
|
||||||
|
"info_player_counterterrorist", "info_player_terrorist", "infodecal", \
|
||||||
|
"item_assaultsuit", "item_defuser", "item_kevlar", \
|
||||||
|
"light", "light_environment", "light_spot", "move_rope", "path_track", "planted_c4", \
|
||||||
|
"point_viewcontrol", "shadow_control", "vgui_screen", "func_tracktrain", "worldspawn", \
|
||||||
|
"func_tanktrain"};
|
||||||
|
|
||||||
|
bool bEnabled[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
int iDistance[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
float g_fClientOrigin[MAXPLAYERS + 1][3];
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
// Run the cache timer every 0.5 seconds globally
|
||||||
|
CreateTimer(0.5, Timer_CacheOrigins, _, TIMER_REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Timer_CacheOrigins(Handle timer)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i))
|
||||||
|
{
|
||||||
|
GetClientAbsOrigin(i, g_fClientOrigin[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "Render Distance Control",
|
||||||
|
author = "null138 & (ty ZombieFeyk), modified for webclient on unloze",
|
||||||
|
description = "Sets entities render distance and etc for players",
|
||||||
|
version = "3.0.5",
|
||||||
|
url = "https://steamcommunity.com/id/null138/"
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientAuthorized(int client, const char[] auth)
|
||||||
|
{
|
||||||
|
bEnabled[client] = false;
|
||||||
|
iDistance[client] = 800;
|
||||||
|
|
||||||
|
char sIP[32];
|
||||||
|
GetClientIP(client, sIP, sizeof(sIP));
|
||||||
|
|
||||||
|
char allowed_ips[128];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
sv_set_steam_id_ips.GetString(allowed_ips, sizeof(allowed_ips));
|
||||||
|
if (StrEqual(sIP, allowed_ips))
|
||||||
|
{
|
||||||
|
bEnabled[client] = true;
|
||||||
|
iDistance[client] = 1200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnEntityCreated(int entity, const char[] classname)
|
||||||
|
{
|
||||||
|
bool hook = false;
|
||||||
|
|
||||||
|
if (!strncmp(classname, "prop_", 5))
|
||||||
|
{
|
||||||
|
hook = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i; i < sizeof(entityList); i++)
|
||||||
|
{
|
||||||
|
if(!strcmp(classname, entityList[i]))
|
||||||
|
{
|
||||||
|
hook = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hook)
|
||||||
|
{
|
||||||
|
SDKHook(entity, SDKHook_SetTransmit, DoTransmit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action DoTransmit(int entity, int client)
|
||||||
|
{
|
||||||
|
if (IsFakeClient(client) || !bEnabled[client])
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
if (GetEdictFlags(entity) & FL_EDICT_ALWAYS)
|
||||||
|
SetEdictFlags(entity, GetEdictFlags(entity) ^ FL_EDICT_ALWAYS);
|
||||||
|
|
||||||
|
// Get Entity Origin
|
||||||
|
static float entVec[3];
|
||||||
|
if (HasEntProp(entity, Prop_Send, "m_vecOrigin"))
|
||||||
|
{
|
||||||
|
GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entVec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Plugin_Continue; // If it doesnt have an origin, let it render safely
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use GetVectorDistance with UseSquared=true (avoids an expensive Square Root calculation)
|
||||||
|
float maxDist = float(iDistance[client]);
|
||||||
|
float distanceSq = ((g_fClientOrigin[client][0] - entVec[0]) * (g_fClientOrigin[client][0] - entVec[0])) +
|
||||||
|
((g_fClientOrigin[client][1] - entVec[1]) * (g_fClientOrigin[client][1] - entVec[1])) +
|
||||||
|
((g_fClientOrigin[client][2] - entVec[2]) * (g_fClientOrigin[client][2] - entVec[2]));
|
||||||
|
|
||||||
|
if (distanceSq > (maxDist * maxDist))
|
||||||
|
{
|
||||||
|
return Plugin_Handled; // Out of range, hide it from the software renderer!
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
|||||||
|
#if defined _selfmute_included_
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _selfmute_included_
|
||||||
|
|
||||||
|
native bool SelfMute_IsIgnoring(int client, int target);
|
||||||
@@ -38,7 +38,7 @@ ConVar g_cvarUseProximityCheck = null;
|
|||||||
ConVar g_cvarSendSpraysToConnectingClients = null;
|
ConVar g_cvarSendSpraysToConnectingClients = null;
|
||||||
ConVar g_cvarUsePersistentSprays = null;
|
ConVar g_cvarUsePersistentSprays = null;
|
||||||
ConVar g_cvarMaxSprayLifetime = null;
|
ConVar g_cvarMaxSprayLifetime = null;
|
||||||
ConVar g_cvarHourRequirement = null;
|
ConVar g_cvarSprayTierRequired = null;
|
||||||
|
|
||||||
int g_iNSFWDecalIndex;
|
int g_iNSFWDecalIndex;
|
||||||
int g_iHiddenDecalIndex;
|
int g_iHiddenDecalIndex;
|
||||||
@@ -53,7 +53,6 @@ bool g_bGotBlacklist;
|
|||||||
bool g_bGotNSFWList;
|
bool g_bGotNSFWList;
|
||||||
bool g_bFullyConnected;
|
bool g_bFullyConnected;
|
||||||
bool g_bSkipDecalHook;
|
bool g_bSkipDecalHook;
|
||||||
bool g_bFullFillHourRequirement[MAXPLAYERS + 1] = {false,...};
|
|
||||||
|
|
||||||
char g_sBanIssuer[MAXPLAYERS + 1][64];
|
char g_sBanIssuer[MAXPLAYERS + 1][64];
|
||||||
char g_sBanIssuerSID[MAXPLAYERS + 1][32];
|
char g_sBanIssuerSID[MAXPLAYERS + 1][32];
|
||||||
@@ -61,8 +60,6 @@ char g_sBanReason[MAXPLAYERS + 1][32];
|
|||||||
char g_sSprayHash[MAXPLAYERS + 1][16];
|
char g_sSprayHash[MAXPLAYERS + 1][16];
|
||||||
char g_csSID[MAXPLAYERS + 1][65];
|
char g_csSID[MAXPLAYERS + 1][65];
|
||||||
|
|
||||||
int g_iClientHoursNotFullFilled[MAXPLAYERS + 1];
|
|
||||||
int g_iClientMinutesNotFullFilled[MAXPLAYERS + 1];
|
|
||||||
int g_iClientToClientSprayLifetime[MAXPLAYERS + 1][MAXPLAYERS + 1];
|
int g_iClientToClientSprayLifetime[MAXPLAYERS + 1][MAXPLAYERS + 1];
|
||||||
int g_iClientSprayLifetime[MAXPLAYERS + 1] = { 2, ... };
|
int g_iClientSprayLifetime[MAXPLAYERS + 1] = { 2, ... };
|
||||||
int g_iSprayLifetime[MAXPLAYERS + 1];
|
int g_iSprayLifetime[MAXPLAYERS + 1];
|
||||||
@@ -163,7 +160,7 @@ public void OnPluginStart()
|
|||||||
|
|
||||||
g_cvarMaxSprayLifetime = CreateConVar("sm_spraymanager_maxspraylifetime", "2", "If not using persistent sprays, remove sprays after their global lifetime (in rounds) exceeds this number");
|
g_cvarMaxSprayLifetime = CreateConVar("sm_spraymanager_maxspraylifetime", "2", "If not using persistent sprays, remove sprays after their global lifetime (in rounds) exceeds this number");
|
||||||
|
|
||||||
g_cvarHourRequirement = CreateConVar("sm_spraymanager_hour_requirement", "5", "Using the unloze play time plugin to set a minimum amount of hours for allowing players access to spraying.");
|
g_cvarSprayTierRequired = CreateConVar("sm_spraymanager_tier_required", "1", "Using the unloze play time plugin to set a minimum tier for allowing players access to spraying.");
|
||||||
|
|
||||||
AutoExecConfig(true, "plugin.SprayManager");
|
AutoExecConfig(true, "plugin.SprayManager");
|
||||||
|
|
||||||
@@ -339,13 +336,6 @@ public void OnClientPostAdminCheck(int client)
|
|||||||
UpdateHideSprays();
|
UpdateHideSprays();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetPlayerHoursServer(int client, int hours, int minutes)
|
|
||||||
{
|
|
||||||
g_iClientHoursNotFullFilled[client] = hours;
|
|
||||||
g_iClientMinutesNotFullFilled[client] = minutes;
|
|
||||||
g_bFullFillHourRequirement[client] = g_iClientHoursNotFullFilled[client] > g_cvarHourRequirement.IntValue ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update_client_online(int client, int is_online)
|
public void update_client_online(int client, int is_online)
|
||||||
{
|
{
|
||||||
if (!g_hDatabase)
|
if (!g_hDatabase)
|
||||||
@@ -2277,9 +2267,11 @@ public Action HookDecal(const char[] sTEName, const int[] iClients, int iNumClie
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check for an arbitrary amount of hours before allowing spraying
|
//check for an arbitrary amount of hours before allowing spraying
|
||||||
if (!g_bFullFillHourRequirement[client])
|
int clientTier = GetPlayerTier_native(client);
|
||||||
|
int TierRequired = g_cvarSprayTierRequired.IntValue;
|
||||||
|
if (TierRequired > clientTier)
|
||||||
{
|
{
|
||||||
PrintToChat(client, "\x01\x04[SprayManager]\x01 You cannot spray because you dont have enough play time yet. (You have \x04%i Hours and \x04%i minutes. You need \x04%i\x01 hours)", g_iClientHoursNotFullFilled[client], g_iClientMinutesNotFullFilled[client], g_cvarHourRequirement.IntValue);
|
PrintToChat(client, "\x01\x04[SprayManager]\x01 You cannot spray because you dont have reached tier %i yet. (You have tier \x04%i)", TierRequired, clientTier);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3329,9 +3321,6 @@ stock void ClearPlayerInfo(int client)
|
|||||||
g_SprayAABB[client] = view_as<float>({ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }); //???
|
g_SprayAABB[client] = view_as<float>({ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }); //???
|
||||||
g_bHasNSFWSpray[client] = false;
|
g_bHasNSFWSpray[client] = false;
|
||||||
g_bMarkedNSFWByAdmin[client] = false;
|
g_bMarkedNSFWByAdmin[client] = false;
|
||||||
g_bFullFillHourRequirement[client] = false;
|
|
||||||
g_iClientHoursNotFullFilled[client] = 0;
|
|
||||||
g_iClientMinutesNotFullFilled[client] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stock void UpdateClientToClientSprayLifeTime(int client, int iLifeTime)
|
stock void UpdateClientToClientSprayLifeTime(int client, int iLifeTime)
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
#include <sdktools>
|
#include <sdktools>
|
||||||
#include <multicolors>
|
#include <multicolors>
|
||||||
#include <zombiereloaded>
|
#include <zombiereloaded>
|
||||||
#include <loghelper>
|
|
||||||
|
|
||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
#pragma newdecls required
|
#pragma newdecls required
|
||||||
|
|
||||||
/* CONVARS */
|
/* CONVARS */
|
||||||
ConVar g_hCVar_Delay;
|
ConVar g_hCVar_Delay;
|
||||||
|
ConVar g_hCVar_KnifemadnessEnabled;
|
||||||
|
|
||||||
/* BOOLS */
|
/* BOOLS */
|
||||||
bool g_bClientKnifed[MAXPLAYERS+1];
|
bool g_bClientKnifed[MAXPLAYERS+1];
|
||||||
@@ -32,6 +32,9 @@ public Plugin myinfo =
|
|||||||
public void OnPluginStart()
|
public void OnPluginStart()
|
||||||
{
|
{
|
||||||
g_hCVar_Delay = CreateConVar("sm_knife_madness_kill_delay", "3", "Delay before ZMs die after being knifed by a human.", 0, true, 0.0);
|
g_hCVar_Delay = CreateConVar("sm_knife_madness_kill_delay", "3", "Delay before ZMs die after being knifed by a human.", 0, true, 0.0);
|
||||||
|
g_hCVar_KnifemadnessEnabled = CreateConVar("sm_knifemadness_enabled", "0", "", FCVAR_NONE, true, 0.0, true, 1.0);
|
||||||
|
g_hCVar_KnifemadnessEnabled.AddChangeHook(OnConVarChanged);
|
||||||
|
AutoExecConfig(true);
|
||||||
|
|
||||||
HookEvent("player_spawn", OnClientSpawn, EventHookMode_Post);
|
HookEvent("player_spawn", OnClientSpawn, EventHookMode_Post);
|
||||||
HookEvent("player_death", OnClientDeath, EventHookMode_Pre);
|
HookEvent("player_death", OnClientDeath, EventHookMode_Pre);
|
||||||
@@ -39,11 +42,23 @@ public void OnPluginStart()
|
|||||||
HookEvent("player_team", OnClientTeam, EventHookMode_Pre);
|
HookEvent("player_team", OnClientTeam, EventHookMode_Pre);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
if(g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
CPrintToChatAll("{cyan}[Knifemadness] {white}has been allowed.");
|
||||||
|
else
|
||||||
|
CPrintToChatAll("{cyan}[Knifemadness] {white}has been disabled.");
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnClientSpawn(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnClientSpawn(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
g_bClientKnifed[client] = false;
|
g_bClientKnifed[client] = false;
|
||||||
@@ -58,6 +73,10 @@ public void OnClientSpawn(Event hEvent, const char[] sEvent, bool bDontBroadcast
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public Action OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
if (g_bSupressDeath[client])
|
if (g_bSupressDeath[client])
|
||||||
@@ -74,6 +93,10 @@ public Action OnClientDeath(Event hEvent, const char[] sEvent, bool bDontBroadca
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int attacker = GetClientOfUserId(hEvent.GetInt("attacker"));
|
int attacker = GetClientOfUserId(hEvent.GetInt("attacker"));
|
||||||
int victim = GetClientOfUserId(hEvent.GetInt("userid"));
|
int victim = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
@@ -107,12 +130,16 @@ public void OnClientHurt(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnClientTeam(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
public void OnClientTeam(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
int client = GetClientOfUserId(hEvent.GetInt("userid"));
|
||||||
|
|
||||||
if (g_bClientKnifed[client])
|
if (g_bClientKnifed[client])
|
||||||
{
|
{
|
||||||
g_bClientKnifed[client] = false;
|
g_bClientKnifed[client] = false;
|
||||||
LogPlayerEvent(client, "triggered", "switch_to_spec");
|
//LogPlayerEvent(client, "triggered", "switch_to_spec");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +148,10 @@ public void OnClientTeam(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn)
|
public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!IsValidClient(attacker))
|
if (!IsValidClient(attacker))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -137,6 +168,10 @@ public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, boo
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public Action KillZM(Handle timer, DataPack pack)
|
public Action KillZM(Handle timer, DataPack pack)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
int attacker = 0;
|
int attacker = 0;
|
||||||
int client = 0;
|
int client = 0;
|
||||||
|
|
||||||
@@ -145,21 +180,21 @@ public Action KillZM(Handle timer, DataPack pack)
|
|||||||
client = GetClientOfUserId(pack.ReadCell());
|
client = GetClientOfUserId(pack.ReadCell());
|
||||||
|
|
||||||
if (client == 0)
|
if (client == 0)
|
||||||
return;
|
return Plugin_Continue;
|
||||||
|
|
||||||
if (!(IsValidClient(client, false) && IsPlayerAlive(client) && ZR_IsClientZombie(client) && g_bClientKnifed[client]))
|
if (!(IsValidClient(client, false) && IsPlayerAlive(client) && ZR_IsClientZombie(client) && g_bClientKnifed[client]))
|
||||||
return;
|
return Plugin_Continue;
|
||||||
|
|
||||||
g_bSupressDeath[client] = true;
|
g_bSupressDeath[client] = true;
|
||||||
ForcePlayerSuicide(client);
|
ForcePlayerSuicide(client);
|
||||||
g_bClientKnifed[client] = false;
|
g_bClientKnifed[client] = false;
|
||||||
|
|
||||||
if (!(IsValidClient(attacker, false)))
|
if (!(IsValidClient(attacker, false)))
|
||||||
return;
|
return Plugin_Continue;
|
||||||
|
|
||||||
Event hEvent = CreateEvent("player_death");
|
Event hEvent = CreateEvent("player_death");
|
||||||
if (hEvent == null)
|
if (hEvent == null)
|
||||||
return;
|
return Plugin_Continue;
|
||||||
|
|
||||||
hEvent.SetInt("userid", GetClientUserId(client));
|
hEvent.SetInt("userid", GetClientUserId(client));
|
||||||
hEvent.SetInt("attacker", GetClientUserId(attacker));
|
hEvent.SetInt("attacker", GetClientUserId(attacker));
|
||||||
@@ -168,6 +203,7 @@ public Action KillZM(Handle timer, DataPack pack)
|
|||||||
hEvent.SetInt("dominated", 0);
|
hEvent.SetInt("dominated", 0);
|
||||||
hEvent.SetInt("revenge", 0);
|
hEvent.SetInt("revenge", 0);
|
||||||
hEvent.Fire();
|
hEvent.Fire();
|
||||||
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -190,6 +226,10 @@ public void QueryClient(int client)
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void OnConVarQueryFinished(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, int iSerial)
|
public void OnConVarQueryFinished(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, int iSerial)
|
||||||
{
|
{
|
||||||
|
if(!g_hCVar_KnifemadnessEnabled.BoolValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (GetClientFromSerial(iSerial) != client)
|
if (GetClientFromSerial(iSerial) != client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -251,4 +291,4 @@ stock int IsValidClient(int client, bool nobots = true)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return IsClientInGame(client);
|
return IsClientInGame(client);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <sdkhooks>
|
#include <sdkhooks>
|
||||||
#include <sourcemod>
|
#include <sourcemod>
|
||||||
#include <zombiereloaded>
|
#include <zombiereloaded>
|
||||||
|
#include <unloze_playtime>
|
||||||
#include <TransmitManager>
|
#include <TransmitManager>
|
||||||
#include <leader>
|
#include <leader>
|
||||||
#include <entWatch_core>
|
#include <entWatch_core>
|
||||||
@@ -15,6 +16,7 @@ bool g_bHidePlayers[MAXPLAYERS + 1][MAXPLAYERS + 1];
|
|||||||
/* INTEGERS */
|
/* INTEGERS */
|
||||||
int g_iHideRange[MAXPLAYERS+1];
|
int g_iHideRange[MAXPLAYERS+1];
|
||||||
int g_iLeader = 0;
|
int g_iLeader = 0;
|
||||||
|
int g_iTierHide = 0;
|
||||||
|
|
||||||
/* HANDLES */
|
/* HANDLES */
|
||||||
Handle g_hTimer;
|
Handle g_hTimer;
|
||||||
@@ -72,6 +74,7 @@ public void OnPluginStart()
|
|||||||
}
|
}
|
||||||
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Hide");
|
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Hide");
|
||||||
g_hTimer = CreateTimer(1.0, UpdateHide, INVALID_HANDLE, TIMER_REPEAT);
|
g_hTimer = CreateTimer(1.0, UpdateHide, INVALID_HANDLE, TIMER_REPEAT);
|
||||||
|
g_iTierHide = FindTierForCommandOverride("sm_hide");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPluginEnd()
|
public void OnPluginEnd()
|
||||||
@@ -316,11 +319,85 @@ public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int se
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stock int FindTierForCommandOverride(const char[] command)
|
||||||
|
{
|
||||||
|
char sPath[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/admin_groups.cfg");
|
||||||
|
|
||||||
|
KeyValues kv = new KeyValues("Groups");
|
||||||
|
if (!kv.ImportFromFile(sPath))
|
||||||
|
{
|
||||||
|
delete kv;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect tier group names first
|
||||||
|
char groupNames[32][64];
|
||||||
|
int groupCount = 0;
|
||||||
|
|
||||||
|
if (kv.GotoFirstSubKey())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char sName[64];
|
||||||
|
kv.GetSectionName(sName, sizeof(sName));
|
||||||
|
if (StrContains(sName, "tier", false) == 0)
|
||||||
|
{
|
||||||
|
strcopy(groupNames[groupCount], 64, sName);
|
||||||
|
groupCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (kv.GotoNextKey() && groupCount < 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
int foundTier = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < groupCount; i++)
|
||||||
|
{
|
||||||
|
kv.Rewind();
|
||||||
|
|
||||||
|
if (!kv.JumpToKey(groupNames[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!kv.JumpToKey("Overrides"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!kv.GotoFirstSubKey(false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char overrideCmd[64];
|
||||||
|
kv.GetSectionName(overrideCmd, sizeof(overrideCmd));
|
||||||
|
|
||||||
|
if (StrEqual(overrideCmd, command, false))
|
||||||
|
{
|
||||||
|
char tierStr[8];
|
||||||
|
strcopy(tierStr, sizeof(tierStr), groupNames[i][4]); // skip "tier"
|
||||||
|
foundTier = StringToInt(tierStr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (kv.GotoNextKey(false));
|
||||||
|
|
||||||
|
if (foundTier != -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete kv;
|
||||||
|
return foundTier;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
|
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
|
||||||
{
|
{
|
||||||
|
int client_tier = GetPlayerTier_native(client);
|
||||||
|
if (g_iTierHide > client_tier)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch(action)
|
switch(action)
|
||||||
{
|
{
|
||||||
case(CookieMenuAction_DisplayOption):
|
case(CookieMenuAction_DisplayOption):
|
||||||
|
|||||||
@@ -2718,7 +2718,7 @@ public Action Event_PlayerSay(Handle event, const char[] name, bool dontBroadcas
|
|||||||
{
|
{
|
||||||
if (IsClientInGame(client) && GetClientTeam(client) == team)
|
if (IsClientInGame(client) && GetClientTeam(client) == team)
|
||||||
{
|
{
|
||||||
if(!g_Ignored[client * (MAXPLAYERS + 1) + g_msgAuthor] /*&& MessageForward(client, g_msgAuthor, g_msgText)*/ )
|
if(!g_Ignored[client * (MAXPLAYERS + 1) + g_msgAuthor] && MessageForward(client, g_msgAuthor, g_msgText) )
|
||||||
players[playersNum++] = client;
|
players[playersNum++] = client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2729,7 +2729,7 @@ public Action Event_PlayerSay(Handle event, const char[] name, bool dontBroadcas
|
|||||||
{
|
{
|
||||||
if (IsClientInGame(client))
|
if (IsClientInGame(client))
|
||||||
{
|
{
|
||||||
if(!g_Ignored[client * (MAXPLAYERS + 1) + g_msgAuthor] /* && MessageForward(client, g_msgAuthor, g_msgText)*/ )
|
if(!g_Ignored[client * (MAXPLAYERS + 1) + g_msgAuthor] && MessageForward(client, g_msgAuthor, g_msgText) )
|
||||||
players[playersNum++] = client;
|
players[playersNum++] = client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
//2026: add playtime requirements for being unrestricted
|
//2026: add playtime requirements for being unrestricted
|
||||||
#include <unloze_playtime>
|
#include <unloze_playtime>
|
||||||
|
|
||||||
|
Database g_hDatabase;
|
||||||
|
|
||||||
/* FORWARDS */
|
/* FORWARDS */
|
||||||
Handle g_hFwd_OnClientRestricted;
|
Handle g_hFwd_OnClientRestricted;
|
||||||
@@ -35,7 +36,8 @@ Handle g_hCookie_RestrictLength_minutes;
|
|||||||
|
|
||||||
/* BOOLEANS */
|
/* BOOLEANS */
|
||||||
bool g_bRestrictedTemp[MAXPLAYERS+1];
|
bool g_bRestrictedTemp[MAXPLAYERS+1];
|
||||||
bool g_bDontSpamMsg[MAXPLAYERS+1]
|
bool g_bDontSpamMsg[MAXPLAYERS+1];
|
||||||
|
bool g_bActiveEban[MAXPLAYERS+1];
|
||||||
|
|
||||||
/* INTERGERS */
|
/* INTERGERS */
|
||||||
int g_iRestrictIssued[MAXPLAYERS+1];
|
int g_iRestrictIssued[MAXPLAYERS+1];
|
||||||
@@ -54,7 +56,7 @@ int g_iClientMinutes[MAXPLAYERS + 1];
|
|||||||
StringMap g_hTrie_Storage;
|
StringMap g_hTrie_Storage;
|
||||||
|
|
||||||
/* CONVARS */
|
/* CONVARS */
|
||||||
ConVar g_cvarHourRequirement = null;
|
ConVar g_cvarItemTierRequirement = null;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
@@ -118,7 +120,46 @@ public void OnPluginStart()
|
|||||||
OnClientCookiesCached(client);
|
OnClientCookiesCached(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_cvarHourRequirement = CreateConVar("sm_entwatch_hour_requirement", "10", "Using the unloze play time plugin to set a minimum amount of hours for allowing players access to items.");
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_entwatch_web");
|
||||||
|
}
|
||||||
|
CreateTimer(5.0, CheckIfEntwatchBanExpired, _, TIMER_REPEAT);
|
||||||
|
|
||||||
|
g_cvarItemTierRequirement = CreateConVar("sm_entwatch_tier_requirement", "1", "Using the unloze play time plugin to set a tier for allowing players access to items.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//could probably fail at detecting when a client finally gets entwatch unbanned but risk is pretty small as they need the ingame playtime to accomplish it.
|
||||||
|
public Action CheckIfEntwatchBanExpired(Handle timer)
|
||||||
|
{
|
||||||
|
for (int client = 1; client <= MaxClients; client++)
|
||||||
|
{
|
||||||
|
if (Client_IsValid(client) && IsClientInGame(client))
|
||||||
|
{
|
||||||
|
//we only need to check for bans with durations. temporary and permanent bans dont need to be updated as expired obviusly
|
||||||
|
if (g_iRestrictIssued[client] && g_iRestrictExpire[client] >= g_iClientHours[client] && g_iClientHours[client] > 0) //assuring playtime is set for client
|
||||||
|
{
|
||||||
|
//example: client restricted until 1335 hours and currently has 1320
|
||||||
|
if (g_iRestrictExpire[client] > g_iClientHours[client])
|
||||||
|
{
|
||||||
|
g_bActiveEban[client] = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//example client restricted until 1335 hours and 45 minutes. currently has 1335 hours and 20 minutes.
|
||||||
|
if (g_iRestrictExpire_minutes[client] > g_iClientMinutes[client])
|
||||||
|
{
|
||||||
|
g_bActiveEban[client] = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (g_bActiveEban[client])
|
||||||
|
{
|
||||||
|
g_bActiveEban[client] = false;
|
||||||
|
update_entwatchban_mysql_is_expired(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -127,6 +168,20 @@ public void OnPluginStart()
|
|||||||
public void OnMapStart()
|
public void OnMapStart()
|
||||||
{
|
{
|
||||||
g_hTrie_Storage.Clear();
|
g_hTrie_Storage.Clear();
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_entwatch_web");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if(!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Database error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hDatabase = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
@@ -138,6 +193,7 @@ public void OnClientPutInServer(int client)
|
|||||||
GetClientIP(client, sAddress, sizeof(sAddress));
|
GetClientIP(client, sAddress, sizeof(sAddress));
|
||||||
|
|
||||||
g_bDontSpamMsg[client] = false;
|
g_bDontSpamMsg[client] = false;
|
||||||
|
g_bActiveEban[client] = false;
|
||||||
bool bRestrictedTemp;
|
bool bRestrictedTemp;
|
||||||
if (g_hTrie_Storage.GetValue(sAddress, bRestrictedTemp))
|
if (g_hTrie_Storage.GetValue(sAddress, bRestrictedTemp))
|
||||||
{
|
{
|
||||||
@@ -175,6 +231,7 @@ public void OnClientDisconnect(int client)
|
|||||||
|
|
||||||
g_bDontSpamMsg[client] = false;
|
g_bDontSpamMsg[client] = false;
|
||||||
g_bRestrictedTemp[client] = false;
|
g_bRestrictedTemp[client] = false;
|
||||||
|
g_bActiveEban[client] = false;
|
||||||
|
|
||||||
g_iRestrictIssued[client] = 0;
|
g_iRestrictIssued[client] = 0;
|
||||||
g_iRestrictIssued_minutes[client] = 0;
|
g_iRestrictIssued_minutes[client] = 0;
|
||||||
@@ -232,6 +289,7 @@ public Action Command_ClientRestrict(int client, int args)
|
|||||||
CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s restricted \x07%s%N\x07%s permanently.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767");
|
CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s restricted \x07%s%N\x07%s permanently.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767");
|
||||||
LogAction(client, target, "%L restricted %L permanently.", client, target);
|
LogAction(client, target, "%L restricted %L permanently.", client, target);
|
||||||
}
|
}
|
||||||
|
insert_entwatchban_mysql(client, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -289,7 +347,8 @@ public Action Command_DisplayRestrictions(int client, int args)
|
|||||||
{
|
{
|
||||||
if (ClientRestricted(i))
|
if (ClientRestricted(i))
|
||||||
{
|
{
|
||||||
if (g_iClientHours[i] < g_cvarHourRequirement.IntValue)
|
int client_tier = GetPlayerTier_native(i);
|
||||||
|
if (client_tier < g_cvarItemTierRequirement.IntValue)
|
||||||
{
|
{
|
||||||
GetClientName(i, aBuf2_time_requirement, sizeof(aBuf2_time_requirement));
|
GetClientName(i, aBuf2_time_requirement, sizeof(aBuf2_time_requirement));
|
||||||
StrCat(aBuf_time_requirement, sizeof(aBuf_time_requirement), aBuf2_time_requirement);
|
StrCat(aBuf_time_requirement, sizeof(aBuf_time_requirement), aBuf2_time_requirement);
|
||||||
@@ -316,10 +375,10 @@ public Action Command_DisplayRestrictions(int client, int args)
|
|||||||
if (strlen(aBuf_time_requirement))
|
if (strlen(aBuf_time_requirement))
|
||||||
{
|
{
|
||||||
aBuf_time_requirement[strlen(aBuf_time_requirement) - 2] = 0;
|
aBuf_time_requirement[strlen(aBuf_time_requirement) - 2] = 0;
|
||||||
CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrent clients with not enough playtime: \x07%s%s", "E01B5D", "F16767", "EDEDED", aBuf_time_requirement);
|
CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrent clients with not high enough Tier: \x07%s%s", "E01B5D", "F16767", "EDEDED", aBuf_time_requirement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrent clients with not enough playtime: \x07%snone", "E01B5D", "F16767", "EDEDED");
|
CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrent clients with not high enough Tier: \x07%snone", "E01B5D", "F16767", "EDEDED");
|
||||||
|
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
@@ -473,6 +532,7 @@ stock bool ClientRestrict(int client, int target, int length)
|
|||||||
g_iRestrictIssued[target] = g_iClientHours[target];
|
g_iRestrictIssued[target] = g_iClientHours[target];
|
||||||
g_iRestrictExpire[target] = 0;
|
g_iRestrictExpire[target] = 0;
|
||||||
g_iRestrictLength[target] = 0;
|
g_iRestrictLength[target] = 0;
|
||||||
|
g_iRestrictLength_minutes[target] = 0;
|
||||||
|
|
||||||
SetClientCookieInt(target, g_hCookie_RestrictIssued, GetTime());
|
SetClientCookieInt(target, g_hCookie_RestrictIssued, GetTime());
|
||||||
SetClientCookieInt(target, g_hCookie_RestrictExpire, 0);
|
SetClientCookieInt(target, g_hCookie_RestrictExpire, 0);
|
||||||
@@ -558,6 +618,8 @@ stock bool ClientUnrestrict(int client, int target)
|
|||||||
|
|
||||||
SetClientCookieInt(target, g_hCookie_RestrictLength, 0);
|
SetClientCookieInt(target, g_hCookie_RestrictLength, 0);
|
||||||
SetClientCookieInt(target, g_hCookie_RestrictLength_minutes, 0);
|
SetClientCookieInt(target, g_hCookie_RestrictLength_minutes, 0);
|
||||||
|
|
||||||
|
update_entwatchban_mysql_is_expired(target);
|
||||||
|
|
||||||
Call_StartForward(g_hFwd_OnClientUnrestricted);
|
Call_StartForward(g_hFwd_OnClientUnrestricted);
|
||||||
Call_PushCell(client);
|
Call_PushCell(client);
|
||||||
@@ -602,12 +664,13 @@ stock bool ClientRestricted(int client)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//hour requirement for picking up items
|
//tier requirement for picking up items
|
||||||
if (g_iClientHours[client] < g_cvarHourRequirement.IntValue)
|
int client_tier = GetPlayerTier_native(client);
|
||||||
|
if (client_tier < g_cvarItemTierRequirement.IntValue)
|
||||||
{
|
{
|
||||||
if (!g_bDontSpamMsg[client])
|
if (!g_bDontSpamMsg[client])
|
||||||
{
|
{
|
||||||
CPrintToChat(client, "\x07%s[entWatch] \x07%s You have \x07%s%i\x07%s hours and \x07%s%i\x07%s minutes playtime and need %i hours for picking up items.", "E01B5D", "EDEDED", "EDEDED", g_iClientHours[client], "EDEDED", "EDEDED", g_iClientMinutes[client], "EDEDED", g_cvarHourRequirement.IntValue);
|
CPrintToChat(client, "\x07%s[entWatch] \x07%s You need to reach Tier \x07%s%i\x07%s for picking up items.", "E01B5D", "EDEDED", "EDEDED", g_cvarItemTierRequirement.IntValue, "EDEDED");
|
||||||
g_bDontSpamMsg[client] = true;
|
g_bDontSpamMsg[client] = true;
|
||||||
CreateTimer(1.0, allow_message_again, GetClientSerial(client));
|
CreateTimer(1.0, allow_message_again, GetClientSerial(client));
|
||||||
}
|
}
|
||||||
@@ -672,6 +735,53 @@ public void GetPlayerHoursServer(int client, int hours, int minutes)
|
|||||||
g_iClientMinutes[client] = minutes;
|
g_iClientMinutes[client] = minutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void update_entwatchban_mysql_is_expired(int entwatch_banned_player)
|
||||||
|
{
|
||||||
|
char sSIDClient[64];
|
||||||
|
GetClientAuthId(entwatch_banned_player, AuthId_Steam2, sSIDClient, sizeof(sSIDClient));
|
||||||
|
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "update `EntWatch_Current_Eban` set is_expired = 1 where client_steamid = '%s' and is_expired = 0", sSIDClient);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert_entwatchban_mysql(int admin, int entwatch_banned_player)
|
||||||
|
{
|
||||||
|
char sNameAdmin[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(admin, sNameAdmin, sizeof(sNameAdmin));
|
||||||
|
int size2 = 2 * strlen(sNameAdmin) + 1;
|
||||||
|
char[] sEscapedNameAdmin = new char[size2 + 1];
|
||||||
|
g_hDatabase.Escape(sNameAdmin, sEscapedNameAdmin, size2 + 1);
|
||||||
|
char sSIDAdmin[64];
|
||||||
|
GetClientAuthId(admin, AuthId_Steam2, sSIDAdmin, sizeof(sSIDAdmin));
|
||||||
|
|
||||||
|
|
||||||
|
char sNameClient[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(entwatch_banned_player, sNameClient, sizeof(sNameClient));
|
||||||
|
size2 = 2 * strlen(sNameClient) + 1;
|
||||||
|
char[] sEscapedNameClient = new char[size2 + 1];
|
||||||
|
g_hDatabase.Escape(sNameClient, sEscapedNameClient, size2 + 1);
|
||||||
|
char sSIDClient[64];
|
||||||
|
GetClientAuthId(entwatch_banned_player, AuthId_Steam2, sSIDClient, sizeof(sSIDClient));
|
||||||
|
|
||||||
|
int playtime_start_client = (g_iRestrictIssued[entwatch_banned_player] * 60) + g_iRestrictIssued_minutes[entwatch_banned_player];
|
||||||
|
int playtime_end_client = (g_iRestrictExpire[entwatch_banned_player] * 60) + g_iRestrictExpire_minutes[entwatch_banned_player];
|
||||||
|
|
||||||
|
int length = (g_iRestrictLength[entwatch_banned_player] * 60) + g_iRestrictLength_minutes[entwatch_banned_player];
|
||||||
|
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "INSERT INTO `EntWatch_Current_Eban` (`client_name`, `client_steamid`, `admin_name`, `admin_steamid`, `duration`, `reason`, `time_played_start`, `time_played_end`) VALUES ('%s', '%s', '%s', '%s', '%i', '%s', '%i', '%i')", sEscapedNameClient, sSIDClient, sEscapedNameAdmin, sSIDAdmin, length, "get fucked", playtime_start_client, playtime_end_client);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error 3: %s", error);
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
//====================================================================================================
|
||||||
|
//
|
||||||
|
// Name: [entWatch] UseAnywhere
|
||||||
|
// Author: marisakirisame.net
|
||||||
|
// Description: Allow the owner of an item to activate it with their USE key anywhere
|
||||||
|
//
|
||||||
|
//====================================================================================================
|
||||||
|
#include <multicolors>
|
||||||
|
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <sdkhooks>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <entWatch_core>
|
||||||
|
#include <entWatch_helpers>
|
||||||
|
|
||||||
|
/* BOOLS */
|
||||||
|
bool g_bDisabled[MAXPLAYERS+1];
|
||||||
|
|
||||||
|
/* COOKIES */
|
||||||
|
Handle g_hCookie_Disabled;
|
||||||
|
|
||||||
|
/* INTEGERS */
|
||||||
|
int g_iLastButtons[MAXPLAYERS+1];
|
||||||
|
int g_iActivateTick[MAXPLAYERS+1];
|
||||||
|
int g_iActivateButton[MAXPLAYERS+1];
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "[entWatch] UseAnywhere",
|
||||||
|
author = "marisakirisame.net",
|
||||||
|
description = "Allow the owner of an item to activate it with their USE key anywhere",
|
||||||
|
version = "4.0.0"
|
||||||
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
g_hCookie_Disabled = RegClientCookie("EW_UseAnywhereDisabled", "", CookieAccess_Private);
|
||||||
|
|
||||||
|
RegConsoleCmd("sm_euseanywhere", Command_ToggleUseAnywhere);
|
||||||
|
|
||||||
|
for (int client = 1; client <= MaxClients; client++)
|
||||||
|
{
|
||||||
|
if (!IsClientInGame(client) || IsFakeClient(client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
OnClientPutInServer(client);
|
||||||
|
|
||||||
|
if (AreClientCookiesCached(client))
|
||||||
|
OnClientCookiesCached(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnClientPutInServer(int client)
|
||||||
|
{
|
||||||
|
g_bDisabled[client] = false;
|
||||||
|
g_iLastButtons[client] = 0;
|
||||||
|
g_iActivateTick[client] = 0;
|
||||||
|
g_iActivateButton[client] = INVALID_ENT_REFERENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public void OnClientCookiesCached(int client)
|
||||||
|
{
|
||||||
|
g_bDisabled[client] = GetClientCookieBool(client, g_hCookie_Disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Action Command_ToggleUseAnywhere(int client, int args)
|
||||||
|
{
|
||||||
|
if (!Client_IsValid(client))
|
||||||
|
return Plugin_Handled;
|
||||||
|
|
||||||
|
g_bDisabled[client] = !g_bDisabled[client];
|
||||||
|
|
||||||
|
if (g_bDisabled[client])
|
||||||
|
{
|
||||||
|
SetClientCookieBool(client, g_hCookie_Disabled, true);
|
||||||
|
|
||||||
|
CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou will now have to aim at the item's trigger to use it.", "E01B5D", "F16767");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetClientCookieBool(client, g_hCookie_Disabled, false);
|
||||||
|
|
||||||
|
CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou can now use your item by pressing your USE key anywhere.", "E01B5D", "F16767");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: Activate the clients item on +use, without having to aim at its button.
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Action OnPlayerRunCmd(int client, int &buttons)
|
||||||
|
{
|
||||||
|
bool bPressed = view_as<bool>((buttons & IN_USE) && !(g_iLastButtons[client] & IN_USE));
|
||||||
|
|
||||||
|
g_iLastButtons[client] = buttons;
|
||||||
|
|
||||||
|
if (!bPressed || g_bDisabled[client] || !IsPlayerAlive(client))
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
int button = FindClientItemButton(client);
|
||||||
|
|
||||||
|
if (button == INVALID_ENT_REFERENCE)
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
// Fires the buttons Use input, which runs the core's SDKHook_Use handler as if the
|
||||||
|
// client had aimed at it, so every cooldown, restriction and message is handled there.
|
||||||
|
AcceptEntityInput(button, "Use", client, client);
|
||||||
|
|
||||||
|
// Set after the input, so the press above is not blocked by its own guard.
|
||||||
|
g_iActivateTick[client] = GetGameTickCount();
|
||||||
|
g_iActivateButton[client] = button;
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: Ignore the engines own +use if we already fired this button for the client this tick,
|
||||||
|
// so aiming at the button while pressing USE cannot activate the item twice.
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
public Action EW_OnClientItemCanActivate(int client, int index)
|
||||||
|
{
|
||||||
|
if (g_iActivateTick[client] != GetGameTickCount())
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
CItem item = EW_GetItemData(index);
|
||||||
|
|
||||||
|
if (item.bButton && item.iButton == g_iActivateButton[client])
|
||||||
|
return Plugin_Handled;
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose: Get the button of the clients item, but only if they carry exactly one.
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
stock int FindClientItemButton(int client)
|
||||||
|
{
|
||||||
|
int iFound = -1;
|
||||||
|
|
||||||
|
for (int index; index < EW_GetItemCount(); index++)
|
||||||
|
{
|
||||||
|
CItem item = EW_GetItemData(index);
|
||||||
|
|
||||||
|
if (!(item.bClient && item.iClient == client))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (iFound != -1)
|
||||||
|
return INVALID_ENT_REFERENCE;
|
||||||
|
|
||||||
|
iFound = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iFound != -1)
|
||||||
|
{
|
||||||
|
CItem itemFound = EW_GetItemData(iFound);
|
||||||
|
|
||||||
|
if (itemFound.bButton && Entity_IsValid(itemFound.iButton))
|
||||||
|
return itemFound.iButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INVALID_ENT_REFERENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
stock void SetClientCookieBool(int client, Handle hCookie, bool value)
|
||||||
|
{
|
||||||
|
char sValue[32];
|
||||||
|
IntToString(view_as<int>(value), sValue, sizeof(sValue));
|
||||||
|
|
||||||
|
SetClientCookie(client, hCookie, sValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
stock bool GetClientCookieBool(int client, Handle hCookie)
|
||||||
|
{
|
||||||
|
char sValue[32];
|
||||||
|
GetClientCookie(client, hCookie, sValue, sizeof(sValue));
|
||||||
|
|
||||||
|
return view_as<bool>(StringToInt(sValue));
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
-- entwatchban_web.EntWatch_Current_Eban definition
|
||||||
|
|
||||||
|
CREATE TABLE `EntWatch_Current_Eban` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`client_name` varchar(32) NOT NULL,
|
||||||
|
`client_steamid` varchar(64) NOT NULL,
|
||||||
|
`admin_name` varchar(32) NOT NULL,
|
||||||
|
`admin_steamid` varchar(64) NOT NULL,
|
||||||
|
`duration` int(10) unsigned NOT NULL,
|
||||||
|
`time_stamp_start` datetime DEFAULT current_timestamp(),
|
||||||
|
`reason` varchar(64) DEFAULT NULL,
|
||||||
|
`reason_unban` varchar(64) DEFAULT NULL,
|
||||||
|
`admin_name_unban` varchar(32) DEFAULT NULL,
|
||||||
|
`admin_steamid_unban` varchar(64) DEFAULT NULL,
|
||||||
|
`timestamp_unban` int(11) DEFAULT NULL,
|
||||||
|
`time_played_start` int(11) NOT NULL DEFAULT -1,
|
||||||
|
`time_played_end` int(11) NOT NULL DEFAULT -1,
|
||||||
|
`is_expired` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_steamid_search` (`client_steamid`,`admin_steamid`),
|
||||||
|
KEY `idx_expiry_sort` (`time_stamp_start`,`duration`),
|
||||||
|
KEY `idx_server_expiry` (`duration`,`time_stamp_start`),
|
||||||
|
KEY `idx_is_expired` (`is_expired`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
|
|
||||||
|
-- entwatchban_web.web_logs definition
|
||||||
|
|
||||||
|
CREATE TABLE `web_logs` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`message` varchar(255) NOT NULL,
|
||||||
|
`admin_name` varchar(32) NOT NULL,
|
||||||
|
`admin_steamid` varchar(64) NOT NULL,
|
||||||
|
`client_name` varchar(32) NOT NULL,
|
||||||
|
`client_steamid` varchar(64) NOT NULL,
|
||||||
|
`time_stamp` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
"Games"
|
||||||
|
{
|
||||||
|
"cstrike"
|
||||||
|
{
|
||||||
|
"Signatures"
|
||||||
|
{
|
||||||
|
"CBasePlayer::InputSetFogController"
|
||||||
|
{
|
||||||
|
"library" "server"
|
||||||
|
"windows" "\x55\x8B\xEC\x56\x8B\xF1\x8B\x4D\x08\x83\xC1\x08\x83\x79\x10\x02\x75\x2A\x8B\x01\xBA\x2A\x2A\x2A\x2A\x85\xC0\x0F\x45\xD0\xEB\x2A\xE8\x2A\x2A\x2A\x2A\x8B\xD0\x6A\x00"
|
||||||
|
"linux" "@_ZN11CBasePlayer21InputSetFogControllerER11inputdata_t"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Functions"
|
||||||
|
{
|
||||||
|
"CBasePlayer::InputSetFogController"
|
||||||
|
{
|
||||||
|
"signature" "CBasePlayer::InputSetFogController"
|
||||||
|
"callconv" "thiscall"
|
||||||
|
"return" "void"
|
||||||
|
"this" "entity"
|
||||||
|
"arguments"
|
||||||
|
{
|
||||||
|
"inputdata"
|
||||||
|
{
|
||||||
|
"type" "objectptr"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
#include <sourcemod>
|
||||||
|
#include <sdktools>
|
||||||
|
#include <dhooks>
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "Render Distance Limiter",
|
||||||
|
author = "Dysphie, repurposed for unloze webclient using some AI",
|
||||||
|
description = "",
|
||||||
|
version = "",
|
||||||
|
url = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
int g_iClientFogEntity[MAXPLAYERS + 1] = { INVALID_ENT_REFERENCE, ... };
|
||||||
|
float g_OverrideDist[MAXPLAYERS + 1] = { -1.0, ... };
|
||||||
|
bool bEnabled[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
float g_fClientEstimatedFPS[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
// New tracking arrays for your global variables section
|
||||||
|
float g_fLastStableDist[MAXPLAYERS + 1] = { -1.0, ... };
|
||||||
|
float g_fDistCooldown[MAXPLAYERS + 1] = { 0.0, ... };
|
||||||
|
|
||||||
|
int g_iLastCmdNum[MAXPLAYERS + 1];
|
||||||
|
float g_fFPSIntervalStart[MAXPLAYERS + 1];
|
||||||
|
int g_iCmdsInInterval[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
SetupDetours();
|
||||||
|
CreateTimer(0.5, Timer_printFPS, _, TIMER_REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ai generated
|
||||||
|
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 (IsFakeClient(client) || !bEnabled[client])
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
// Check if this is a brand new user command execution frame
|
||||||
|
if (cmdnum != g_iLastCmdNum[client])
|
||||||
|
{
|
||||||
|
g_iLastCmdNum[client] = cmdnum;
|
||||||
|
g_iCmdsInInterval[client]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
float fCurrentTime = GetEngineTime();
|
||||||
|
float fTimeElapsed = fCurrentTime - g_fFPSIntervalStart[client];
|
||||||
|
|
||||||
|
// Evaluate the true input frequency every 0.5 seconds
|
||||||
|
if (fTimeElapsed >= 0.5)
|
||||||
|
{
|
||||||
|
if (g_fFPSIntervalStart[client] > 0.0)
|
||||||
|
{
|
||||||
|
// Raw calculated input framerate based on sequential command progression
|
||||||
|
float fCalculatedFPS = float(g_iCmdsInInterval[client]) / fTimeElapsed;
|
||||||
|
|
||||||
|
// FAST-DROP BYPASS: If the client just lost more than 25% of their frame rate instantly
|
||||||
|
// skip the dampening math and force the estimation down immediately.
|
||||||
|
if (fCalculatedFPS < (g_fClientEstimatedFPS[client] * 0.75))
|
||||||
|
{
|
||||||
|
g_fClientEstimatedFPS[client] = fCalculatedFPS; // Hard-drop the value
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Smoothly recover/climb when frame rates are stable or increasing
|
||||||
|
g_fClientEstimatedFPS[client] = (g_fClientEstimatedFPS[client] * 0.8) + (fCalculatedFPS * 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset interval buckets
|
||||||
|
g_fFPSIntervalStart[client] = fCurrentTime;
|
||||||
|
g_iCmdsInInterval[client] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ai generated
|
||||||
|
public Action Timer_printFPS(Handle timer)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i) && bEnabled[i])
|
||||||
|
{
|
||||||
|
float fCurrentFPS = g_fClientEstimatedFPS[i] - 4.0;
|
||||||
|
float currentDist = g_OverrideDist[i];
|
||||||
|
float targetDist = currentDist;
|
||||||
|
|
||||||
|
// 1. HARD CRASH: FPS has tanked down to unplayable levels.
|
||||||
|
if (fCurrentFPS <= 25.0)
|
||||||
|
{
|
||||||
|
// If we have a cached, proven stable distance, use it immediately!
|
||||||
|
if (g_fLastStableDist[i] != -1.0 && g_fLastStableDist[i] < currentDist)
|
||||||
|
{
|
||||||
|
targetDist = g_fLastStableDist[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Emergency fallback steps if we dont have a cached history yet
|
||||||
|
if (currentDist == -1.0 || currentDist > 1200.0)
|
||||||
|
{
|
||||||
|
targetDist = 1200.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetDist = 600.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Penalize the cooldown heavily because we just choked on rendering
|
||||||
|
g_fDistCooldown[i] = GetEngineTime() + 15.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. WARNING ZONE: Framerate is beginning to dip
|
||||||
|
else if (fCurrentFPS <= 38.0)
|
||||||
|
{
|
||||||
|
if (currentDist == -1.0 || currentDist > 2000.0)
|
||||||
|
{
|
||||||
|
targetDist = 2000.0;
|
||||||
|
g_fDistCooldown[i] = GetEngineTime() + 10.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. RECOVERY ZONE: Performance is solid. Lets see if we can open up the view.
|
||||||
|
else if (fCurrentFPS >= 48.0)
|
||||||
|
{
|
||||||
|
if (currentDist != -1.0)
|
||||||
|
{
|
||||||
|
// Since the game is running flawlessly at this specific distance,
|
||||||
|
// we update our safety cache to remember this specific float.
|
||||||
|
g_fLastStableDist[i] = currentDist;
|
||||||
|
|
||||||
|
// Only venture out if our time barrier has expired
|
||||||
|
if (GetEngineTime() >= g_fDistCooldown[i])
|
||||||
|
{
|
||||||
|
if (currentDist == 600.0) targetDist = 1200.0;
|
||||||
|
else if (currentDist == 1200.0) targetDist = 2000.0;
|
||||||
|
else if (currentDist == 2000.0) targetDist = 4000.0;
|
||||||
|
else if (currentDist == 4000.0) targetDist = -1.0;
|
||||||
|
|
||||||
|
// Give the client a test window to sample the new distance
|
||||||
|
g_fDistCooldown[i] = GetEngineTime() + 8.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the client is running fine at infinite distance (-1.0),
|
||||||
|
// clear the history out so we can recalculate from a clean slate later
|
||||||
|
g_fLastStableDist[i] = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetDist != currentDist)
|
||||||
|
{
|
||||||
|
ApplyFogValues(i, targetDist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyFogValues(int client, float dist)
|
||||||
|
{
|
||||||
|
g_OverrideDist[client] = dist;
|
||||||
|
int fog = EntRefToEntIndex(g_iClientFogEntity[client]);
|
||||||
|
|
||||||
|
// Create the persistent entity once if it vanished or hasnt been created yet
|
||||||
|
if (fog == -1 || !IsValidEntity(fog))
|
||||||
|
{
|
||||||
|
fog = CreateEntityByName("env_fog_controller");
|
||||||
|
if (fog != -1)
|
||||||
|
{
|
||||||
|
DispatchSpawn(fog);
|
||||||
|
g_iClientFogEntity[client] = EntIndexToEntRef(fog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fog != -1 && IsValidEntity(fog))
|
||||||
|
{
|
||||||
|
if (dist == -1.0)
|
||||||
|
{
|
||||||
|
// Back to map defaults safely
|
||||||
|
SetEntProp(fog, Prop_Send, "m_fog.enable", 0);
|
||||||
|
SetEntPropFloat(fog, Prop_Send, "m_fog.farz", 0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Apply strict culling boundaries explicitly
|
||||||
|
SetEntProp(fog, Prop_Send, "m_fog.enable", 1);
|
||||||
|
SetEntPropFloat(fog, Prop_Send, "m_fog.farz", dist);
|
||||||
|
SetEntPropFloat(fog, Prop_Send, "m_fog.end", dist);
|
||||||
|
SetEntPropFloat(fog, Prop_Send, "m_fog.maxdensity", 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the entity assigned cleanly inside data tables
|
||||||
|
SetFogController(client, fog);
|
||||||
|
|
||||||
|
// Single fire state changes to replicate out smoothly
|
||||||
|
ChangeEdictState(client, FindSendPropInfo("CBasePlayer", "m_hCtrl"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(int client)
|
||||||
|
{
|
||||||
|
// Clean up entity allocation to prevent lingering map errors
|
||||||
|
int fog = EntRefToEntIndex(g_iClientFogEntity[client]);
|
||||||
|
if (fog != -1 && IsValidEntity(fog))
|
||||||
|
{
|
||||||
|
RemoveEntity(fog);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_iClientFogEntity[client] = INVALID_ENT_REFERENCE;
|
||||||
|
g_OverrideDist[client] = -1.0;
|
||||||
|
bEnabled[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupDetours()
|
||||||
|
{
|
||||||
|
GameData gamedata = new GameData("player-fog.games");
|
||||||
|
if (!gamedata) {
|
||||||
|
SetFailState("Missing gamedata file");
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicDetour detour = DynamicDetour.FromConf(gamedata, "CBasePlayer::InputSetFogController");
|
||||||
|
if (!detour)
|
||||||
|
SetFailState("Failed to find signature CBasePlayer::InputSetFogController");
|
||||||
|
detour.Enable(Hook_Pre, Detour_InputSetFogController);
|
||||||
|
delete detour;
|
||||||
|
}
|
||||||
|
|
||||||
|
MRESReturn Detour_InputSetFogController(int client, DHookParam params)
|
||||||
|
{
|
||||||
|
RequestFrame(Frame_FogControllerChanged, GetClientSerial(client));
|
||||||
|
return MRES_Ignored;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FogControllerChanged(int client)
|
||||||
|
{
|
||||||
|
if (g_OverrideDist[client] != -1.0) {
|
||||||
|
ApplyFogValues(client, g_OverrideDist[client]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Frame_FogControllerChanged(int clientSerial)
|
||||||
|
{
|
||||||
|
int client = GetClientFromSerial(clientSerial);
|
||||||
|
if (client && IsClientInGame(client))
|
||||||
|
{
|
||||||
|
FogControllerChanged(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientAuthorized(int client, const char[] auth)
|
||||||
|
{
|
||||||
|
bEnabled[client] = false;
|
||||||
|
g_OverrideDist[client] = -1.0;
|
||||||
|
g_iClientFogEntity[client] = INVALID_ENT_REFERENCE;
|
||||||
|
|
||||||
|
char sIP[32];
|
||||||
|
GetClientIP(client, sIP, sizeof(sIP));
|
||||||
|
|
||||||
|
char allowed_ips[128];
|
||||||
|
ConVar sv_set_steam_id_ips = FindConVar("sv_set_steam_id_ips");
|
||||||
|
if (sv_set_steam_id_ips != null)
|
||||||
|
{
|
||||||
|
sv_set_steam_id_ips.GetString(allowed_ips, sizeof(allowed_ips));
|
||||||
|
if (StrEqual(sIP, allowed_ips))
|
||||||
|
{
|
||||||
|
bEnabled[client] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFogController(int client, int fog)
|
||||||
|
{
|
||||||
|
SetEntPropEnt(client, Prop_Data, "m_hCtrl", fog);
|
||||||
|
}
|
||||||
@@ -78,6 +78,11 @@ forward void OnMapVoteStart();
|
|||||||
*/
|
*/
|
||||||
forward void OnMapVoteEnd(const char[] map);
|
forward void OnMapVoteEnd(const char[] map);
|
||||||
|
|
||||||
|
/**
|
||||||
|
just send the steamID, vote choice and voteweight of the client as a forward
|
||||||
|
**/
|
||||||
|
|
||||||
|
forward void OnMapVoteClientResult(char[] steamID, char[] vote_choice, int voteweight);
|
||||||
/**
|
/**
|
||||||
* Is a map on the current game's official list?
|
* Is a map on the current game's official list?
|
||||||
* This should be treated as informative only.
|
* This should be treated as informative only.
|
||||||
@@ -85,6 +90,7 @@ forward void OnMapVoteEnd(const char[] map);
|
|||||||
* @param map Name of map to check
|
* @param map Name of map to check
|
||||||
* @return true if it's on the list of official maps for this game
|
* @return true if it's on the list of official maps for this game
|
||||||
*/
|
*/
|
||||||
|
|
||||||
native bool IsMapOfficial(const char[] map);
|
native bool IsMapOfficial(const char[] map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,13 +114,22 @@ native CanNominateResult CanNominate();
|
|||||||
native bool ExcludeMap(const char[] map, int cooldown = 0, int mode = 0);
|
native bool ExcludeMap(const char[] map, int cooldown = 0, int mode = 0);
|
||||||
// Cooldown in seconds
|
// Cooldown in seconds
|
||||||
native bool ExcludeMapTime(const char[] map, int cooldown = 0, int mode = 0);
|
native bool ExcludeMapTime(const char[] map, int cooldown = 0, int mode = 0);
|
||||||
|
// cooldown based on mysql table rows listing
|
||||||
|
native bool ExcludeMapListingPriority(const char[] map, int index);
|
||||||
|
|
||||||
native int GetMapCooldown(const char[] map);
|
native int GetMapCooldown(const char[] map);
|
||||||
native int GetMapCooldownTime(const char[] map); // in unix time
|
native int GetMapCooldownTime(const char[] map); // in unix time
|
||||||
|
native int GetMapCooldownTime2(const char[] map); // in unix time
|
||||||
|
native int GetMapLowPopHelpCount(const char[] map);
|
||||||
|
native int GetMapLaserFag(const char[] map);
|
||||||
|
native int GetMapTrails(const char[] map);
|
||||||
|
native int GetMapTickRate(const char[] map);
|
||||||
native int GetMapMinTime(const char[] map);
|
native int GetMapMinTime(const char[] map);
|
||||||
native int GetMapMaxTime(const char[] map);
|
native int GetMapMaxTime(const char[] map);
|
||||||
native int GetMapMinPlayers(const char[] map);
|
native int GetMapMinPlayers(const char[] map);
|
||||||
native int GetMapMaxPlayers(const char[] map);
|
native int GetMapMaxPlayers(const char[] map);
|
||||||
|
native int GetMapMinHoursAvg(const char[] map);
|
||||||
|
native int GetExcludedMapListingPriority(const char[] map);
|
||||||
|
|
||||||
// 0 = Okay
|
// 0 = Okay
|
||||||
// >0 = Minutes till Okay
|
// >0 = Minutes till Okay
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#define PLUGIN_AUTHOR "jenz"
|
||||||
|
#define PLUGIN_VERSION "1.0"
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <cstrike>
|
||||||
|
#include <mapchooser_extended>
|
||||||
|
|
||||||
|
int g_iPlayerCount_time_track;
|
||||||
|
int g_iTopMapsToMarkWithCooldown;
|
||||||
|
int g_iUnmarkCooldowns;
|
||||||
|
int g_iCurrentPlayerCount;
|
||||||
|
int g_iMapStartTime;
|
||||||
|
Database g_hDatabase;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "map_tracker_cooldown",
|
||||||
|
author = PLUGIN_AUTHOR,
|
||||||
|
description = "assigns cooldowns on maps and tracks their played time on the server",
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = "www.unloze.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
}
|
||||||
|
|
||||||
|
ConVar cvar;
|
||||||
|
HookConVarChange((cvar = CreateConVar("mce_min_players_track_time", "20", "Playercount in full number required for tracking minutes spend on a map.")), Cvar_playersCount);
|
||||||
|
g_iPlayerCount_time_track = cvar.IntValue;
|
||||||
|
delete cvar;
|
||||||
|
|
||||||
|
ConVar cvar1;
|
||||||
|
HookConVarChange((cvar1 = CreateConVar("mce_top_ordered_maps_on_cooldown", "30", "These highest listed maps will receive the cooldown boolean")), Cvar_TopMarkedWithCooldown);
|
||||||
|
g_iTopMapsToMarkWithCooldown = cvar1.IntValue;
|
||||||
|
delete cvar1;
|
||||||
|
|
||||||
|
ConVar cvar2;
|
||||||
|
HookConVarChange((cvar2 = CreateConVar("mce_UnmarkCooldowns", "120", "How far down the list does a map need to be for getting unmarked again")), Cvar_UnmarkedCooldown);
|
||||||
|
g_iUnmarkCooldowns = cvar2.IntValue;
|
||||||
|
delete cvar2;
|
||||||
|
|
||||||
|
g_iCurrentPlayerCount = GetClientCount(false);
|
||||||
|
CreateTimer(30.0, CheckPlayerCount, _, TIMER_REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CheckPlayerCount(Handle timer)
|
||||||
|
{
|
||||||
|
g_iCurrentPlayerCount = GetClientCount(false);
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_playersCount(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iPlayerCount_time_track = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_TopMarkedWithCooldown(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iTopMapsToMarkWithCooldown = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_UnmarkedCooldown(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iUnmarkCooldowns = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if(!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Database error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hDatabase = db;
|
||||||
|
UpdateTopListedMapsWithCooldown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
int i_port = GetConVarInt(FindConVar("hostport"));
|
||||||
|
if (i_port != 27019 && i_port != 27015)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_iMapStartTime = GetTime();
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateTopListedMapsWithCooldown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateTopListedMapsWithCooldown()
|
||||||
|
{
|
||||||
|
//just set every map in top g_iTopMapsToMarkWithCooldown on cooldown
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "update unloze_playtimestats.map_minutes_played set on_cooldown = true where mapname in ( SELECT mapname FROM (select mmp.mapname from unloze_playtimestats.map_minutes_played mmp order by mmp.minutes desc limit %i) as top) and on_cooldown is false", g_iTopMapsToMarkWithCooldown);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery1, sQuery, _, DBPrio_High);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuery1(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error: %s", error);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
UpdateUnmarkCooldown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateUnmarkCooldown()
|
||||||
|
{
|
||||||
|
//if map in listing fell below g_iUnmarkCooldowns then set the bool to false again.
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "update unloze_playtimestats.map_minutes_played set on_cooldown = false where mapname not in ( SELECT mapname FROM (select mmp.mapname from unloze_playtimestats.map_minutes_played mmp order by mmp.minutes desc limit %i) as top) and on_cooldown is true", g_iUnmarkCooldowns);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery2, sQuery, _, DBPrio_High);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuery2(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error: %s", error);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
SelectMapsToCooldownForMapChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectMapsToCooldownForMapChooser()
|
||||||
|
{
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "select mapname, map_list_index from (select mapname, ROW_NUMBER() OVER(ORDER BY minutes DESC) as map_list_index, mmp.on_cooldown from unloze_playtimestats.map_minutes_played mmp) as targets where on_cooldown");
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuerySelectMaps, sQuery, _, DBPrio_High);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuerySelectMaps(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error in SQL_FinishedQuerySelectMaps: %s", error);
|
||||||
|
delete results;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (results.RowCount && results.FetchRow())
|
||||||
|
{
|
||||||
|
char mapname[256];
|
||||||
|
results.FetchString(0, mapname, sizeof(mapname));
|
||||||
|
int map_list_index = results.FetchInt(1);
|
||||||
|
ExcludeMapListingPriority(mapname, g_iUnmarkCooldowns - map_list_index);
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapEnd()
|
||||||
|
{
|
||||||
|
int i_port = GetConVarInt(FindConVar("hostport"));
|
||||||
|
if (i_port != 27019 && i_port != 27015)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int elapsed = GetTime() - g_iMapStartTime;
|
||||||
|
int minutes = RoundToFloor(elapsed / 60.0);
|
||||||
|
|
||||||
|
char Mapname[128];
|
||||||
|
GetCurrentMap(Mapname, sizeof(Mapname));
|
||||||
|
//LogMessage("minutes: %i. map: %s", minutes, Mapname);
|
||||||
|
|
||||||
|
if (g_iCurrentPlayerCount > g_iPlayerCount_time_track)
|
||||||
|
{
|
||||||
|
char sQuery[512];
|
||||||
|
Format(sQuery, sizeof(sQuery), "INSERT INTO `map_minutes_played` (`mapname`, `minutes`, `updated_on`) VALUES ('%s', '%i', NOW()) ON DUPLICATE KEY UPDATE `minutes` = `minutes` + '%i', `updated_on` = NOW()", Mapname, minutes, minutes);
|
||||||
|
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Query error: %s", error);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+423
-395
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,9 @@ Handle g_Cvar_VIPTimeframe = INVALID_HANDLE;
|
|||||||
Handle g_Cvar_VIPTimeframeMinTime = INVALID_HANDLE;
|
Handle g_Cvar_VIPTimeframeMinTime = INVALID_HANDLE;
|
||||||
Handle g_Cvar_VIPTimeframeMaxTime = INVALID_HANDLE;
|
Handle g_Cvar_VIPTimeframeMaxTime = INVALID_HANDLE;
|
||||||
|
|
||||||
|
KeyValues g_Config;
|
||||||
|
|
||||||
|
|
||||||
int g_Player_NominationDelay[MAXPLAYERS+1];
|
int g_Player_NominationDelay[MAXPLAYERS+1];
|
||||||
int g_NominationDelay;
|
int g_NominationDelay;
|
||||||
|
|
||||||
@@ -127,6 +130,26 @@ public void OnMapStart()
|
|||||||
//we have too many dbs so i am just re-using racetimercss
|
//we have too many dbs so i am just re-using racetimercss
|
||||||
Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
|
Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_Config)
|
||||||
|
delete g_Config;
|
||||||
|
|
||||||
|
char sConfigFile[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/mapchooser_extended.cfg");
|
||||||
|
if(!FileExists(sConfigFile))
|
||||||
|
{
|
||||||
|
LogMessage("Could not find config: \"%s\"", sConfigFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_Config = new KeyValues("mapchooser_extended");
|
||||||
|
if(!g_Config.ImportFromFile(sConfigFile))
|
||||||
|
{
|
||||||
|
delete g_Config;
|
||||||
|
LogMessage("ImportFromFile() failed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_Config.Rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||||
@@ -327,47 +350,6 @@ public Action Command_Addmap(int client, int args)
|
|||||||
AttemptAdminNominate(client, mapname);
|
AttemptAdminNominate(client, mapname);
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
int Cooldown1 = GetMapCooldownTime(mapname);
|
|
||||||
if(Cooldown1 > GetTime())
|
|
||||||
{
|
|
||||||
int Seconds = Cooldown1 - GetTime();
|
|
||||||
CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60);
|
|
||||||
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) )
|
|
||||||
{
|
|
||||||
bool RestrictionsActive = AreRestrictionsActive();
|
|
||||||
|
|
||||||
int TimeRestriction = GetMapTimeRestriction(mapname);
|
|
||||||
if(RestrictionsActive && TimeRestriction)
|
|
||||||
{
|
|
||||||
CPrintToChat(client, "[NE] %t", "Map Nominate Time Error", TimeRestriction / 60, TimeRestriction % 60);
|
|
||||||
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(mapname);
|
|
||||||
if (RestrictionsActive && AverageHourRestricted > 0)
|
|
||||||
{
|
|
||||||
PrintToChat(client, "%s requires +%i hours average. Use sm_houravg to check average.", mapname, AverageHourRestricted);
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PlayerRestriction = GetMapPlayerRestriction(mapname);
|
|
||||||
if(RestrictionsActive && PlayerRestriction)
|
|
||||||
{
|
|
||||||
if(PlayerRestriction < 0)
|
|
||||||
CPrintToChat(client, "[NE] %t", "Map Nominate MinPlayers Error", PlayerRestriction * -1);
|
|
||||||
else
|
|
||||||
CPrintToChat(client, "[NE] %t", "Map Nominate MaxPlayers Error", PlayerRestriction);
|
|
||||||
|
|
||||||
return Plugin_Handled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NominateResult result = NominateMap(mapname, true, 0);
|
NominateResult result = NominateMap(mapname, true, 0);
|
||||||
|
|
||||||
@@ -570,12 +552,11 @@ public Action Command_Nominate(int client, int args)
|
|||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Cooldown1 = GetMapCooldownTime(mapname);
|
//yeah admins and leaders cant bypass these restrictions, maybe the admins really are the problem sometimes for skipping restrictions.
|
||||||
if(Cooldown1 > GetTime())
|
int Index_Cooldown = GetExcludedMapListingPriority(mapname);
|
||||||
|
if (Index_Cooldown > 0)
|
||||||
{
|
{
|
||||||
int Seconds = Cooldown1 - GetTime();
|
CPrintToChat(client, "[NE] Map is on Cooldown for being overplayed. List Posistion: %i", Index_Cooldown);
|
||||||
CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60);
|
|
||||||
|
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,6 +564,17 @@ public Action Command_Nominate(int client, int args)
|
|||||||
if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(client))
|
if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(client))
|
||||||
{
|
{
|
||||||
bool RestrictionsActive = AreRestrictionsActive();
|
bool RestrictionsActive = AreRestrictionsActive();
|
||||||
|
|
||||||
|
//restrictions not being active now also skips all the cooldowns.
|
||||||
|
int Cooldown1 = GetMapCooldownTime(mapname);
|
||||||
|
if(RestrictionsActive && Cooldown1 > GetTime())
|
||||||
|
{
|
||||||
|
int Seconds = Cooldown1 - GetTime();
|
||||||
|
CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60);
|
||||||
|
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
bool VIPRestriction = GetMapVIPRestriction(mapname, client);
|
bool VIPRestriction = GetMapVIPRestriction(mapname, client);
|
||||||
if(RestrictionsActive && VIPRestriction)
|
if(RestrictionsActive && VIPRestriction)
|
||||||
{
|
{
|
||||||
@@ -731,26 +723,45 @@ public int Handler_NominateListMenu(Menu menu, MenuAction action, int param1, in
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNominateMenuTitle(Menu menu, int client)
|
||||||
|
{
|
||||||
|
int nominate_worth = GetPlayerWorthRTV_boost_(client);
|
||||||
|
if (Leader_Is(client))
|
||||||
|
SetMenuTitle(menu, "Nominate Map: (%i Nomination Boost Leader)", 999);
|
||||||
|
else
|
||||||
|
SetMenuTitle(menu, "Nominate Map: (%i Nomination Boost)", nominate_worth);
|
||||||
|
}
|
||||||
|
|
||||||
void AttemptNominate(int client, const char[] filter = "")
|
void AttemptNominate(int client, const char[] filter = "")
|
||||||
{
|
{
|
||||||
if(!client)
|
if(!client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Menu menu = g_MapMenu;
|
Menu menu = g_MapMenu;
|
||||||
menu = BuildMapMenu(filter, client);
|
if (filter[0])
|
||||||
|
|
||||||
int nominate_worth = GetPlayerWorthRTV_boost_(client);
|
|
||||||
if (Leader_Is(client))
|
|
||||||
{
|
{
|
||||||
SetMenuTitle(menu, "Nominate Map: (%i Nomination Boost Leader)", 999);
|
// preserves the existing behavior for the "map wasnt found, try a substring search" fallback
|
||||||
|
menu = BuildMapMenu(filter, client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetMenuTitle(menu, "Nominate Map: (%i Nomination Boost)", nominate_worth);
|
menu = BuildCategoryMenu(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetNominateMenuTitle(menu, client);
|
||||||
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
DisplayMenu(menu, client, MENU_TIME_FOREVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AttemptAdminNominate(int client, const char[] filter = "")
|
void AttemptAdminNominate(int client, const char[] filter = "")
|
||||||
{
|
{
|
||||||
if(!client)
|
if(!client)
|
||||||
@@ -817,6 +828,7 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "")
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringMap sm = new StringMap();
|
StringMap sm = new StringMap();
|
||||||
|
StringMap sm_special_noms = new StringMap(); //storing leaders and admin noms.
|
||||||
static char map[PLATFORM_MAX_PATH];
|
static char map[PLATFORM_MAX_PATH];
|
||||||
static char display[PLATFORM_MAX_PATH];
|
static char display[PLATFORM_MAX_PATH];
|
||||||
for(int i = 0; i < GetArraySize(MapList); i++)
|
for(int i = 0; i < GetArraySize(MapList); i++)
|
||||||
@@ -833,11 +845,12 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "")
|
|||||||
if (!owner || Leader_Is(owner))
|
if (!owner || Leader_Is(owner))
|
||||||
{
|
{
|
||||||
nominate_count_for_particular_map = 1999;
|
nominate_count_for_particular_map = 1999;
|
||||||
|
sm_special_noms.SetValue(map, owner); //admin noms and leaders are unique per each map, so cant be overwritten.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int nominate_worth = GetPlayerWorthRTV_boost_(owner);
|
int nominate_worth = GetPlayerWorthRTV_boost_(owner);
|
||||||
//atm everybody just has equal voting again, so this is just += 1
|
//2026 march: the boosting can now range from 1 to 2. so for most its +=1 and for a few +=2.
|
||||||
nominate_count_for_particular_map += nominate_worth;
|
nominate_count_for_particular_map += nominate_worth;
|
||||||
}
|
}
|
||||||
sm.SetValue(map, nominate_count_for_particular_map, true);
|
sm.SetValue(map, nominate_count_for_particular_map, true);
|
||||||
@@ -863,24 +876,26 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "")
|
|||||||
{
|
{
|
||||||
int nominate_count_for_particular_map = 0;
|
int nominate_count_for_particular_map = 0;
|
||||||
sm.GetValue(map, nominate_count_for_particular_map);
|
sm.GetValue(map, nominate_count_for_particular_map);
|
||||||
|
|
||||||
|
int leader_or_admin_map_owner = -1;
|
||||||
|
sm_special_noms.GetValue(map, leader_or_admin_map_owner);
|
||||||
strcopy(display, sizeof(display), map);
|
strcopy(display, sizeof(display), map);
|
||||||
|
|
||||||
bool VIPRestriction = GetMapVIPRestriction(map);
|
bool VIPRestriction = GetMapVIPRestriction(map);
|
||||||
if((VIPRestriction) && AreRestrictionsActive())
|
if((VIPRestriction) && AreRestrictionsActive())
|
||||||
Format(display, sizeof(display), "%s (%T)", display, "VIP Nomination", client);
|
Format(display, sizeof(display), "%s (%T)", display, "VIP Nomination", client);
|
||||||
|
|
||||||
int owner = GetArrayCell(OwnerList, i);
|
|
||||||
char spelling[8];
|
char spelling[8];
|
||||||
|
|
||||||
Format(spelling, sizeof(spelling), nominate_count_for_particular_map == 1 ? "Vote" : "Votes");
|
Format(spelling, sizeof(spelling), nominate_count_for_particular_map == 1 ? "Vote" : "Votes");
|
||||||
|
if (leader_or_admin_map_owner != -1)
|
||||||
if(!owner)
|
{
|
||||||
Format(display, sizeof(display), "%s (Admin)", display);
|
if(!leader_or_admin_map_owner)
|
||||||
else if (Leader_Is(owner))
|
Format(display, sizeof(display), "%s (Admin)", display);
|
||||||
Format(display, sizeof(display), "%s (Leader)", display);
|
else
|
||||||
|
Format(display, sizeof(display), "%s (Leader)", display);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Format(display, sizeof(display), "%s (%i %s)", display, nominate_count_for_particular_map, spelling);
|
Format(display, sizeof(display), "%s (%i %s)", display, nominate_count_for_particular_map, spelling);
|
||||||
|
|
||||||
AddMenuItem(menu, map, display);
|
AddMenuItem(menu, map, display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -889,15 +904,87 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "")
|
|||||||
delete OwnerList;
|
delete OwnerList;
|
||||||
delete SortedList;
|
delete SortedList;
|
||||||
delete sm;
|
delete sm;
|
||||||
|
delete sm_special_noms;
|
||||||
delete sm_snapshot;
|
delete sm_snapshot;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu BuildMapMenu(const char[] filter, int client)
|
Menu BuildCategoryMenu(int client)
|
||||||
|
{
|
||||||
|
Menu menu = CreateMenu(Handler_CategorySelectMenu, MENU_ACTIONS_DEFAULT);
|
||||||
|
|
||||||
|
//2023 edit to allow hiding/unhiding unavailable maps
|
||||||
|
char hiding_unavailable_maps[MAX_NAME_LENGTH];
|
||||||
|
if (g_bClientsIgnoring[client])
|
||||||
|
Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Show all unavailable maps");
|
||||||
|
else
|
||||||
|
Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Hide all unavailable maps");
|
||||||
|
AddMenuItem(menu, hiding_unavailable_maps, hiding_unavailable_maps);
|
||||||
|
|
||||||
|
ArrayList categories = CreateArray(ByteCountToCells(64));
|
||||||
|
static char map[PLATFORM_MAX_PATH];
|
||||||
|
static char category[64];
|
||||||
|
|
||||||
|
for (int i = 0; i < GetArraySize(g_MapList); i++)
|
||||||
|
{
|
||||||
|
GetArrayString(g_MapList, i, map, sizeof(map));
|
||||||
|
GetMapCategory(map, category, sizeof(category));
|
||||||
|
|
||||||
|
if (FindStringInArray(categories, category) == -1)
|
||||||
|
PushArrayString(categories, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
SortADTArray(categories, Sort_Ascending, Sort_String);
|
||||||
|
|
||||||
|
for (int i = 0; i < GetArraySize(categories); i++)
|
||||||
|
{
|
||||||
|
GetArrayString(categories, i, category, sizeof(category));
|
||||||
|
AddMenuItem(menu, category, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddMenuItem(menu, "Full Map list", "Full Map list");
|
||||||
|
delete categories;
|
||||||
|
|
||||||
|
SetMenuExitButton(menu, true);
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Handler_CategorySelectMenu(Menu menu, MenuAction action, int param1, int param2)
|
||||||
|
{
|
||||||
|
switch(action)
|
||||||
|
{
|
||||||
|
case MenuAction_End:
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
case MenuAction_Select:
|
||||||
|
{
|
||||||
|
static char item[64];
|
||||||
|
GetMenuItem(menu, param2, item, sizeof(item));
|
||||||
|
|
||||||
|
if (StrEqual(item, "Hide all unavailable maps") || StrEqual(item, "Show all unavailable maps"))
|
||||||
|
{
|
||||||
|
sql_insert_update_hiding_unavailable(param1);
|
||||||
|
Menu refreshed = BuildCategoryMenu(param1);
|
||||||
|
SetNominateMenuTitle(refreshed, param1);
|
||||||
|
DisplayMenu(refreshed, param1, MENU_TIME_FOREVER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu submenu = BuildMapMenu("", param1, item);
|
||||||
|
SetNominateMenuTitle(submenu, param1);
|
||||||
|
DisplayMenu(submenu, param1, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu BuildMapMenu(const char[] filter, int client, const char[] category = "")
|
||||||
{
|
{
|
||||||
Menu menu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem);
|
Menu menu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem);
|
||||||
|
|
||||||
static char map[PLATFORM_MAX_PATH * 2];
|
static char map[PLATFORM_MAX_PATH * 2];
|
||||||
|
static char mapCategory[64];
|
||||||
|
|
||||||
int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
|
int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
|
||||||
ArrayList MapList = CreateArray(arraySize);
|
ArrayList MapList = CreateArray(arraySize);
|
||||||
@@ -935,22 +1022,19 @@ Menu BuildMapMenu(const char[] filter, int client)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//2023 edit to allow hiding/unhiding unavailable maps
|
|
||||||
char hiding_unavailable_maps[MAX_NAME_LENGTH];
|
|
||||||
if (g_bClientsIgnoring[client])
|
|
||||||
{
|
|
||||||
Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Show all unavailable maps");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Hide all unavailable maps");
|
|
||||||
}
|
|
||||||
AddMenuItem(menu, hiding_unavailable_maps, hiding_unavailable_maps);
|
|
||||||
|
|
||||||
for(int i = 0; i < GetArraySize(g_MapList); i++)
|
for(int i = 0; i < GetArraySize(g_MapList); i++)
|
||||||
{
|
{
|
||||||
GetArrayString(g_MapList, i, map, sizeof(map));
|
GetArrayString(g_MapList, i, map, sizeof(map));
|
||||||
|
|
||||||
|
if (category[0] && !StrEqual(category, "Full Map list"))
|
||||||
|
{
|
||||||
|
//only shows maps that are in this actual category.
|
||||||
|
GetMapCategory(map, mapCategory, sizeof(mapCategory));
|
||||||
|
if (!StrEqual(mapCategory, category))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!filter[0] || StrContains(map, filter, false) != -1)
|
if(!filter[0] || StrContains(map, filter, false) != -1)
|
||||||
{
|
{
|
||||||
if (client != 0 && nominated_maps)
|
if (client != 0 && nominated_maps)
|
||||||
@@ -973,11 +1057,9 @@ Menu BuildMapMenu(const char[] filter, int client)
|
|||||||
}
|
}
|
||||||
if (g_bClientsIgnoring[client])
|
if (g_bClientsIgnoring[client])
|
||||||
{
|
{
|
||||||
if (GetMapCooldownTime(map) > GetTime())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(AreRestrictionsActive() && (
|
if(AreRestrictionsActive() && (
|
||||||
|
GetMapCooldownTime(map) > GetTime() ||
|
||||||
|
GetExcludedMapListingPriority(map) > 0 ||
|
||||||
GetMapTimeRestriction(map) ||
|
GetMapTimeRestriction(map) ||
|
||||||
GetMapPlayerRestriction(map) ||
|
GetMapPlayerRestriction(map) ||
|
||||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||||
@@ -994,7 +1076,10 @@ Menu BuildMapMenu(const char[] filter, int client)
|
|||||||
delete OwnerList;
|
delete OwnerList;
|
||||||
delete sm;
|
delete sm;
|
||||||
|
|
||||||
SetMenuExitButton(menu, true);
|
if (category[0])
|
||||||
|
SetMenuExitBackButton(menu, true);
|
||||||
|
else
|
||||||
|
SetMenuExitButton(menu, true);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
@@ -1041,6 +1126,15 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
|||||||
delete menu;
|
delete menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case MenuAction_Cancel:
|
||||||
|
{
|
||||||
|
if (param2 == MenuCancel_ExitBack)
|
||||||
|
{
|
||||||
|
Menu back = BuildCategoryMenu(param1);
|
||||||
|
SetNominateMenuTitle(back, param1);
|
||||||
|
DisplayMenu(back, param1, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
case MenuAction_Select:
|
case MenuAction_Select:
|
||||||
{
|
{
|
||||||
//2023-03-22 edit since client sometimes is 0 which fucks up mapchooser
|
//2023-03-22 edit since client sometimes is 0 which fucks up mapchooser
|
||||||
@@ -1056,30 +1150,18 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
|||||||
char name[MAX_NAME_LENGTH];
|
char name[MAX_NAME_LENGTH];
|
||||||
GetMenuItem(menu, param2, map, sizeof(map));
|
GetMenuItem(menu, param2, map, sizeof(map));
|
||||||
|
|
||||||
if (StrEqual(map, "Hide all unavailable maps"))
|
|
||||||
{
|
|
||||||
PrintToChat(param1, "Hiding all unavailable maps from the nomination list");
|
|
||||||
sql_insert_update_hiding_unavailable(param1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (StrEqual(map, "Show all unavailable maps"))
|
|
||||||
{
|
|
||||||
PrintToChat(param1, "Displaying all unavailable maps from the nomination list");
|
|
||||||
sql_insert_update_hiding_unavailable(param1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetClientName(param1, name, MAX_NAME_LENGTH);
|
GetClientName(param1, name, MAX_NAME_LENGTH);
|
||||||
|
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||||
if (GetMapCooldownTime(map) > GetTime())
|
if (Index_Cooldown > 0)
|
||||||
{
|
{
|
||||||
PrintToChat(param1, "[NE] You cant nominate this map right now.");
|
PrintToChat(param1, "[NE] You cant nominate this map right now. Overplayed Position: %i", Index_Cooldown);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
if (!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
||||||
{
|
{
|
||||||
if(AreRestrictionsActive() && (
|
if(AreRestrictionsActive() && (
|
||||||
|
GetMapCooldownTime(map) > GetTime() ||
|
||||||
GetMapTimeRestriction(map) ||
|
GetMapTimeRestriction(map) ||
|
||||||
GetMapPlayerRestriction(map) ||
|
GetMapPlayerRestriction(map) ||
|
||||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||||
@@ -1172,14 +1254,16 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
|||||||
}
|
}
|
||||||
delete MapList;
|
delete MapList;
|
||||||
delete OwnerList;
|
delete OwnerList;
|
||||||
if (GetMapCooldownTime(map) > GetTime())
|
|
||||||
|
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||||
|
if (Index_Cooldown > 0)
|
||||||
{
|
{
|
||||||
return ITEMDRAW_DISABLED;
|
return ITEMDRAW_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
if(!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
||||||
{
|
{
|
||||||
if(AreRestrictionsActive() && (
|
if(AreRestrictionsActive() && (
|
||||||
|
GetMapCooldownTime(map) > GetTime() ||
|
||||||
GetMapTimeRestriction(map) ||
|
GetMapTimeRestriction(map) ||
|
||||||
GetMapPlayerRestriction(map) ||
|
GetMapPlayerRestriction(map) ||
|
||||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||||
@@ -1231,8 +1315,15 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
|||||||
Format(buffer, sizeof(buffer), "%s (%T)", buffer, "VIP Restriction", param1);
|
Format(buffer, sizeof(buffer), "%s (%T)", buffer, "VIP Restriction", param1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||||
|
if (Index_Cooldown > 0)
|
||||||
|
{
|
||||||
|
Format(display, sizeof(display), "%s (Overplayed pos: %i)", map, Index_Cooldown);
|
||||||
|
return RedrawMenuItem(display);
|
||||||
|
}
|
||||||
|
|
||||||
int Cooldown = GetMapCooldownTime(map);
|
int Cooldown = GetMapCooldownTime(map);
|
||||||
if(Cooldown > GetTime())
|
if(RestrictionsActive && Cooldown > GetTime())
|
||||||
{
|
{
|
||||||
int Seconds = Cooldown - GetTime();
|
int Seconds = Cooldown - GetTime();
|
||||||
char time[16];
|
char time[16];
|
||||||
@@ -1340,6 +1431,7 @@ public int Handler_AdminMapSelectMenu(Menu menu, MenuAction action, int param1,
|
|||||||
{
|
{
|
||||||
if(AreRestrictionsActive() && (
|
if(AreRestrictionsActive() && (
|
||||||
GetMapCooldownTime(map) > GetTime() || //this one is fine cause its admin nomination.
|
GetMapCooldownTime(map) > GetTime() || //this one is fine cause its admin nomination.
|
||||||
|
GetExcludedMapListingPriority(map) > 0 ||
|
||||||
GetMapTimeRestriction(map) ||
|
GetMapTimeRestriction(map) ||
|
||||||
GetMapPlayerRestriction(map) ||
|
GetMapPlayerRestriction(map) ||
|
||||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ void UpdateRTV()
|
|||||||
public int get_voted_rtv()
|
public int get_voted_rtv()
|
||||||
{
|
{
|
||||||
int Votes = 0;
|
int Votes = 0;
|
||||||
for (int i = 0; i < MaxClients; i++)
|
for (int i = 0; i <= MaxClients; i++)
|
||||||
{
|
{
|
||||||
if (IsValidClient(i) && g_Voted[i])
|
if (IsValidClient(i) && g_Voted[i])
|
||||||
{
|
{
|
||||||
@@ -319,10 +319,10 @@ void AttemptRTV(int client)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
update_g_VotesNeeded();
|
update_g_VotesNeeded();
|
||||||
int Votes = get_voted_rtv();
|
|
||||||
|
|
||||||
if (g_Voted[client])
|
if (g_Voted[client])
|
||||||
{
|
{
|
||||||
|
int Votes = get_voted_rtv();
|
||||||
ReplyToCommand(client, "[RTVE] You have already voted to Rock the Vote. (%i/%i Votes. (%i RTV boost))", Votes, g_VotesNeeded, GetPlayerWorthRTV_boost_(client));
|
ReplyToCommand(client, "[RTVE] You have already voted to Rock the Vote. (%i/%i Votes. (%i RTV boost))", Votes, g_VotesNeeded, GetPlayerWorthRTV_boost_(client));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -332,7 +332,7 @@ void AttemptRTV(int client)
|
|||||||
|
|
||||||
g_Voted[client] = true;
|
g_Voted[client] = true;
|
||||||
|
|
||||||
Votes = get_voted_rtv();
|
int Votes = get_voted_rtv();
|
||||||
|
|
||||||
PrintToChatAll("[RTVE] %s wants to rock the vote. (%i/%i RTV reached) (%i RTV boost).", name, Votes, g_VotesNeeded, GetPlayerWorthRTV_boost_(client));
|
PrintToChatAll("[RTVE] %s wants to rock the vote. (%i/%i RTV reached) (%i RTV boost).", name, Votes, g_VotesNeeded, GetPlayerWorthRTV_boost_(client));
|
||||||
|
|
||||||
|
|||||||
@@ -234,9 +234,10 @@ public MRESReturn TryPlayerMove_Dhook(Address pThis, Handle hReturn, Handle hPar
|
|||||||
Address pFirstTrace = DHookGetParam(hParams, 2);
|
Address pFirstTrace = DHookGetParam(hParams, 2);
|
||||||
|
|
||||||
DHookSetReturn(hReturn, TryPlayerMove(view_as<CGameMovement>(pThis), view_as<Vector>(pFirstDest), view_as<CGameTrace>(pFirstTrace)));
|
DHookSetReturn(hReturn, TryPlayerMove(view_as<CGameMovement>(pThis), view_as<Vector>(pFirstDest), view_as<CGameTrace>(pFirstTrace)));
|
||||||
|
return MRES_Supercede;
|
||||||
}
|
}
|
||||||
|
return MRES_Ignored;
|
||||||
|
|
||||||
return MRES_Supercede;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TryPlayerMove(CGameMovement pThis, Vector pFirstDest, CGameTrace pFirstTrace)
|
int TryPlayerMove(CGameMovement pThis, Vector pFirstDest, CGameTrace pFirstTrace)
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#define PLUGIN_AUTHOR "jenz"
|
||||||
|
#define PLUGIN_VERSION "1.0"
|
||||||
|
#include <sourcemod>
|
||||||
|
|
||||||
|
Database g_hDatabase;
|
||||||
|
char g_cTimeRecords[18][256];
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "unloze top activity",
|
||||||
|
author = PLUGIN_AUTHOR,
|
||||||
|
description = "listing top activity on ze",
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = "www.unloze.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
}
|
||||||
|
RegConsoleCmd("sm_activity", Command_topactivity, "retrieve top activity on ze for the week");
|
||||||
|
RegConsoleCmd("sm_myactivity", Command_myactivity, "retrieve your own activity on ze for the week");
|
||||||
|
CreateTimer(1800.0, update_top_activity, _, TIMER_REPEAT);
|
||||||
|
update_top_activity_ze();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action update_top_activity(Handle timer)
|
||||||
|
{
|
||||||
|
update_top_activity_ze();
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update_top_activity_ze()
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char sQuery[1024];
|
||||||
|
Format(sQuery, sizeof(sQuery), "select pt.steam_id, pt.player_name, SUM(pt.ze_time) - pa.ze_time_start_week AS time_this_week from unloze_playtimestats.player_activity_ze pa inner join unloze_playtimestats.player_time pt on pa.steamid = pt.steam_id where pa.steamid not in ('STEAM_0:0:518094602', 'STEAM_0:0:204398871', 'STEAM_0:1:60189040', 'STEAM_0:0:610560766') GROUP BY pt.steam_id ORDER BY time_this_week DESC limit 15");
|
||||||
|
g_hDatabase.Query(SQL_top_activity, sQuery, DBPrio_Low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_top_activity(Database db, DBResultSet results, const char[] error, int iSerial)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
LogError("Query error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
int counter_menu = 1;
|
||||||
|
Format(g_cTimeRecords[counter], sizeof(g_cTimeRecords[]), "Top activity: 5 days VIP");
|
||||||
|
counter++;
|
||||||
|
while (results.RowCount && results.FetchRow())
|
||||||
|
{
|
||||||
|
char sBuffer[528];
|
||||||
|
char sName[MAX_NAME_LENGTH];
|
||||||
|
results.FetchString(1, sName, sizeof(sName));
|
||||||
|
float time_this_week = results.FetchFloat(2);
|
||||||
|
|
||||||
|
int hours_server = RoundToFloor((time_this_week / 60) / 60);
|
||||||
|
int minutes_server = RoundToFloor((time_this_week / 60) % 60);
|
||||||
|
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%i %s %d Hours %d Minutes", counter_menu, sName, hours_server, minutes_server);
|
||||||
|
Format(g_cTimeRecords[counter], sizeof(g_cTimeRecords[]), sBuffer);
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
counter_menu++;
|
||||||
|
if (counter == 6)
|
||||||
|
{
|
||||||
|
Format(g_cTimeRecords[counter], sizeof(g_cTimeRecords[]), "Top activity: 3 days VIP");
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
if (counter == 11)
|
||||||
|
{
|
||||||
|
Format(g_cTimeRecords[counter], sizeof(g_cTimeRecords[]), "Top activity: 1 day VIP");
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||||
|
{
|
||||||
|
if(!db || strlen(error))
|
||||||
|
{
|
||||||
|
LogError("Database error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_hDatabase = db;
|
||||||
|
|
||||||
|
char sQuery[1024];
|
||||||
|
Format(sQuery, sizeof(sQuery), "select pt.steam_id, pt.player_name, SUM(pt.ze_time) - pa.ze_time_start_week AS time_this_week from unloze_playtimestats.player_activity_ze pa inner join unloze_playtimestats.player_time pt on pa.steamid = pt.steam_id where pa.steamid not in ('STEAM_0:0:518094602', 'STEAM_0:0:204398871', 'STEAM_0:1:60189040', 'STEAM_0:0:610560766') GROUP BY pt.steam_id ORDER BY time_this_week DESC limit 15");
|
||||||
|
g_hDatabase.Query(SQL_top_activity, sQuery, DBPrio_Low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_myactivity(int client, int args)
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sSID[64];
|
||||||
|
GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
|
||||||
|
|
||||||
|
char sQuery[1024];
|
||||||
|
Format(sQuery, sizeof(sQuery), "select pt.steam_id, pt.player_name, SUM(pt.ze_time) - pa.ze_time_start_week AS time_this_week from unloze_playtimestats.player_activity_ze pa inner join unloze_playtimestats.player_time pt on pa.steamid = pt.steam_id where pa.steamid = '%s' GROUP BY pt.steam_id ORDER BY time_this_week DESC limit 15", sSID);
|
||||||
|
g_hDatabase.Query(SQL_my_activity, sQuery, GetClientSerial(client));
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SQL_my_activity(Database db, DBResultSet results, const char[] error, int iSerial)
|
||||||
|
{
|
||||||
|
if (!db || strlen(error))
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
LogError("Query error: %s", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int client;
|
||||||
|
if ((client = GetClientFromSerial(iSerial)) == 0)
|
||||||
|
{
|
||||||
|
delete results;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sTitle[64];
|
||||||
|
Format(sTitle, sizeof(sTitle), "[UNLOZE your weekly activity ZE]");
|
||||||
|
Menu menu = new Menu(MenuHandler1);
|
||||||
|
menu.SetTitle(sTitle);
|
||||||
|
|
||||||
|
if (results.RowCount && results.FetchRow())
|
||||||
|
{
|
||||||
|
char sBuffer[528];
|
||||||
|
char sName[MAX_NAME_LENGTH];
|
||||||
|
results.FetchString(1, sName, sizeof(sName));
|
||||||
|
float time_this_week = results.FetchFloat(2);
|
||||||
|
|
||||||
|
int hours_server = RoundToFloor((time_this_week / 60) / 60);
|
||||||
|
int minutes_server = RoundToFloor((time_this_week / 60) % 60);
|
||||||
|
|
||||||
|
Format(sBuffer, sizeof(sBuffer), "%s %d Hours %d Minutes", sName, hours_server, minutes_server);
|
||||||
|
menu.AddItem("-1", sBuffer, ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
delete results;
|
||||||
|
|
||||||
|
menu.ExitButton = true;
|
||||||
|
menu.Display(client, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_topactivity(int client, int args)
|
||||||
|
{
|
||||||
|
if (!g_hDatabase)
|
||||||
|
{
|
||||||
|
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
char sTitle[64];
|
||||||
|
Format(sTitle, sizeof(sTitle), "[UNLOZE weekly activity ZE]");
|
||||||
|
Menu menu = new Menu(MenuHandler1);
|
||||||
|
menu.SetTitle(sTitle);
|
||||||
|
for (int i = 0; i < sizeof(g_cTimeRecords); i++)
|
||||||
|
{
|
||||||
|
menu.AddItem("-1", g_cTimeRecords[i], ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
menu.ExitButton = true;
|
||||||
|
menu.Display(client, 0);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)
|
||||||
|
{
|
||||||
|
switch(action)
|
||||||
|
{
|
||||||
|
case MenuAction_End:
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
"Trails"
|
||||||
|
{
|
||||||
|
"Dollars"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/dollars.vmt"
|
||||||
|
"tier" "9"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Donuts"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/donuts.vmt"
|
||||||
|
"tier" "9"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Double Rainbow"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/doublerainbow.vmt"
|
||||||
|
"tier" "10"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Dragon"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/dragon.vmt"
|
||||||
|
"tier" "10"
|
||||||
|
}
|
||||||
|
"8Bit Mushroom"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/8bitmushroom.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
}
|
||||||
|
"Arrow Rainbow"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/arrowrainbow.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Arrows"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/arrows.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Assasin"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/assasin.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Awesome"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/awesome.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"8Bit Pow"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/8bitpow.vmt"
|
||||||
|
"tier" "11"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"Banknote"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/banknote.vmt"
|
||||||
|
"tier" "12"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Barcalona"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/barcalona.vmt"
|
||||||
|
"tier" "12"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Batman"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/batman.vmt"
|
||||||
|
"tier" "12"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Battlefield"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/battlefield.vmt"
|
||||||
|
"tier" "12"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Beer Mug"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/beermug.vmt"
|
||||||
|
"tier" "12"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Blue Lightning"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/bluelightning.vmt"
|
||||||
|
"tier" "13"
|
||||||
|
}
|
||||||
|
|
||||||
|
"BMW Logo"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/bmwlogo.vmt"
|
||||||
|
"tier" "13"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Bom Bomb"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/bombomb.vmt"
|
||||||
|
"tier" "13"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Boo"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/boo.vmt"
|
||||||
|
"tier" "13"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Canada Flag"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/canadaflag.vmt"
|
||||||
|
"tier" "14"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Cereal-guy"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/cereal-guy.vmt"
|
||||||
|
"tier" "14"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Challenge"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/challenge.vmt"
|
||||||
|
"tier" "14"
|
||||||
|
}
|
||||||
|
"Coca-Cola"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/cocacola.vmt"
|
||||||
|
"tier" "14"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Cookies"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/cookies.vmt"
|
||||||
|
"tier" "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Cracked Beam"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/crackedbeam.vmt"
|
||||||
|
"tier" "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Creed"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/creed.vmt"
|
||||||
|
"tier" "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Creeper"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/creeper.vmt"
|
||||||
|
"tier" "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Crown"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/crown.vmt"
|
||||||
|
"tier" "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Danish Flag"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/danishflag.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Dark Knight"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/darkknight.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Coca-Cola 2"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/cocacola2.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"Bullet Bill"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/bulletbill.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Biohazard"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/biohazard.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"Apple"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/apple.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
"Airforce"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/airforce.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
"Airforce 2"
|
||||||
|
{
|
||||||
|
"material" "materials/sprites/store/trails/airforce2.vmt"
|
||||||
|
"VIP" "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,478 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
#define PLUGIN_AUTHOR "jenz"
|
||||||
|
#define PLUGIN_VERSION "1.0"
|
||||||
|
|
||||||
|
#include <unloze_playtime>
|
||||||
|
#include <clientprefs>
|
||||||
|
#include <mapchooser_extended>
|
||||||
|
#include <zombiereloaded>
|
||||||
|
#include <sdkhooks>
|
||||||
|
#include <sdktools>
|
||||||
|
|
||||||
|
bool g_bTrailsEnabled;
|
||||||
|
bool g_bRoundStartSpawnTrails;
|
||||||
|
int g_iSpriteModel[MAXPLAYERS + 1] = {-1, ...};
|
||||||
|
|
||||||
|
int g_iClientTrail[MAXPLAYERS + 1] = { -1, ... }; // index into g_hTrails, -1 = none
|
||||||
|
|
||||||
|
float g_fTrailsLifeTime = 1.0;
|
||||||
|
int g_iTrailsStartWidth = 10;
|
||||||
|
int g_iTrailsEndWidth = 6;
|
||||||
|
|
||||||
|
Handle g_hCookie_trailName;
|
||||||
|
Handle g_hCookie_trailHide;
|
||||||
|
|
||||||
|
bool g_bHideTrails[MAXPLAYERS + 1];
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "unloze trails",
|
||||||
|
author = PLUGIN_AUTHOR,
|
||||||
|
description = "adds trails based on tier, vip and maps",
|
||||||
|
version = PLUGIN_VERSION,
|
||||||
|
url = "www.unloze.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum struct TrailData
|
||||||
|
{
|
||||||
|
char name[128];
|
||||||
|
char material[512];
|
||||||
|
int tier;
|
||||||
|
int vip;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList g_hTrails;
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
RegConsoleCmd("sm_trails", Command_Trail, "The Trails menu");
|
||||||
|
RegConsoleCmd("sm_trail", Command_Trail, "The Trails menu");
|
||||||
|
|
||||||
|
HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy);
|
||||||
|
HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
|
||||||
|
HookEvent("player_death", PlayerDeath);
|
||||||
|
|
||||||
|
g_hCookie_trailName = RegClientCookie("unloze_trail", "Select your trail", CookieAccess_Protected);
|
||||||
|
g_hCookie_trailHide = RegClientCookie("unloze_trail_hide", "Hide trails", CookieAccess_Protected);
|
||||||
|
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Unloze Trails");
|
||||||
|
|
||||||
|
g_hTrails = new ArrayList(sizeof(TrailData));
|
||||||
|
|
||||||
|
|
||||||
|
ConVar cvar;
|
||||||
|
HookConVarChange((cvar = CreateConVar("sm_unloze_trails_lifetime", "1.0", "Lifetime of trails")), Cvar_TrailsLifeTime);
|
||||||
|
g_fTrailsLifeTime = cvar.FloatValue;
|
||||||
|
delete cvar;
|
||||||
|
|
||||||
|
ConVar cvar1;
|
||||||
|
HookConVarChange((cvar1 = CreateConVar("sm_unloze_trails_start_width", "10", "Start width of trails")), Cvar_TrailsStartWidth);
|
||||||
|
g_iTrailsStartWidth = cvar1.IntValue;
|
||||||
|
delete cvar1;
|
||||||
|
|
||||||
|
ConVar cvar2;
|
||||||
|
HookConVarChange((cvar2 = CreateConVar("sm_unloze_trails_end_width", "6", "End width of trails")), Cvar_TrailsEndWidth);
|
||||||
|
g_iTrailsEndWidth = cvar2.IntValue;
|
||||||
|
delete cvar2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_TrailsEndWidth(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iTrailsEndWidth = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_TrailsStartWidth(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_iTrailsStartWidth = convar.IntValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cvar_TrailsLifeTime(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||||
|
{
|
||||||
|
g_fTrailsLifeTime = convar.FloatValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case CookieMenuAction_DisplayOption:
|
||||||
|
{
|
||||||
|
Format(buffer, maxlen, "Trails");
|
||||||
|
}
|
||||||
|
case CookieMenuAction_SelectOption:
|
||||||
|
{
|
||||||
|
if (!g_bTrailsEnabled)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[Trails] Trails are disabled on this map.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OpenTrailsMenu(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayerDeath(Handle:event,const String:name[],bool:dontBroadcast)
|
||||||
|
{
|
||||||
|
int client = GetClientOfUserId(GetEventInt(event, "userid"));
|
||||||
|
KillTrail(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast)
|
||||||
|
{
|
||||||
|
if (!g_bTrailsEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int client = 1; client <= MAXPLAYERS; client++)
|
||||||
|
{
|
||||||
|
KillTrail(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Event_RoundStart(Handle event, const char[] name, bool dontBroadcast)
|
||||||
|
{
|
||||||
|
if (!g_bTrailsEnabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_bRoundStartSpawnTrails = false;
|
||||||
|
//From Round start we wait 5 seconds before spawning trails so map has time to load its edicts for the round.
|
||||||
|
CreateTimer(5.0, allow_spawning_trails);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action allow_spawning_trails(Handle hTimer)
|
||||||
|
{
|
||||||
|
g_bRoundStartSpawnTrails = true;
|
||||||
|
for (int client = 1; client <= MAXPLAYERS; client++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(client) && g_iClientTrail[client] != -1 && IsPlayerAlive(client) && ZR_IsClientHuman(client))
|
||||||
|
{
|
||||||
|
SpawnTrail(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_Trail(int client, int args)
|
||||||
|
{
|
||||||
|
if (!g_bTrailsEnabled)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "[Trails] Trails are disabled on this map.");
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
OpenTrailsMenu(client);
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenTrailsMenu(int client)
|
||||||
|
{
|
||||||
|
Menu menu = new Menu(MenuHandler_Trails);
|
||||||
|
menu.SetTitle("Trails Menu");
|
||||||
|
|
||||||
|
if (g_bHideTrails[client])
|
||||||
|
{
|
||||||
|
menu.AddItem("-1", "Unhide Trails");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu.AddItem("-1", "Hide Trails");
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = g_hTrails.Length;
|
||||||
|
int clientTier = GetPlayerTier_native(client);
|
||||||
|
bool vipAccess = CheckCommandAccess(client, "", ADMFLAG_RESERVATION, false);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
TrailData trail;
|
||||||
|
g_hTrails.GetArray(i, trail);
|
||||||
|
|
||||||
|
char info[128];
|
||||||
|
IntToString(i, info, sizeof(info));
|
||||||
|
|
||||||
|
if (trail.tier > clientTier)
|
||||||
|
{
|
||||||
|
char displayName[128];
|
||||||
|
Format(displayName, sizeof(displayName), "%s (Tier %d)", trail.name, trail.tier);
|
||||||
|
menu.AddItem(info, displayName, ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
else if (trail.vip && !vipAccess)
|
||||||
|
{
|
||||||
|
char displayName[128];
|
||||||
|
Format(displayName, sizeof(displayName), "%s (VIP)", trail.name);
|
||||||
|
menu.AddItem(info, displayName, ITEMDRAW_DISABLED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu.AddItem(info, trail.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.ExitButton = true;
|
||||||
|
menu.Display(client, MENU_TIME_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MenuHandler_Trails(Menu menu, MenuAction action, int param1, int param2)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case MenuAction_Select:
|
||||||
|
{
|
||||||
|
char info[8];
|
||||||
|
menu.GetItem(param2, info, sizeof(info));
|
||||||
|
int index = StringToInt(info);
|
||||||
|
g_iClientTrail[param1] = index;
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
g_bHideTrails[param1] = !g_bHideTrails[param1];
|
||||||
|
PrintToChat(param1, "Trails are now %s", g_bHideTrails[param1]? "Hidden": "Unhidden");
|
||||||
|
SetClientCookie(param1, g_hCookie_trailName, "");
|
||||||
|
KillTrail(param1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TrailData trail;
|
||||||
|
g_hTrails.GetArray(index, trail);
|
||||||
|
PrintToChat(param1, "[Trails] Trail set to: %s", trail.name);
|
||||||
|
SetClientCookie(param1, g_hCookie_trailName, trail.name);
|
||||||
|
if (IsPlayerAlive(param1) && ZR_IsClientHuman(param1))
|
||||||
|
{
|
||||||
|
SpawnTrail(param1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintToChat(param1, "Not Applying trail right now since you are not alive as human.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//OpenTrailsMenu(param1); // reopen
|
||||||
|
}
|
||||||
|
case MenuAction_End:
|
||||||
|
{
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnMapEnd()
|
||||||
|
{
|
||||||
|
for (int client = 1; client <= MAXPLAYERS; client++)
|
||||||
|
{
|
||||||
|
KillTrail(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int client = 1; client <= MAXPLAYERS; client++)
|
||||||
|
{
|
||||||
|
g_iSpriteModel[client] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientDisconnect(client)
|
||||||
|
{
|
||||||
|
g_bHideTrails[client] = false;
|
||||||
|
KillTrail(client);
|
||||||
|
g_iClientTrail[client] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientCookiesCached(int client)
|
||||||
|
{
|
||||||
|
char sBuffer[512];
|
||||||
|
GetClientCookie(client, g_hCookie_trailHide, sBuffer, sizeof(sBuffer));
|
||||||
|
|
||||||
|
if (sBuffer[0])
|
||||||
|
{
|
||||||
|
g_bHideTrails[client] = StringToInt(sBuffer) != 0 ? true : false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_bHideTrails[client] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetClientCookie(client, g_hCookie_trailName, sBuffer, sizeof(sBuffer));
|
||||||
|
if (sBuffer[0])
|
||||||
|
{
|
||||||
|
g_iClientTrail[client] = -1;
|
||||||
|
int count = g_hTrails.Length;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
TrailData trail;
|
||||||
|
g_hTrails.GetArray(i, trail);
|
||||||
|
if (StrEqual(trail.name, sBuffer, true))
|
||||||
|
{
|
||||||
|
g_iClientTrail[client] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_iClientTrail[client] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientPostAdminCheck(int client)
|
||||||
|
{
|
||||||
|
g_iSpriteModel[client] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMapStart()
|
||||||
|
{
|
||||||
|
char Mapname[128];
|
||||||
|
GetCurrentMap(Mapname, sizeof(Mapname));
|
||||||
|
g_bTrailsEnabled = GetMapTrails(Mapname) != 0 ? true : false;
|
||||||
|
LoadTrails();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadTrails()
|
||||||
|
{
|
||||||
|
g_hTrails.Clear();
|
||||||
|
char path[PLATFORM_MAX_PATH];
|
||||||
|
BuildPath(Path_SM, path, sizeof(path), "configs/unloze_trails.cfg");
|
||||||
|
|
||||||
|
KeyValues kv = new KeyValues("Trails");
|
||||||
|
if (!kv.ImportFromFile(path))
|
||||||
|
{
|
||||||
|
LogError("[trails] Could not load %s", path);
|
||||||
|
delete kv;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter the root "Trails" section, then iterate its children
|
||||||
|
if (kv.GotoFirstSubKey())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
TrailData trail;
|
||||||
|
kv.GetSectionName(trail.name, sizeof(trail.name));
|
||||||
|
kv.GetString("material", trail.material, sizeof(trail.material), "");
|
||||||
|
trail.tier = kv.GetNum("tier", 0);
|
||||||
|
trail.vip = kv.GetNum("VIP", 0);
|
||||||
|
g_hTrails.PushArray(trail);
|
||||||
|
|
||||||
|
PrecacheModel(trail.material, false);
|
||||||
|
AddFileToDownloadsTable(trail.material);
|
||||||
|
|
||||||
|
char vtf_download[512];
|
||||||
|
strcopy(vtf_download, sizeof(vtf_download), trail.material);
|
||||||
|
|
||||||
|
//modifying last two characters so its .vtf
|
||||||
|
int len = strlen(vtf_download);
|
||||||
|
vtf_download[len - 2] = 't';
|
||||||
|
vtf_download[len - 1] = 'f';
|
||||||
|
AddFileToDownloadsTable(vtf_download);
|
||||||
|
}
|
||||||
|
while (kv.GotoNextKey());
|
||||||
|
}
|
||||||
|
delete kv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn)
|
||||||
|
{
|
||||||
|
KillTrail(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void KillTrail(int client)
|
||||||
|
{
|
||||||
|
if (g_iSpriteModel[client] > MaxClients && IsValidEdict(g_iSpriteModel[client]))
|
||||||
|
{
|
||||||
|
SDKUnhook(g_iSpriteModel[client], SDKHook_SetTransmit, Hook_TrailShouldHide);
|
||||||
|
AcceptEntityInput(g_iSpriteModel[client], "kill");
|
||||||
|
}
|
||||||
|
g_iSpriteModel[client] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SpawnTrail(int client)
|
||||||
|
{
|
||||||
|
KillTrail(client);
|
||||||
|
if (!g_bRoundStartSpawnTrails)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "Cant spawn trails this early in the round.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//we got 2048 edicts in total
|
||||||
|
int edict_limit = 1700;
|
||||||
|
int edict_count = GetEntityCount();
|
||||||
|
if (edict_count > edict_limit)
|
||||||
|
{
|
||||||
|
PrintToChat(client, "Not spawning your trail due to edict limitations");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_iSpriteModel[client] = CreateEntityByName("env_spritetrail");
|
||||||
|
|
||||||
|
if (g_iSpriteModel[client] != -1)
|
||||||
|
{
|
||||||
|
DispatchKeyValueFloat(g_iSpriteModel[client], "lifetime", g_fTrailsLifeTime);
|
||||||
|
char startwidth[16];
|
||||||
|
Format(startwidth, sizeof(startwidth), "%i", g_iTrailsStartWidth);
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "startwidth", startwidth);
|
||||||
|
|
||||||
|
char endwidth[16];
|
||||||
|
Format(endwidth, sizeof(endwidth), "%i", g_iTrailsEndWidth);
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "endwidth", endwidth);
|
||||||
|
|
||||||
|
TrailData trail;
|
||||||
|
g_hTrails.GetArray(g_iClientTrail[client], trail);
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "spritename", trail.material);
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "renderamt", "255");
|
||||||
|
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "rendercolor", "255 255 255 255");
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "rendermode", "1");
|
||||||
|
|
||||||
|
// We give the name for our entities here
|
||||||
|
char buffer[1024];
|
||||||
|
Format(buffer, sizeof(buffer), "unloze_trails_%d", g_iSpriteModel[client]);
|
||||||
|
DispatchKeyValue(g_iSpriteModel[client], "targetname", buffer);
|
||||||
|
|
||||||
|
DispatchSpawn(g_iSpriteModel[client]);
|
||||||
|
|
||||||
|
float dest_vector[3];
|
||||||
|
dest_vector[0] = 0.0;
|
||||||
|
dest_vector[1] = 0.0;
|
||||||
|
dest_vector[2] = 5.0;
|
||||||
|
|
||||||
|
float or[3];
|
||||||
|
float ang[3];
|
||||||
|
float fForward[3];
|
||||||
|
float fRight[3];
|
||||||
|
float fUp[3];
|
||||||
|
|
||||||
|
GetClientAbsOrigin(client, or);
|
||||||
|
GetClientAbsAngles(client, ang);
|
||||||
|
|
||||||
|
GetAngleVectors(ang, fForward, fRight, fUp);
|
||||||
|
|
||||||
|
or[0] += fRight[0]*dest_vector[0] + fForward[0]*dest_vector[1] + fUp[0]*dest_vector[2];
|
||||||
|
or[1] += fRight[1]*dest_vector[0] + fForward[1]*dest_vector[1] + fUp[1]*dest_vector[2];
|
||||||
|
or[2] += fRight[2]*dest_vector[0] + fForward[2]*dest_vector[1] + fUp[2]*dest_vector[2];
|
||||||
|
|
||||||
|
TeleportEntity(g_iSpriteModel[client], or, NULL_VECTOR, NULL_VECTOR);
|
||||||
|
|
||||||
|
SetVariantString("!activator");
|
||||||
|
AcceptEntityInput(g_iSpriteModel[client], "SetParent", client);
|
||||||
|
SetEntPropFloat(g_iSpriteModel[client], Prop_Send, "m_flTextureRes", 0.05);
|
||||||
|
SetEntPropEnt(g_iSpriteModel[client], Prop_Send, "m_hOwnerEntity", client);
|
||||||
|
|
||||||
|
SDKHook(g_iSpriteModel[client], SDKHook_SetTransmit, Hook_TrailShouldHide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Hook_TrailShouldHide(int entity, int client)
|
||||||
|
{
|
||||||
|
if (g_bHideTrails[client])
|
||||||
|
{
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client)
|
||||||
|
{
|
||||||
|
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user