#pragma semicolon 1
#include <sourcemod>
#include <clientprefs>
#define PLUGIN_VERSION "1.3"
#define MAX_LINES 40
#define BUFFER 512
new g_TotalRounds;
new i_info[MAXPLAYERS+1];
new kills, deaths, String:s_Kills[8], String:s_Deaths[8];
new Handle:g_Cvar_WinLimit;
new Handle:g_Cvar_FragLimit;
new Handle:g_Cvar_MaxRounds;
new Handle:cookieResPref;
new Handle:h_AdminFlag, String:s_adminflag[12];
new String:s_Buffer[BUFFER], bool:IsAdmin[MAXPLAYERS+1];
new Handle:h_ServerName;
new String:s_ServerName[64], String:s_MapName[33], String:s_NextMapName[33],
String:s_Time[32], String:s_Date[32], String:s_TimeLeft[64], String:s_Admins[512],
String:s_InGame[10], String:s_Total[10], String:s_Connecting[10];
ConVar Hud_x;
ConVar Hud_y;
ConVar Hud_Timer;
ConVar Hud_Time;
ConVar Hud_color_r;
ConVar Hud_color_g;
ConVar Hud_color_b;
ConVar Hud_Alive;
public Plugin:myinfo =
{
name = "Hud Info",
author = "FrozDark (rework by Drumanid for CS:GO)",
description = "Hud Info",
version = PLUGIN_VERSION,
url = "www.hlmod.ru"
}
public OnPluginStart()
{
LoadTranslations("common.phrases");
LoadTranslations("basetriggers.phrases");
h_AdminFlag = CreateConVar("sm_hudinfo_admin_flag", "b", "Флаг администратора для отображения в hud. Оставьте поле пустым для любого флага");
Hud_x = CreateConVar("Hud_x", "0.0", "Позиция худа в x");
Hud_y = CreateConVar("Hud_y", "0.0", "Позиция худа в y");
Hud_Timer = CreateConVar("Hud_Timer", "5.0", "Время демонстрации худа игрокам");
Hud_Time = CreateConVar("Hud_Time", "3.0", "Время задержки худа игрокам");
Hud_color_r = CreateConVar("Hud_color_r", "255", "Цвет RGB | Красный");
Hud_color_g = CreateConVar("Hud_color_g", "255", "Цвет RGB | Зеленый");
Hud_color_b = CreateConVar("Hud_color_b", "255", "Цвет RGB | Синий");
Hud_Alive = CreateConVar("Hud_Alive", "1", "Показывать худ только мертвым игрокам? | 1 - включить / 0 - выключить");
h_ServerName = FindConVar("hostname");
g_Cvar_WinLimit = FindConVar("mp_winlimit");
g_Cvar_FragLimit = FindConVar("mp_fraglimit");
g_Cvar_MaxRounds = FindConVar("mp_maxrounds");
GetConVarString(h_ServerName, s_ServerName, sizeof(s_ServerName));
HookConVarChange(h_ServerName, OnCvarChange);
HookConVarChange(h_AdminFlag, OnCvarChange);
new info;
RegConsoleCmd("sm_info", Command_Info, "Shows the server's information");
cookieResPref = RegClientCookie("Hud Info", "Hud Info", CookieAccess_Private);
SetCookieMenuItem(InfoPrefSelected, any:info, "Hud Info");
RegAdminCmd("sm_hudinfo_reload", ParseInfo, ADMFLAG_ROOT, "Reloads the information list");
decl String:folder[64];
GetGameFolderName(folder, sizeof(folder));
if (!strcmp(folder, "insurgency"))
{
HookEvent("game_newmap", Event_GameStart);
}
else
{
HookEvent("game_start", Event_GameStart);
}
HookEvent("round_end", Event_RoundEnd);
HookEventEx("teamplay_win_panel", Event_TeamPlayWinPanel);
HookEventEx("teamplay_restart_round", Event_TFRestartRound);
HookEventEx("arena_win_panel", Event_TeamPlayWinPanel);
AutoExecConfig(true, "Hud_info");
}
public OnMapStart()
{
g_TotalRounds = 0;
GetCurrentMap(s_MapName, sizeof(s_MapName));
CreateTimer(GetConVarFloat(Hud_Timer), UpdateHud, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
ParseInfo(0, 0);
}
public Action:Command_Info(client, args)
{
if (!i_info[client])
i_info[client] = 1;
else
i_info[client] = 0;
PrintToChat(client, " \x04[\x01HudInfo\x04] Показ информации %s", i_info[client] ? "включен" : "выключен");
decl String:buffer[5];
IntToString(i_info[client], buffer, sizeof(buffer));
SetClientCookie(client, cookieResPref, buffer);
return Plugin_Handled;
}
public Action:ParseInfo(client, args)
{
new count, String:Lines[MAX_LINES+1][256], String:s_Path[PLATFORM_MAX_PATH];
BuildPath(Path_SM, s_Path, sizeof(s_Path), "data/hud_info/");
if (!DirExists(s_Path))
CreateDirectory(s_Path, 511);
BuildPath(Path_SM, s_Path, sizeof(s_Path), "data/hud_info/%s.txt", s_MapName);
if (!FileExists(s_Path))
{
BuildPath(Path_SM, s_Path, sizeof(s_Path), "data/hud_info/all.txt", s_MapName);
if (!FileExists(s_Path))
SetFailState("No info-file found for the current map in the sourcemod/data/hud_info/ folder");
}
new Handle:file = OpenFile(s_Path, "r");
if (file == INVALID_HANDLE)
SetFailState("Can not open file - %s", s_Path);
while (!IsEndOfFile(file) && count < MAX_LINES)
{
s_Path[0] = '\0';
ReadFileLine(file, s_Path, sizeof(s_Path));
new pos;
pos = StrContains((s_Path), "//");
if (pos != -1)
s_Path[pos] = '\0';
pos = StrContains((s_Path), "#");
if (pos != -1)
s_Path[pos] = '\0';
pos = StrContains((s_Path), ";");
if (pos != -1)
s_Path[pos] = '\0';
TrimString(s_Path);
if (s_Path[0] == '\0')
continue;
strcopy(Lines[count], sizeof(Lines[]), s_Path);
count++;
}
ImplodeStrings(Lines, count, "\n", s_Buffer, sizeof(s_Buffer));
return Plugin_Handled;
}
/* Round count tracking */
public Event_TFRestartRound(Handle:event, const String:name[], bool:dontBroadcast)
{
/* Game got restarted - reset our round count tracking */
g_TotalRounds = 0;
}
public Event_GameStart(Handle:event, const String:name[], bool:dontBroadcast)
{
/* Game got restarted - reset our round count tracking */
g_TotalRounds = 0;
}
public Event_TeamPlayWinPanel(Handle:event, const String:name[], bool:dontBroadcast)
{
if(GetEventInt(event, "round_complete") == 1 || StrEqual(name, "arena_win_panel"))
{
g_TotalRounds++;
}
}
/* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */
public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
g_TotalRounds++;
}
loadClientCookiesFor(client)
{
new String:buffer[5];
GetClientCookie(client, cookieResPref, buffer, sizeof(buffer));
i_info[client] = buffer[0] ? StringToInt(buffer) : 0;
}
public OnClientPostAdminCheck(client)
{
new AdminId:adminid = GetUserAdmin(client);
new AdminFlag:flag;
if (adminid != INVALID_ADMIN_ID)
{
if(!s_adminflag[0])
IsAdmin[client] = true;
else if (FindFlagByChar(s_adminflag[0], flag))
{
if (GetAdminFlag(adminid, flag))
IsAdmin[client] = true;
}
else
IsAdmin[client] = false;
}
else
IsAdmin[client] = false;
GetAdmins(s_Admins, sizeof(s_Admins));
i_info[client] = true;
}
public OnClientConnected(client)
{
new ClientConn = GetClientCount(false);
new ClientGame = GetClientCount(true);
new ClientLimbo = ClientConn - ClientGame;
IntToString(ClientConn, s_Total, sizeof(s_Total));
IntToString(ClientGame, s_InGame, sizeof(s_InGame));
IntToString(ClientLimbo, s_Connecting, sizeof(s_Connecting));
}
public OnClientPutInServer(client)
{
if (!IsFakeClient(client))
{
if(AreClientCookiesCached(client))
loadClientCookiesFor(client);
}
new ClientConn = GetClientCount(false);
new ClientGame = GetClientCount(true);
new ClientLimbo = ClientConn - ClientGame;
IntToString(ClientConn, s_Total, sizeof(s_Total));
IntToString(ClientGame, s_InGame, sizeof(s_InGame));
IntToString(ClientLimbo, s_Connecting, sizeof(s_Connecting));
}
public OnClientDisconnect(client)
{
IsAdmin[client] = false;
GetAdmins(s_Admins, sizeof(s_Admins));
new ClientConn = GetClientCount(false);
new ClientGame = GetClientCount(true);
new ClientLimbo = ClientConn - ClientGame;
IntToString(ClientConn, s_Total, sizeof(s_Total));
IntToString(ClientGame, s_InGame, sizeof(s_InGame));
IntToString(ClientLimbo, s_Connecting, sizeof(s_Connecting));
}
public Action:UpdateHud(Handle:timer)
{
decl String:buf[BUFFER];
FormatTime(s_Time, sizeof(s_Time), "%H:%M:%S");
FormatTime(s_Date, sizeof(s_Date), "%d.%m.%Y");
GetNextMap(s_NextMapName, sizeof(s_NextMapName));
for (new i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i) && !IsFakeClient(i) && i_info[i])
{
GetTimeLeft(i, s_TimeLeft, sizeof(s_TimeLeft));
kills = Client_GetScore(i);
IntToString(kills, s_Kills, sizeof(s_Kills));
deaths = Client_GetDeaths(i);
IntToString(deaths, s_Deaths, sizeof(s_Deaths));
strcopy(buf, sizeof(buf), s_Buffer);
ReplaceString(buf, sizeof(buf), "{CONNECTING}", s_Connecting, false);
ReplaceString(buf, sizeof(buf), "{CURRENTMAP}", s_MapName, false);
ReplaceString(buf, sizeof(buf), "{HOSTNAME}", s_ServerName, false);
ReplaceString(buf, sizeof(buf), "{TIMELEFT}", s_TimeLeft, false);
ReplaceString(buf, sizeof(buf), "{NEXTMAP}", s_NextMapName, false);
ReplaceString(buf, sizeof(buf), "{INGAME}", s_InGame, false);
ReplaceString(buf, sizeof(buf), "{ADMINS}", s_Admins, false);
ReplaceString(buf, sizeof(buf), "{DEATHS}", s_Deaths, false);
ReplaceString(buf, sizeof(buf), "{KILLS}", s_Kills, false);
ReplaceString(buf, sizeof(buf), "{TOTAL}", s_Total, false);
ReplaceString(buf, sizeof(buf), "{TIME}", s_Time, false);
ReplaceString(buf, sizeof(buf), "{DATE}", s_Date, false);
if(GetConVarInt(Hud_Alive) == 0)
{
Client_PrintKeyHintText(i, buf);
}
else if(GetConVarInt(Hud_Alive) == 1 && !IsPlayerAlive(i))
{
Client_PrintKeyHintText(i, buf);
}
}
}
}
public OnCvarChange(Handle:convar, const String:oldValue[], const String:newValue[])
{
if (convar == h_ServerName)
strcopy(s_ServerName, sizeof(s_ServerName), newValue);
else if (convar == h_AdminFlag)
{
if (!StrEqual(oldValue, newValue, false))
{
strcopy(s_adminflag, sizeof(s_adminflag), newValue);
for (new i = 1; i <= MaxClients; i++)
{
if (IsClientAuthorized(i))
OnClientPostAdminCheck(i);
}
}
}
}
public InfoPrefSelected(client, CookieMenuAction:action, any:info, String:buffer[], maxlen)
{
switch (action)
{
case CookieMenuAction_DisplayOption :
{
decl String:status[10];
Format(status, sizeof(status), "%T", i_info[client] ? "On" : "Off", client);
Format(buffer, maxlen, "Показ информации: %s", status);
}
default :
{
switch (i_info[client])
{
case 0 :
i_info[client] = 1;
default :
i_info[client] = 0;
}
ShowCookieMenu(client);
}
}
}
stock GetAdmins(String:buffer[], size)
{
new count, String:AdminNames[MAXPLAYERS+1][MAX_NAME_LENGTH+1];
for (new i = 1; i <= MaxClients; i++)
{
if (IsAdmin[i])
{
GetClientName(i, AdminNames[count], sizeof(AdminNames[]));
count++;
}
}
ImplodeStrings(AdminNames, count, ", ", buffer, size);
}
stock GetTimeLeft(client, String:finalOutput[], size)
{
new bool:lastround = false;
new bool:written = false;
new bool:notimelimit = false;
new timeleft;
if (GetMapTimeLeft(timeleft))
{
new mins, secs;
new timelimit;
if (timeleft > 0)
{
mins = timeleft / 60;
secs = timeleft % 60;
written = true;
Format(finalOutput, size, "%d:%02d", mins, secs);
}
else if (GetMapTimeLimit(timelimit) && timelimit == 0)
{
notimelimit = true;
}
else
{
/* 0 timeleft so this must be the last round */
lastround=true;
}
}
if (!lastround)
{
if (g_Cvar_WinLimit != INVALID_HANDLE)
{
new winlimit = GetConVarInt(g_Cvar_WinLimit);
if (winlimit > 0)
{
if (written)
{
new len = strlen(finalOutput);
if (len < size)
{
if (winlimit > 1)
{
FormatEx(finalOutput[len], size-len, "%T", "WinLimitAppendPlural" ,client, winlimit);
}
else
{
FormatEx(finalOutput[len], size-len, "%T", "WinLimitAppend" ,client);
}
}
}
else
{
if (winlimit > 1)
{
FormatEx(finalOutput, size, "%T", "WinLimitPlural", client, winlimit);
}
else
{
FormatEx(finalOutput, size, "%T", "WinLimit", client);
}
written = true;
}
}
}
if (g_Cvar_FragLimit != INVALID_HANDLE)
{
new fraglimit = GetConVarInt(g_Cvar_FragLimit);
if (fraglimit > 0)
{
if (written)
{
new len = strlen(finalOutput);
if (len < size)
{
if (fraglimit > 1)
{
FormatEx(finalOutput[len], size-len, "%T", "FragLimitAppendPlural", client, fraglimit);
}
else
{
FormatEx(finalOutput[len], size-len, "%T", "FragLimitAppend", client);
}
}
}
else
{
if (fraglimit > 1)
{
FormatEx(finalOutput, size, "%T", "FragLimitPlural", client, fraglimit);
}
else
{
FormatEx(finalOutput, size, "%T", "FragLimit", client);
}
written = true;
}
}
}
if (g_Cvar_MaxRounds != INVALID_HANDLE)
{
new maxrounds = GetConVarInt(g_Cvar_MaxRounds);
if (maxrounds > 0)
{
new remaining = maxrounds - g_TotalRounds;
if (written)
{
new len = strlen(finalOutput);
if (len < size)
{
if (remaining > 1)
{
FormatEx(finalOutput[len], size-len, "%T", "MaxRoundsAppendPlural", client, remaining);
}
else
{
FormatEx(finalOutput[len], size-len, "%T", "MaxRoundsAppend", client);
}
}
}
else
{
if (remaining > 1)
{
FormatEx(finalOutput, size, "%T", "MaxRoundsPlural", client, remaining);
}
else
{
FormatEx(finalOutput, size, "%T", "MaxRounds", client);
}
written = true;
}
}
}
}
if (lastround)
{
FormatEx(finalOutput, size, "%T", "LastRound", client);
}
else if (notimelimit && !written)
{
FormatEx(finalOutput, size, "%T", "NoTimelimit", client);
}
}
stock bool:Client_PrintKeyHintText(client, const String:format[], any:...)
{
decl String:buffer[254];
SetGlobalTransTarget(client);
VFormat(buffer, sizeof(buffer), format, 3);
SetHudTextParams(GetConVarFloat(Hud_x), GetConVarFloat(Hud_y), GetConVarFloat(Hud_Time), GetConVarInt(Hud_color_r), GetConVarInt(Hud_color_g), GetConVarInt(Hud_color_b), 255, 0, 0.0, 0.0, 0.0);
ShowHudText(client, -1, buffer);
}
stock Client_GetDeaths(client)
{
return GetEntProp(client, Prop_Data, "m_iDeaths");
}
stock Client_GetScore(client)
{
return GetClientFrags(client);
}