༼ つ ◕_◕ ༽つ

This commit is contained in:
zaCade 2017-03-24 16:59:05 +01:00
parent b5e1c481fa
commit dac8227326
4 changed files with 699 additions and 0 deletions

View File

@ -0,0 +1,441 @@
#include <sourcemod>
#include <sdktools>
#include <cstrike>
#include <AFKManager>
#undef REQUIRE_PLUGIN
#include <zombiereloaded>
#define REQUIRE_PLUGIN
#pragma semicolon 1
#pragma newdecls required
#define AFK_CHECK_INTERVAL 5.0
bool g_Players_bEnabled[MAXPLAYERS + 1];
bool g_Players_bFlagged[MAXPLAYERS + 1];
int g_Players_iLastAction[MAXPLAYERS + 1];
float g_Players_fEyePosition[MAXPLAYERS + 1][3];
int g_Players_iButtons[MAXPLAYERS + 1];
int g_Players_iSpecMode[MAXPLAYERS + 1];
int g_Players_iSpecTarget[MAXPLAYERS + 1];
int g_Players_iIgnore[MAXPLAYERS + 1];
enum
{
IGNORE_EYEPOSITION = 1,
IGNORE_TEAMSWITCH = 2,
IGNORE_OBSERVER = 4
}
float g_fKickTime;
float g_fMoveTime;
float g_fWarnTime;
int g_iKickMinPlayers;
int g_iMoveMinPlayers;
int g_iImmunity;
public Plugin myinfo =
{
name = "Good AFK Manager",
author = "BotoX",
description = "A good AFK manager?",
version = "1.3",
url = ""
};
public void Cvar_KickTime(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_fKickTime = GetConVarFloat(convar);
}
public void Cvar_MoveTime(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_fMoveTime = GetConVarFloat(convar);
}
public void Cvar_WarnTime(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_fWarnTime = GetConVarFloat(convar);
}
public void Cvar_KickMinPlayers(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_iKickMinPlayers = GetConVarInt(convar);
}
public void Cvar_MoveMinPlayers(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_iMoveMinPlayers = GetConVarInt(convar);
}
public void Cvar_Immunity(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_iImmunity = GetConVarInt(convar);
}
public void OnPluginStart()
{
ConVar cvar;
HookConVarChange((cvar = CreateConVar("sm_afk_move_min", "10", "Min players for AFK move")), Cvar_MoveMinPlayers);
g_iMoveMinPlayers = GetConVarInt(cvar);
HookConVarChange((cvar = CreateConVar("sm_afk_kick_min", "30", "Min players for AFK kick")), Cvar_KickMinPlayers);
g_iKickMinPlayers = GetConVarInt(cvar);
HookConVarChange((cvar = CreateConVar("sm_afk_move_time", "60.0", "Time in seconds for AFK Move. 0 = DISABLED")), Cvar_MoveTime);
g_fMoveTime = GetConVarFloat(cvar);
HookConVarChange((cvar = CreateConVar("sm_afk_kick_time", "120.0", "Time in seconds to AFK Kick. 0 = DISABLED")), Cvar_KickTime);
g_fKickTime = GetConVarFloat(cvar);
HookConVarChange((cvar = CreateConVar("sm_afk_warn_time", "30.0", "Time in seconds remaining before warning")), Cvar_WarnTime);
g_fWarnTime = GetConVarFloat(cvar);
HookConVarChange((cvar = CreateConVar("sm_afk_immunity", "1", "AFK admins immunity: 0 = DISABLED, 1 = COMPLETE, 2 = KICK, 3 = MOVE")), Cvar_Immunity);
g_iImmunity = GetConVarInt(cvar);
CloseHandle(cvar);
AddCommandListener(Command_Say, "say");
AddCommandListener(Command_Say, "say_team");
HookEvent("player_team", Event_PlayerTeamPost, EventHookMode_Post);
HookEvent("player_spawn", Event_PlayerSpawnPost, EventHookMode_Post);
HookEvent("player_death", Event_PlayerDeathPost, EventHookMode_Post);
HookEvent("round_end", Event_RoundEnd, EventHookMode_Pre);
HookEntityOutput("trigger_teleport", "OnEndTouch", Teleport_OnEndTouch);
AutoExecConfig(true, "plugin.AFKManager");
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("GetClientIdleTime", Native_GetClientIdleTime);
RegPluginLibrary("AFKManager");
return APLRes_Success;
}
public void OnMapStart()
{
CreateTimer(AFK_CHECK_INTERVAL, Timer_CheckPlayer, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
/* Handle late load */
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i))
{
OnClientConnected(i);
if(IsClientInGame(i) && IsClientAuthorized(i))
OnClientPostAdminCheck(i);
}
}
}
public void OnClientConnected(int client)
{
ResetPlayer(client);
}
public void OnClientPostAdminCheck(int client)
{
if(!IsFakeClient(client))
InitializePlayer(client);
}
public void OnClientDisconnect(int client)
{
ResetPlayer(client);
}
int CheckAdminImmunity(int client)
{
if(!IsClientAuthorized(client))
return false;
AdminId Id = GetUserAdmin(client);
return GetAdminFlag(Id, Admin_Generic);
}
void ResetPlayer(int client)
{
g_Players_bEnabled[client] = false;
g_Players_bFlagged[client] = false;
g_Players_iLastAction[client] = 0;
g_Players_fEyePosition[client] = view_as<float>({0.0, 0.0, 0.0});
g_Players_iButtons[client] = 0;
g_Players_iIgnore[client] = 0;
}
void InitializePlayer(int client)
{
if(!(g_iImmunity == 1 && CheckAdminImmunity(client)))
{
ResetPlayer(client);
g_Players_iLastAction[client] = GetTime();
g_Players_bEnabled[client] = true;
}
}
public void Event_PlayerTeamPost(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(client > 0 && !IsFakeClient(client))
{
if(g_Players_iIgnore[client] & IGNORE_TEAMSWITCH)
g_Players_iIgnore[client] &= ~IGNORE_TEAMSWITCH;
else
g_Players_iLastAction[client] = GetTime();
}
}
public void Event_PlayerSpawnPost(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(client > 0 && !IsFakeClient(client))
g_Players_iIgnore[client] |= IGNORE_EYEPOSITION;
}
public void Event_PlayerDeathPost(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(client > 0 && !IsFakeClient(client))
g_Players_iIgnore[client] |= IGNORE_OBSERVER;
}
public void Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast)
{
for(int client = 1; client <= MaxClients; client++)
{
if(g_Players_bEnabled[client])
g_Players_iIgnore[client] |= IGNORE_TEAMSWITCH;
}
}
public Action Command_Say(int client, const char[] Command, int Args)
{
g_Players_iLastAction[client] = GetTime();
return Plugin_Continue;
}
public Action OnPlayerRunCmd(int client, int &iButtons, int &iImpulse, float fVel[3], float fAngles[3], int &iWeapon)
{
if(IsClientObserver(client))
{
int iSpecMode = g_Players_iSpecMode[client];
int iSpecTarget = g_Players_iSpecTarget[client];
g_Players_iSpecMode[client] = GetEntProp(client, Prop_Send, "m_iObserverMode");
g_Players_iSpecTarget[client] = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget");
if(g_Players_iSpecMode[client] == 1) // OBS_MODE_DEATHCAM
g_Players_iIgnore[client] |= IGNORE_OBSERVER;
if(iSpecTarget && g_Players_iSpecTarget[client] != iSpecTarget)
{
if(iSpecTarget == -1 || g_Players_iSpecTarget[client] == -1 ||
!IsClientInGame(iSpecTarget) || !IsPlayerAlive(iSpecTarget))
g_Players_iIgnore[client] |= IGNORE_OBSERVER;
}
if((iSpecMode && g_Players_iSpecMode[client] != iSpecMode) || (iSpecTarget && g_Players_iSpecTarget[client] != iSpecTarget))
{
if(g_Players_iIgnore[client] & IGNORE_OBSERVER)
g_Players_iIgnore[client] &= ~IGNORE_OBSERVER;
else
g_Players_iLastAction[client] = GetTime();
}
}
if(((g_Players_fEyePosition[client][0] != fAngles[0]) ||
(g_Players_fEyePosition[client][1] != fAngles[1]) ||
(g_Players_fEyePosition[client][2] != fAngles[2])) &&
(!IsClientObserver(client) ||
g_Players_iSpecMode[client] != 4)) // OBS_MODE_IN_EYE
{
if(!((iButtons & IN_LEFT) || (iButtons & IN_RIGHT)))
{
if(g_Players_iIgnore[client] & IGNORE_EYEPOSITION)
g_Players_iIgnore[client] &= ~IGNORE_EYEPOSITION;
else
g_Players_iLastAction[client] = GetTime();
}
g_Players_fEyePosition[client] = fAngles;
}
if(g_Players_iButtons[client] != iButtons)
{
g_Players_iLastAction[client] = GetTime();
g_Players_iButtons[client] = iButtons;
}
return Plugin_Continue;
}
public Action Teleport_OnEndTouch(const char[] output, int caller, int activator, float delay)
{
if(activator < 1 || activator > MaxClients)
return Plugin_Continue;
g_Players_iIgnore[activator] |= IGNORE_EYEPOSITION;
return Plugin_Continue;
}
public Action ZR_OnClientInfect(int &client, int &attacker, bool &motherInfect, bool &respawnOverride, bool &respawn)
{
g_Players_iIgnore[client] |= IGNORE_TEAMSWITCH;
}
public Action ZR_OnClientHuman(int &client, bool &respawn, bool &protect)
{
g_Players_iIgnore[client] |= IGNORE_TEAMSWITCH;
}
public Action Timer_CheckPlayer(Handle Timer, any Data)
{
int client;
int Clients = 0;
for(client = 1; client <= MaxClients; client++)
{
if(IsClientInGame(client) && !IsFakeClient(client))
Clients++;
}
bool bMovePlayers = (Clients >= g_iMoveMinPlayers && g_fMoveTime > 0.0);
bool bKickPlayers = (Clients >= g_iKickMinPlayers && g_fKickTime > 0.0);
if(!bMovePlayers && !bKickPlayers)
return Plugin_Continue;
for(client = 1; client <= MaxClients; client++)
{
if(!g_Players_bEnabled[client])
continue;
int iTeamNum = GetClientTeam(client);
int IdleTime = GetTime() - g_Players_iLastAction[client];
if(g_Players_bFlagged[client] && (g_fKickTime - IdleTime) > 0.0)
{
PrintCenterText(client, "Welcome back!");
PrintToChat(client, "\x04[AFK]\x01 You have been un-flagged for being inactive.");
g_Players_bFlagged[client] = false;
}
if(bMovePlayers && iTeamNum > CS_TEAM_SPECTATOR && (!g_iImmunity || g_iImmunity == 2 || !CheckAdminImmunity(client)))
{
float iTimeleft = g_fMoveTime - IdleTime;
if(iTimeleft > 0.0)
{
if(iTimeleft <= g_fWarnTime)
{
PrintCenterText(client, "Warning: If you do not move in %d seconds, you will be moved to spectate.", RoundToFloor(iTimeleft));
PrintToChat(client, "\x04[AFK]\x01 Warning: If you do not move in %d seconds, you will be moved to spectate.", RoundToFloor(iTimeleft));
}
}
else
{
PrintToChatAll("\x04[AFK] \x03%N\x01 was moved to spectate for being AFK too long.", client);
ForcePlayerSuicide(client);
g_Players_iIgnore[client] |= IGNORE_TEAMSWITCH;
ChangeClientTeam(client, CS_TEAM_SPECTATOR);
}
}
else if(g_fKickTime > 0.0 && (!g_iImmunity || g_iImmunity == 3 || !CheckAdminImmunity(client)))
{
float iTimeleft = g_fKickTime - IdleTime;
if(iTimeleft > 0.0)
{
if(iTimeleft <= g_fWarnTime)
{
PrintCenterText(client, "Warning: If you do not move in %d seconds, you will be kick-flagged for being inactive.", RoundToFloor(iTimeleft));
PrintToChat(client, "\x04[AFK]\x01 Warning: If you do not move in %d seconds, you will be kick-flagged for being inactive.", RoundToFloor(iTimeleft));
}
}
else
{
if(!g_Players_bFlagged[client])
{
PrintToChat(client, "\x04[AFK]\x01 You have been kick-flagged for being inactive.");
g_Players_bFlagged[client] = true;
}
int FlaggedPlayers = 0;
int Position = 1;
for(int client_ = 1; client_ <= MaxClients; client_++)
{
if(!g_Players_bFlagged[client_])
continue;
FlaggedPlayers++;
int IdleTime_ = GetTime() - g_Players_iLastAction[client_];
if(IdleTime_ > IdleTime)
Position++;
}
PrintCenterText(client, "You have been kick-flagged for being inactive. [%d/%d]", Position, FlaggedPlayers);
}
}
}
while(bKickPlayers)
{
int InactivePlayer = -1;
int InactivePlayerTime = 0;
for(client = 1; client <= MaxClients; client++)
{
if(!g_Players_bEnabled[client] || !g_Players_bFlagged[client])
continue;
int IdleTime = GetTime() - g_Players_iLastAction[client];
if(IdleTime >= g_fKickTime && IdleTime > InactivePlayerTime)
{
InactivePlayer = client;
InactivePlayerTime = IdleTime;
}
}
if(InactivePlayer == -1)
break;
else
{
PrintToChatAll("\x04[AFK] \x03%N\x01 was kicked for being AFK too long. (%d seconds)", InactivePlayer, InactivePlayerTime);
KickClient(InactivePlayer, "[AFK] You were kicked for being AFK too long. (%d seconds)", InactivePlayerTime);
Clients--;
g_Players_bFlagged[InactivePlayer] = false;
}
bKickPlayers = (Clients >= g_iKickMinPlayers && g_fKickTime > 0.0);
}
return Plugin_Continue;
}
public int Native_GetClientIdleTime(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if(client > MaxClients || client <= 0)
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid.");
return -1;
}
if(!IsClientInGame(client))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game.");
return -1;
}
if(IsFakeClient(client))
{
ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client.");
return -1;
}
if(!g_Players_bEnabled[client])
return 0;
return GetTime() - g_Players_iLastAction[client];
}

