csgo-plugins/SelfMute/scripting/SelfMute.sp
2020-03-25 20:09:12 +02:00

1359 lines
34 KiB
SourcePawn

#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <adminmenu>
#include <cstrike>
#include <clientprefs>
#undef REQUIRE_PLUGIN
#include <ccc>
#include <zombiereloaded>
#tryinclude <voiceannounce_ex>
#include <AdvancedTargeting>
#define REQUIRE_PLUGIN
#undef REQUIRE_EXTENSIONS
#tryinclude <voice>
#define REQUIRE_EXTENSIONS
#pragma newdecls required
bool g_Plugin_ccc = false;
bool g_Plugin_zombiereloaded = false;
bool g_Plugin_voiceannounce_ex = false;
bool g_Plugin_AdvancedTargeting = false;
bool g_Extension_Voice = false;
bool g_bIsProtoBuf = false;
Handle g_hCookieTorchMuted = null;
#define PLUGIN_VERSION "2.4"
public Plugin myinfo =
{
name = "SelfMute",
author = "BotoX",
description = "Ignore other players in text and voicechat.",
version = PLUGIN_VERSION,
url = ""
};
enum
{
MUTE_NONE = 0,
MUTE_SPEC = 1,
MUTE_CT = 2,
MUTE_T = 4,
MUTE_DEAD = 8,
MUTE_ALIVE = 16,
MUTE_NOTFRIENDS = 32,
MUTE_ALL = 64,
MUTE_LAST = 64
};
bool g_Ignored[(MAXPLAYERS + 1) * (MAXPLAYERS + 1)];
bool g_Exempt[MAXPLAYERS + 1][MAXPLAYERS + 1];
int g_SpecialMutes[MAXPLAYERS + 1];
char g_PlayerNames[MAXPLAYERS+1][MAX_NAME_LENGTH];
public void OnPluginStart()
{
LoadTranslations("common.phrases");
CreateConVar("sm_selfmute_version", PLUGIN_VERSION, "Version of Self-Mute", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
RegConsoleCmd("sm_sm", Command_SelfMute, "Mute player by typing !sm [playername]");
RegConsoleCmd("sm_su", Command_SelfUnMute, "Unmute player by typing !su [playername]");
RegConsoleCmd("sm_cm", Command_CheckMutes, "Check who you have self-muted");
RegAdminCmd("sm_debugtorch", Command_CheckPermaTorchMutes, ADMFLAG_GENERIC, "Check who has permanently self-muted Torch");
HookEvent("round_start", Event_Round);
HookEvent("round_end", Event_Round);
HookEvent("player_team", Event_TeamChange);
if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf)
g_bIsProtoBuf = true;
UserMsg RadioText = GetUserMessageId("RadioText");
if(RadioText == INVALID_MESSAGE_ID)
SetFailState("This game doesn't support RadioText user messages.");
HookUserMessage(RadioText, Hook_UserMessageRadioText, true);
UserMsg SendAudio = GetUserMessageId("SendAudio");
if(SendAudio == INVALID_MESSAGE_ID)
SetFailState("This game doesn't support SendAudio user messages.");
HookUserMessage(SendAudio, Hook_UserMessageSendAudio, true);
g_hCookieTorchMuted = RegClientCookie("torch_muted", "is torch muted", CookieAccess_Protected);
}
public void OnAllPluginsLoaded()
{
g_Plugin_ccc = LibraryExists("ccc");
g_Plugin_zombiereloaded = LibraryExists("zombiereloaded");
g_Plugin_voiceannounce_ex = LibraryExists("voiceannounce_ex");
g_Plugin_AdvancedTargeting = LibraryExists("AdvancedTargeting");
g_Extension_Voice = LibraryExists("Voice");
LogMessage("SelfMute capabilities:\nProtoBuf: %s\nCCC: %s\nZombieReloaded: %s\nVoiceAnnounce: %s\nAdvancedTargeting: %s\nVoice: %s",
(g_bIsProtoBuf ? "yes" : "no"),
(g_Plugin_ccc ? "loaded" : "not loaded"),
(g_Plugin_zombiereloaded ? "loaded" : "not loaded"),
(g_Plugin_voiceannounce_ex ? "loaded" : "not loaded"),
(g_Plugin_AdvancedTargeting ? "loaded" : "not loaded"),
(g_Extension_Voice ? "loaded" : "not loaded"));
}
void OnLibrary(const char[] name, bool added)
{
if(StrEqual(name, "ccc"))
g_Plugin_ccc = added;
else if(StrEqual(name, "zombiereloaded"))
g_Plugin_zombiereloaded = added;
else if(StrEqual(name, "voiceannounce_ex"))
g_Plugin_voiceannounce_ex = added;
else if(StrEqual(name, "AdvancedTargeting"))
g_Plugin_AdvancedTargeting = added;
else if(StrEqual(name, "Voice"))
g_Extension_Voice = added;
}
public void OnLibraryAdded(const char[] name) { OnLibrary(name, true); }
public void OnLibraryRemoved(const char[] name) { OnLibrary(name, false); }
public void OnClientPutInServer(int client)
{
g_SpecialMutes[client] = MUTE_NONE;
for(int i = 1; i < MAXPLAYERS; i++)
{
SetIgnored(client, i, false);
SetExempt(client, i, false);
SetIgnored(i, client, false);
SetExempt(i, client, false);
}
UpdateSpecialMutesOtherClients(client);
UpdateIgnored();
GetCookiesForTorch(client);
}
public void OnClientDisconnect(int client)
{
g_SpecialMutes[client] = MUTE_NONE;
for(int i = 1; i < MAXPLAYERS; i++)
{
SetIgnored(client, i, false);
SetExempt(client, i, false);
SetIgnored(i, client, false);
SetExempt(i, client, false);
if(IsClientInGame(i) && i != client)
SetListenOverride(i, client, Listen_Yes);
}
UpdateIgnored();
}
public void GetCookiesForTorch(int client)
{
char sBuffer[2];
GetClientCookie(client, g_hCookieTorchMuted, sBuffer, sizeof(sBuffer));
if(sBuffer[0] != '\0')
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && IsClientSourceTV(i))
Ignore(client, i);
}
}
UpdateIgnored();
}
public void Event_Round(Handle event, const char[] name, bool dontBroadcast)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i))
UpdateSpecialMutesThisClient(i);
}
}
public void Event_TeamChange(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
UpdateSpecialMutesOtherClients(client);
}
public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn)
{
UpdateSpecialMutesOtherClients(client);
}
public void ZR_OnClientHumanPost(int client, bool respawn, bool protect)
{
UpdateSpecialMutesOtherClients(client);
}
/*
* Mutes this client on other players
*/
void UpdateSpecialMutesOtherClients(int client)
{
bool Alive = IsPlayerAlive(client);
int Team = GetClientTeam(client);
for(int i = 1; i <= MaxClients; i++)
{
if(i == client || !IsClientInGame(i))
continue;
int Flags = MUTE_NONE;
if(g_SpecialMutes[i] & MUTE_SPEC && Team == CS_TEAM_SPECTATOR)
Flags |= MUTE_SPEC;
else if(g_SpecialMutes[i] & MUTE_CT && Alive &&
((g_Plugin_zombiereloaded && ZR_IsClientHuman(client)) || (!g_Plugin_zombiereloaded && Team == CS_TEAM_CT)))
Flags |= MUTE_CT;
else if(g_SpecialMutes[i] & MUTE_T && Alive &&
((g_Plugin_zombiereloaded && ZR_IsClientZombie(client)) || (!g_Plugin_zombiereloaded && Team == CS_TEAM_T)))
Flags |= MUTE_T;
else if(g_SpecialMutes[i] & MUTE_DEAD && !Alive)
Flags |= MUTE_DEAD;
else if(g_SpecialMutes[i] & MUTE_ALIVE && Alive)
Flags |= MUTE_ALIVE;
else if(g_SpecialMutes[i] & MUTE_NOTFRIENDS &&
g_Plugin_AdvancedTargeting && IsClientFriend(i, client) == 0)
Flags |= MUTE_NOTFRIENDS;
else if(g_SpecialMutes[i] & MUTE_ALL)
Flags |= MUTE_ALL;
if(Flags && !GetExempt(i, client))
SetListenOverride(i, client, Listen_No);
else if(!GetIgnored(i, client))
SetListenOverride(i, client, Listen_Yes);
}
}
/*
* Mutes other players on this client
*/
void UpdateSpecialMutesThisClient(int client)
{
for(int i = 1; i <= MaxClients; i++)
{
if(i == client || !IsClientInGame(i))
continue;
bool Alive = IsPlayerAlive(i);
int Team = GetClientTeam(i);
int Flags = MUTE_NONE;
if(g_SpecialMutes[client] & MUTE_SPEC && Team == CS_TEAM_SPECTATOR)
Flags |= MUTE_SPEC;
else if(g_SpecialMutes[client] & MUTE_CT && Alive &&
((g_Plugin_zombiereloaded && ZR_IsClientHuman(i) || (!g_Plugin_zombiereloaded) && Team == CS_TEAM_CT)))
Flags |= MUTE_CT;
else if(g_SpecialMutes[client] & MUTE_T && Alive &&
((g_Plugin_zombiereloaded && ZR_IsClientZombie(i) || (!g_Plugin_zombiereloaded) && Team == CS_TEAM_T)))
Flags |= MUTE_T;
else if(g_SpecialMutes[client] & MUTE_DEAD && !Alive)
Flags |= MUTE_DEAD;
else if(g_SpecialMutes[client] & MUTE_ALIVE && Alive)
Flags |= MUTE_ALIVE;
else if(g_SpecialMutes[client] & MUTE_NOTFRIENDS &&
g_Plugin_AdvancedTargeting && IsClientFriend(client, i) == 0)
Flags |= MUTE_NOTFRIENDS;
else if(g_SpecialMutes[client] & MUTE_ALL)
Flags |= MUTE_ALL;
if(Flags && !GetExempt(client, i))
SetListenOverride(client, i, Listen_No);
else if(!GetIgnored(client, i))
SetListenOverride(client, i, Listen_Yes);
}
}
int GetSpecialMutesFlags(char[] Argument)
{
int SpecialMute = MUTE_NONE;
if(StrEqual(Argument, "@spec", false) || StrEqual(Argument, "@!ct", false) || StrEqual(Argument, "@!t", false))
SpecialMute |= MUTE_SPEC;
if(StrEqual(Argument, "@ct", false) || StrEqual(Argument, "@!t", false) || StrEqual(Argument, "@!spec", false))
SpecialMute |= MUTE_CT;
if(StrEqual(Argument, "@t", false) || StrEqual(Argument, "@!ct", false) || StrEqual(Argument, "@!spec", false))
SpecialMute |= MUTE_T;
if(StrEqual(Argument, "@dead", false) || StrEqual(Argument, "@!alive", false))
SpecialMute |= MUTE_DEAD;
if(StrEqual(Argument, "@alive", false) || StrEqual(Argument, "@!dead", false))
SpecialMute |= MUTE_ALIVE;
if(g_Plugin_AdvancedTargeting && StrEqual(Argument, "@!friends", false))
SpecialMute |= MUTE_NOTFRIENDS;
if(StrEqual(Argument, "@all", false))
SpecialMute |= MUTE_ALL;
return SpecialMute;
}
void FormatSpecialMutes(int SpecialMute, char[] aBuf, int BufLen)
{
if(!SpecialMute)
{
StrCat(aBuf, BufLen, "none");
return;
}
bool Status = false;
if(SpecialMute & MUTE_ALL)
{
StrCat(aBuf, BufLen, "Everyone, ");
Status = true;
}
if(SpecialMute & MUTE_SPEC)
{
StrCat(aBuf, BufLen, "Spectators, ");
Status = true;
}
if(SpecialMute & MUTE_CT)
{
StrCat(aBuf, BufLen, "Counter-Terrorists, ");
Status = true;
}
if(SpecialMute & MUTE_T)
{
StrCat(aBuf, BufLen, "Terrorists, ");
Status = true;
}
if(SpecialMute & MUTE_DEAD)
{
StrCat(aBuf, BufLen, "Dead players, ");
Status = true;
}
if(SpecialMute & MUTE_ALIVE)
{
StrCat(aBuf, BufLen, "Alive players, ");
Status = true;
}
if(SpecialMute & MUTE_NOTFRIENDS)
{
StrCat(aBuf, BufLen, "Not Steam friends, ");
Status = true;
}
// Cut off last ', '
if(Status)
aBuf[strlen(aBuf) - 2] = 0;
}
bool MuteSpecial(int client, char[] Argument)
{
bool RetValue = false;
int SpecialMute = GetSpecialMutesFlags(Argument);
if(SpecialMute & MUTE_NOTFRIENDS && g_Plugin_AdvancedTargeting && ReadClientFriends(client) != 1)
{
PrintToChat(client, "\x04[Self-Mute]\x01 Could not read your friendslist, your profile must be set to public!");
SpecialMute &= ~MUTE_NOTFRIENDS;
RetValue = true;
}
if(SpecialMute)
{
if(SpecialMute & MUTE_ALL || g_SpecialMutes[client] & MUTE_ALL)
{
g_SpecialMutes[client] = MUTE_ALL;
SpecialMute = MUTE_ALL;
}
else
g_SpecialMutes[client] |= SpecialMute;
UpdateSpecialMutesThisClient(client);
char aBuf[128];
FormatSpecialMutes(SpecialMute, aBuf, sizeof(aBuf));
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted group:\x04 %s", aBuf);
RetValue = true;
}
return RetValue;
}
bool UnMuteSpecial(int client, char[] Argument)
{
int SpecialMute = GetSpecialMutesFlags(Argument);
if(SpecialMute)
{
if(SpecialMute & MUTE_ALL)
{
if(g_SpecialMutes[client])
{
SpecialMute = g_SpecialMutes[client];
g_SpecialMutes[client] = MUTE_NONE;
}
else
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && !IsClientSourceTV(i))
UnIgnore(client, i);
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 all players");
return true;
}
}
}
else
g_SpecialMutes[client] &= ~SpecialMute;
UpdateSpecialMutesThisClient(client);
char aBuf[256];
FormatSpecialMutes(SpecialMute, aBuf, sizeof(aBuf));
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted group:\x04 %s", aBuf);
return true;
}
return false;
}
void Ignore(int client, int target)
{
SetIgnored(client, target, true);
SetListenOverride(client, target, Listen_No);
}
void UnIgnore(int client, int target)
{
SetIgnored(client, target, false);
SetListenOverride(client, target, Listen_Yes);
}
void Exempt(int client, int target)
{
SetExempt(client, target, true);
UpdateSpecialMutesThisClient(client);
}
void UnExempt(int client, int target)
{
SetExempt(client, target, false);
UpdateSpecialMutesThisClient(client);
}
/*
* CHAT COMMANDS
*/
public Action Command_CheckPermaTorchMutes(int client, int args)
{
int iTorchPermMuted;
int iPlayers;
char sBuffer[2];
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientInGame(i) || IsFakeClient(i))
continue;
GetClientCookie(i, g_hCookieTorchMuted, sBuffer, sizeof(sBuffer));
if(sBuffer[0] != '\0')
iTorchPermMuted++;
iPlayers++;
}
ReplyToCommand(client, "[SM] There are currently %d out of %d Players who've got Torch permanently self-muted.", iTorchPermMuted, iPlayers);
return Plugin_Handled;
}
public Action Command_SelfMute(int client, int args)
{
if(client == 0)
{
PrintToServer("[SM] Cannot use command from server console.");
return Plugin_Handled;
}
if(args < 1)
{
DisplayMuteMenu(client);
return Plugin_Handled;
}
char Argument[65];
GetCmdArg(1, Argument, sizeof(Argument));
char Filtered[65];
strcopy(Filtered, sizeof(Filtered), Argument);
StripQuotes(Filtered);
TrimString(Filtered);
if(MuteSpecial(client, Filtered))
return Plugin_Handled;
char sTargetName[MAX_TARGET_LENGTH];
int aTargetList[MAXPLAYERS];
int TargetCount;
bool TnIsMl;
if((TargetCount = ProcessTargetString(
Argument,
client,
aTargetList,
MAXPLAYERS,
COMMAND_FILTER_CONNECTED|COMMAND_FILTER_NO_IMMUNITY,
sTargetName,
sizeof(sTargetName),
TnIsMl)) <= 0)
{
ReplyToTargetError(client, TargetCount);
return Plugin_Handled;
}
if(TargetCount == 1)
{
if(aTargetList[0] == client)
{
PrintToChat(client, "\x04[Self-Mute]\x01 You can't mute yourself, don't be silly.");
return Plugin_Handled;
}
if(IsClientSourceTV(aTargetList[0]))
{
Ignore(client, aTargetList[0]);
SetClientCookie(client, g_hCookieTorchMuted, "1");
PrintToChat(client, "\x04[Self-Mute]\x01 You have permanently self-muted:\x04 %s", sTargetName);
return Plugin_Handled;
}
if(GetExempt(client, aTargetList[0]))
{
UnExempt(client, aTargetList[0]);
PrintToChat(client, "\x04[Self-Mute]\x01 You have removed exempt from self-mute:\x04 %s", sTargetName);
return Plugin_Handled;
}
}
for(int i = 0; i < TargetCount; i++)
{
if(aTargetList[i] == client)
continue;
Ignore(client, aTargetList[i]);
}
UpdateIgnored();
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted:\x04 %s", sTargetName);
return Plugin_Handled;
}
public Action Command_SelfUnMute(int client, int args)
{
if(client == 0)
{
PrintToServer("[SM] Cannot use command from server console.");
return Plugin_Handled;
}
if(args < 1)
{
DisplayUnMuteMenu(client);
return Plugin_Handled;
}
char Argument[65];
GetCmdArg(1, Argument, sizeof(Argument));
char Filtered[65];
strcopy(Filtered, sizeof(Filtered), Argument);
StripQuotes(Filtered);
TrimString(Filtered);
if(UnMuteSpecial(client, Filtered))
return Plugin_Handled;
char sTargetName[MAX_TARGET_LENGTH];
int aTargetList[MAXPLAYERS];
int TargetCount;
bool TnIsMl;
if((TargetCount = ProcessTargetString(
Argument,
client,
aTargetList,
MAXPLAYERS,
COMMAND_FILTER_CONNECTED|COMMAND_FILTER_NO_IMMUNITY,
sTargetName,
sizeof(sTargetName),
TnIsMl)) <= 0)
{
ReplyToTargetError(client, TargetCount);
return Plugin_Handled;
}
if(TargetCount == 1)
{
if(aTargetList[0] == client)
{
PrintToChat(client, "\x04[Self-Mute]\x01 Unmuting won't work either.");
return Plugin_Handled;
}
if(IsClientSourceTV(aTargetList[0]))
{
UnIgnore(client, aTargetList[0]);
SetClientCookie(client, g_hCookieTorchMuted, "");
PrintToChat(client, "\x04[Self-Mute]\x01 You have permanently self-unmuted:\x04 %s", sTargetName);
return Plugin_Handled;
}
if(!GetIgnored(client, aTargetList[0]))
{
Exempt(client, aTargetList[0]);
PrintToChat(client, "\x04[Self-Mute]\x01 You have exempted from self-mute:\x04 %s", sTargetName);
return Plugin_Handled;
}
}
for(int i = 0; i < TargetCount; i++)
{
if(aTargetList[i] == client)
continue;
UnIgnore(client, aTargetList[i]);
}
UpdateIgnored();
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 %s", sTargetName);
return Plugin_Handled;
}
public Action Command_CheckMutes(int client, int args)
{
if(client == 0)
{
PrintToServer("[SM] Cannot use command from server console.");
return Plugin_Handled;
}
char aMuted[1024];
char aExempted[1024];
char aName[MAX_NAME_LENGTH];
for(int i = 1; i <= MaxClients; i++)
{
if(!IsClientInGame(i))
continue;
GetClientName(i, aName, sizeof(aName));
if(GetIgnored(client, i))
{
StrCat(aMuted, sizeof(aMuted), aName);
StrCat(aMuted, sizeof(aMuted), ", ");
}
if(GetExempt(client, i))
{
StrCat(aExempted, sizeof(aExempted), aName);
StrCat(aExempted, sizeof(aExempted), ", ");
}
}
if(strlen(aMuted))
{
aMuted[strlen(aMuted) - 2] = 0;
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted:\x04 %s", aMuted);
}
if(g_SpecialMutes[client] != MUTE_NONE)
{
aMuted[0] = 0;
FormatSpecialMutes(g_SpecialMutes[client], aMuted, sizeof(aMuted));
PrintToChat(client, "\x04[Self-Mute]\x01 You have self-muted group:\x04 %s", aMuted);
}
else if(!strlen(aMuted) && !strlen(aExempted))
PrintToChat(client, "\x04[Self-Mute]\x01 You have not self-muted anyone!");
if(strlen(aExempted))
{
aExempted[strlen(aExempted) - 2] = 0;
PrintToChat(client, "\x04[Self-Mute]\x01 You have exempted from self-mute:\x04 %s", aExempted);
}
return Plugin_Handled;
}
stock bool _IsClientSpeaking(int client)
{
#if defined _voiceannounceex_included_
if(g_Plugin_voiceannounce_ex)
return IsClientSpeaking(client);
#endif
#if defined _voice_included
if(g_Extension_Voice)
return IsClientTalking(client);
#endif
return false;
}
/*
* MENU
*/
void DisplayMuteMenu(int client)
{
Menu menu = new Menu(MenuHandler_MuteMenu, MenuAction_Select|MenuAction_Cancel|MenuAction_End|MenuAction_DrawItem|MenuAction_DisplayItem);
menu.ExitButton = true;
int[] aClients = new int[MaxClients + 1];
{
// Count talking players and insert id's into aClients array
int CurrentlyTalking = 0;
for(int i = 1; i <= MaxClients; i++)
{
if(i != client && IsClientInGame(i) && _IsClientSpeaking(i))
aClients[CurrentlyTalking++] = i;
}
if(CurrentlyTalking > 0)
{
// insert player names into g_PlayerNames array
for(int i = 0; i < CurrentlyTalking; i++)
GetClientName(aClients[i], g_PlayerNames[aClients[i]], sizeof(g_PlayerNames[]));
// sort aClients array by player name
SortCustom1D(aClients, CurrentlyTalking, SortByPlayerName);
// insert players sorted
char aBuf[12];
for(int i = 0; i < CurrentlyTalking; i++)
{
IntToString(GetClientUserId(aClients[i]), aBuf, sizeof(aBuf));
menu.AddItem(aBuf, g_PlayerNames[aClients[i]]);
}
// insert spacers
int Entries = 7 - CurrentlyTalking % 7;
while(Entries--)
menu.AddItem("", "", ITEMDRAW_RAWLINE);
}
}
menu.AddItem("@all", "Everyone");
menu.AddItem("@spec", "Spectators");
menu.AddItem("@ct", "Counter-Terrorists");
menu.AddItem("@t", "Terrorists");
menu.AddItem("@dead", "Dead players");
menu.AddItem("@alive", "Alive players");
if(g_Plugin_AdvancedTargeting)
menu.AddItem("@!friends", "Not Steam friends");
else
menu.AddItem("", "", ITEMDRAW_RAWLINE);
// Count valid players and insert id's into aClients array
int Players = 0;
for(int i = 1; i <= MaxClients; i++)
{
if(i != client && IsClientInGame(i))
aClients[Players++] = i;
}
// insert player names into g_PlayerNames array
for(int i = 0; i < Players; i++)
GetClientName(aClients[i], g_PlayerNames[aClients[i]], sizeof(g_PlayerNames[]));
// sort aClients array by player name
SortCustom1D(aClients, Players, SortByPlayerName);
// insert players sorted
char aBuf[12];
for(int i = 0; i < Players; i++)
{
IntToString(GetClientUserId(aClients[i]), aBuf, sizeof(aBuf));
menu.AddItem(aBuf, g_PlayerNames[aClients[i]]);
}
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_MuteMenu(Menu menu, MenuAction action, int param1, int param2)
{
switch(action)
{
case MenuAction_End:
{
if(param1 != MenuEnd_Selected)
CloseHandle(menu);
}
case MenuAction_Select:
{
int Style;
char aItem[32];
char aDisp[MAX_NAME_LENGTH + 4];
menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp));
if(Style != ITEMDRAW_DEFAULT || !aItem[0])
{
PrintToChat(param1, "Internal error: aItem[0] -> %d | Style -> %d", aItem[0], Style);
return 0;
}
if(aItem[0] == '@')
{
int Flag = GetSpecialMutesFlags(aItem);
if(Flag && g_SpecialMutes[param1] & Flag)
UnMuteSpecial(param1, aItem);
else
MuteSpecial(param1, aItem);
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client)
{
PrintToChat(param1, "\x04[Self-Mute]\x01 Player no longer available.");
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
if(GetIgnored(param1, client))
{
if(IsClientSourceTV(client))
{
UnIgnore(param1, client);
SetClientCookie(param1, g_hCookieTorchMuted, "");
PrintToChat(param1, "\x04[Self-Mute]\x01 You have permanently self-unmuted:\x04 %N", client);
}
else
{
UnIgnore(param1, client);
PrintToChat(param1, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 %N", client);
}
}
else if(GetExempt(param1, client))
{
UnExempt(param1, client);
PrintToChat(param1, "\x04[Self-Mute]\x01 You have removed exempt from self-mute:\x04 %N", client);
}
else
{
if(IsClientSourceTV(client))
{
Ignore(param1, client);
SetClientCookie(param1, g_hCookieTorchMuted, "1");
PrintToChat(param1, "\x04[Self-Mute]\x01 You have permanently self-muted:\x04 %N", client);
}
else
{
Ignore(param1, client);
PrintToChat(param1, "\x04[Self-Mute]\x01 You have self-muted:\x04 %N", client);
}
}
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
case MenuAction_DrawItem:
{
int Style;
char aItem[32];
menu.GetItem(param2, aItem, sizeof(aItem), Style);
if(!aItem[0])
return ITEMDRAW_DISABLED;
if(aItem[0] == '@')
{
int Flag = GetSpecialMutesFlags(aItem);
if(Flag & MUTE_ALL)
return Style;
else if(g_SpecialMutes[param1] & MUTE_ALL)
return ITEMDRAW_DISABLED;
return Style;
}
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
return ITEMDRAW_DISABLED;
return Style;
}
case MenuAction_DisplayItem:
{
int Style;
char aItem[32];
char aDisp[MAX_NAME_LENGTH + 4];
menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp));
// Start of current page
if((param2 + 1) % 7 == 1)
{
if(aItem[0] == '@')
menu.SetTitle("[Self-Mute] Groups");
else if(param2 == 0)
menu.SetTitle("[Self-Mute] Talking players");
else
menu.SetTitle("[Self-Mute] All players");
}
if(!aItem[0])
return 0;
if(aItem[0] == '@')
{
int Flag = GetSpecialMutesFlags(aItem);
if(Flag && g_SpecialMutes[param1] & Flag)
{
char aBuf[32] = "[M] ";
FormatSpecialMutes(Flag, aBuf, sizeof(aBuf));
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
return 0;
}
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
{
char aBuf[MAX_NAME_LENGTH + 4] = "[D] ";
StrCat(aBuf, sizeof(aBuf), aDisp);
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
if(GetIgnored(param1, client))
{
char aBuf[MAX_NAME_LENGTH + 4] = "[M] ";
GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[]));
StrCat(aBuf, sizeof(aBuf), g_PlayerNames[client]);
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
else if(GetExempt(param1, client))
{
char aBuf[MAX_NAME_LENGTH + 4] = "[E] ";
GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[]));
StrCat(aBuf, sizeof(aBuf), g_PlayerNames[client]);
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
else
{
GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[]));
if(!StrEqual(aDisp, g_PlayerNames[client]))
return RedrawMenuItem(g_PlayerNames[client]);
}
return 0;
}
}
return 0;
}
void DisplayUnMuteMenu(int client)
{
Menu menu = new Menu(MenuHandler_UnMuteMenu, MenuAction_Select|MenuAction_Cancel|MenuAction_End|MenuAction_DrawItem|MenuAction_DisplayItem);
menu.SetTitle("[Self-UnMute]");
menu.ExitButton = true;
if(g_SpecialMutes[client] & MUTE_ALL)
menu.AddItem("@all", "Everyone");
if(g_SpecialMutes[client] & MUTE_SPEC)
menu.AddItem("@spec", "Spectators");
if(g_SpecialMutes[client] & MUTE_CT)
menu.AddItem("@ct", "Counter-Terrorists");
if(g_SpecialMutes[client] & MUTE_T)
menu.AddItem("@t", "Terrorists");
if(g_SpecialMutes[client] & MUTE_DEAD)
menu.AddItem("@dead", "Dead players");
if(g_SpecialMutes[client] & MUTE_ALIVE)
menu.AddItem("@alive", "Alive players");
if(g_SpecialMutes[client] & MUTE_NOTFRIENDS)
menu.AddItem("@!friends", "Not Steam friends");
if(g_SpecialMutes[client])
menu.AddItem("", "", ITEMDRAW_RAWLINE);
int[] aClients = new int[MaxClients + 1];
// Count valid players and insert id's into aClients array
int Players = 0;
for(int i = 1; i <= MaxClients; i++)
{
if(i != client && IsClientInGame(i) && (GetIgnored(client, i) || GetExempt(client, i)))
aClients[Players++] = i;
}
// insert player names into g_PlayerNames array
for(int i = 0; i < Players; i++)
{
GetClientName(aClients[i], g_PlayerNames[aClients[i]], sizeof(g_PlayerNames[]));
}
// sort aClients array by player name
SortCustom1D(aClients, Players, SortByPlayerName);
// insert players sorted
char aBuf[12];
for(int i = 0; i < Players; i++)
{
IntToString(GetClientUserId(aClients[i]), aBuf, sizeof(aBuf));
menu.AddItem(aBuf, g_PlayerNames[aClients[i]]);
}
if(!menu.ItemCount)
{
delete menu;
PrintToChat(client, "\x04[Self-Mute]\x01 You haven't muted or exempted anyone.");
return;
}
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_UnMuteMenu(Menu menu, MenuAction action, int param1, int param2)
{
switch(action)
{
case MenuAction_End:
{
if(param1 != MenuEnd_Selected)
CloseHandle(menu);
}
case MenuAction_Select:
{
int Style;
char aItem[32];
char aDisp[MAX_NAME_LENGTH + 4];
menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp));
if(Style != ITEMDRAW_DEFAULT || !aItem[0])
{
PrintToChat(param1, "Internal error: aItem[0] -> %d | Style -> %d", aItem[0], Style);
return 0;
}
if(aItem[0] == '@')
{
int Flag = GetSpecialMutesFlags(aItem);
if(Flag && g_SpecialMutes[param1] & Flag)
UnMuteSpecial(param1, aItem);
menu.RemoveItem(GetMenuSelectionPosition());
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client)
{
PrintToChat(param1, "\x04[Self-Mute]\x01 Player no longer available.");
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
if(GetIgnored(param1, client))
{
if(IsClientSourceTV(client))
{
UnIgnore(param1, client);
SetClientCookie(param1, g_hCookieTorchMuted, "");
PrintToChat(param1, "\x04[Self-Mute]\x01 You have permanently self-unmuted:\x04 %N", client);
}
else
{
UnIgnore(param1, client);
PrintToChat(param1, "\x04[Self-Mute]\x01 You have self-unmuted:\x04 %N", client);
}
}
else if(GetExempt(param1, client))
{
UnExempt(param1, client);
PrintToChat(param1, "\x04[Self-Mute]\x01 You have removed exempt from self-mute:\x04 %N", client);
}
menu.RemoveItem(GetMenuSelectionPosition());
menu.DisplayAt(param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
return 0;
}
case MenuAction_DrawItem:
{
int Style;
char aItem[32];
menu.GetItem(param2, aItem, sizeof(aItem), Style);
if(!aItem[0])
return ITEMDRAW_DISABLED;
if(aItem[0] == '@')
return Style;
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
return ITEMDRAW_DISABLED;
return Style;
}
case MenuAction_DisplayItem:
{
int Style;
char aItem[32];
char aDisp[MAX_NAME_LENGTH + 4];
menu.GetItem(param2, aItem, sizeof(aItem), Style, aDisp, sizeof(aDisp));
if(!aItem[0])
return 0;
int UserId = StringToInt(aItem);
int client = GetClientOfUserId(UserId);
if(!client) // Player disconnected
{
char aBuf[MAX_NAME_LENGTH + 4] = "[D] ";
StrCat(aBuf, sizeof(aBuf), aDisp);
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
if(GetExempt(param1, client))
{
char aBuf[MAX_NAME_LENGTH + 4] = "[E] ";
GetClientName(client, g_PlayerNames[client], sizeof(g_PlayerNames[]));
StrCat(aBuf, sizeof(aBuf), g_PlayerNames[client]);
if(!StrEqual(aDisp, aBuf))
return RedrawMenuItem(aBuf);
}
return 0;
}
}
return 0;
}
/*
* HOOKS
*/
int g_MsgDest;
int g_MsgClient;
char g_MsgName[256];
char g_MsgParam1[256];
char g_MsgParam2[256];
char g_MsgParam3[256];
char g_MsgParam4[256];
char g_MsgRadioSound[256];
int g_MsgPlayersNum;
int g_MsgPlayers[MAXPLAYERS + 1];
public Action Hook_UserMessageRadioText(UserMsg msg_id, Handle bf, const int[] players, int playersNum, bool reliable, bool init)
{
if(g_bIsProtoBuf)
{
g_MsgDest = PbReadInt(bf, "msg_dst");
g_MsgClient = PbReadInt(bf, "client");
PbReadString(bf, "msg_name", g_MsgName, sizeof(g_MsgName));
PbReadString(bf, "params", g_MsgParam1, sizeof(g_MsgParam1), 0);
PbReadString(bf, "params", g_MsgParam2, sizeof(g_MsgParam2), 1);
PbReadString(bf, "params", g_MsgParam3, sizeof(g_MsgParam3), 2);
PbReadString(bf, "params", g_MsgParam4, sizeof(g_MsgParam4), 3);
}
else
{
g_MsgDest = BfReadByte(bf);
g_MsgClient = BfReadByte(bf);
BfReadString(bf, g_MsgName, sizeof(g_MsgName), false);
BfReadString(bf, g_MsgParam1, sizeof(g_MsgParam1), false);
BfReadString(bf, g_MsgParam2, sizeof(g_MsgParam2), false);
BfReadString(bf, g_MsgParam3, sizeof(g_MsgParam3), false);
BfReadString(bf, g_MsgParam4, sizeof(g_MsgParam4), false);
}
// Check which clients need to be excluded.
g_MsgPlayersNum = 0;
for(int i = 0; i < playersNum; i++)
{
int client = players[i];
if(!GetIgnored(client, g_MsgClient))
g_MsgPlayers[g_MsgPlayersNum++] = client;
}
// No clients were excluded.
if(g_MsgPlayersNum == playersNum)
{
g_MsgClient = -1;
return Plugin_Continue;
}
else if(g_MsgPlayersNum == 0) // All clients were excluded and there is no need to broadcast.
{
g_MsgClient = -2;
return Plugin_Handled;
}
return Plugin_Handled;
}
public Action Hook_UserMessageSendAudio(UserMsg msg_id, Handle bf, const int[] players, int playersNum, bool reliable, bool init)
{
if(g_MsgClient == -1)
return Plugin_Continue;
else if(g_MsgClient == -2)
return Plugin_Handled;
if(g_bIsProtoBuf)
PbReadString(bf, "radio_sound", g_MsgRadioSound, sizeof(g_MsgRadioSound));
else
BfReadString(bf, g_MsgRadioSound, sizeof(g_MsgRadioSound), false);
if(StrEqual(g_MsgRadioSound, "radio.locknload"))
return Plugin_Continue;
DataPack pack = new DataPack();
pack.WriteCell(g_MsgDest);
pack.WriteCell(g_MsgClient);
pack.WriteString(g_MsgName);
pack.WriteString(g_MsgParam1);
pack.WriteString(g_MsgParam2);
pack.WriteString(g_MsgParam3);
pack.WriteString(g_MsgParam4);
pack.WriteString(g_MsgRadioSound);
pack.WriteCell(g_MsgPlayersNum);
for(int i = 0; i < g_MsgPlayersNum; i++)
pack.WriteCell(g_MsgPlayers[i]);
RequestFrame(OnPlayerRadio, pack);
return Plugin_Handled;
}
public void OnPlayerRadio(DataPack pack)
{
pack.Reset();
g_MsgDest = pack.ReadCell();
g_MsgClient = pack.ReadCell();
pack.ReadString(g_MsgName, sizeof(g_MsgName));
pack.ReadString(g_MsgParam1, sizeof(g_MsgParam1));
pack.ReadString(g_MsgParam2, sizeof(g_MsgParam2));
pack.ReadString(g_MsgParam3, sizeof(g_MsgParam3));
pack.ReadString(g_MsgParam4, sizeof(g_MsgParam4));
pack.ReadString(g_MsgRadioSound, sizeof(g_MsgRadioSound));
g_MsgPlayersNum = pack.ReadCell();
int playersNum = 0;
for(int i = 0; i < g_MsgPlayersNum; i++)
{
int client_ = pack.ReadCell();
if(IsClientInGame(client_))
g_MsgPlayers[playersNum++] = client_;
}
CloseHandle(pack);
Handle RadioText = StartMessage("RadioText", g_MsgPlayers, playersNum, USERMSG_RELIABLE);
if(g_bIsProtoBuf)
{
PbSetInt(RadioText, "msg_dst", g_MsgDest);
PbSetInt(RadioText, "client", g_MsgClient);
PbSetString(RadioText, "msg_name", g_MsgName);
PbSetString(RadioText, "params", g_MsgParam1, 0);
PbSetString(RadioText, "params", g_MsgParam2, 1);
PbSetString(RadioText, "params", g_MsgParam3, 2);
PbSetString(RadioText, "params", g_MsgParam4, 3);
}
else
{
BfWriteByte(RadioText, g_MsgDest);
BfWriteByte(RadioText, g_MsgClient);
BfWriteString(RadioText, g_MsgName);
BfWriteString(RadioText, g_MsgParam1);
BfWriteString(RadioText, g_MsgParam2);
BfWriteString(RadioText, g_MsgParam3);
BfWriteString(RadioText, g_MsgParam4);
}
EndMessage();
Handle SendAudio = StartMessage("SendAudio", g_MsgPlayers, playersNum, USERMSG_RELIABLE);
if(g_bIsProtoBuf)
PbSetString(SendAudio, "radio_sound", g_MsgRadioSound);
else
BfWriteString(SendAudio, g_MsgRadioSound);
EndMessage();
}
/*
* HELPERS
*/
void UpdateIgnored()
{
if(g_Plugin_ccc)
CCC_UpdateIgnoredArray(g_Ignored);
}
public int SortByPlayerName(int elem1, int elem2, const int[] array, Handle hndl)
{
return strcmp(g_PlayerNames[elem1], g_PlayerNames[elem2], false);
}
bool GetIgnored(int client, int target)
{
return g_Ignored[(client * (MAXPLAYERS + 1) + target)];
}
void SetIgnored(int client, int target, bool ignored)
{
g_Ignored[(client * (MAXPLAYERS + 1) + target)] = ignored;
}
bool GetExempt(int client, int target)
{
return g_Exempt[client][target];
}
void SetExempt(int client, int target, bool exempt)
{
g_Exempt[client][target] = exempt;
}