#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#tryinclude <jenkins>
#define VERSION "1.4fix"
#if !defined BUILD
#define BUILD "0"
#endif
#define SPECTATOR 1
#define JOIN_MESSAGE "Player %N has joined the game"
#define QUIT_MESSAGE "Player %N left the game (Disconnected by user.)"
public Plugin:myinfo =
{
name = "Admin Stealth",
author = "necavi",
description = "Allows administrators to become nearly completely invisible.",
version = VERSION,
url = "
http://necavi.org/"
}
new bool:g_bIsInvisible[MAXPLAYERS + 1];
new g_iSpectateTarget[MAXPLAYERS + 1];
new Float:g_fLastSpecChange[MAXPLAYERS + 1];
new g_iOldTeam[MAXPLAYERS + 1];
new Handle:g_hHostname = INVALID_HANDLE;
public OnPluginStart()
{
CreateConVar("sm_adminstealth_version", VERSION);
CreateConVar("sm_adminstealth_build", BUILD);
RegAdminCmd("sm_stealth", Command_Stealth, ADMFLAG_CUSTOM3, "Allows an administrator to toggle complete invisibility on themselves.");
g_hHostname = FindConVar("hostname");
AddCommandListener(Command_JoinTeam, "jointeam");
AddCommandListener(Command_Status, "status");
HookEventEx("round_prestart", Event_RoundPrestart, EventHookMode_PostNoCopy);
HookEventEx("round_poststart", Event_RoundPoststart, EventHookMode_PostNoCopy);
}
public OnClientDisconnect(client)
{
if(g_bIsInvisible[client]) InvisOff(client, false);
}
public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2])
{
if(g_bIsInvisible[client] && buttons & IN_JUMP && GetGameTime() > g_fLastSpecChange[client] + 1.0)
{
static current_target, new_target;
current_target = GetClientOfUserId(g_iSpectateTarget[client]);
for(new i = current_target + 1; i <= MaxClients + current_target; i++)
{
new_target = (i >= MaxClients) ? i % MaxClients : i;
PrintToChat(client, "current_target: %d new_target = %d", current_target, new_target);
if(new_target != client && ValidPlayer(new_target) && IsPlayerAlive(new_target))
{
g_iSpectateTarget[client] = GetClientUserId(new_target);
decl Float:target_origin[3], Float:target_angles[3];
GetClientAbsOrigin(new_target, target_origin);
GetClientEyeAngles(new_target, target_angles);
TeleportEntity(client, target_origin, target_angles, NULL_VECTOR);
g_fLastSpecChange[client] = GetGameTime();
return Plugin_Continue;
}
}
}
return Plugin_Continue;
}
public Action:Command_JoinTeam(client, const String:command[], args)
{
if(g_bIsInvisible[client])
{
PrintToChat(client, "[SM] Can not join team when in invisible mode!");
return Plugin_Handled;
}
return Plugin_Continue;
}
public Action:Event_WeaponCanUse(client,weapon)
{
return Plugin_Handled;
}
public Action:Command_Status(client, const String:command[], args)
{
if(CheckCommandAccess(client, "sm_stealth", 0))
{
return Plugin_Continue;
}
decl String:buffer[64];
GetConVarString(g_hHostname,buffer,sizeof(buffer));
PrintToConsole(client,"hostname: %s",buffer);
PrintToConsole(client,"version : 1909615/24 1909615 secure");
GetCurrentMap(buffer,sizeof(buffer));
decl Float:vec[3];
GetClientAbsOrigin(client, vec);
PrintToConsole(client,"map : %s at: %.0f x, %.0f y, %.0f z", buffer, vec[0], vec[1], vec[2]);
PrintToConsole(client,"players : %d (%d max)", GetClientCount() - GetInvisCount(), MaxClients);
PrintToConsole(client,"# userid name uniqueid connected ping loss state");
decl String:name[18], String:steamID[19], String:time[9];
for(new i = 1; i <= MaxClients; i++)
{
if(ValidPlayer(i))
{
if(!g_bIsInvisible
)
{
Format(name,sizeof(name),"\"%N\"",i);
#if SOURCEMOD_V_MAJOR > 1 || SOURCEMOD_V_MINOR > 5
GetClientAuthId(i,AuthId_Engine,steamID,sizeof(steamID));
#else
GetClientAuthString(i,steamID,sizeof(steamID));
#endif
if(!IsFakeClient(i))
{
FormatShortTime(RoundToFloor(GetClientTime(i)),time,sizeof(time));
PrintToConsole(client,"# %6d %-19s %19s %9s %4d %4d active", GetClientUserId(i),
name, steamID, time, RoundToFloor(GetClientAvgLatency(i,NetFlow_Both) * 1000.0),
RoundToFloor(GetClientAvgLoss(i,NetFlow_Both) * 100.0));
}
else
{
PrintToConsole(client,"# %6d %-19s %19s active", GetClientUserId(i), name, steamID);
}
}
}
}
return Plugin_Stop;
}
public Action:Command_Stealth(client, args)
{
if(client)
{
ToggleInvis(client);
LogAction(client, -1, "%N has toggled stealth mode.", client);
}
return Plugin_Handled;
}
ToggleInvis(client)
{
if(g_bIsInvisible[client]) InvisOff(client);
else InvisOn(client);
}
InvisOff(client, bool:stop=true, bool:announce=true)
{
g_bIsInvisible[client] = !announce;
if(stop)
{
SetEntProp(client, Prop_Send, "m_iTeamNum", g_iOldTeam[client]);
if(GetClientTeam(client) != SPECTATOR)
{
SetEntProp(client, Prop_Send, "m_lifeState", 0);
SetEntProp(client, Prop_Data, "m_takedamage", 2);
SetEntityMoveType(client, MOVETYPE_ISOMETRIC);
SDKUnhook(client, SDKHook_WeaponCanUse, Event_WeaponCanUse);
if(IsPlayerAlive(client)) GivePlayerItem(client, "weapon_knife");
if(announce) PrintToChat(client, "You are no longer in stealth mode.");
}
}
if(announce) PrintToChatAll(JOIN_MESSAGE, client);
}
InvisOn(client, bool:announce=true)
{
g_bIsInvisible[client] = true;
g_iOldTeam[client] = GetEntProp(client,Prop_Send,"m_iTeamNum");
SetEntProp(client, Prop_Send, "m_iTeamNum", 4);
if(GetClientTeam(client) != SPECTATOR)
{
SetEntProp(client, Prop_Send, "m_lifeState",2);
SetEntProp(client, Prop_Data, "m_takedamage",0);
SetEntityMoveType(client, MOVETYPE_NOCLIP);
new entity = CreateEntityByName("player_weaponstrip");
AcceptEntityInput(entity, "strip", client);
AcceptEntityInput(entity, "kill");
SDKHook(client, SDKHook_WeaponCanUse, Event_WeaponCanUse);
}
if(announce)
{
PrintToChat(client, "You are now in stealth mode.");
PrintToChatAll(QUIT_MESSAGE, client);
}
}
bool:ValidPlayer(client)
{
return client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client);
}
FormatShortTime(time, String:outTime[], size)
{
new temp;
temp = time % 60;
Format(outTime, size,"%02d",temp);
temp = (time % 3600) / 60;
Format(outTime, size,"%02d:%s", temp, outTime);
temp = (time % 86400) / 3600;
if(temp > 0)
{
Format(outTime, size, "%d%:s", temp, outTime);
}
}
GetInvisCount()
{
new count = 0;
for(new i = 1; i <= MaxClients; i++)
{
if(g_bIsInvisible)
{
count++;
}
}
return count;
}
public Event_RoundPrestart(Handle:event, String:name[], bool:dontBroadcast)
{
for (new i = 1; i <= MaxClients; ++i)
{
if(g_bIsInvisible) InvisOff(i, true, false);
}
}
public Event_RoundPoststart(Handle:event, String:name[], bool:dontBroadcast)
{
for (new i = 1; i <= MaxClients; ++i)
{
if(g_bIsInvisible) InvisOn(i, false);
}
}