View File

@ -0,0 +1,24 @@
#if defined _AFKManager_Included
#endinput
#endif
#define _AFKManager_Included
native int GetClientIdleTime(int client);
public SharedPlugin __pl_AFKManager =
{
name = "AFKManager",
file = "AFKManager.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_PLUGIN
public __pl_AFKManager_SetNTVOptional()
{
MarkNativeAsOptional("GetClientIdleTime");
}
#endif

View File

@ -0,0 +1,233 @@
#include <sourcemod>
#include <cstrike>
#include <connect>
#undef REQUIRE_PLUGIN
#include <AFKManager>
#include <GFLClanru>
#include <entWatch>
#define REQUIRE_PLUGIN
#pragma semicolon 1
#pragma newdecls required
bool g_Plugin_AFKManager;
bool g_Plugin_GFLClanru;
bool g_Plugin_entWatch;
int g_Client_Reservation[MAXPLAYERS + 1] = {0, ...};
public Plugin myinfo =
{
name = "Reserved Slot",
author = "BotoX",
description = "Kicks someone to make space for a connecting donator.",
version = "1.0",
url = ""
};
public void OnPluginStart()
{
/* Late load */
for(int client = 1; client <= MaxClients; client++)
{
if(IsClientInGame(client) && !IsFakeClient(client) && IsClientAuthorized(client))
OnClientPostAdminCheck(client);
}
}
public void OnAllPluginsLoaded()
{
g_Plugin_AFKManager = LibraryExists("AFKManager");
g_Plugin_GFLClanru = LibraryExists("GFLClanru");
g_Plugin_entWatch = LibraryExists("entWatch");
LogMessage("ReservedSlots capabilities:\nAFKManager: %s\nGFLClanru: %s\nentWatch: %s",
(g_Plugin_AFKManager ? "loaded" : "not loaded"),
(g_Plugin_GFLClanru ? "loaded" : "not loaded"),
(g_Plugin_entWatch ? "loaded" : "not loaded"));
}
public void OnClientPostAdminCheck(int client)
{
AdminId admin = GetUserAdmin(client);
if(admin == INVALID_ADMIN_ID)
return;
if(GetAdminFlag(admin, Admin_Reservation))
{
g_Client_Reservation[client] = GetAdminImmunityLevel(admin);
if(!g_Client_Reservation[client])
g_Client_Reservation[client] = 1;
}
}
public void OnClientDisconnect(int client)
{
g_Client_Reservation[client] = 0;
}
public EConnect OnClientPreConnectEx(const char[] sName, char sPassword[255], const char[] sIP, const char[] sSteam32ID, char sRejectReason[255])
{
// Server not full, nothing to do...
if(GetClientCount(false) < MaxClients)
return k_OnClientPreConnectEx_Accept;
// Try to get precached admin id.
AdminId admin = FindAdminByIdentity(AUTHMETHOD_STEAM, sSteam32ID);
int Immunity = 0;
// Valid and has reserved slot?
if(admin != INVALID_ADMIN_ID && GetAdminFlag(admin, Admin_Reservation))
{
Immunity = GetAdminImmunityLevel(admin);
if(!KickValidClient(sName, sSteam32ID, admin, Immunity))
{
Format(sRejectReason, sizeof(sRejectReason), "No reserved slot available, sorry.");
return k_OnClientPreConnectEx_Reject;
}
else
return k_OnClientPreConnectEx_Accept;
}
if(g_Plugin_GFLClanru)
{
DataPack pack = new DataPack();
pack.WriteCell(admin);
pack.WriteCell(Immunity);
pack.WriteString(sName);
AsyncHasSteamIDReservedSlot(sSteam32ID, AsyncHasSteamIDReservedSlotCallback, pack);
return k_OnClientPreConnectEx_Async;
}
// Let the engine handle the rest.
return k_OnClientPreConnectEx_Accept;
}
public void AsyncHasSteamIDReservedSlotCallback(const char[] sSteam32ID, int Result, any Data)
{
DataPack pack = view_as<DataPack>(Data);
// Slot free'd up while waiting or doesn't have a reserved slot?
if(GetClientCount(false) < MaxClients || Result <= 0)
{
delete pack;
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Accept, "");
return;
}
pack.Reset();
AdminId admin = view_as<AdminId>(pack.ReadCell());
int Immunity = pack.ReadCell();
char sName[MAX_NAME_LENGTH];
pack.ReadString(sName, sizeof(sName));
delete pack;
if(Result > Immunity)
Immunity = Result;
if(!KickValidClient(sName, sSteam32ID, admin, Immunity))
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Reject, "No reserved slot available, sorry.");
else
ClientPreConnectEx(sSteam32ID, k_OnClientPreConnectEx_Accept, "");
}
stock bool KickValidClient(const char[] sName, const char[] sSteam32ID, AdminId admin, int Immunity)
{
int HighestValue[4] = {0, ...};
int HighestValueClient[4] = {0, ...};
for(int client = 1; client <= MaxClients; client++)
{
if(!IsClientInGame(client) || IsFakeClient(client))
continue;
int Donator = g_Client_Reservation[client];
int ConnectionTime = RoundToNearest(GetClientTime(client));
int IdleTime;
if(g_Plugin_AFKManager)
IdleTime = GetClientIdleTime(client);
else // Fall back to highest connection time.
IdleTime = ConnectionTime;
bool HasItem = false;
if(g_Plugin_entWatch)
HasItem = entWatch_HasSpecialItem(client);
/* Spectators
* Sort by idle time and also kick donators if IdleTime > 30
*/
if(GetClientTeam(client) <= CS_TEAM_SPECTATOR)
{
if(!Donator || IdleTime > 30)
{
if(IdleTime > HighestValue[0])
{
HighestValue[0] = IdleTime;
HighestValueClient[0] = client;
}
}
}
/* Spectators */
/* Dead non-donator with IdleTime > 30
* Sort by idle time and don't kick donators.
*/
if(!Donator && GetClientTeam(client) > CS_TEAM_SPECTATOR && !IsPlayerAlive(client))
{
if(IdleTime > 30 && IdleTime > HighestValue[1])
{
HighestValue[1] = IdleTime;
HighestValueClient[1] = client;
}
}
/* Dead non-donator with IdleTime > 30 */
/* Alive non-donator with IdleTime > 30
* Sort by idle time and don't kick donators and item owners.
*/
if(!Donator && IsPlayerAlive(client) && !HasItem)
{
if(IdleTime > 30 && IdleTime > HighestValue[2])
{
HighestValue[2] = IdleTime;
HighestValueClient[2] = client;
}
}
/* Alive non-donator with IdleTime > 30 */
/* Non-donator with highest connection time
* Sort by connection time and don't kick donators and item owners.
*/
if(!Donator && !HasItem)
{
if(ConnectionTime > HighestValue[3])
{
HighestValue[3] = ConnectionTime;
HighestValueClient[3] = client;
}
}
/* Non-donator with highest connection time */
}
// Check if any condition was met in the correct order and perform kick
for(int i = 0; i < sizeof(HighestValue); i++)
{
if(HighestValue[i])
{
ExecuteKickValidClient(HighestValueClient[i], sName, sSteam32ID, admin, Immunity);
return true;
}
}
return false;
}
stock void ExecuteKickValidClient(int client, const char[] sName, const char[] sSteam32ID, AdminId admin, int Immunity)
{
KickClientEx(client, "Kicked for reserved slot (%s joined).", sName);
}

View File

@ -0,0 +1 @@
../../../AFKManager/scripting/include/AFKManager.inc