mirror of
https://github.com/shavitush/bhoptimer.git
synced 2025-12-06 18:08:26 +00:00
858 lines
20 KiB
SourcePawn
858 lines
20 KiB
SourcePawn
/*
|
|
* shavit's Timer - Chat
|
|
* by: shavit
|
|
*
|
|
* This file is part of shavit's Timer.
|
|
*
|
|
* 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 <cstrike>
|
|
|
|
#undef REQUIRE_PLUGIN
|
|
#include <basecomm>
|
|
#include <rtler>
|
|
#include <chat-processor>
|
|
#define USES_CHAT_COLORS
|
|
#include <shavit>
|
|
|
|
#pragma newdecls required
|
|
#pragma semicolon 1
|
|
#pragma dynamic 131072
|
|
|
|
// cache
|
|
float gF_LastMessage[MAXPLAYERS+1];
|
|
|
|
char gS_Cached_Prefix[MAXPLAYERS+1][32];
|
|
char gS_Cached_Name[MAXPLAYERS+1][MAX_NAME_LENGTH*2];
|
|
char gS_Cached_Message[MAXPLAYERS+1][255];
|
|
char gS_Cached_ClanTag[MAXPLAYERS+1][32];
|
|
|
|
StringMap gSM_Custom_Prefix = null;
|
|
StringMap gSM_Custom_Name = null;
|
|
StringMap gSM_Custom_Message = null;
|
|
StringMap gSM_Custom_ClanTag = null;
|
|
|
|
int gI_TotalChatRanks = 0;
|
|
int gI_UnassignedTitle = -1;
|
|
int gI_UnrankedTitle = -1;
|
|
|
|
Dynamic gD_ChatRanks[64]; // limited to 64 chat ranks right now, i really don't think there's a need for more.
|
|
|
|
// modules
|
|
bool gB_BaseComm = false;
|
|
bool gB_RTLer = false;
|
|
bool gB_ChatProcessor = false;
|
|
|
|
// game-related
|
|
EngineVersion gEV_Type = Engine_Unknown;
|
|
|
|
public Plugin myinfo =
|
|
{
|
|
name = "[shavit] Chat",
|
|
author = "shavit",
|
|
description = "Chat handler for shavit's bhop timer.",
|
|
version = SHAVIT_VERSION,
|
|
url = "https://github.com/shavitush/bhoptimer"
|
|
}
|
|
|
|
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
|
{
|
|
// natives
|
|
CreateNative("Shavit_FormatChat", Native_FormatChat);
|
|
|
|
// registers library, check "bool LibraryExists(const char[] name)" in order to use with other plugins
|
|
RegPluginLibrary("shavit-chat");
|
|
|
|
return APLRes_Success;
|
|
}
|
|
|
|
public void OnAllPluginsLoaded()
|
|
{
|
|
if(!LibraryExists("shavit-rankings"))
|
|
{
|
|
SetFailState("shavit-rankings is required for the plugin to work.");
|
|
}
|
|
|
|
// modules
|
|
gB_BaseComm = LibraryExists("basecomm");
|
|
gB_RTLer = LibraryExists("rtler");
|
|
gB_ChatProcessor = LibraryExists("chat-processor");
|
|
}
|
|
|
|
public void OnPluginStart()
|
|
{
|
|
LoadTranslations("shavit-chat.phrases");
|
|
|
|
// game specific
|
|
gEV_Type = GetEngineVersion();
|
|
|
|
// commands
|
|
RegAdminCmd("sm_reloadchat", Command_ReloadChat, ADMFLAG_ROOT, "Reload chat config.");
|
|
|
|
RegConsoleCmd("sm_chatranks", Command_ChatRanks, "Shows a list of all the possible chat ranks.");
|
|
RegConsoleCmd("sm_ranks", Command_ChatRanks, "Shows a list of all the possible chat ranks. Alias for sm_chatranks.");
|
|
|
|
// hooks
|
|
HookEvent("player_spawn", Player_Spawn);
|
|
}
|
|
|
|
public void OnPluginEnd()
|
|
{
|
|
ResetCache();
|
|
}
|
|
|
|
public void OnMapStart()
|
|
{
|
|
LoadConfig();
|
|
}
|
|
|
|
public void OnClientPutInServer(int client)
|
|
{
|
|
gF_LastMessage[client] = GetEngineTime();
|
|
|
|
if(gI_TotalChatRanks >= 1 && gD_ChatRanks[0].IsValid)
|
|
{
|
|
gD_ChatRanks[0].GetString("prefix", gS_Cached_Prefix[client], 32);
|
|
gD_ChatRanks[0].GetString("name", gS_Cached_Name[client], MAX_NAME_LENGTH*2);
|
|
gD_ChatRanks[0].GetString("message", gS_Cached_Message[client], 255);
|
|
gD_ChatRanks[0].GetString("clantag", gS_Cached_ClanTag[client], 32);
|
|
|
|
UpdateClanTag(client);
|
|
}
|
|
}
|
|
|
|
public void OnClientSettingsChanged(int client)
|
|
{
|
|
UpdateClanTag(client);
|
|
}
|
|
|
|
void UpdateClanTag(int client)
|
|
{
|
|
if(IsValidClient(client) && strlen(gS_Cached_ClanTag[client]) > 0)
|
|
{
|
|
CS_SetClientClanTag(client, gS_Cached_ClanTag[client]);
|
|
}
|
|
}
|
|
|
|
public void OnClientAuthorized(int client, const char[] auth)
|
|
{
|
|
LoadChatCache(client);
|
|
}
|
|
|
|
public void OnLibraryAdded(const char[] name)
|
|
{
|
|
if(StrEqual(name, "basecomm"))
|
|
{
|
|
gB_BaseComm = true;
|
|
}
|
|
|
|
else if(StrEqual(name, "rtler"))
|
|
{
|
|
gB_RTLer = true;
|
|
}
|
|
|
|
else if(StrEqual(name, "chat-processor"))
|
|
{
|
|
gB_ChatProcessor = true;
|
|
}
|
|
}
|
|
|
|
public void OnLibraryRemoved(const char[] name)
|
|
{
|
|
if(StrEqual(name, "basecomm"))
|
|
{
|
|
gB_BaseComm = false;
|
|
}
|
|
|
|
else if(StrEqual(name, "rtler"))
|
|
{
|
|
gB_RTLer = false;
|
|
}
|
|
|
|
else if(StrEqual(name, "chat-processor"))
|
|
{
|
|
gB_ChatProcessor = false;
|
|
}
|
|
}
|
|
|
|
public void Shavit_OnRankUpdated(int client)
|
|
{
|
|
LoadChatCache(client);
|
|
}
|
|
|
|
void LoadChatCache(int client)
|
|
{
|
|
// assign rank properties
|
|
int iRank = Shavit_GetRank(client);
|
|
int iTitle = (iRank == -1)? gI_UnassignedTitle:gI_UnrankedTitle;
|
|
|
|
if(iRank <= 0)
|
|
{
|
|
gD_ChatRanks[iTitle].GetString("prefix", gS_Cached_Prefix[client], 32);
|
|
gD_ChatRanks[iTitle].GetString("name", gS_Cached_Name[client], MAX_NAME_LENGTH*2);
|
|
gD_ChatRanks[iTitle].GetString("message", gS_Cached_Message[client], 255);
|
|
gD_ChatRanks[iTitle].GetString("clantag", gS_Cached_ClanTag[client], 255);
|
|
}
|
|
|
|
else
|
|
{
|
|
for(int i = 0; i < gI_TotalChatRanks; i++)
|
|
{
|
|
if(gD_ChatRanks[i].IsValid)
|
|
{
|
|
int iFrom = gD_ChatRanks[i].GetInt("rank_from");
|
|
int iTo = gD_ChatRanks[i].GetInt("rank_to");
|
|
|
|
if(iRank < iFrom || (iRank > iTo && iTo != -3))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
gD_ChatRanks[i].GetString("prefix", gS_Cached_Prefix[client], 32);
|
|
gD_ChatRanks[i].GetString("name", gS_Cached_Name[client], MAX_NAME_LENGTH*2);
|
|
gD_ChatRanks[i].GetString("message", gS_Cached_Message[client], 255);
|
|
gD_ChatRanks[i].GetString("clantag", gS_Cached_ClanTag[client], 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
char[] sAuthID = new char[32];
|
|
|
|
if(GetClientAuthId(client, AuthId_Steam3, sAuthID, 32))
|
|
{
|
|
char[] sBuffer = new char[255];
|
|
|
|
if(gSM_Custom_Prefix.GetString(sAuthID, sBuffer, 255))
|
|
{
|
|
strcopy(gS_Cached_Prefix[client], 32, sBuffer);
|
|
}
|
|
|
|
if(gSM_Custom_Name.GetString(sAuthID, sBuffer, 255))
|
|
{
|
|
strcopy(gS_Cached_Name[client], MAX_NAME_LENGTH*2, sBuffer);
|
|
}
|
|
|
|
if(gSM_Custom_Message.GetString(sAuthID, sBuffer, 255))
|
|
{
|
|
strcopy(gS_Cached_Message[client], 255, sBuffer);
|
|
}
|
|
|
|
if(gSM_Custom_ClanTag.GetString(sAuthID, sBuffer, 255))
|
|
{
|
|
strcopy(gS_Cached_ClanTag[client], 32, sBuffer);
|
|
}
|
|
}
|
|
|
|
UpdateClanTag(client);
|
|
}
|
|
|
|
void ResetCache()
|
|
{
|
|
for(int i = 0; i < 64; i++)
|
|
{
|
|
if(gD_ChatRanks[i].IsValid)
|
|
{
|
|
gD_ChatRanks[i].Dispose();
|
|
}
|
|
}
|
|
|
|
gI_TotalChatRanks = 0;
|
|
gI_UnassignedTitle = -1;
|
|
gI_UnrankedTitle = -1;
|
|
}
|
|
|
|
void LoadConfig()
|
|
{
|
|
delete gSM_Custom_Prefix;
|
|
delete gSM_Custom_Name;
|
|
delete gSM_Custom_Message;
|
|
delete gSM_Custom_ClanTag;
|
|
|
|
gSM_Custom_Prefix = new StringMap();
|
|
gSM_Custom_Name = new StringMap();
|
|
gSM_Custom_Message = new StringMap();
|
|
gSM_Custom_ClanTag = new StringMap();
|
|
|
|
ResetCache();
|
|
|
|
KeyValues kvConfig = new KeyValues("Chat");
|
|
|
|
char[] sFile = new char[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-chat.cfg");
|
|
|
|
if(!kvConfig.ImportFromFile(sFile))
|
|
{
|
|
SetFailState("File %s could not be found or accessed.", sFile);
|
|
}
|
|
|
|
if(kvConfig.GotoFirstSubKey())
|
|
{
|
|
char[] sBuffer = new char[255];
|
|
|
|
do
|
|
{
|
|
kvConfig.GetSectionName(sBuffer, 255);
|
|
|
|
char[] sPrefix = new char[32];
|
|
kvConfig.GetString("prefix", sPrefix, 32);
|
|
|
|
char[] sName = new char[MAX_NAME_LENGTH*2];
|
|
kvConfig.GetString("name", sName, MAX_NAME_LENGTH*2);
|
|
|
|
char[] sMessage = new char[255];
|
|
kvConfig.GetString("message", sMessage, 255);
|
|
|
|
char[] sCustomClanTag = new char[32];
|
|
kvConfig.GetString("clantag", sCustomClanTag, 32);
|
|
|
|
// custom
|
|
if(StrContains(sBuffer[0], "[U:") != -1)
|
|
{
|
|
if(strlen(sPrefix) > 0)
|
|
{
|
|
gSM_Custom_Prefix.SetString(sBuffer, sPrefix);
|
|
}
|
|
|
|
if(strlen(sName) > 0)
|
|
{
|
|
gSM_Custom_Name.SetString(sBuffer, sName);
|
|
}
|
|
|
|
if(strlen(sMessage) > 0)
|
|
{
|
|
gSM_Custom_Message.SetString(sBuffer, sMessage);
|
|
}
|
|
|
|
if(strlen(sCustomClanTag) > 0)
|
|
{
|
|
gSM_Custom_ClanTag.SetString(sBuffer, sCustomClanTag);
|
|
}
|
|
}
|
|
|
|
// ranks
|
|
else
|
|
{
|
|
int iFrom = kvConfig.GetNum("rank_from", -2);
|
|
|
|
if(iFrom == -2)
|
|
{
|
|
LogError("Invalid \"rank_from\" value for \"%s\": %d or non-existant.", sBuffer, iFrom);
|
|
|
|
continue;
|
|
}
|
|
|
|
char[] sTo = new char[16];
|
|
kvConfig.GetString("rank_to", sTo, 16, "-2");
|
|
int iTo = StrEqual(sTo, "infinity", false)? -3:StringToInt(sTo);
|
|
|
|
if(iTo == -2)
|
|
{
|
|
LogError("Invalid \"rank_to\" value for \"%s\": %d or non-existant.", sBuffer, iTo);
|
|
|
|
continue;
|
|
}
|
|
|
|
gD_ChatRanks[gI_TotalChatRanks] = Dynamic();
|
|
gD_ChatRanks[gI_TotalChatRanks].SetInt("rank_from", iFrom);
|
|
gD_ChatRanks[gI_TotalChatRanks].SetInt("rank_to", iTo);
|
|
gD_ChatRanks[gI_TotalChatRanks].SetString("prefix", sPrefix, 32);
|
|
gD_ChatRanks[gI_TotalChatRanks].SetString("name", (strlen(sName) > 0)? sName:"{name}", MAX_NAME_LENGTH*2);
|
|
gD_ChatRanks[gI_TotalChatRanks].SetString("message", (strlen(sMessage) > 0)? sMessage:"{message}", 255);
|
|
gD_ChatRanks[gI_TotalChatRanks].SetString("clantag", (strlen(sCustomClanTag) > 0)? sCustomClanTag:"", 32);
|
|
|
|
if(iFrom == -1 && gI_UnassignedTitle == -1)
|
|
{
|
|
gI_UnassignedTitle = gI_TotalChatRanks;
|
|
}
|
|
|
|
else if(iFrom == 0 && gI_UnrankedTitle == -1)
|
|
{
|
|
gI_UnrankedTitle = gI_TotalChatRanks;
|
|
}
|
|
|
|
gI_TotalChatRanks++;
|
|
}
|
|
}
|
|
|
|
while(kvConfig.GotoNextKey());
|
|
}
|
|
|
|
else
|
|
{
|
|
LogError("File %s might be empty?", sFile);
|
|
}
|
|
|
|
delete kvConfig;
|
|
|
|
for(int i = 1; i <= MaxClients; i++)
|
|
{
|
|
if(IsValidClient(i)) // late loading
|
|
{
|
|
OnClientPutInServer(i);
|
|
|
|
char[] sAuth = new char[32];
|
|
|
|
if(GetClientAuthId(i, AuthId_Steam3, sAuth, 32))
|
|
{
|
|
OnClientAuthorized(i, sAuth);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Action Command_ChatRanks(int client, int args)
|
|
{
|
|
if(!IsValidClient(client))
|
|
{
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
// dummies
|
|
// char[] sExample = "Example."; // I tried using this variable, but it seemed to pick up "List of Chat ranks:" instead, I wonder why..
|
|
int[] clients = new int[1];
|
|
clients[0] = client;
|
|
char[] sChatMessage = new char[64];
|
|
FormatEx(sChatMessage, 64, "\x01%T", "ChatRankList", client);
|
|
|
|
ChatMessage(client, clients, 1, sChatMessage);
|
|
|
|
for(int i = gI_TotalChatRanks - 1; i >= 0; i--)
|
|
{
|
|
if(gD_ChatRanks[i].IsValid)
|
|
{
|
|
int iFrom = gD_ChatRanks[i].GetInt("rank_from");
|
|
|
|
if(iFrom <= 0)
|
|
{
|
|
continue; // don't show unranked/due-lookup 'chat ranks'
|
|
}
|
|
|
|
int iTo = gD_ChatRanks[i].GetInt("rank_to");
|
|
char[] sRankText = new char[16];
|
|
|
|
if(iFrom == iTo)
|
|
{
|
|
FormatEx(sRankText, 16, "#%d", iFrom);
|
|
}
|
|
|
|
else
|
|
{
|
|
PrintToConsole(client, "%d", iTo);
|
|
|
|
if(iTo == -3)
|
|
{
|
|
FormatEx(sRankText, 16, "#%d - ∞", iFrom, iTo);
|
|
}
|
|
|
|
else
|
|
{
|
|
FormatEx(sRankText, 16, "#%d - #%d", iFrom, iTo);
|
|
}
|
|
}
|
|
char[] sExampleMessage = new char[32];
|
|
FormatEx(sExampleMessage, 64, "\x01%T", "ExampleMessage", client);
|
|
|
|
char[] sPrefix = new char[32];
|
|
gD_ChatRanks[i].GetString("prefix", sPrefix, 32);
|
|
FormatVariables(client, sPrefix, 32, sPrefix, sExampleMessage);
|
|
|
|
char[] sName = new char[MAX_NAME_LENGTH*2];
|
|
gD_ChatRanks[i].GetString("name", sName, MAX_NAME_LENGTH*2);
|
|
FormatVariables(client, sName, MAX_NAME_LENGTH*2, sName, sExampleMessage);
|
|
|
|
char[] sMessage = new char[255];
|
|
gD_ChatRanks[i].GetString("message", sMessage, 255);
|
|
FormatVariables(client, sMessage, 255, sMessage, sExampleMessage);
|
|
|
|
char[] sBuffer = new char[300];
|
|
FormatEx(sBuffer, 300, "%s\x04[%s]\x01 %s%s %s %s %s", gEV_Type == Engine_CSGO? " ":"", sRankText, strlen(sPrefix) == 0? "\x03":"", sPrefix, sName, gEV_Type == Engine_CSGO? ":\x01":"\x01:", sMessage);
|
|
|
|
ChatMessage(client, clients, 1, sBuffer);
|
|
}
|
|
}
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action Command_ReloadChat(int client, int args)
|
|
{
|
|
LoadConfig();
|
|
|
|
ReplyToCommand(client, "%T", "ReloadChat", client);
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action OnChatMessage(int &author, ArrayList recipients, eChatFlags &flag, char[] name, char[] message, bool &bProcessColors, bool &bRemoveColors)
|
|
{
|
|
if(!gB_ChatProcessor)
|
|
{
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
char[] sBuffer = new char[255];
|
|
char[] sPrefix = new char[32];
|
|
|
|
if(strlen(gS_Cached_Prefix[author]) > 0)
|
|
{
|
|
FormatVariables(author, sBuffer, 255, gS_Cached_Prefix[author], message);
|
|
int iLen = strlen(sBuffer);
|
|
sBuffer[iLen] = (iLen > 0)? ' ':'\0';
|
|
strcopy(sPrefix, 32, sBuffer);
|
|
}
|
|
|
|
char[] sName = new char[MAX_NAME_LENGTH*2];
|
|
|
|
if(strlen(gS_Cached_Name[author]) > 0)
|
|
{
|
|
FormatVariables(author, sBuffer, 255, gS_Cached_Name[author], message);
|
|
strcopy(sName, MAX_NAME_LENGTH*2, sBuffer);
|
|
}
|
|
|
|
else
|
|
{
|
|
FormatEx(sName, MAX_NAME_LENGTH*2, "\x03%N", author);
|
|
}
|
|
|
|
char[] sFormattedText = new char[MAXLENGTH_MESSAGE];
|
|
strcopy(sFormattedText, MAXLENGTH_MESSAGE, message);
|
|
|
|
// solve shitty exploits
|
|
ReplaceString(sFormattedText, MAXLENGTH_MESSAGE, "\n", "");
|
|
ReplaceString(sFormattedText, MAXLENGTH_MESSAGE, "\t", "");
|
|
ReplaceString(sFormattedText, MAXLENGTH_MESSAGE, " ", " ");
|
|
TrimString(sFormattedText);
|
|
|
|
if(strlen(gS_Cached_Message[author]) > 0)
|
|
{
|
|
FormatVariables(author, sBuffer, 255, gS_Cached_Message[author], sFormattedText);
|
|
strcopy(sFormattedText, 255, sBuffer);
|
|
}
|
|
|
|
else
|
|
{
|
|
strcopy(sFormattedText, 255, message);
|
|
}
|
|
|
|
FormatEx(name, MAXLENGTH_NAME, "%s%s%s", (gEV_Type == Engine_CSGO)? " ":"", sPrefix, sName);
|
|
strcopy(message, MAXLENGTH_MESSAGE, sFormattedText);
|
|
|
|
return Plugin_Changed;
|
|
}
|
|
|
|
public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
|
|
{
|
|
if(gB_ChatProcessor || !IsValidClient(client) || !IsClientAuthorized(client) || (gB_BaseComm && BaseComm_IsClientGagged(client)))
|
|
{
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
if(GetEngineTime() - gF_LastMessage[client] < 0.70)
|
|
{
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
bool bTeam = StrEqual(command, "say_team");
|
|
|
|
if(bTeam || (CheckCommandAccess(client, "sm_say", ADMFLAG_CHAT) && sArgs[0] == '@'))
|
|
{
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
char[] sMessage = new char[300];
|
|
strcopy(sMessage, 300, sArgs);
|
|
|
|
if(ReplaceString(sMessage[0], 4, "!", "sm_") > 0 || ReplaceString(sMessage[0], 4, "/", "sm_") > 0)
|
|
{
|
|
bool bCmd = false;
|
|
Handle hCon = FindFirstConCommand(sMessage, 300, bCmd);
|
|
|
|
if(hCon != null)
|
|
{
|
|
FindNextConCommand(hCon, sMessage, 300, bCmd);
|
|
delete hCon;
|
|
|
|
if(bCmd)
|
|
{
|
|
return Plugin_Handled;
|
|
}
|
|
}
|
|
}
|
|
|
|
gF_LastMessage[client] = GetEngineTime();
|
|
|
|
int iTeam = GetClientTeam(client);
|
|
|
|
FormatChatLine(client, sArgs, IsPlayerAlive(client), iTeam, bTeam, sMessage, 300);
|
|
|
|
int[] clients = new int[MaxClients];
|
|
int count = 0;
|
|
|
|
PrintToServer("%N: %s", client, sArgs);
|
|
|
|
for(int i = 1; i <= MaxClients; i++)
|
|
{
|
|
if(IsValidClient(i))
|
|
{
|
|
if(GetClientTeam(i) == iTeam || !bTeam)
|
|
{
|
|
clients[count++] = i;
|
|
|
|
PrintToConsole(i, "%N: %s", client, sArgs);
|
|
}
|
|
}
|
|
}
|
|
|
|
ChatMessage(client, clients, count, sMessage);
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
void FormatChatLine(int client, const char[] sMessage, bool bAlive, int iTeam, bool bTeam, char[] buffer, int maxlen)
|
|
{
|
|
char[] sTeam = new char[32];
|
|
char[] sTeamName = new char[32];
|
|
|
|
if(!bTeam)
|
|
{
|
|
if(iTeam == CS_TEAM_SPECTATOR)
|
|
{
|
|
FormatEx(sTeamName, 32, "%T", "TeamSpec", client);
|
|
strcopy(sTeam, 32, sTeamName);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
switch(iTeam)
|
|
{
|
|
case CS_TEAM_SPECTATOR:
|
|
{
|
|
FormatEx(sTeamName, 32, "%T", "TeamSpectator", client);
|
|
strcopy(sTeam, 32, sTeamName);
|
|
}
|
|
|
|
case CS_TEAM_T:
|
|
{
|
|
FormatEx(sTeamName, 32, "%T", "TeamT", client);
|
|
strcopy(sTeam, 32, sTeamName);
|
|
}
|
|
|
|
case CS_TEAM_CT:
|
|
{
|
|
FormatEx(sTeamName, 32, "%T", "TeamCT", client);
|
|
strcopy(sTeam, 32, sTeamName);
|
|
}
|
|
}
|
|
}
|
|
|
|
char[] sAuthID = new char[32];
|
|
GetClientAuthId(client, AuthId_Steam3, sAuthID, 32);
|
|
|
|
char[] sBuffer = new char[255];
|
|
char[] sNewPrefix = new char[32];
|
|
|
|
if(strlen(gS_Cached_Prefix[client]) > 0)
|
|
{
|
|
FormatVariables(client, sBuffer, 255, gS_Cached_Prefix[client], sMessage);
|
|
int iLen = strlen(sBuffer);
|
|
sBuffer[iLen] = (iLen > 0)? ' ':'\0';
|
|
strcopy(sNewPrefix, 32, sBuffer);
|
|
}
|
|
|
|
char[] sNewName = new char[MAX_NAME_LENGTH*2];
|
|
|
|
if(strlen(gS_Cached_Name[client]) > 0)
|
|
{
|
|
FormatVariables(client, sBuffer, 255, gS_Cached_Name[client], sMessage);
|
|
strcopy(sNewName, MAX_NAME_LENGTH*2, sBuffer);
|
|
}
|
|
|
|
else
|
|
{
|
|
FormatEx(sNewName, MAX_NAME_LENGTH*2, "\x03%N", client);
|
|
}
|
|
|
|
char[] sFormattedText = new char[maxlen];
|
|
strcopy(sFormattedText, maxlen, sMessage);
|
|
|
|
// solve shitty exploits
|
|
ReplaceString(sFormattedText, maxlen, "\n", "");
|
|
ReplaceString(sFormattedText, maxlen, "\t", "");
|
|
ReplaceString(sFormattedText, maxlen, " ", " ");
|
|
TrimString(sFormattedText);
|
|
|
|
if(gB_RTLer)
|
|
{
|
|
char[][] sExploded = new char[96][96]; // fixed size from RTLer
|
|
ExplodeString(sFormattedText, " ", sExploded, 96, 96);
|
|
|
|
bool bRTLify = true;
|
|
|
|
for(int i = 0; i < 96; i++)
|
|
{
|
|
if(strlen(sExploded[i]) > 32)
|
|
{
|
|
bRTLify = false;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bRTLify)
|
|
{
|
|
RTLify(sFormattedText, maxlen, sFormattedText);
|
|
}
|
|
}
|
|
|
|
if(strlen(gS_Cached_Message[client]) > 0)
|
|
{
|
|
FormatVariables(client, sBuffer, 255, gS_Cached_Message[client], sFormattedText);
|
|
strcopy(sFormattedText, 255, sBuffer);
|
|
}
|
|
|
|
FormatEx(buffer, maxlen, "\x01%s%s%s\x03%s%s %s %s", gEV_Type == Engine_CSGO? " ":"", (bAlive || iTeam == CS_TEAM_SPECTATOR)? "":"*DEAD* ", sTeam, sNewPrefix, sNewName, gEV_Type == Engine_CSGO? ":\x01":"\x01:", sFormattedText);
|
|
}
|
|
|
|
void FormatVariables(int client, char[] buffer, int maxlen, const char[] formattingrules, const char[] message)
|
|
{
|
|
char[] sTempFormattingRules = new char[maxlen];
|
|
strcopy(sTempFormattingRules, maxlen, formattingrules);
|
|
|
|
for(int i = 0; i < sizeof(gS_GlobalColorNames); i++)
|
|
{
|
|
ReplaceString(sTempFormattingRules, maxlen, gS_GlobalColorNames[i], gS_GlobalColors[i]);
|
|
}
|
|
|
|
if(gEV_Type == Engine_CSS)
|
|
{
|
|
ReplaceString(sTempFormattingRules, maxlen, "{RGB}", "\x07");
|
|
ReplaceString(sTempFormattingRules, maxlen, "{RGBA}", "\x08");
|
|
|
|
char[] sColorBuffer = new char[16];
|
|
|
|
do
|
|
{
|
|
Format(sColorBuffer, 16, "\x07%x%x%x", RealRandomInt(1, 255), RealRandomInt(1, 255), RealRandomInt(1, 255));
|
|
}
|
|
|
|
while(ReplaceStringEx(sTempFormattingRules, maxlen, "{RGBX}", sColorBuffer) > 0);
|
|
|
|
do
|
|
{
|
|
Format(sColorBuffer, 16, "\x08%x%x%x%x", RealRandomInt(1, 255), RealRandomInt(1, 255), RealRandomInt(1, 255), RealRandomInt(1, 255));
|
|
}
|
|
|
|
while(ReplaceStringEx(sTempFormattingRules, maxlen, "{RGBAX}", sColorBuffer) > 0);
|
|
}
|
|
|
|
else
|
|
{
|
|
for(int i = 0; i < sizeof(gS_CSGOColorNames); i++)
|
|
{
|
|
ReplaceString(sTempFormattingRules, maxlen, gS_CSGOColorNames[i], gS_CSGOColors[i]);
|
|
}
|
|
}
|
|
|
|
char[] sName = new char[MAX_NAME_LENGTH];
|
|
GetClientName(client, sName, MAX_NAME_LENGTH);
|
|
ReplaceString(sTempFormattingRules, maxlen, "{name}", sName);
|
|
|
|
char[] sCustomClanTag = new char[32];
|
|
CS_GetClientClanTag(client, sCustomClanTag, 32);
|
|
int iLen = strlen(sCustomClanTag);
|
|
sCustomClanTag[iLen] = (iLen > 0)? ' ':'\0';
|
|
ReplaceString(sTempFormattingRules, maxlen, "{clan}", sCustomClanTag);
|
|
|
|
ReplaceString(sTempFormattingRules, maxlen, "{message}", message);
|
|
|
|
strcopy(buffer, maxlen, sTempFormattingRules);
|
|
}
|
|
|
|
void ChatMessage(int from, int[] clients, int count, const char[] sMessage)
|
|
{
|
|
Handle hSayText2 = StartMessage("SayText2", clients, count);
|
|
|
|
if(hSayText2 != null)
|
|
{
|
|
if(gEV_Type == Engine_CSGO)
|
|
{
|
|
PbSetInt(hSayText2, "ent_idx", from);
|
|
PbSetBool(hSayText2, "chat", true);
|
|
PbSetString(hSayText2, "msg_name", sMessage);
|
|
|
|
for(int i = 1; i <= 4; i++)
|
|
{
|
|
PbAddString(hSayText2, "params", "");
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
BfWriteByte(hSayText2, from);
|
|
BfWriteByte(hSayText2, true);
|
|
BfWriteString(hSayText2, sMessage);
|
|
}
|
|
|
|
EndMessage();
|
|
}
|
|
}
|
|
|
|
public void Player_Spawn(Event event, const char[] name, bool dontBroadcast)
|
|
{
|
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
|
|
|
if(!IsFakeClient(client))
|
|
{
|
|
LoadChatCache(client);
|
|
}
|
|
}
|
|
|
|
public int Native_FormatChat(Handle handler, int numParams)
|
|
{
|
|
int client = GetNativeCell(1);
|
|
|
|
if(!IsValidClient(client))
|
|
{
|
|
ThrowNativeError(200, "Invalid client index %d", client);
|
|
|
|
return -1;
|
|
}
|
|
|
|
char[] sMessage = new char[255];
|
|
GetNativeString(2, sMessage, 255);
|
|
|
|
char[] sBuffer = new char[300];
|
|
FormatChatLine(client, sMessage, IsPlayerAlive(client), GetClientTeam(client), view_as<bool>(GetNativeCell(3)), sBuffer, 300);
|
|
|
|
int maxlength = GetNativeCell(5);
|
|
|
|
return SetNativeString(6, sBuffer, maxlength);
|
|
}
|
|
|
|
// from SMLib
|
|
int RealRandomInt(int min, int max)
|
|
{
|
|
int random = GetURandomInt();
|
|
|
|
if(random == 0)
|
|
{
|
|
random++;
|
|
}
|
|
|
|
return RoundToCeil(float(random) / (float(2147483647) / float(max - min + 1))) + min - 1;
|
|
}
|