PHP Code:
/*
* HexTags Plugin.
* by: Hexah
* https://github.com/Hexer10/HexTags
*
* Copyright (C) 2017 Mattia (Hexah|Hexer10|Papero)
*
* This file is part of the HexTags SourceMod Plugin.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sourcemod>
#include <sdktools>
#include <chat-processor>
#include <geoip>
#include <hextags>
#undef REQUIRE_EXTENSIONS
#undef REQUIRE_PLUGIN
#include <mostactive>
#include <cstrike>
#include <rankme>
#define REQUIRE_EXTENSIONS
#define REQUIRE_PLUGIN
#define PLUGIN_AUTHOR "Hexah"
#define PLUGIN_VERSION "<TAG>"
#pragma semicolon 1
#pragma newdecls required
Handle fTagsUpdated;
bool bLate;
bool bMostActive;
char newCountry[3];
char sTags[MAXPLAYERS+1][eTags][128];
char g_szRankMetag[MAXPLAYERS+1][32];
KeyValues kv;
//Plugin infos
public Plugin myinfo =
{
name = "hextags",
author = PLUGIN_AUTHOR,
description = "Edit Tags & Colors!",
version = PLUGIN_VERSION,
url = "github.com/Hexer10/HexTags"
};
//Startup
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
//API
RegPluginLibrary("hextags");
CreateNative("HexTags_GetClientTag", Native_GetClientTag);
CreateNative("HexTags_SetClientTag", Native_SetClientTag);
CreateNative("HexTags_ResetClientTag", Native_ResetClientTags);
fTagsUpdated = CreateGlobalForward("HexTags_OnTagsUpdated", ET_Ignore, Param_Cell);
//LateLoad
bLate = late;
return APLRes_Success;
}
public void OnPluginStart()
{
CreateConVar("sm_hextags_version", PLUGIN_VERSION, "HexTags plugin version", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
//Reg Cmds
RegAdminCmd("sm_reloadtags", Cmd_ReloadTags, ADMFLAG_BAN, "Reload HexTags plugin config");
RegConsoleCmd("sm_getteam", Cmd_GetTeam, "Get current team name");
RegConsoleCmd("sm_settag", Cmd_SetTag, "Reload Scoreboard Tags.");
HookEvent("round_end", Event_RoundEnd);
HookEvent("player_connect_full", Event_OnFullConnect, EventHookMode_Post);
LoadKv();
//LateLoad
if (bLate)
{
for (int i = 1; i <= MaxClients; i++)if (IsClientInGame(i))
{
OnClientPostAdminCheck(i);
Frame_SetTag(GetClientUserId(i));
}
}
}
public void OnAllPluginsLoaded()
{
bMostActive = LibraryExists("mostactive");
}
public void OnLibraryAdded(const char[] name)
{
if (StrEqual(name, "mostactive"))
bMostActive = true;
}
public void OnLibraryRemoved(const char[] name)
{
if (StrEqual(name, "mostactive"))
bMostActive = false;
}
//Thanks to https://forums.alliedmods.net/showpost.php?p=2573907&postcount=6
public Action OnClientCommandKeyValues(int client, KeyValues TagKv)
{
char sKey[64];
if (!TagKv.GetSectionName(sKey, sizeof(sKey)))
return Plugin_Continue;
if(StrEqual(sKey, "ClanTagChanged"))
{
RequestFrame(Frame_SetTag, GetClientUserId(client));
}
return Plugin_Continue;
}
public void Frame_SetTag(any iUserID)
{
int client = GetClientOfUserId(iUserID);
LoadTags(client);
if (strlen(sTags[client][ScoreTag]) > 0 && IsCS())
CS_SetClientClanTag(client, sTags[client][ScoreTag]);
}
public void OnClientDisconnect(int client)
{
ResetTags(client);
}
//Commands
public Action Cmd_ReloadTags(int client, int args)
{
LoadKv();
for (int i = 1; i <= MaxClients; i++)
if (IsClientInGame(i))
{
LoadTags(i);
SetClantag(i);
}
ReplyToCommand(client, "[SM] Tags succesfully reloaded!");
return Plugin_Handled;
}
public Action Cmd_GetTeam(int client, int args)
{
char sTeam[32];
GetTeamName(GetClientTeam(client), sTeam, sizeof(sTeam));
ReplyToCommand(client, "[SM] Current team name: %s", sTeam);
return Plugin_Handled;
}
public Action Cmd_SetTag(int client, int args)
{
if(IsValidClient(client))
SetClantag(client);
}
//Events
public int GetClientRankCallback(int client, int rank, any data)
{
if(IsFakeClient(client))
strcopy(g_szRankMetag[client], 32, "");
else if(rank == 0)
strcopy(g_szRankMetag[client], 32, "[No Rank]");
else
Format(g_szRankMetag[client], 32, "[Rank %d]", rank);
}
public Action Timer_Settag(Handle timer)
{
for(int c = 1; c <= MaxClients; c++)
{
if(IsValidClient(c))
{
RankMe_GetRank(c, GetClientRankCallback);
SetClantag(c);
}
}
}
public void OnClientPutInServer(int client)
{
//Update params
char sIP[32];
GetClientIP(client, sIP, sizeof(sIP));
GeoipCode2(sIP, newCountry);
}
public void OnClientPostAdminCheck(int client)
{
LoadTags(client);
}
public void Event_OnFullConnect(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(IsValidClient(client) && IsCS)
{
CreateTimer(2.0, Timer_Settag);
}
}
public void Event_RoundEnd(Handle event, char[] name, bool dbc)
{
if(IsCS)
{
for(int c = 1; c <= MaxClients; c++)
{
if(IsClientInGame(c))
{
RankMe_GetRank(c, GetClientRankCallback);
SetClantag(c);
}
}
}
}
void SetClantag(int client)
{
ReplaceString(sTags[client][ScoreTag], sizeof(sTags[][]), "{rank}", g_szRankMetag[client]);
ReplaceString(sTags[client][ScoreTag], sizeof(sTags[][]), "{country}", newCountry);
if (strlen(sTags[client][ScoreTag]) > 0 && IsCS() && IsValidClient(client))
CS_SetClientClanTag(client, sTags[client][ScoreTag]);
}
public Action CP_OnChatMessage(int& author, ArrayList recipients, char[] flagstring, char[] name, char[] message, bool& processcolors, bool& removecolors)
{
//Add colors & tags
char sNewName[MAXLENGTH_NAME];
char sNewMessage[MAXLENGTH_MESSAGE];
Format(sNewName, MAXLENGTH_NAME, "%s%s%s{default}", sTags[author][ChatTag], sTags[author][NameColor], name);
Format(sNewMessage, MAXLENGTH_MESSAGE, "%s%s", sTags[author][ChatColor], message);
//Update the params
char sTime[16];
FormatTime(sTime, sizeof(sTime), "%H:%M");
ReplaceString(sNewName, sizeof(sNewName), "{time}", sTime);
ReplaceString(sNewMessage, sizeof(sNewMessage), "{time}", sTime);
char sIP[32];
char sCountry[3];
GetClientIP(author, sIP, sizeof(sIP));
GeoipCode2(sIP, sCountry);
ReplaceString(sNewName, sizeof(sNewName), "{country}", sCountry);
ReplaceString(sNewMessage, sizeof(sNewMessage), "{country}", sCountry);
ReplaceString(sNewName, sizeof(sNewName), "{rank}", g_szRankMetag[author]);
ReplaceString(sNewMessage, sizeof(sNewMessage), "{rank}", g_szRankMetag[author]);
//Rainbow Chat
if (StrEqual(sTags[author][ChatColor], "{rainbow}", false))
{
ReplaceString(sNewMessage, sizeof(sNewMessage), "{rainbow}", "");
char sTemp[MAXLENGTH_MESSAGE];
int sub = -1;
for(int i = 0; i < strlen(sNewMessage); i++)
{
if (sNewMessage[i] == ' ')
{
Format(sTemp, sizeof(sTemp), "%s%c", sTemp, sNewMessage[i]);
sub++;
continue;
}
Format(sTemp, sizeof(sTemp), "%s%c%c", sTemp, GetColor(i-sub), sNewMessage[i]);
}
Format(sNewMessage, MAXLENGTH_MESSAGE, "%s", sTemp);
}
//Random Chat
if (StrEqual(sTags[author][ChatColor], "{random}", false))
{
ReplaceString(sNewMessage, sizeof(sNewMessage), "{random}", "");
char sTemp[MAXLENGTH_MESSAGE];
for(int i = 0; i < strlen(sNewMessage); i++)
{
if (sNewMessage[i] == ' ')
{
Format(sTemp, sizeof(sTemp), "%s%c", sTemp, sNewMessage[i]);
continue;
}
Format(sTemp, sizeof(sTemp), "%s%c%c", sTemp, GetRandomColor(), sNewMessage[i]);
}
Format(sNewMessage, MAXLENGTH_MESSAGE, "%s", sTemp);
}
//Update the name & message
strcopy(name, MAXLENGTH_NAME, sNewName);
strcopy(message, MAXLENGTH_MESSAGE, sNewMessage);
processcolors = true;
removecolors = false;
return Plugin_Changed;
}
//Functions
void LoadKv()
{
char sConfig[PLATFORM_MAX_PATH];
BuildPath(Path_SM, sConfig, sizeof(sConfig), "configs/hextags.cfg"); //Get cfg file
if (OpenFile(sConfig, "rt") == null)
SetFailState("Couldn't find: \"%s\"", sConfig); //Check if cfg exist
if (kv != null)
delete kv;
kv = new KeyValues("HexTags"); //Create the kv
if (!kv.ImportFromFile(sConfig))
SetFailState("Couldn't import: \"%s\"", sConfig); //Check if file was imported properly
if (!kv.GotoFirstSubKey())
LogMessage("No entries found in: \"%s\"", sConfig); //Notify that there aren't any entry
}
void LoadTags(int client)
{
if (!client)
return;
//Clear the tags when re-checking
ResetTags(client);
kv.Rewind();
//Check steamid checking
char steamid[32];
if (!GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid)))
return;
if (kv.JumpToKey(steamid))
{
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
GetTags(client);
return;
}
steamid[6] = '0'; //Replace the STEAM_1 to STEAM_0
if (kv.JumpToKey(steamid)) //Check again with STEAM_0
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
//Start AdminGroups checking
AdminId admin = GetUserAdmin(client);
if (admin != INVALID_ADMIN_ID)
{
char sGroup[32];
admin.GetGroup(0, sGroup, sizeof(sGroup));
Format(sGroup, sizeof(sGroup), "@%s", sGroup);
if (kv.JumpToKey(sGroup))
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
}
//Start flags checking
char sFlags[21] = "abcdefghijklmnopqrstz";
for (int i = sizeof(sFlags)-1; 0 <= i; i--)
{
char sFlag[1];
sFlag[0] = sFlags[i];
if (ReadFlagString(sFlag) & GetUserFlagBits(client))
{
if (kv.JumpToKey(sFlag))
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
}
}
//Start total play-time checking
if (bMostActive)
{
int iOldTime;
bool bReturn;
if (!kv.GotoFirstSubKey())
return;
do
{
char sSecs[16];
kv.GetSectionName(sSecs, sizeof(sSecs));
if (sSecs[0] != '#') //Check if it's a "time-format"
continue;
Format(sSecs, sizeof(sSecs), "%s", sSecs[1]); //Cut the '#' at the start
if (iOldTime >= StringToInt(sSecs)) //Select only the higher time.
continue;
if (StringToInt(sSecs) <= MostActive_GetPlayTimeTotal(client))
{
GetTags(client);
iOldTime = StringToInt(sSecs); //Save the time
bReturn = true;
}
}
while (kv.GotoNextKey());
kv.Rewind();
if (bReturn)
{
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
}
//BOTS
if(IsFakeClient(client) && kv.JumpToKey("Bots"))
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
//Start team checking
char sTeam[32];
int team = GetClientTeam(client);
GetTeamName(team, sTeam, sizeof(sTeam));
if (kv.JumpToKey(sTeam))
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
return;
}
//Check for 'All' entry
if (kv.JumpToKey("Default"))
{
GetTags(client);
Call_StartForward(fTagsUpdated);
Call_PushCell(client);
Call_Finish();
}
}
//Stocks
void GetTags(int client)
{
kv.GetString("ScoreTag", sTags[client][ScoreTag], sizeof(sTags[][]), "");
kv.GetString("ChatTag", sTags[client][ChatTag], sizeof(sTags[][]), "");
kv.GetString("ChatColor", sTags[client][ChatColor], sizeof(sTags[][]), "");
kv.GetString("NameColor", sTags[client][NameColor], sizeof(sTags[][]), "{teamcolor}");
}
void ResetTags(int client)
{
strcopy(sTags[client][ScoreTag], sizeof(sTags[][]), "");
strcopy(sTags[client][ChatTag], sizeof(sTags[][]), "");
strcopy(sTags[client][ChatColor], sizeof(sTags[][]), "");
strcopy(sTags[client][NameColor], sizeof(sTags[][]), "");
}
bool IsCS()
{
EngineVersion engine = GetEngineVersion();
return (engine == Engine_CSGO || engine == Engine_CSS);
}
int GetRandomColor()
{
switch(GetRandomInt(1, 16))
{
case 1: return '\x01';
case 2: return '\x02';
case 3: return '\x03';
case 4: return '\x03';
case 5: return '\x04';
case 6: return '\x05';
case 7: return '\x06';
case 8: return '\x07';
case 9: return '\x08';
case 10: return '\x09';
case 11: return '\x10';
case 12: return '\x0A';
case 13: return '\x0B';
case 14: return '\x0C';
case 15: return '\x0E';
case 16: return '\x0F';
}
return '\01';
}
int GetColor(int color)
{
while(color > 7)
color -= 7;
switch(color)
{
case 1: return '\x02';
case 2: return '\x10';
case 3: return '\x09';
case 4: return '\x06';
case 5: return '\x0B';
case 6: return '\x0C';
case 7: return '\x0E';
}
return '\x01';
}
//API
public int Native_GetClientTag(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
}
if (!IsClientConnected(client))
{
return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected", client);
}
eTags Tag = view_as<eTags>(GetNativeCell(2));
SetNativeString(3, sTags[client][Tag], GetNativeCell(4));
return 0;
}
public int Native_SetClientTag(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
}
if (!IsClientConnected(client))
{
return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected", client);
}
char sTag[32];
eTags Tag = view_as<eTags>(GetNativeCell(2));
GetNativeString(3, sTag, sizeof(sTag));
ReplaceString(sTag, sizeof(sTag), "{darkgray}", "{gray2}");
strcopy(sTags[client][Tag], sizeof(sTags[][]), sTag);
return 0;
}
public int Native_ResetClientTags(Handle plugin, int numParams)
{
int client = GetNativeCell(1);
if (client < 1 || client > MaxClients)
{
return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index (%d)", client);
}
if (!IsClientConnected(client))
{
return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected", client);
}
LoadTags(client);
return 0;
}
stock bool IsValidClient(int client, bool nobots = true)
{
if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client)))
{
return false;
}
return IsClientInGame(client);
}