mirror of
https://github.com/shavitush/bhoptimer.git
synced 2025-12-07 18:38:26 +00:00
Chat plugin rewrite. (#436)
This commit is contained in:
parent
066f60c057
commit
8ff72fed0a
@ -17,6 +17,12 @@ Zones are trigger based and are very lightweight.
|
||||
|
||||
The zones plugin includes some less common features such as: Multiple tracks (main/bonus), zone editing (after setup), snapping zones to walls/corners/grid, zone setup using the cursor's position, configurable sprite/colors for zone types, zone tracks (main/bonus - can be extended), manual adjustments of coordinates before confirmations, teleport zones, glitch zones, no-limit zones (for styles like 400-velocity), flat/3D boxes for zone rendering, an API and more.
|
||||
|
||||
#### shavit-chat
|
||||
The chat plugin manipulates chat messages sent by players.
|
||||
It includes custom chat names, tags, colors and all can be defined by the players/admins.
|
||||
Admins need the chat flag, or the "shavit_chat" override (good for a donator perk).
|
||||
There's a user-friendly command named !cchelp so the users can easily understand what's going on.
|
||||
|
||||
#### shavit-hud
|
||||
The HUD plugin is `bhoptimer`'s OSD frontend.
|
||||
It shows most (if not all) of the information that the player needs to see.
|
||||
|
||||
@ -22,6 +22,7 @@ Including a records system, map zones (start/end marks etc), bonuses, HUD with u
|
||||
* [DHooks](http://users.alliedmods.net/~drifter/builds/dhooks/2.0/) - required for 250/260 runspeed for all weapons.
|
||||
* [Bunnyhop Statistics](https://forums.alliedmods.net/showthread.php?t=286135) - to show amount of scrolls for non-auto styles in the key display. CS:S only!
|
||||
* [SteamWorks](https://forums.alliedmods.net/showthread.php?t=229556) - for the `{serverip}` advertisement variable.
|
||||
* [Chat-Processor](https://github.com/Drixevel/Chat-Processor) - if you're enabling the `shavit-chat` module.
|
||||
|
||||
# Installation:
|
||||
1. If you want to use MySQL (**VERY RECOMMENDED**) add a database entry in addons/sourcemod/configs/databases.cfg, call it "shavit". The plugin also supports the "sqlite" driver. You can also skip this step and not modify databases.cfg.
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
// Use SteamID3 for a value if you want a per-client setting.
|
||||
// "Custom" is for per-client settings.
|
||||
// "Ranks" is for rank range settings. It is limited to 64 entries and the way you sort this file will be also sorted in-game when a player uses /ranks.
|
||||
//
|
||||
// Available settings:
|
||||
// "rank_from" - rank range to start with
|
||||
// "rank_to" - rank range to end with; you can use "infinity" if it's for every player below "rank_from".
|
||||
//
|
||||
// "prefix" - prefix before the name (don't add a space after it)
|
||||
// "name" - custom name appearance (color from prefix will be applied here too)
|
||||
// "message" - the message itself
|
||||
// "clantag" - custom clan tag
|
||||
//
|
||||
// Global variables:
|
||||
// {default} - default color
|
||||
// {team} - team color
|
||||
// {green} - green color
|
||||
// {name} - player name
|
||||
// {clan} - clan tag
|
||||
// {message} - message text
|
||||
//
|
||||
// If you use variables that aren't compatible with the game, it might break some stuff.
|
||||
// The default config will work with both CS:S and CS:GO, you can modify it for your needs.
|
||||
// Use `sm_reloadchat` in your server to reload this config.
|
||||
//
|
||||
// For CS:S, you have the following variables available: (NOTE: The format for colors is like HTML. RRGGBBAA)
|
||||
// {RGB} - like \x07, usage: "{RGB}FF0000" for red
|
||||
// {RGBA} - like \x08, usage: "{RGBA}FF0000FE" for 254 alpha red
|
||||
// {RGBX} - random rgb color
|
||||
// {RGBAX} - random rgba color
|
||||
//
|
||||
// CS:GO colors:
|
||||
// {team} will become purple for spectators
|
||||
// {blue}
|
||||
// {bluegrey}
|
||||
// {darkblue}
|
||||
// {darkred}
|
||||
// {gold}
|
||||
// {grey}
|
||||
// {grey2}
|
||||
// {lightgreen}
|
||||
// {lightred}
|
||||
// {lime}
|
||||
// {orchid}
|
||||
// {yellow}
|
||||
//
|
||||
"Chat"
|
||||
{
|
||||
"[U:1:204506329]" // my steamid for example, use steamid3
|
||||
{
|
||||
"prefix" "{green}/dev/"
|
||||
"name" "{default}{team}{clan}{name}"
|
||||
"clantag" "shave"
|
||||
}
|
||||
|
||||
"-1" // lookup is due, shouldn't happen unless there's some error!
|
||||
{
|
||||
"rank_from" "-1"
|
||||
"rank_to" "-1"
|
||||
|
||||
"prefix" ""
|
||||
"name" "{team}{name}"
|
||||
"message" "{message}"
|
||||
}
|
||||
|
||||
"0" // unranked
|
||||
{
|
||||
"rank_from" "0"
|
||||
"rank_to" "0"
|
||||
|
||||
"prefix" "[Unranked]"
|
||||
"name" "{team}{name}"
|
||||
"message" "{message}"
|
||||
}
|
||||
|
||||
"1"
|
||||
{
|
||||
"rank_from" "1"
|
||||
"rank_to" "1"
|
||||
|
||||
"prefix" "{green}ONE TRUE GOD"
|
||||
"name" "{clan}{team}{name}"
|
||||
}
|
||||
|
||||
"2"
|
||||
{
|
||||
"rank_from" "2"
|
||||
"rank_to" "2"
|
||||
|
||||
"prefix" "LEGENDARY"
|
||||
"name" "{name}"
|
||||
}
|
||||
|
||||
"3"
|
||||
{
|
||||
"rank_from" "3"
|
||||
"rank_to" "3"
|
||||
|
||||
"prefix" "HERO"
|
||||
"name" "{team}{name}"
|
||||
}
|
||||
|
||||
"4"
|
||||
{
|
||||
"rank_from" "4"
|
||||
"rank_to" "infinity"
|
||||
|
||||
"prefix" "scrub!"
|
||||
}
|
||||
}
|
||||
@ -1,857 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
79
scripting/include/chat-processor.inc
Normal file
79
scripting/include/chat-processor.inc
Normal file
@ -0,0 +1,79 @@
|
||||
#if defined _chat_processor_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _chat_processor_included
|
||||
|
||||
//Globals
|
||||
#define MAXLENGTH_FLAG 32
|
||||
#define MAXLENGTH_NAME 128
|
||||
#define MAXLENGTH_MESSAGE 128
|
||||
#define MAXLENGTH_BUFFER 255
|
||||
|
||||
//Natives
|
||||
/**
|
||||
* Retrieves the current format string assigned from a flag string.
|
||||
* Example: "Cstrike_Chat_All" = "{1} : {2}"
|
||||
* You can find the config formats in either the translations or the configs.
|
||||
*
|
||||
* param sFlag Flag string to retrieve the format string from.
|
||||
* param sBuffer Format string from the flag string.
|
||||
* param iSize Size of the format string buffer.
|
||||
*
|
||||
* noreturn
|
||||
**/
|
||||
native void ChatProcessor_GetFlagFormatString(const char[] sFlag, char[] sBuffer, int iSize);
|
||||
|
||||
//Forwards
|
||||
/**
|
||||
* Called while sending a chat message before It's sent.
|
||||
* Limits on the name and message strings can be found above.
|
||||
*
|
||||
* param author Author that created the message.
|
||||
* param recipients Array of clients who will receive the message.
|
||||
* param flagstring Flag string to determine the type of message.
|
||||
* param name Name string of the author to be pushed.
|
||||
* param message Message string from the author to be pushed.
|
||||
* param processcolors Toggle to process colors in the buffer strings.
|
||||
* param removecolors Toggle to remove colors in the buffer strings. (Requires bProcessColors = true)
|
||||
*
|
||||
* return types
|
||||
* - Plugin_Continue Stops the message.
|
||||
* - Plugin_Stop Stops the message.
|
||||
* - Plugin_Changed Fires the post-forward below and prints out a message.
|
||||
* - Plugin_Handled Fires the post-forward below but doesn't print a message.
|
||||
**/
|
||||
forward Action CP_OnChatMessage(int& author, ArrayList recipients, char[] flagstring, char[] name, char[] message, bool& processcolors, bool& removecolors);
|
||||
|
||||
/**
|
||||
* Called after the chat message is sent to the designated clients by the author.
|
||||
*
|
||||
* param author Author that sent the message.
|
||||
* param recipients Array of clients who received the message.
|
||||
* param flagstring Flag string to determine the type of message.
|
||||
* param formatstring Format string used in the message based on the flag string.
|
||||
* param name Name string of the author.
|
||||
* param message Message string from the author.
|
||||
* param processcolors Check if colors were processed in the buffer strings.
|
||||
* param removecolors Check if colors were removed from the buffer strings.
|
||||
*
|
||||
* noreturn
|
||||
**/
|
||||
forward void CP_OnChatMessagePost(int author, ArrayList recipients, const char[] flagstring, const char[] formatstring, const char[] name, const char[] message, bool processcolors, bool removecolors);
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public __pl_chat_processor_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("ChatProcessor_GetFlagFormatString");
|
||||
}
|
||||
#endif
|
||||
|
||||
public SharedPlugin __pl_chat_processor =
|
||||
{
|
||||
name = "chat-processor",
|
||||
file = "chat-processor.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
@ -803,21 +803,6 @@ native int Shavit_GetRankedPlayers();
|
||||
*/
|
||||
native int Shavit_ForceHUDUpdate(int client, bool spectators);
|
||||
|
||||
/**
|
||||
* Formats chats exactly like the chat handler does.
|
||||
* Takes team, alive status, rank and all those stuff into account.
|
||||
* Called from shavit-chat
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param message Message to use.
|
||||
* @param team Simulate a team chat message?
|
||||
* @param buffer Buffer to store the formatted line on.
|
||||
* @param maxlen Length of 'buffer'
|
||||
* @error Error code 200 if client isn't valid.
|
||||
* @return -1 on error, SP_ERROR_NONE on success.
|
||||
*/
|
||||
native int Shavit_FormatChat(int client, const char[] message, const bool team, char[] buffer, int maxlen);
|
||||
|
||||
/**
|
||||
* Opens the stats menu for a client.
|
||||
*
|
||||
|
||||
507
scripting/shavit-chat.sp
Normal file
507
scripting/shavit-chat.sp
Normal file
@ -0,0 +1,507 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Note: For donator perks, give donators a custom flag and then override it to have "shavit_chat".
|
||||
|
||||
#include <sourcemod>
|
||||
#include <chat-processor>
|
||||
|
||||
#undef REQUIRE_PLUGIN
|
||||
#define USES_CHAT_COLORS
|
||||
#include <shavit>
|
||||
|
||||
// database
|
||||
Database gH_SQL = null;
|
||||
char gS_MySQLPrefix[32];
|
||||
|
||||
// cache
|
||||
EngineVersion gEV_Type = Engine_Unknown;
|
||||
|
||||
bool gB_AllowCustom[MAXPLAYERS+1];
|
||||
|
||||
bool gB_NameEnabled[MAXPLAYERS+1];
|
||||
char gS_CustomName[MAXPLAYERS+1][128];
|
||||
|
||||
bool gB_MessageEnabled[MAXPLAYERS+1];
|
||||
char gS_CustomMessage[MAXPLAYERS+1][16];
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
gEV_Type = GetEngineVersion();
|
||||
|
||||
LoadTranslations("shavit-common.phrases");
|
||||
LoadTranslations("shavit-chat.phrases");
|
||||
|
||||
RegConsoleCmd("sm_cchelp", Command_CCHelp, "Provides help with setting a custom chat name/message color.");
|
||||
RegConsoleCmd("sm_ccname", Command_CCName, "Toggles/sets a custom chat name. Usage: sm_ccname <text> or sm_ccname \"off\" to disable.");
|
||||
RegConsoleCmd("sm_ccmsg", Command_CCMessage, "Toggles/sets a custom chat message color. Usage: sm_ccmsg <color> or sm_ccmsg \"off\" to disable.");
|
||||
RegConsoleCmd("sm_ccmessage", Command_CCMessage, "Toggles/sets a custom chat message color. Usage: sm_ccmessage <color> or sm_ccmessage \"off\" to disable.");
|
||||
|
||||
RegAdminCmd("sm_cclist", Command_CCList, ADMFLAG_CHAT, "Print the custom chat setting of all online players.");
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(IsClientInGame(i) && !IsFakeClient(i))
|
||||
{
|
||||
OnClientPostAdminCheck(i);
|
||||
}
|
||||
}
|
||||
|
||||
if(LibraryExists("shavit"))
|
||||
{
|
||||
Shavit_GetDB(gH_SQL);
|
||||
SQL_SetPrefix();
|
||||
SetSQLInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnLibraryAdded(const char[] name)
|
||||
{
|
||||
if(StrEqual(name, "shavit"))
|
||||
{
|
||||
Shavit_GetDB(gH_SQL);
|
||||
SQL_SetPrefix();
|
||||
SetSQLInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnLibraryRemoved(const char[] name)
|
||||
{
|
||||
if(StrEqual(name, "shavit"))
|
||||
{
|
||||
gH_SQL = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Shavit_OnDatabaseLoaded(Database db)
|
||||
{
|
||||
gH_SQL = db;
|
||||
}
|
||||
|
||||
public Action CheckForSQLInfo(Handle Timer)
|
||||
{
|
||||
return SetSQLInfo();
|
||||
}
|
||||
|
||||
Action SetSQLInfo()
|
||||
{
|
||||
if(gH_SQL == null)
|
||||
{
|
||||
Shavit_GetDB(gH_SQL);
|
||||
|
||||
CreateTimer(0.5, CheckForSQLInfo);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
SQL_DBConnect();
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void SQL_SetPrefix()
|
||||
{
|
||||
char[] sFile = new char[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sFile, PLATFORM_MAX_PATH, "configs/shavit-prefix.txt");
|
||||
|
||||
File fFile = OpenFile(sFile, "r");
|
||||
|
||||
if(fFile == null)
|
||||
{
|
||||
SetFailState("Cannot open \"configs/shavit-prefix.txt\". Make sure this file exists and that the server has read permissions to it.");
|
||||
}
|
||||
|
||||
char[] sLine = new char[PLATFORM_MAX_PATH*2];
|
||||
|
||||
while(fFile.ReadLine(sLine, PLATFORM_MAX_PATH*2))
|
||||
{
|
||||
TrimString(sLine);
|
||||
strcopy(gS_MySQLPrefix, 32, sLine);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
delete fFile;
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
gB_AllowCustom[client] = false;
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
gB_AllowCustom[client] = false;
|
||||
|
||||
gB_NameEnabled[client] = false;
|
||||
strcopy(gS_CustomName[client], 128, "");
|
||||
|
||||
gB_MessageEnabled[client] = false;
|
||||
strcopy(gS_CustomMessage[client], 128, "");
|
||||
}
|
||||
|
||||
public void OnClientPostAdminCheck(int client)
|
||||
{
|
||||
gB_AllowCustom[client] = CheckCommandAccess(client, "shavit_chat", ADMFLAG_CHAT);
|
||||
|
||||
if(gH_SQL != null)
|
||||
{
|
||||
LoadFromDatabase(client);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_CCHelp(int client, int args)
|
||||
{
|
||||
if(client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "%t", "NoConsole");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Shavit_PrintToChat(client, "%T", "CheckConsole", client);
|
||||
|
||||
PrintToConsole(client, "%T\n", "CCHelp_Intro", client);
|
||||
PrintToConsole(client, "%T", "CCHelp_Generic", client);
|
||||
PrintToConsole(client, "%T", "CCHelp_GenericVariables", client);
|
||||
|
||||
if(gEV_Type == Engine_CSS)
|
||||
{
|
||||
PrintToConsole(client, "%T", "CCHelp_CSS_1", client);
|
||||
PrintToConsole(client, "%T", "CCHelp_CSS_2", client);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PrintToConsole(client, "%T", "CCHelp_CSGO_1", client);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_CCName(int client, int args)
|
||||
{
|
||||
if(client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "%t", "NoConsole");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if(!gB_AllowCustom[client])
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "NoCommandAccess", client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char[] sArgs = new char[128];
|
||||
GetCmdArgString(sArgs, 128);
|
||||
TrimString(sArgs);
|
||||
FormatColors(sArgs, 128, true, true);
|
||||
|
||||
if(args == 0 || strlen(sArgs) == 0)
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "ArgumentsMissing", client, "sm_ccname <text>");
|
||||
Shavit_PrintToChat(client, "%T", "ChatCurrent", client, sArgs);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
else if(StrEqual(sArgs, "off"))
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "NameOff", client, sArgs);
|
||||
|
||||
gB_NameEnabled[client] = false;
|
||||
|
||||
SaveToDatabase(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Shavit_PrintToChat(client, "%T", "ChatUpdated", client);
|
||||
|
||||
gB_NameEnabled[client] = true;
|
||||
strcopy(gS_CustomName[client], 128, sArgs);
|
||||
|
||||
SaveToDatabase(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_CCMessage(int client, int args)
|
||||
{
|
||||
if(client == 0)
|
||||
{
|
||||
ReplyToCommand(client, "%t", "NoConsole");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
if(!gB_AllowCustom[client])
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "NoCommandAccess", client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
char[] sArgs = new char[32];
|
||||
GetCmdArgString(sArgs, 32);
|
||||
TrimString(sArgs);
|
||||
FormatColors(sArgs, 32, true, true);
|
||||
|
||||
if(args == 0 || strlen(sArgs) == 0)
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "ArgumentsMissing", client, "sm_ccmsg <text>");
|
||||
Shavit_PrintToChat(client, "%T", "ChatCurrent", client, sArgs);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
else if(StrEqual(sArgs, "off"))
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "MessageOff", client, sArgs);
|
||||
|
||||
gB_MessageEnabled[client] = false;
|
||||
|
||||
SaveToDatabase(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
Shavit_PrintToChat(client, "%T", "ChatUpdated", client);
|
||||
|
||||
gB_MessageEnabled[client] = true;
|
||||
strcopy(gS_CustomMessage[client], 16, sArgs);
|
||||
|
||||
SaveToDatabase(client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_CCList(int client, int args)
|
||||
{
|
||||
ReplyToCommand(client, "%T", "CheckConsole", client);
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(gB_AllowCustom[i])
|
||||
{
|
||||
PrintToConsole(client, "%N (%d/%d) (name: \"%s\"; message: \"%s\")", i, i, GetClientUserId(i), gS_CustomName[i], gS_CustomMessage[i])
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action CP_OnChatMessage(int &author, ArrayList recipients, char[] flagstring, char[] name, char[] message, bool &processcolors, bool &removecolors)
|
||||
{
|
||||
if(!gB_AllowCustom[author])
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
Action retvalue = Plugin_Continue;
|
||||
|
||||
if(gB_NameEnabled[author] && strlen(gS_CustomName[author]) > 0)
|
||||
{
|
||||
char[] sName = new char[MAX_NAME_LENGTH];
|
||||
GetClientName(author, sName, MAX_NAME_LENGTH);
|
||||
ReplaceString(gS_CustomName[author], MAXLENGTH_NAME, "{name}", sName);
|
||||
|
||||
strcopy(name, MAXLENGTH_NAME, gS_CustomName[author]);
|
||||
FormatRandom(name, MAXLENGTH_NAME);
|
||||
|
||||
retvalue = Plugin_Changed;
|
||||
}
|
||||
|
||||
if(gB_MessageEnabled[author] && strlen(gS_CustomMessage[author]) > 0)
|
||||
{
|
||||
Format(message, MAXLENGTH_MESSAGE, "%s%s", gS_CustomMessage[author], message);
|
||||
FormatRandom(message, MAXLENGTH_MESSAGE);
|
||||
|
||||
retvalue = Plugin_Changed;
|
||||
}
|
||||
|
||||
removecolors = true;
|
||||
processcolors = false;
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
void FormatColors(char[] buffer, int size, bool colors, bool escape)
|
||||
{
|
||||
if(colors)
|
||||
{
|
||||
for(int i = 0; i < sizeof(gS_GlobalColorNames); i++)
|
||||
{
|
||||
ReplaceString(buffer, size, gS_GlobalColorNames[i], gS_GlobalColors[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < sizeof(gS_CSGOColorNames); i++)
|
||||
{
|
||||
ReplaceString(buffer, size, gS_CSGOColorNames[i], gS_CSGOColors[i]);
|
||||
}
|
||||
|
||||
ReplaceString(buffer, size, "^", "\x07");
|
||||
ReplaceString(buffer, size, "{RGB}", "\x07");
|
||||
ReplaceString(buffer, size, "&", "\x08");
|
||||
ReplaceString(buffer, size, "{RGBA}", "\x08");
|
||||
}
|
||||
|
||||
if(escape)
|
||||
{
|
||||
ReplaceString(buffer, size, "%%", "");
|
||||
}
|
||||
}
|
||||
|
||||
void FormatRandom(char[] buffer, int size)
|
||||
{
|
||||
char[] temp = new char[8];
|
||||
|
||||
do
|
||||
{
|
||||
int color = ((RealRandomInt(0, 255) & 0xFF) << 16);
|
||||
color |= ((RealRandomInt(0, 255) & 0xFF) << 8);
|
||||
color |= (RealRandomInt(0, 255) & 0xFF);
|
||||
|
||||
FormatEx(temp, 16, "\x07%06X", color);
|
||||
}
|
||||
|
||||
while(ReplaceStringEx(buffer, size, "{rand}", temp) > 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void SQL_DBConnect()
|
||||
{
|
||||
if(gH_SQL != null)
|
||||
{
|
||||
char[] sQuery = new char[512];
|
||||
FormatEx(sQuery, 512, "CREATE TABLE IF NOT EXISTS `%schat` (`auth` VARCHAR(32) NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), PRIMARY KEY (`auth`));", gS_MySQLPrefix);
|
||||
|
||||
gH_SQL.Query(SQL_CreateTable_Callback, sQuery, 0, DBPrio_High);
|
||||
}
|
||||
}
|
||||
|
||||
public void SQL_CreateTable_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if(results == null)
|
||||
{
|
||||
LogError("Timer error! Chat table creation failed. Reason: %s", error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(gB_AllowCustom[i])
|
||||
{
|
||||
LoadFromDatabase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveToDatabase(int client)
|
||||
{
|
||||
char[] sAuthID3 = new char[32];
|
||||
|
||||
if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int iLength = ((strlen(gS_CustomName[client]) * 2) + 1);
|
||||
char[] sEscapedName = new char[iLength];
|
||||
gH_SQL.Escape(gS_CustomName[client], sEscapedName, iLength);
|
||||
|
||||
iLength = ((strlen(gS_CustomMessage[client]) * 2) + 1);
|
||||
char[] sEscapedMessage = new char[iLength];
|
||||
gH_SQL.Escape(gS_CustomMessage[client], sEscapedMessage, iLength);
|
||||
|
||||
char[] sQuery = new char[512];
|
||||
FormatEx(sQuery, 512, "REPLACE INTO %schat (auth, name, ccname, message, ccmessage) VALUES ('%s', %d, '%s', %d, '%s');", gS_MySQLPrefix, sAuthID3, gB_NameEnabled[client], sEscapedName, gB_MessageEnabled[client], sEscapedMessage);
|
||||
|
||||
gH_SQL.Query(SQL_UpdateUser_Callback, sQuery, 0, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_UpdateUser_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if(results == null)
|
||||
{
|
||||
LogError("Timer error! Failed to insert chat data. Reason: %s", error);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadFromDatabase(int client)
|
||||
{
|
||||
char[] sAuthID3 = new char[32];
|
||||
|
||||
if(!GetClientAuthId(client, AuthId_Steam3, sAuthID3, 32))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char sQuery[256];
|
||||
FormatEx(sQuery, 256, "SELECT name, ccname, message, ccmessage FROM %schat WHERE auth = '%s';", gS_MySQLPrefix, sAuthID3);
|
||||
|
||||
gH_SQL.Query(SQL_GetChat_Callback, sQuery, GetClientSerial(client), DBPrio_Low);
|
||||
}
|
||||
|
||||
public void SQL_GetChat_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if(results == null)
|
||||
{
|
||||
LogError("Timer (Chat cache update) SQL query failed. Reason: %s", error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int client = GetClientFromSerial(data);
|
||||
|
||||
if(client == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while(results.FetchRow())
|
||||
{
|
||||
gB_NameEnabled[client] = view_as<bool>(results.FetchInt(0));
|
||||
results.FetchString(1, gS_CustomName[client], 128);
|
||||
|
||||
gB_MessageEnabled[client] = view_as<bool>(results.FetchInt(2));
|
||||
results.FetchString(3, gS_CustomMessage[client], 16);
|
||||
}
|
||||
}
|
||||
@ -190,9 +190,6 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
LoadTranslations("shavit-common.phrases");
|
||||
LoadTranslations("shavit-misc.phrases");
|
||||
|
||||
// cache
|
||||
gEV_Type = GetEngineVersion();
|
||||
|
||||
@ -262,6 +259,8 @@ public void OnPluginStart()
|
||||
|
||||
// phrases
|
||||
LoadTranslations("common.phrases");
|
||||
LoadTranslations("shavit-common.phrases");
|
||||
LoadTranslations("shavit-misc.phrases");
|
||||
|
||||
// advertisements
|
||||
gA_Advertisements = new ArrayList(300);
|
||||
|
||||
49
translations/shavit-chat.phrases.txt
Normal file
49
translations/shavit-chat.phrases.txt
Normal file
@ -0,0 +1,49 @@
|
||||
"Phrases"
|
||||
{
|
||||
// ---------- Commands ---------- //
|
||||
"ChatUpdated"
|
||||
{
|
||||
"en" "Setting updated."
|
||||
}
|
||||
"ChatCurrent"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Current setting: {1}"
|
||||
}
|
||||
"NameOff"
|
||||
{
|
||||
"en" "Custom chat name is now off."
|
||||
}
|
||||
"MessageOff"
|
||||
{
|
||||
"en" "Custom chat text color is now off."
|
||||
}
|
||||
"CheckConsole"
|
||||
{
|
||||
"en" "Check your console."
|
||||
}
|
||||
"CCHelp_Intro"
|
||||
{
|
||||
"en" "- You have access to custom chat.\nUsage information:"
|
||||
}
|
||||
"CCHelp_Generic"
|
||||
{
|
||||
"en" "- !ccname can be used to change your custom chat name. Use \"!ccname off\" to toggle it off.\n- !ccmsg can be used to change your custom message prefix/color. Use \"!ccmsgg off\" to toggle it off.\nThere are custom variables, such as:"
|
||||
}
|
||||
"CCHelp_GenericVariables"
|
||||
{
|
||||
"en" "- {name} - your in-game name.\n- {rand} - a random color.\n- {team} - your team color.\n- {green} - green color."
|
||||
}
|
||||
"CCHelp_CSS_1"
|
||||
{
|
||||
"en" "- To use a custom color, write ^RRGGBB (HEX/HTML colors). For example, ^FFFFFF is white and ^000000 is black."
|
||||
}
|
||||
"CCHelp_CSS_2"
|
||||
{
|
||||
"en" "- You can also use a set alpha (opacity in HEX, where FF is 255). &RRGGBBAA. For example, &FFFFFF7F is 127 alpha, so all text after the color will have 50% opacity."
|
||||
}
|
||||
"CCHelp_CSGO_1"
|
||||
{
|
||||
"en" "- The following colors are also available: {blue}, {bluegrey}, {darkblue}, {darkred}, {gold}, {grey}, {grey2}, {lightgreen}, {lightred}, {lime}, {orchid}, {yellow} and {palered}."
|
||||
}
|
||||
}
|
||||
@ -17,4 +17,18 @@
|
||||
{
|
||||
"en" "Bonus"
|
||||
}
|
||||
// ---------- Commands ---------- //
|
||||
"NoCommandAccess"
|
||||
{
|
||||
"en" "You do not have access to this command."
|
||||
}
|
||||
"NoConsole"
|
||||
{
|
||||
"en" "Run this command from inside the game."
|
||||
}
|
||||
"ArgumentsMissing"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Usage: {1}"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user