diff --git a/_CSGO/FixGloves/scripting/FixGloves.sp b/_CSGO/FixGloves/scripting/FixGloves.sp new file mode 100644 index 00000000..1fa165de --- /dev/null +++ b/_CSGO/FixGloves/scripting/FixGloves.sp @@ -0,0 +1,69 @@ +#pragma newdecls required + +#include +#include +#include +#include + +#define ARMS_MODEL_T "models/weapons/v_models/arms/glove_hardknuckle/v_glove_hardknuckle_black.mdl" +#define ARMS_MODEL_CT "models/weapons/v_models/arms/glove_hardknuckle/v_glove_hardknuckle_black.mdl" + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "Fix Invisible Gloves", + author = "zaCade", + description = "Feex more volvo bullshiet!", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + for (int iClient = 1; iClient <= MaxClients; iClient++) + { + if (IsClientInGame(iClient)) + { + OnClientPutInServer(iClient); + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnMapStart() +{ + PrecacheModel(ARMS_MODEL_T); + PrecacheModel(ARMS_MODEL_CT); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPutInServer(int iClient) +{ + SDKHook(iClient, SDKHook_SpawnPost, OnSpawnPost); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnSpawnPost(int iClient) +{ + if(!IsClientInGame(iClient) || IsClientObserver(iClient) || !IsPlayerAlive(iClient)) + return; + + if (GetEntPropEnt(iClient, Prop_Send, "m_hMyWearables") == INVALID_ENT_REFERENCE) + { + switch(GetClientTeam(iClient)) + { + case CS_TEAM_T: SetEntPropString(iClient, Prop_Send, "m_szArmsModel", ARMS_MODEL_T); + case CS_TEAM_CT: SetEntPropString(iClient, Prop_Send, "m_szArmsModel", ARMS_MODEL_CT); + } + } +} \ No newline at end of file diff --git a/_CSGO/ForceCvars/scripting/ForceCvars.sp b/_CSGO/ForceCvars/scripting/ForceCvars.sp new file mode 100644 index 00000000..e7861d5e --- /dev/null +++ b/_CSGO/ForceCvars/scripting/ForceCvars.sp @@ -0,0 +1,43 @@ +#pragma newdecls required + +#include + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "Force CVars", + author = "zaCade", + description = "Force CVars to specific values.", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + RegServerCmd("sm_forcevar", Command_ForceCVar); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_ForceCVar(int args) +{ + char sArguments[2][128]; + GetCmdArg(1, sArguments[0], sizeof(sArguments[])); + GetCmdArg(2, sArguments[1], sizeof(sArguments[])); + + ConVar CVar; + if ((CVar = FindConVar(sArguments[0])) != null) + { + float fValue = StringToFloat(sArguments[1]); + + CVar.SetBounds(ConVarBound_Lower, true, fValue); + CVar.SetBounds(ConVarBound_Upper, true, fValue); + + CVar.SetFloat(fValue, true, false); + } +} \ No newline at end of file diff --git a/_CSGO/NoSteamDetection/scripting/NoSteamDetection.sp b/_CSGO/NoSteamDetection/scripting/NoSteamDetection.sp new file mode 100644 index 00000000..a53686f8 --- /dev/null +++ b/_CSGO/NoSteamDetection/scripting/NoSteamDetection.sp @@ -0,0 +1,192 @@ +#include +#include + +#pragma semicolon 1 +#pragma newdecls required + +#include "SteamAPI.secret" + +/* BOOLEANS */ +bool g_bValid[MAXPLAYERS+1] = {false, ...}; +bool g_bValidated[MAXPLAYERS+1] = {false, ...}; + +/* FORWARDS */ +Handle g_hFwd_OnClientProfileValidated; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "NoSteamDetection", + author = "zaCade", + description = "Mark people as 'NoSteam' if their steam profiles are incorrect", + version = "1.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public APLRes AskPluginLoad2(Handle myself, bool late, char [] error, int err_max) +{ + CreateNative("IsClientProfileValid", Native_IsClientProfileValid); + CreateNative("IsClientProfileValidated", Native_IsClientProfileValidated); + + RegPluginLibrary("NoSteamDetection"); + return APLRes_Success; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + g_hFwd_OnClientProfileValidated = CreateGlobalForward("OnClientProfileValidated", ET_Ignore, Param_Cell, Param_Cell); + + for(int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client) && IsClientAuthorized(client)) + OnClientAuthorized(client, ""); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientAuthorized(int client, const char[] auth) +{ + char sSteam64ID[32]; + GetClientAuthId(client, AuthId_SteamID64, sSteam64ID, sizeof(sSteam64ID)); + + char sRequest[256]; + Format(sRequest, sizeof(sRequest), "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s&format=vdf", STEAM_API_KEY, sSteam64ID); + + Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest); + if (!hRequest || + !SteamWorks_SetHTTPCallbacks(hRequest, OnClientAuthorized_OnTransferComplete) || + !SteamWorks_SetHTTPRequestContextValue(hRequest, GetClientSerial(client)) || + !SteamWorks_SendHTTPRequest(hRequest)) + { + delete hRequest; + } +} + + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int OnClientAuthorized_OnTransferComplete(Handle hRequest, bool bFailure, bool bSuccessful, EHTTPStatusCode eStatusCode, int serial) +{ + if (bFailure || !bSuccessful || eStatusCode != k_EHTTPStatusCode200OK) + { + delete hRequest; + return; + } + + SteamWorks_GetHTTPResponseBodyCallback(hRequest, OnClientAuthorized_OnTransferResponse, serial); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int OnClientAuthorized_OnTransferResponse(char[] sData, int serial) +{ + int client; + if ((client = GetClientFromSerial(serial)) == 0) + return; + + KeyValues Response = new KeyValues("SteamAPIResponse"); + + if(!Response.ImportFromString(sData, "SteamAPIResponse")) + { + OnClientAuthorized_FinishCall(client, false); + delete Response; + return; + } + + if(!Response.JumpToKey("players")) + { + OnClientAuthorized_FinishCall(client, false); + delete Response; + return; + } + + if(!Response.GotoFirstSubKey()) + { + OnClientAuthorized_FinishCall(client, false); + delete Response; + return; + } + + if ((Response.GetNum("profilestate")) == 0) + { + OnClientAuthorized_FinishCall(client, false); + delete Response; + return; + } + + OnClientAuthorized_FinishCall(client, true); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientAuthorized_FinishCall(int client, bool valid) +{ + g_bValid[client] = valid; + g_bValidated[client] = true; + + Call_StartForward(g_hFwd_OnClientProfileValidated); + Call_PushCell(client); + Call_PushCell(valid); + Call_Finish(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDisconnect(int client) +{ + g_bValid[client] = false; + g_bValidated[client] = false; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_IsClientProfileValid(Handle hPlugin, int numParams) +{ + int client = GetNativeCell(1); + + if (!IsValidClient(client)) + return false; + + return g_bValid[client]; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_IsClientProfileValidated(Handle hPlugin, int numParams) +{ + int client = GetNativeCell(1); + + if (!IsValidClient(client)) + return false; + + return g_bValidated[client]; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool IsValidClient(int client) +{ + if (client < 0) + return false; + + if (client > GetMaxClients()) + return false; + + return true; +} \ No newline at end of file diff --git a/_CSGO/NoSteamDetection/scripting/include/NoSteamDetection.inc b/_CSGO/NoSteamDetection/scripting/include/NoSteamDetection.inc new file mode 100644 index 00000000..fa10ac8b --- /dev/null +++ b/_CSGO/NoSteamDetection/scripting/include/NoSteamDetection.inc @@ -0,0 +1,11 @@ +#if defined NoSteamDetection_included + #endinput +#endif + +#define NoSteamDetection_included + +native bool IsClientProfileValid(int client); + +native bool IsClientProfileValidated(int client); + +forward void OnClientProfileValidated(int client, bool valid); \ No newline at end of file diff --git a/_CSGO/NoSteamManager/scripting/NoSteamManager.sp b/_CSGO/NoSteamManager/scripting/NoSteamManager.sp new file mode 100644 index 00000000..e3f6391e --- /dev/null +++ b/_CSGO/NoSteamManager/scripting/NoSteamManager.sp @@ -0,0 +1,154 @@ +#pragma semicolon 1 + +#include +#include +#include + +#pragma newdecls required + +/* CONVARS */ +ConVar g_hCvar_BlockAdmin; +ConVar g_hCvar_BlockVoice; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "NoSteamManager", + author = "zaCade", + description = "Manage No-Steam clients, denying admin access, ect.", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + g_hCvar_BlockAdmin = CreateConVar("sm_nosteam_block_admin", "1", "Should people marked as nosteam be blocked from admin?", FCVAR_NONE, true, 0.0, true, 1.0); + g_hCvar_BlockVoice = CreateConVar("sm_nosteam_block_voice", "1", "Should people marked as nosteam be blocked from voice?", FCVAR_NONE, true, 0.0, true, 1.0); + + AddMultiTargetFilter("@steam", Filter_Steam, "Steam Players", false); + AddMultiTargetFilter("@nosteam", Filter_NoSteam, "No-Steam Players", false); + + RegConsoleCmd("sm_nosteam", Command_DisplaySteamStats, "Shows the number of Steam and No-Steam players"); + RegConsoleCmd("sm_steam", Command_DisplaySteamStats, "Shows the number of Steam and No-Steam players"); + + AutoExecConfig(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginEnd() +{ + RemoveMultiTargetFilter("@steam", Filter_Steam); + RemoveMultiTargetFilter("@nosteam", Filter_NoSteam); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_DisplaySteamStats(int client, int args) +{ + char aBuf[1024]; + char aBuf2[MAX_NAME_LENGTH]; + + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i)) + { + if(IsClientProfileValidated(i) && !IsClientProfileValid(i)) + { + GetClientName(i, aBuf2, sizeof(aBuf2)); + StrCat(aBuf, sizeof(aBuf), aBuf2); + StrCat(aBuf, sizeof(aBuf), ", "); + } + } + } + + if(strlen(aBuf)) + { + aBuf[strlen(aBuf) - 2] = 0; + ReplyToCommand(client, "[SM] No-Steam clients online: %s", aBuf); + } + else + ReplyToCommand(client, "[SM] No-Steam clients online: none"); + + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool Filter_Steam(const char[] sPattern, Handle hClients) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i)) + { + if(IsClientProfileValidated(i) && IsClientProfileValid(i)) + PushArrayCell(hClients, i); + } + } + return true; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool Filter_NoSteam(const char[] sPattern, Handle hClients) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i)) + { + if(IsClientProfileValidated(i) && !IsClientProfileValid(i)) + PushArrayCell(hClients, i); + } + } + return true; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action OnClientPreAdminCheck(int client) +{ + if(!g_hCvar_BlockAdmin.BoolValue) + return Plugin_Continue; + + if(IsFakeClient(client) || IsClientSourceTV(client)) + return Plugin_Continue; + + if(IsClientProfileValidated(client) && !IsClientProfileValid(client)) + { + LogMessage("%L did not have a valid profile, denying admin.", client); + NotifyPostAdminCheck(client); + + return Plugin_Handled; + } + + return Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPostAdminCheck(int client) +{ + if(!g_hCvar_BlockVoice.BoolValue) + return; + + if(IsFakeClient(client) || IsClientSourceTV(client)) + return; + + if(IsClientProfileValidated(client) && !IsClientProfileValid(client)) + { + LogMessage("%L did not have a valid profile, muting client.", client); + BaseComm_SetClientMute(client, true); + + return; + } +} \ No newline at end of file diff --git a/_CSGO/NoSteamPlayerCount/scripting/NoSteamPlayerCount.sp b/_CSGO/NoSteamPlayerCount/scripting/NoSteamPlayerCount.sp new file mode 100644 index 00000000..a223c851 --- /dev/null +++ b/_CSGO/NoSteamPlayerCount/scripting/NoSteamPlayerCount.sp @@ -0,0 +1,127 @@ +#include +#include +#include + +#pragma semicolon 1 +#pragma newdecls required + +bool g_bHasFakeClient[MAXPLAYERS + 1] = {false,...}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "NoSteamPlayerCount", + author = "Neon", + description = "", + version = "1.0", + url = "https://steamcommunity.com/id/n3ontm" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnGameFrame() +{ + SteamWorks_SetMaxPlayers(65); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + RegAdminCmd("sm_addfake", Command_AddFake, ADMFLAG_ROOT, ""); + RegAdminCmd("sm_removefake", Command_RemoveFake, ADMFLAG_ROOT, ""); + RegAdminCmd("sm_countfakes", Command_CountFakes, ADMFLAG_BAN, ""); + + for(int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client) && IsClientProfileValidated(client)) + OnClientProfileValidated(client, false); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginEnd() +{ + for(int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client)) + OnClientDisconnect(client); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_AddFake(int client, int argc) +{ + SteamWorks_CreateFake("Kaitou Sinbad"); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_RemoveFake(int client, int argc) +{ + SteamWorks_KickFake(); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_CountFakes(int client, int argc) +{ + int iFakes = SteamWorks_CountFakes(); + ReplyToCommand(client, "There are currently %d Fake Clients active.", iFakes); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientProfileValidated(int client, bool valid) +{ + char sName[128]; + GetClientName(client, sName, sizeof(sName)); + + if(!IsClientProfileValid(client)) + { + int iFakeID = SteamWorks_CreateFake(sName); + g_bHasFakeClient[client] = true; + LogMessage("\"%L\" connected as NoSteam. Fake Client with ID: \"%d\" got created.", client, iFakeID); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDisconnect(int client) +{ + if (!g_bHasFakeClient[client]) + return; + + SteamWorks_KickFake(); + g_bHasFakeClient[client] = false; + LogMessage("\"%L\" left as NoSteam. Fake Client got removed.", client); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool IsValidClient(int client) +{ + if (client <= 0) + return false; + + if (client > GetMaxClients()) + return false; + + return true; +} \ No newline at end of file diff --git a/_CSGO/SelfMute/scripting/SelfMute.sp b/_CSGO/SelfMute/scripting/SelfMute.sp new file mode 100644 index 00000000..d7d0de20 --- /dev/null +++ b/_CSGO/SelfMute/scripting/SelfMute.sp @@ -0,0 +1,1116 @@ +#pragma semicolon 1 + +#include +#include +#include +#include + +#undef REQUIRE_PLUGIN +#include +#include +#tryinclude +#include +#include +#define REQUIRE_PLUGIN + +#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_Plugin_NoSteamDetection = false; +bool g_bIsProtoBuf = false; + +#define PLUGIN_VERSION "2.2" + +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_NOSTEAM = 64, + MUTE_ALL = 128, + MUTE_LAST = 128 +}; + +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"); + + 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); +} + +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_Plugin_NoSteamDetection = LibraryExists("NoSteamDetection"); + LogMessage("SelfMute capabilities:\nProtoBuf: %s\nCCC: %s\nZombieReloaded: %s\nVoiceAnnounce: %s\nAdvancedTargeting: %s\nNoSteamDetection: %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_Plugin_NoSteamDetection ? "loaded" : "not loaded")); +} + +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(); +} + +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) && !IsFakeClient(i) && i != client) + SetListenOverride(i, client, Listen_Yes); + } + + UpdateIgnored(); +} + +public void OnClientPostAdminCheck(int client) +{ + g_SpecialMutes[client] = GrabSpecialMutesThisClient(client); + + UpdateSpecialMutesThisClient(client); +} + +public void Event_Round(Handle event, const char[] name, bool dontBroadcast) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(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); +} + +public void OnClientProfileValidated(int client, bool valid) +{ + if (!IsClientInGame(client)) + return; + + 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) || IsFakeClient(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_NOSTEAM && + g_Plugin_NoSteamDetection && IsClientProfileValidated(client) && !IsClientProfileValid(client)) + Flags |= MUTE_NOSTEAM; + + 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) || IsFakeClient(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_NOSTEAM && + g_Plugin_NoSteamDetection && IsClientProfileValidated(i) && !IsClientProfileValid(i)) + Flags |= MUTE_NOSTEAM; + + 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 GrabSpecialMutesThisClient(int client) +{ + if(IsClientProfileValidated(client) && !IsClientProfileValid(client)) + return MUTE_NONE; + + if(GetAdminFlag(GetUserAdmin(client), Admin_Ban)) + return MUTE_NONE; + + return MUTE_NOSTEAM; +} + +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(g_Plugin_NoSteamDetection && StrEqual(Argument, "@nosteam", false)) + SpecialMute |= MUTE_NOSTEAM; + 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; + int MuteCount = RoundFloat(Logarithm(float(MUTE_LAST), 2.0)); + for(int i = 0; i <= MuteCount; i++) + { + switch(SpecialMute & RoundFloat(Pow(2.0, float(i)))) + { + case MUTE_SPEC: + { + StrCat(aBuf, BufLen, "Spectators, "); + Status = true; + } + case MUTE_CT: + { + StrCat(aBuf, BufLen, "CTs, "); + Status = true; + } + case MUTE_T: + { + StrCat(aBuf, BufLen, "Ts, "); + Status = true; + } + case MUTE_DEAD: + { + StrCat(aBuf, BufLen, "Dead players, "); + Status = true; + } + case MUTE_ALIVE: + { + StrCat(aBuf, BufLen, "Alive players, "); + Status = true; + } + case MUTE_NOTFRIENDS: + { + StrCat(aBuf, BufLen, "Not Steam friends, "); + Status = true; + } + case MUTE_NOSTEAM: + { + StrCat(aBuf, BufLen, "No Steam clients, "); + Status = true; + } + case MUTE_ALL: + { + StrCat(aBuf, BufLen, "Everyone, "); + 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] = GrabSpecialMutesThisClient(client); + } + else + { + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(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_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(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(!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; +} + +/* + * 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]; + + #if defined _voiceannounceex_included_ + if(g_Plugin_voiceannounce_ex) + { + // 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) && !IsFakeClient(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); + } + } + #endif + + 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 friend"); + else + menu.AddItem("", "", ITEMDRAW_RAWLINE); + if(g_Plugin_NoSteamDetection) + menu.AddItem("@nosteam", "No Steam clients"); + 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) && !IsFakeClient(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)) + { + 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 + { + 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) +{ + // TODO: Implement me +} + +/* + * 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; +} diff --git a/_CSGO/StopSound/scripting/StopSound.sp b/_CSGO/StopSound/scripting/StopSound.sp new file mode 100644 index 00000000..4f7108d1 --- /dev/null +++ b/_CSGO/StopSound/scripting/StopSound.sp @@ -0,0 +1,804 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include +#include +#include + +#define PLUGIN_VERSION "3.1.0" + +float g_fMusicVolume[MAXPLAYERS+1] = { 1.0, ... }; + +bool g_bStopWeaponSounds[MAXPLAYERS+1] = { false, ... }; +bool g_bStopMapMusic[MAXPLAYERS+1] = { false, ... }; + +bool g_bStopWeaponSoundsHooked = false; +bool g_bStopMapMusicHooked = false; + +StringMap g_MapMusic; + +Handle g_hCookieStopSound = null; +Handle g_hCookieStopMapMusic = null; +Handle g_hCookieMusicVolume = null; + +public Plugin myinfo = +{ + name = "Toggle Game Sounds", + author = "GoD-Tony, edit by Obus + BotoX, Oleg Tsvetkov", + description = "Allows clients to stop hearing weapon sounds and map music", + version = PLUGIN_VERSION, + url = "http://www.sourcemod.net/" +}; + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + if(GetEngineVersion() != Engine_CSGO && GetEngineVersion() != Engine_CSS) + { + strcopy(error, err_max, "This plugin supports only CS:GO and CS:S!"); + return APLRes_Failure; + } + + return APLRes_Success; +} + +public void OnPluginStart() +{ + // Load translations + LoadTranslations("plugin.stopsound.phrases"); + LoadTranslations("common.phrases"); // For On/Off buttons in Cookies Menu + + g_MapMusic = new StringMap(); + + // Detect game and hook appropriate tempent. + AddTempEntHook("Shotgun Shot", Hook_ShotgunShot); + + // Ambient sounds + AddAmbientSoundHook(Hook_AmbientSound); + + // Map music will be caught here + HookEvent("round_end", Event_RoundEnd); + HookEvent("player_spawn", Event_PlayerSpawn); + + CreateConVar("sm_stopsound_version", PLUGIN_VERSION, "Toggle Weapon Sounds", FCVAR_NOTIFY|FCVAR_DONTRECORD|FCVAR_REPLICATED); + RegConsoleCmd("sm_stopsound", Command_StopSound, "Toggle hearing weapon sounds"); + RegConsoleCmd("sm_sound", Command_StopSound, "Toggle hearing weapon sounds"); + RegConsoleCmd("sm_stopmusic", Command_StopMusic, "Toggle hearing map music"); + RegConsoleCmd("sm_music", Command_StopMusic, "Toggle hearing map music"); + RegConsoleCmd("sm_volume", Command_Volume, "Change music volume"); + + // Cookies + g_hCookieStopSound = RegClientCookie("weaponsound_blocked", "Are weapon sounds enabled", CookieAccess_Protected); + g_hCookieStopMapMusic = RegClientCookie("mapmusic_blocked", "Are map music enabled", CookieAccess_Protected); + g_hCookieMusicVolume = RegClientCookie("mapmusic_volume", "The volume for map music", CookieAccess_Protected); + + SetCookieMenuItem(CookieMenuHandler_StopSounds, 0, "Stop sounds"); + + // Suppress reload sound effects + UserMsg ReloadEffect = GetUserMessageId("ReloadEffect"); + + // Game-specific setup + if(GetEngineVersion() == Engine_CSGO) + { + // Weapon sounds will be caught here. + AddNormalSoundHook(Hook_NormalSound_CSGO); + + if(ReloadEffect != INVALID_MESSAGE_ID) + { + HookUserMessage(ReloadEffect, Hook_ReloadEffect_CSGO, true); + } + } + else // CS:S + { + // Weapon sounds will be caught here. + AddNormalSoundHook(Hook_NormalSound_CSS); + + if(ReloadEffect != INVALID_MESSAGE_ID) + { + HookUserMessage(ReloadEffect, Hook_ReloadEffect_CSS, true); + } + } + + // Late load + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client) && AreClientCookiesCached(client)) + { + OnClientCookiesCached(client); + } + } +} + +public void OnPluginEnd() +{ + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client)) + { + OnClientDisconnect(client); + } + } + + // Remove tempent hook + RemoveTempEntHook("Shotgun Shot", Hook_ShotgunShot); + + // Remove ambient sound hook + RemoveAmbientSoundHook(Hook_AmbientSound); + + // Find ReloadEffect + UserMsg ReloadEffect = GetUserMessageId("ReloadEffect"); + + // Remove game-specific + if(GetEngineVersion() == Engine_CSGO) + { + RemoveNormalSoundHook(Hook_NormalSound_CSGO); + + if(ReloadEffect != INVALID_MESSAGE_ID) + UnhookUserMessage(ReloadEffect, Hook_ReloadEffect_CSGO, true); + } + else + { + RemoveNormalSoundHook(Hook_NormalSound_CSS); + + if(ReloadEffect != INVALID_MESSAGE_ID) + UnhookUserMessage(ReloadEffect, Hook_ReloadEffect_CSS, true); + } +} + +public void OnMapStart() +{ + g_MapMusic.Clear(); +} + +public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) +{ + g_MapMusic.Clear(); +} + +public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) +{ + int client = GetClientOfUserId(event.GetInt("userid")); + + if(!IsClientInGame(client) || GetClientTeam(client) <= CS_TEAM_SPECTATOR) + return; + + if(g_bStopWeaponSounds[client]) + CPrintToChat(client, "%t %t", "Chat Prefix", "Weapon sounds disabled"); + + if(g_bStopMapMusic[client]) + CPrintToChat(client, "%t %t", "Chat Prefix", "Map music disabled"); +} + +public Action Command_StopSound(int client, int args) +{ + if(client == 0) + { + ReplyToCommand(client, "[SM] Cannot use command from server console."); + return Plugin_Handled; + } + + g_bStopWeaponSounds[client] = !g_bStopWeaponSounds[client]; + CheckWeaponSoundsHooks(); + + if(g_bStopWeaponSounds[client]) + { + SetClientCookie(client, g_hCookieStopSound, "1"); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Weapon sounds disabled"); + } + else + { + SetClientCookie(client, g_hCookieStopSound, ""); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Weapon sounds enabled"); + } + + return Plugin_Handled; +} + +public Action Command_StopMusic(int client, int args) +{ + if(client == 0) + { + ReplyToCommand(client, "[SM] Cannot use command from server console."); + return Plugin_Handled; + } + + g_bStopMapMusic[client] = !g_bStopMapMusic[client]; + CheckMapMusicHooks(); + + if(g_bStopMapMusic[client]) + { + SetClientCookie(client, g_hCookieStopMapMusic, "1"); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Map music disabled"); + StopMapMusic(client); + } + else + { + SetClientCookie(client, g_hCookieStopMapMusic, ""); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Map music enabled"); + } + + return Plugin_Handled; +} + +public Action Command_Volume(int client, int args) +{ + if(client == 0) + { + ReplyToCommand(client, "[SM] Cannot use command from server console."); + return Plugin_Handled; + } + + ShowStopSoundsVolumeMenu(client); + return Plugin_Handled; +} + +public void OnClientCookiesCached(int client) +{ + char sBuffer[10]; + + // Weapon Sounds cookie + GetClientCookie(client, g_hCookieStopSound, sBuffer, sizeof(sBuffer)); + + if(sBuffer[0] != '\0') + { + g_bStopWeaponSounds[client] = true; + g_bStopWeaponSoundsHooked = true; + } + else + g_bStopWeaponSounds[client] = false; + + // Map Music cookie + GetClientCookie(client, g_hCookieStopMapMusic, sBuffer, sizeof(sBuffer)); + + if(sBuffer[0] != '\0') + { + g_bStopMapMusic[client] = true; + g_bStopMapMusicHooked = true; + } + else + g_bStopMapMusic[client] = false; + + // Music Volume cookie + GetClientCookie(client, g_hCookieMusicVolume, sBuffer, sizeof(sBuffer)); + + if(sBuffer[0] != '\0') + { + g_fMusicVolume[client] = StringToFloat(sBuffer); + g_bStopMapMusicHooked = true; + } + else + g_fMusicVolume[client] = 1.0; +} + +public void OnClientDisconnect(int client) +{ + g_bStopWeaponSounds[client] = false; + g_bStopMapMusic[client] = false; + + CheckWeaponSoundsHooks(); + CheckMapMusicHooks(); +} + +void CheckWeaponSoundsHooks() +{ + bool bShouldHook = false; + + for(int i = 1; i <= MaxClients; i++) + { + if(g_bStopWeaponSounds[i]) + { + bShouldHook = true; + break; + } + } + + // Fake (un)hook because toggling actual hooks will cause server instability. + g_bStopWeaponSoundsHooked = bShouldHook; +} + +void CheckMapMusicHooks() +{ + bool bShouldHook = false; + + for(int i = 1; i <= MaxClients; i++) + { + if(g_bStopMapMusic[i] || g_fMusicVolume[i] != 1.0) + { + bShouldHook = true; + break; + } + } + + // Fake (un)hook because toggling actual hooks will cause server instability. + g_bStopMapMusicHooked = bShouldHook; +} + +void StopMapMusic(int client) +{ + int entity = INVALID_ENT_REFERENCE; + + char sEntity[16]; + char sSample[PLATFORM_MAX_PATH]; + + StringMapSnapshot MapMusicSnap = g_MapMusic.Snapshot(); + for(int i = 0; i < MapMusicSnap.Length; i++) + { + MapMusicSnap.GetKey(i, sEntity, sizeof(sEntity)); + + if((entity = EntRefToEntIndex(StringToInt(sEntity))) == INVALID_ENT_REFERENCE) + { + g_MapMusic.Remove(sEntity); + continue; + } + + g_MapMusic.GetString(sEntity, sSample, sizeof(sSample)); + + EmitSoundToClient(client, sSample, entity, SNDCHAN_STATIC, SNDLEVEL_NONE, SND_STOPLOOPING, SNDVOL_NORMAL, SNDPITCH_NORMAL); + } + delete MapMusicSnap; +} + +public void CookieMenuHandler_StopSounds(int client, CookieMenuAction action, any info, char[] buffer, int maxlen) +{ + if(action == CookieMenuAction_DisplayOption) + { + Format(buffer, maxlen, "%T", "Cookie Menu Stop Sounds", client); + } + else if(action == CookieMenuAction_SelectOption) + { + ShowStopSoundsSettingsMenu(client); + } +} + +void ShowStopSoundsSettingsMenu(int client) +{ + Menu menu = new Menu(MenuHandler_StopSoundsSettings); + + menu.SetTitle("%T", "Cookie Menu Stop Sounds Title", client); + + char sBuffer[128]; + + Format(sBuffer, sizeof(sBuffer), "%T%T", "Weapon Sounds", client, g_bStopWeaponSounds[client] ? "Disabled" : "Enabled", client); + menu.AddItem("0", sBuffer); + + Format(sBuffer, sizeof(sBuffer), "%T%T", "Map Sounds", client, g_bStopMapMusic[client] ? "Disabled" : "Enabled", client); + menu.AddItem("1", sBuffer); + + menu.ExitBackButton = true; + menu.Display(client, MENU_TIME_FOREVER); +} + +public int MenuHandler_StopSoundsSettings(Menu menu, MenuAction action, int client, int selection) +{ + if(action == MenuAction_Cancel) + { + ShowCookieMenu(client); + } + else if(action == MenuAction_Select) + { + if(selection == 0) + { + g_bStopWeaponSounds[client] = !g_bStopWeaponSounds[client]; + CheckWeaponSoundsHooks(); + + if(g_bStopWeaponSounds[client]) + { + SetClientCookie(client, g_hCookieStopSound, "1"); + CPrintToChat(client, "%t %t", "Chat Prefix", "Weapon sounds disabled"); + } + else + { + SetClientCookie(client, g_hCookieStopSound, ""); + CPrintToChat(client, "%t %t", "Chat Prefix", "Weapon sounds enabled"); + } + + } + else if(selection == 1) + { + g_bStopMapMusic[client] = !g_bStopMapMusic[client]; + CheckMapMusicHooks(); + + if(g_bStopMapMusic[client]) + { + SetClientCookie(client, g_hCookieStopMapMusic, "1"); + CPrintToChat(client, "%t %t", "Chat Prefix", "Map music disabled"); + StopMapMusic(client); + } + else + { + SetClientCookie(client, g_hCookieStopMapMusic, ""); + CPrintToChat(client, "%t %t", "Chat Prefix", "Map music enabled"); + } + } + + ShowStopSoundsSettingsMenu(client); + } + else if(action == MenuAction_End) + { + delete menu; + } +} + +void ShowStopSoundsVolumeMenu(int client) +{ + Menu menu = new Menu(MenuHandler_StopSoundsVolume); + + menu.SetTitle("Map music volume menu"); + + menu.AddItem("100", "100%"); + menu.AddItem("90", "90%"); + menu.AddItem("80", "80%"); + menu.AddItem("70", "70%"); + menu.AddItem("60", "60%"); + menu.AddItem("50", "50%"); + menu.AddItem("40", "40%"); + menu.AddItem("30", "30%"); + menu.AddItem("20", "20%"); + menu.AddItem("10", "10%"); + menu.AddItem("0", "0%"); + + menu.Display(client, MENU_TIME_FOREVER); +} + +public int MenuHandler_StopSoundsVolume(Menu menu, MenuAction action, int client, int selection) +{ + if(action == MenuAction_Select) + { + if (selection == 0) + { + g_fMusicVolume[client] = 1.0; + } + else if (selection == 1) + { + g_fMusicVolume[client] = 0.9; + } + else if (selection == 2) + { + g_fMusicVolume[client] = 0.8; + } + else if (selection == 3) + { + g_fMusicVolume[client] = 0.7; + } + else if (selection == 4) + { + g_fMusicVolume[client] = 0.6; + } + else if (selection == 5) + { + g_fMusicVolume[client] = 0.5; + } + else if (selection == 6) + { + g_fMusicVolume[client] = 0.4; + } + else if (selection == 7) + { + g_fMusicVolume[client] = 0.3; + } + else if (selection == 8) + { + g_fMusicVolume[client] = 0.2; + } + else if (selection == 9) + { + g_fMusicVolume[client] = 0.1; + } + else if (selection == 10) + { + g_fMusicVolume[client] = 0.0; + } + + char sBuffer[10]; + FloatToString(g_fMusicVolume[client], sBuffer, sizeof(sBuffer)); + + SetClientCookie(client, g_hCookieMusicVolume, sBuffer); + CPrintToChat(client, "%t Map music volume set to: %d", "Chat Prefix", RoundFloat(g_fMusicVolume[client] * 100)); + CheckMapMusicHooks(); + } + else if(action == MenuAction_End) + { + delete menu; + } +} + +public Action Hook_NormalSound_CSS(int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], + int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, + char soundEntry[PLATFORM_MAX_PATH], int &seed) +{ + if(!g_bStopWeaponSoundsHooked) + return Plugin_Continue; + + // Ignore non-weapon sounds. + if(channel != SNDCHAN_WEAPON && + !(channel == SNDCHAN_AUTO && strncmp(sample, "physics/flesh", 13) == 0) && + !(channel == SNDCHAN_VOICE && StrContains(sample, "player/headshot", true) != -1)) + { + return Plugin_Continue; + } + + int j = 0; + for(int i = 0; i < numClients; i++) + { + int client = clients[i]; + if(!g_bStopWeaponSounds[client] && IsClientInGame(client)) + { + // Keep client. + clients[j] = clients[i]; + j++; + } + } + + numClients = j; + + return (numClients > 0) ? Plugin_Changed : Plugin_Stop; +} + +public Action Hook_NormalSound_CSGO(int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], + int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, + char soundEntry[PLATFORM_MAX_PATH], int &seed) +{ + if(!g_bStopWeaponSoundsHooked) + return Plugin_Continue; + + // Ignore non-weapon sounds. + if(channel != SNDCHAN_WEAPON && + !(channel == SNDCHAN_AUTO && strncmp(sample, "physics/flesh", 13) == 0) && + !(channel == SNDCHAN_STATIC && StrContains(sample, "player/headshot", true) != -1)) + { + return Plugin_Continue; + } + + int j = 0; + for(int i = 0; i < numClients; i++) + { + int client = clients[i]; + if(!g_bStopWeaponSounds[client] && IsClientInGame(client)) + { + // Keep client. + clients[j] = clients[i]; + j++; + } + } + + numClients = j; + + return (numClients > 0) ? Plugin_Changed : Plugin_Stop; +} + +public Action Hook_ShotgunShot(const char[] te_name, const int[] Players, int numClients, float delay) +{ + if(!g_bStopWeaponSoundsHooked) + return Plugin_Continue; + + // Check which clients need to be excluded. + int[] newClients = new int[numClients]; + int newTotal = 0; + + for(int i = 0; i < numClients; i++) + { + if(!g_bStopWeaponSounds[Players[i]]) + { + newClients[newTotal++] = Players[i]; + } + } + + if(newTotal == numClients) + { + // No clients were excluded. + return Plugin_Continue; + } + else if(newTotal == 0) + { + // All clients were excluded and there is no need to broadcast. + return Plugin_Stop; + } + + // Re-broadcast to clients that still need it. + if(GetEngineVersion() == Engine_CSGO) + { + float vTemp[3]; + TE_Start("Shotgun Shot"); + TE_ReadVector("m_vecOrigin", vTemp); + TE_WriteVector("m_vecOrigin", vTemp); + TE_WriteFloat("m_vecAngles[0]", TE_ReadFloat("m_vecAngles[0]")); + TE_WriteFloat("m_vecAngles[1]", TE_ReadFloat("m_vecAngles[1]")); + TE_WriteNum("m_weapon", TE_ReadNum("m_weapon")); + TE_WriteNum("m_iMode", TE_ReadNum("m_iMode")); + TE_WriteNum("m_iSeed", TE_ReadNum("m_iSeed")); + TE_WriteNum("m_iPlayer", TE_ReadNum("m_iPlayer")); + TE_WriteFloat("m_fInaccuracy", TE_ReadFloat("m_fInaccuracy")); + TE_WriteFloat("m_fSpread", TE_ReadFloat("m_fSpread")); + TE_Send(newClients, newTotal, delay); + } + else + { + float vTemp[3]; + TE_Start("Shotgun Shot"); + TE_ReadVector("m_vecOrigin", vTemp); + TE_WriteVector("m_vecOrigin", vTemp); + TE_WriteFloat("m_vecAngles[0]", TE_ReadFloat("m_vecAngles[0]")); + TE_WriteFloat("m_vecAngles[1]", TE_ReadFloat("m_vecAngles[1]")); + TE_WriteNum("m_iWeaponID", TE_ReadNum("m_iWeaponID")); + TE_WriteNum("m_iMode", TE_ReadNum("m_iMode")); + TE_WriteNum("m_iSeed", TE_ReadNum("m_iSeed")); + TE_WriteNum("m_iPlayer", TE_ReadNum("m_iPlayer")); + TE_WriteFloat("m_fInaccuracy", TE_ReadFloat("m_fInaccuracy")); + TE_WriteFloat("m_fSpread", TE_ReadFloat("m_fSpread")); + TE_Send(newClients, newTotal, delay); + } + + return Plugin_Stop; +} + +public Action Hook_ReloadEffect_CSS(UserMsg msg_id, BfRead msg, const int[] players, int playersNum, bool reliable, bool init) +{ + if(!g_bStopWeaponSoundsHooked) + return Plugin_Continue; + + int client = msg.ReadShort(); + + // Check which clients need to be excluded. + int[] newClients = new int[playersNum]; + int newTotal = 0; + + for(int i = 0; i < playersNum; i++) + { + int client_ = players[i]; + if(IsClientInGame(client_) && !g_bStopWeaponSounds[client_]) + { + newClients[newTotal++] = client_; + } + } + + if(newTotal == playersNum) + { + // No clients were excluded. + return Plugin_Continue; + } + else if(newTotal == 0) + { + // All clients were excluded and there is no need to broadcast. + return Plugin_Handled; + } + + DataPack pack = new DataPack(); + pack.WriteCell(client); + pack.WriteCell(newTotal); + + for(int i = 0; i < newTotal; i++) + { + pack.WriteCell(newClients[i]); + } + + RequestFrame(OnReloadEffect, pack); + + return Plugin_Handled; +} + +public Action Hook_ReloadEffect_CSGO(UserMsg msg_id, Protobuf msg, const int[] players, int playersNum, bool reliable, bool init) +{ + if(!g_bStopWeaponSoundsHooked) + return Plugin_Continue; + + int client = PbReadInt(msg, "entidx"); + + // Check which clients need to be excluded. + int[] newClients = new int[playersNum]; + int newTotal = 0; + + for(int i = 0; i < playersNum; i++) + { + int client_ = players[i]; + if(IsClientInGame(client_) && !g_bStopWeaponSounds[client_]) + { + newClients[newTotal++] = client_; + } + } + + if(newTotal == playersNum) + { + // No clients were excluded. + return Plugin_Continue; + } + else if(newTotal == 0) + { + // All clients were excluded and there is no need to broadcast. + return Plugin_Handled; + } + + DataPack pack = new DataPack(); + pack.WriteCell(client); + pack.WriteCell(newTotal); + + for(int i = 0; i < newTotal; i++) + { + pack.WriteCell(newClients[i]); + } + + RequestFrame(OnReloadEffect, pack); + + return Plugin_Handled; +} + +public void OnReloadEffect(DataPack pack) +{ + pack.Reset(); + int client = pack.ReadCell(); + int newTotal = pack.ReadCell(); + + int[] players = new int[newTotal]; + int playersNum = 0; + + for(int i = 0; i < newTotal; i++) + { + int client_ = pack.ReadCell(); + if(IsClientInGame(client_)) + { + players[playersNum++] = client_; + } + } + + CloseHandle(pack); + + Handle ReloadEffect = StartMessage("ReloadEffect", players, playersNum, USERMSG_RELIABLE | USERMSG_BLOCKHOOKS); + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) + { + PbSetInt(ReloadEffect, "entidx", client); + } + else + { + BfWriteShort(ReloadEffect, client); + } + + EndMessage(); +} + +public Action Hook_AmbientSound(char sample[PLATFORM_MAX_PATH], int &entity, float &volume, int &level, int &pitch, float pos[3], int &flags, float &delay) +{ + // Are we playing music? + if(!strncmp(sample, "music", 5, false) && !strncmp(sample, "#", 1, false)) + return Plugin_Continue; + + char sEntity[16]; + IntToString(EntIndexToEntRef(entity), sEntity, sizeof(sEntity)); + + g_MapMusic.SetString(sEntity, sample, true); + + if(!g_bStopMapMusicHooked) + return Plugin_Continue; + + switch(flags) + { + case(SND_NOFLAGS): + { + // Starting sound.. + for(int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || g_bStopMapMusic[client]) + continue; + + // Stop the old sound.. + EmitSoundToClient(client, sample, entity, SNDCHAN_STATIC, SNDLEVEL_NONE, SND_STOPLOOPING, SNDVOL_NORMAL, SNDPITCH_NORMAL); + + // Pass through the new sound.. + EmitSoundToClient(client, sample, entity, SNDCHAN_STATIC, level, flags, volume * g_fMusicVolume[client], pitch); + } + } + default: + { + // Nothing special going on.. Pass it through.. + for(int client = 1; client <= MaxClients; client++) + { + if (!IsClientInGame(client) || g_bStopMapMusic[client]) + continue; + + EmitSoundToClient(client, sample, entity, SNDCHAN_STATIC, level, flags, volume * g_fMusicVolume[client], pitch); + } + } + } + + // Block the default sound.. + return Plugin_Handled; +} \ No newline at end of file diff --git a/_CSGO/StopSound/translations/plugin.stopsound.phrases.txt b/_CSGO/StopSound/translations/plugin.stopsound.phrases.txt new file mode 100644 index 00000000..5f28ef2e --- /dev/null +++ b/_CSGO/StopSound/translations/plugin.stopsound.phrases.txt @@ -0,0 +1,68 @@ +"Phrases" +{ + "Chat Prefix" + { + "en" "{green}[StopSound]{default}" + "ru" "{green}[StopSound]{default}" + } + + "Weapon sounds enabled" + { + "en" "Weapon sounds {green}enabled{default}!" + "ru" "Звуки стрельбы {green}включены{default}!" + } + + "Weapon sounds disabled" + { + "en" "Weapon sounds {darkred}disabled{default}!" + "ru" "Звуки стрельбы {darkred}отключены{default}!" + } + + "Map music enabled" + { + "en" "Map music {green}enabled{default}!" + "ru" "Музыка на картах {green}включена{default}!" + } + + "Map music disabled" + { + "en" "Map music {darkred}disabled{default}!" + "ru" "Музыка на картах {darkred}отключена{default}!" + } + + "Cookie Menu Stop Sounds" + { + "en" "Stop Sounds" + "ru" "Отключение звуков" + } + + "Cookie Menu Stop Sounds Title" + { + "en" "Stop Sounds Configuration" + "ru" "Настройки Отключения Звуков" + } + + "Weapon Sounds" + { + "en" "Weapon sounds" + "ru" "Звуки стрельбы" + } + + "Map Sounds" + { + "en" "Map music" + "ru" "Музыка на картах" + } + + "Disabled" + { + "en" ": Disabled" + "ru" " [Выключено]" + } + + "Enabled" + { + "en" ": Enabled" + "ru" " [Включено]" + } +} \ No newline at end of file diff --git a/_CSGO/_IncreaseReserveAmmo/scripting/IncreaseReserveAmmo.sp b/_CSGO/_IncreaseReserveAmmo/scripting/IncreaseReserveAmmo.sp new file mode 100644 index 00000000..51b5a6d9 --- /dev/null +++ b/_CSGO/_IncreaseReserveAmmo/scripting/IncreaseReserveAmmo.sp @@ -0,0 +1,67 @@ +#include +#include +#include + +#define MAXAMMO 10000 +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "IncreaseReserveAmmo", + author = "zaCade", + description = "Feex volvo bullshiet!", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client) && !IsFakeClient(client)) + OnClientPutInServer(client); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPutInServer(int client) +{ + if (!IsFakeClient(client)) + { + SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponAction); + SDKHook(client, SDKHook_WeaponDropPost, OnWeaponAction); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnWeaponAction(int client, int weapon) +{ + if (IsValidEntity(weapon)) + { + if (!HasEntProp(client, Prop_Send, "m_iAmmo")) + return; + + SetEntProp(weapon, Prop_Send, "m_iPrimaryReserveAmmoCount", MAXAMMO); + SetEntProp(weapon, Prop_Send, "m_iSecondaryReserveAmmoCount", MAXAMMO); + + int AmmoTypePrimary = GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); + int AmmoTypeSecondary = GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType"); + +// PrintToChatAll("Primary: %d | Secondary: %d", AmmoTypePrimary, AmmoTypeSecondary) + + if (AmmoTypePrimary >= 0 && AmmoTypePrimary <= 13 || AmmoTypePrimary == 20) + if (GetEntProp(client, Prop_Send, "m_iAmmo", _, AmmoTypePrimary) >= 0) + SetEntProp(client, Prop_Send, "m_iAmmo", MAXAMMO, _, AmmoTypePrimary); + + if (AmmoTypeSecondary >= 0 && AmmoTypeSecondary <= 13 || AmmoTypeSecondary == 20) + if (GetEntProp(client, Prop_Send, "m_iAmmo", _, AmmoTypeSecondary) >= 0) + SetEntProp(client, Prop_Send, "m_iAmmo", MAXAMMO, _, AmmoTypeSecondary); + } +} \ No newline at end of file diff --git a/_CSS/Meteors/scripting/Meteors.sp b/_CSS/Meteors/scripting/Meteors.sp new file mode 100644 index 00000000..27e77aaf --- /dev/null +++ b/_CSS/Meteors/scripting/Meteors.sp @@ -0,0 +1,431 @@ +#include +#include +#include +#include + +public Plugin myinfo = +{ + name = "Meteors", + author = "Neon", + description = "", + version = "Meteors", + url = "https://steamcommunity.com/id/n3ontm" +} + +//ambient/explosions/explode_9.wav +//models/effects/vol_light128x512.mdl + +new String:debugString[64]; + +bool g_bEnabled = false; + +public void OnPluginStart() +{ + HookEvent("round_end", OnRoundEnding); + RegAdminCmd("sm_meteors", Command_Meteors, ADMFLAG_ROOT); +} + +public void OnMapStart() +{ + g_bEnabled = false; + PrecacheModel("models/props/cs_office/vending_machine.mdl"); + CreateTimer(5.0, MeteorMain, INVALID_HANDLE, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); +} + +public void OnRoundEnding(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + g_bEnabled = false; +} + +public Action Command_Meteors(int client, int args) +{ + if (g_bEnabled) + { + g_bEnabled = false; + CPrintToChatAll("{darkred}[Meteors] {white}%N has disabled Meteors!", client); + } + else if (!(g_bEnabled)) + { + g_bEnabled = true; + CPrintToChatAll("{darkred}[Meteors] {white}%N has enabled Meteors!", client); + } +} + +public Action MeteorMain(Handle timer) +{ + if (!(g_bEnabled)) + return; + + int victimClient = GetTargetClient() + + if (victimClient == -1) + return; + + int indicator = SpawnIndicator(victimClient); + int model = SpawnMeteor2(victimClient); + int hurt = SpawnTriggerHurt(victimClient); + int move = SpawnMoveLinear(victimClient); + int explosion = SpawnExplosion(victimClient); + int sound = SpawnAmbientGeneric(victimClient); + int particle = SpawnParticle(victimClient); + int particle2 = SpawnParticle(victimClient); + + SetVariantString("!activator"); + AcceptEntityInput(model, "SetParent", move); + + SetVariantString("!activator"); + AcceptEntityInput(hurt, "SetParent", move); + + SetVariantString("!activator"); + AcceptEntityInput(particle, "SetParent", move); + + SetVariantString("!activator"); + AcceptEntityInput(particle2, "SetParent", move); + + AcceptEntityInput(move, "Open"); +} + +public Action SpawnParticle(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("info_particle_system")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "info_particle_system_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_particle"); + DispatchKeyValue(Entity, "effect_name", "fire_large_01"); + DispatchSpawn(Entity); + ActivateEntity(Entity); + AcceptEntityInput(Entity, "start"); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + fVector[2] += 7000.0; + + TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR); + + return Entity; + +} + +public Action SpawnAmbientGeneric(int client) +{ + new Entity; + + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("ambient_generic")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "ambient_generic_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_sound"); + DispatchKeyValue(Entity, "spawnflags", "48"); + DispatchKeyValue(Entity, "SourceEntityName", "meteor_model2"); + DispatchKeyValue(Entity, "radius", "3050"); + DispatchKeyValue(Entity, "message", "ambient/explosions/explode_9.wav"); + DispatchKeyValue(Entity, "volume", "10"); + DispatchKeyValue(Entity, "health", "10"); + DispatchKeyValue(Entity, "preset", "0"); + DispatchKeyValue(Entity, "pitch", "100"); + DispatchKeyValue(Entity, "pitchstart", "100"); + DispatchSpawn(Entity); + ActivateEntity(Entity); + + return Entity; +} + +public Action SpawnTriggerHurt(int client) +{ + new Entity; + + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("trigger_hurt")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "trigger_hurt_%i", Entity); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + fVector[2] += 7000.0; + + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_hurt"); + DispatchKeyValue(Entity, "spawnflags", "1"); + DispatchKeyValue(Entity, "StartDisabled", "0"); + DispatchKeyValueVector(Entity, "origin", fVector); + DispatchKeyValue(Entity, "nodmgforce", "0"); + DispatchKeyValue(Entity, "damage", "320"); + DispatchKeyValue(Entity, "damagetype", "128"); + DispatchKeyValue(Entity, "damagemodel", "0"); + DispatchSpawn(Entity); + ActivateEntity(Entity); + + SetEntityModel(Entity, "models/props/cs_office/vending_machine.mdl"); + + new Float:minbounds[3] = {-50.0, -50.0, -100.0}; + new Float:maxbounds[3] = {50.0, 50.0, 100.0}; + SetEntPropVector(Entity, Prop_Send, "m_vecMins", minbounds); + SetEntPropVector(Entity, Prop_Send, "m_vecMaxs", maxbounds); + + SetEntProp(Entity, Prop_Send, "m_nSolidType", 2); + + new enteffects = GetEntProp(Entity, Prop_Send, "m_fEffects"); + enteffects |= 32; + SetEntProp(Entity, Prop_Send, "m_fEffects", enteffects); + + return Entity; +} + +public Action SpawnMeteor2(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("prop_physics_multiplayer")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "prop_physics_multiplayer_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_model2"); + DispatchKeyValue(Entity, "model", "models/props/cs_militia/militiarock05.mdl"); + DispatchKeyValue(Entity, "spawnflags", "8"); + DispatchKeyValue(Entity, "pressuredelay", "0"); + DispatchKeyValue(Entity, "physicsmode", "2"); + DispatchKeyValue(Entity, "physdamagescale", "0.1"); + DispatchKeyValue(Entity, "modelscale", "2.0"); + DispatchSpawn(Entity); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + fVector[2] += 7000.0; + //fVector[1] += 1000.0; + + TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR); + + return Entity; + +} +public Action SpawnExplosion(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("env_explosion")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "env_explosion_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_explosion"); + DispatchKeyValue(Entity, "fireballsprite", "sprites/zerogxplode.spr"); + DispatchKeyValue(Entity, "rendermode", "5"); + DispatchKeyValue(Entity, "iMagnitude", "300"); + DispatchKeyValue(Entity, "iRadiusOverride", "70"); + + DispatchKeyValue(Entity, "spawnflags", "81"); + + DispatchSpawn(Entity); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR); + + return Entity; + + +} + +public Action SpawnMeteor(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("prop_dynamic")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "prop_dynamic_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_model"); + DispatchKeyValue(Entity, "model", "models/props/cs_militia/militiarock05.mdl"); + DispatchKeyValue(Entity, "solid", "0"); + DispatchKeyValue(Entity, "modelscale", "1.0"); + DispatchKeyValue(Entity, "renderamt", "255"); + DispatchKeyValue(Entity, "rendercolor", "0 181 240"); + DispatchKeyValue(Entity, "renderfx", "0"); + DispatchKeyValue(Entity, "rendermode", "0"); + + DispatchSpawn(Entity); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + fVector[2] += 7000.0; + //fVector[1] += 1000.0; + + TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR); + + return Entity; + + +} + +public Action SpawnMoveLinear(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("func_movelinear")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "func_movelinear_%i", Entity); + + float fVectorClient[3]; + float fVectorStart[3]; + float fAngles[3]; + float fVectorCalculated[3]; + float fAnglesCalculated[3]; + GetClientAbsOrigin(client, fVectorClient); + GetClientAbsAngles(client, fAngles); + + fVectorStart = fVectorClient; + fVectorStart[2] += 7000.0; + + SubtractVectors(fVectorClient, fVectorStart, fVectorCalculated); + float distanceF = GetVectorLength(fVectorCalculated, false) + distanceF -= 128.0; + NormalizeVector(fVectorCalculated, fVectorCalculated); + GetVectorAngles(fVectorCalculated, fAnglesCalculated); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_linear"); + DispatchKeyValueVector(Entity, "movedir", fAnglesCalculated); + DispatchKeyValueVector(Entity, "origin", fVectorStart); + DispatchKeyValue(Entity, "speed", "3000"); + DispatchKeyValueFloat(Entity, "movedistance", distanceF); + DispatchKeyValue(Entity, "spawnflags", "8"); + DispatchKeyValue(Entity, "rendermode", "3"); + DispatchKeyValue(Entity, "rendercolor", "136 0 0"); + DispatchKeyValue(Entity, "OnFullyOpen", "!self,KillHierarchy,,0.01,1"); + DispatchKeyValue(Entity, "OnFullyOpen", "meteor_indicator,Kill,,0,1"); + DispatchKeyValue(Entity, "OnFullyOpen", "meteor_explosion,Explode,,0,1"); + DispatchKeyValue(Entity, "OnFullyOpen", "meteor_explosion,Kill,,0.01,1"); + DispatchKeyValue(Entity, "OnFullyOpen", "meteor_sound,PlaySound,,0,1"); + DispatchKeyValue(Entity, "OnFullyOpen", "meteor_sound,Kill,,0.01,1"); + DispatchSpawn(Entity); + + return Entity; +} + + +public Action SpawnIndicator(int client) +{ + new Entity; + // Spawn dynamic prop entity + if ((Entity = CreateEntityByName("prop_dynamic")) == INVALID_ENT_REFERENCE) + return -1; + + // Generate unique id for the entity + new String:StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "prop_dynamic_%i", Entity); + + // Setup entity + DispatchKeyValue(Entity, "targetname", "meteor_indicator"); + DispatchKeyValue(Entity, "model", "models/effects/vol_light128x512.mdl"); + DispatchKeyValue(Entity, "solid", "0"); + DispatchKeyValue(Entity, "modelscale", "1.0"); + DispatchKeyValue(Entity, "angles", "0 0 180"); + DispatchKeyValue(Entity, "renderamt", "255"); + DispatchKeyValue(Entity, "rendercolor", "0 181 240"); + DispatchKeyValue(Entity, "renderfx", "0"); + DispatchKeyValue(Entity, "rendermode", "0"); + + DispatchSpawn(Entity); + + float fVector[3]; + float fAngles[3]; + GetClientAbsOrigin(client, fVector); + GetClientAbsAngles(client, fAngles); + + //fVector[2] += 320.0; + + TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR); + + return Entity; +} + +public int GetTargetClient() +{ + + int outsideClientCount = 0; + new int:outsideClients[MaxClients]; + + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && IsPlayerAlive(i) && (ZR_IsClientHuman(i)) && (GetClientDistanceToCeiling(i) > 200.0)) + { + outsideClients[outsideClientCount] = i + outsideClientCount += 1; + } + } + + if (outsideClientCount == 0) + return -1; + + int randomIndex = GetRandomInt(0, outsideClientCount - 1) + + return outsideClients[randomIndex]; + +} + +public float GetClientDistanceToCeiling(int client) +{ + float distanceF = 0.0; + + new Float:fOrigin[3], Float:fCeiling[3]; + GetClientAbsOrigin(client, fOrigin); + + fOrigin[2] += 10.0; + + TR_TraceRayFilter(fOrigin, Float:{-90.0,0.0,0.0}, MASK_PLAYERSOLID, RayType_Infinite, TraceRayNoPlayers, client); + if (TR_DidHit()) + { + TR_GetEndPosition(fCeiling); + fOrigin[2] -= 10.0; + distanceF = GetVectorDistance(fOrigin, fCeiling); + } + //PrintToChatAll("Client: %d - %f", client,distanceF); + return distanceF; +} + +public bool:TraceRayNoPlayers(entity, mask, any:data) +{ + if(entity == data || (entity >= 1 && entity <= MaxClients)) + { + return false; + } + return true; +} + diff --git a/_CSS/RandomizeSpawns/gamedata/RandomizeSpawns.games.txt b/_CSS/RandomizeSpawns/gamedata/RandomizeSpawns.games.txt new file mode 100644 index 00000000..f1055713 --- /dev/null +++ b/_CSS/RandomizeSpawns/gamedata/RandomizeSpawns.games.txt @@ -0,0 +1,14 @@ +"Games" +{ + "cstrike" + { + "Offsets" + { + "SelectSpawnPoint" + { + "windows" "392" + "linux" "393" + } + } + } +} \ No newline at end of file diff --git a/_CSS/RandomizeSpawns/scripting/RandomizeSpawns.sp b/_CSS/RandomizeSpawns/scripting/RandomizeSpawns.sp new file mode 100644 index 00000000..844e22ae --- /dev/null +++ b/_CSS/RandomizeSpawns/scripting/RandomizeSpawns.sp @@ -0,0 +1,147 @@ +#pragma newdecls required + +#include +#include +#include + +Handle hSelectSpawnPoint; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "RandomizeSpawns", + author = "zaCade", + description = "Randomize player spawns.", + version = "1.0.0" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + Handle hGameConf; + if ((hGameConf = LoadGameConfigFile("RandomizeSpawns.games")) == INVALID_HANDLE) + { + SetFailState("Couldn't load \"RandomizeSpawns.games\" game config!"); + return; + } + + // + int iOffset; + if ((iOffset = GameConfGetOffset(hGameConf, "SelectSpawnPoint")) == -1) + { + CloseHandle(hGameConf); + SetFailState("GameConfGetOffset(hGameConf, \"SelectSpawnPoint\") failed!"); + return; + } + + if ((hSelectSpawnPoint = DHookCreate(iOffset, HookType_Entity, ReturnType_CBaseEntity, ThisPointer_CBaseEntity, OnPlayerSelectSpawnPoint)) == INVALID_HANDLE) + { + CloseHandle(hGameConf); + SetFailState("DHookCreate(iOffset, HookType_Entity, ReturnType_CBaseEntity, ThisPointer_CBaseEntity, OnPlayerSelectSpawnPoint) failed!"); + return; + } + + // Late load. + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client)) + { + OnClientPutInServer(client); + } + } + + CloseHandle(hGameConf); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPutInServer(int client) +{ + DHookEntity(hSelectSpawnPoint, false, client); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int RandomizeSpawnPoints(int elem1, int elem2, int[] array, Handle hndl) +{ + return GetRandomInt(-1, 1); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public MRESReturn OnPlayerSelectSpawnPoint(int client, Handle hReturn) +{ + if (IsValidEntity(client) && !IsClientInGame(client)) + return MRES_Ignored; + + static int spawnPoints[128]; + static int spawnCount; + + if (!spawnCount) + { + int spawnPoint = INVALID_ENT_REFERENCE; + while ((spawnPoint = FindEntityByClassname(spawnPoint, "info_player_*")) != INVALID_ENT_REFERENCE) + { + char sClassname[64]; + GetEntityClassname(spawnPoint, sClassname, sizeof(sClassname)); + + if (StrEqual(sClassname, "info_player_terrorist", true) || StrEqual(sClassname, "info_player_counterterrorist", true)) + { + spawnPoints[spawnCount++] = spawnPoint; + } + } + } + + if (spawnCount) + { + int spawnCountAttempts; + while (spawnCountAttempts >= spawnCount) + { + SortCustom1D(spawnPoints, spawnCount, RandomizeSpawnPoints); + + int spawnPoint = spawnPoints[0]; + if (IsValidEntity(spawnPoint) && IsValidPlayerSpawn(client, spawnPoint)) + { + DHookSetReturn(hReturn, spawnPoint); + return MRES_Supercede; + } + + spawnCountAttempts++; + } + } + + return MRES_Ignored; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool IsValidPlayerSpawn(int client, int spawnPoint) +{ + float clientMins[3]; + float clientMaxs[3]; + GetClientMins(client, clientMins); + GetClientMaxs(client, clientMaxs); + + float spawnPointOrigin[3]; + GetEntPropVector(spawnPoint, Prop_Send, "m_vecOrigin", spawnPointOrigin); + + TR_TraceHullFilter(spawnPointOrigin, spawnPointOrigin, clientMins, clientMaxs, MASK_PLAYERSOLID, IsValidPlayerSpawnFilter); + + return !TR_DidHit(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public bool IsValidPlayerSpawnFilter(int entity, int contentsMask) +{ + return view_as(entity); +} \ No newline at end of file