diff --git a/StopSound/scripting/StopSound.sp b/StopSound/scripting/StopSound.sp index 633ca13a..36527b56 100644 --- a/StopSound/scripting/StopSound.sp +++ b/StopSound/scripting/StopSound.sp @@ -1,206 +1,393 @@ #pragma semicolon 1 -#pragma newdecls required #include #include +#include +#include +#include + #include -#define PLUGIN_VERSION "1.3.0" +#pragma newdecls required + +#define MAX_MAPMUSIC_ENTITIES 2048 + +#define PLUGIN_VERSION "2.0.4" + +int MAX_ENTITIES = 0; +bool g_bLateLoad = false; + +bool g_bStopWeaponSounds[MAXPLAYERS+1] = { false, ... }; +bool g_bStopMapMusic[MAXPLAYERS+1] = { false, ... }; + +bool g_bStopWeaponSoundsHooked = false; +bool g_bStopMapMusicHooked = false; + +int g_iMapMusicEntities[MAX_MAPMUSIC_ENTITIES]; +int g_iNumSounds = 0; -bool g_bStopSound[MAXPLAYERS+1]; -bool g_bHooked; static char g_sKVPATH[PLATFORM_MAX_PATH]; KeyValues g_hWepSounds; +Handle g_hCookieStopSound = null; +Handle g_hCookieStopMapMusic = null; + public Plugin myinfo = { - name = "Toggle Weapon Sounds", - author = "GoD-Tony, edit by Obus + BotoX", - description = "Allows clients to stop hearing weapon sounds", + 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; + } + + g_bLateLoad = late; + + return APLRes_Success; +} + public void OnPluginStart() { + // Load translations + LoadTranslations("plugin.stopsound.phrases"); + LoadTranslations("common.phrases"); // For On/Off buttons in Cookies Menu + // Detect game and hook appropriate tempent. - static char sGame[32]; - GetGameFolderName(sGame, sizeof(sGame)); + AddTempEntHook("Shotgun Shot", CSS_Hook_ShotgunShot); - if(StrEqual(sGame, "cstrike")) - AddTempEntHook("Shotgun Shot", CSS_Hook_ShotgunShot); - else if(StrEqual(sGame, "dod")) - AddTempEntHook("FireBullets", DODS_Hook_FireBullets); + // Ambient sounds + AddAmbientSoundHook(Hook_AmbientSound); - // TF2/HL2:DM and misc weapon sounds will be caught here. - AddNormalSoundHook(Hook_NormalSound); + // 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_stopmusic", Command_StopMusic, "Toggle hearing map music"); + RegConsoleCmd("sm_music", Command_StopMusic, "Toggle hearing map music"); + // Create KeyValues g_hWepSounds = new KeyValues("WeaponSounds"); BuildPath(Path_SM, g_sKVPATH, sizeof(g_sKVPATH), "data/playerprefs.WepSounds.txt"); g_hWepSounds.ImportFromFile(g_sKVPATH); + // Cookies + g_hCookieStopSound = RegClientCookie("weaponsound_blocked", "Are weapon sounds enabled", CookieAccess_Protected); + g_hCookieStopMapMusic = RegClientCookie("mapmusic_blocked", "Are map music enabled", CookieAccess_Protected); + + SetCookieMenuItem(CookieMenuHandler_StopSounds, 0, "Stop sounds"); + // Suppress reload sound effects UserMsg ReloadEffect = GetUserMessageId("ReloadEffect"); - if(ReloadEffect != INVALID_MESSAGE_ID) - HookUserMessage(ReloadEffect, Hook_ReloadEffect, true); + + // Game-specific setup + if (GetEngineVersion() == Engine_CSGO) + { + MAX_ENTITIES = 4096; + + // Weapon sounds will be caught here. + AddNormalSoundHook(Hook_NormalSound_CSGO); + + if (ReloadEffect != INVALID_MESSAGE_ID) + { + HookUserMessage(ReloadEffect, Hook_ReloadEffect_CSGO, true); + } + } + else + { + // CS:S + MAX_ENTITIES = 2048; + + // 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 (g_bLateLoad) { - if(IsClientInGame(client) && IsClientAuthorized(client)) + int entity = -1; + while ((entity = FindEntityByClassname(entity, "ambient_generic*")) != -1) { - static char sAuth[32]; - GetClientAuthId(client, AuthId_Steam2, sAuth, sizeof(sAuth)); - OnClientAuthorized(client, sAuth); + OnEntitySpawned(entity); } + + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client) && AreClientCookiesCached(client)) + { + OnClientCookiesCached(client); + } + } + + g_bLateLoad = false; } } public void OnPluginEnd() { - for(int client = 1; client <= MaxClients; client++) + for (int client = 1; client <= MaxClients; client++) { - if(IsClientInGame(client)) + if (IsClientInGame(client)) + { OnClientDisconnect_Post(client); + } } - // Detect game and unhook appropriate tempent. - static char sGame[32]; - GetGameFolderName(sGame, sizeof(sGame)); + // Remove tempent hook + RemoveTempEntHook("Shotgun Shot", CSS_Hook_ShotgunShot); - if(StrEqual(sGame, "cstrike")) - RemoveTempEntHook("Shotgun Shot", CSS_Hook_ShotgunShot); - else if(StrEqual(sGame, "dod")) - RemoveTempEntHook("FireBullets", DODS_Hook_FireBullets); - - // TF2/HL2:DM and misc weapon sounds were caught here. - RemoveNormalSoundHook(Hook_NormalSound); + // Remove ambient sound hook + RemoveAmbientSoundHook(Hook_AmbientSound); + // Find ReloadEffect UserMsg ReloadEffect = GetUserMessageId("ReloadEffect"); - if(ReloadEffect != INVALID_MESSAGE_ID) - UnhookUserMessage(ReloadEffect, Hook_ReloadEffect, true); + + // Remove game-specific staff + 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); + } + } + + // Delete KeyValues + delete g_hWepSounds; +} + +public void OnMapStart() +{ + g_iNumSounds = 0; +} + +public void OnEntityCreated(int entity, const char[] classname) +{ + if (!StrEqual(classname, "ambient_generic", false)) + { + return; + } + + SDKHook(entity, SDKHook_Spawn, OnEntitySpawned); +} + +public void OnEntitySpawned(int entity) +{ + if (entity < 0 || entity > MAX_ENTITIES || !IsValidEntity(entity)) + { + return; + } + + if (g_iNumSounds >= MAX_MAPMUSIC_ENTITIES) + { + // Something went wrong... + return; + } + char sSoundPath[PLATFORM_MAX_PATH]; + GetEntPropString(entity, Prop_Data, "m_iszSound", sSoundPath, sizeof(sSoundPath)); + + int iLen = strlen(sSoundPath); + + if (iLen > 4 && (StrEqual(sSoundPath[iLen - 4], ".mp3", false) || StrEqual(sSoundPath[iLen - 4], ".wav", false))) + { + g_iMapMusicEntities[g_iNumSounds++] = EntIndexToEntRef(entity); + } +} + +public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) +{ + g_iNumSounds = 0; +} + +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 Timer_DelayedStopForEntity(Handle timer, any data) +{ + DataPack datapack = view_as(data); + datapack.Reset(); + + char sSample[PLATFORM_MAX_PATH]; + datapack.ReadString(sSample, sizeof(sSample)); + int entity = datapack.ReadCell(); + + StopSoundFromEntity(sSample, entity); + + return Plugin_Stop; } public Action Command_StopSound(int client, int args) { - if(client == 0) + if (client == 0) { - PrintToServer("[SM] Cannot use command from server console."); + ReplyToCommand(client, "[SM] Cannot use command from server console."); return Plugin_Handled; } - if(args > 0) + g_bStopWeaponSounds[client] = !g_bStopWeaponSounds[client]; + CheckWeaponSoundsHooks(); + + if (g_bStopWeaponSounds[client]) { - static char Arguments[32]; - GetCmdArg(1, Arguments, sizeof(Arguments)); - - static char SID[32]; - GetClientAuthId(client, AuthId_Steam2, SID, sizeof(SID)); - - if(StrEqual(Arguments, "save")) - { - g_hWepSounds.Rewind(); - - if(g_hWepSounds.JumpToKey(SID, true)) - { - int disabled = g_hWepSounds.GetNum("disabled", 0); - if(!disabled) - { - //CPrintToChat(client, "[StopSound] Saved entry for STEAMID({green}%s{default}) {green}successfully{default}.", SID); - g_hWepSounds.SetNum("disabled", 1); - g_hWepSounds.Rewind(); - g_hWepSounds.ExportToFile(g_sKVPATH); - - g_bStopSound[client] = true; - CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {red}disabled{default} - {green}entry saved{default}."); - CheckHooks(); - - return Plugin_Handled; - } - else - { - //CPrintToChat(client, "[StopSound] Entry for STEAMID({green}%s{default}) {green}successfully deleted{default}.", SID); - g_hWepSounds.DeleteThis(); - g_hWepSounds.Rewind(); - g_hWepSounds.ExportToFile(g_sKVPATH); - - g_bStopSound[client] = false; - CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {green}enabled{default} - {red}entry deleted{default}."); - CheckHooks(); - - return Plugin_Handled; - } - } - - g_hWepSounds.Rewind(); - } - else if(StrEqual(Arguments, "delete")) - { - g_hWepSounds.Rewind(); - - if(g_hWepSounds.JumpToKey(SID, false)) - { - g_bStopSound[client] = false; - CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds {green}enabled{default} - {red}entry deleted{default}."); - CheckHooks(); - - g_hWepSounds.DeleteThis(); - g_hWepSounds.Rewind(); - g_hWepSounds.ExportToFile(g_sKVPATH); - - return Plugin_Handled; - } - else - { - CPrintToChat(client, "{green}[StopSound]{default} Entry {red}not found{default}."); - return Plugin_Handled; - } - } - else - { - PrintToChat(client, "[SM] Usage sm_stopsound "); - return Plugin_Handled; - } + SetClientCookie(client, g_hCookieStopSound, "1"); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Weapon sounds disabled"); + } + else + { + SetClientCookie(client, g_hCookieStopSound, "0"); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Weapon sounds enabled"); } - - g_bStopSound[client] = !g_bStopSound[client]; - CReplyToCommand(client, "{green}[StopSound]{default} Weapon sounds %s.", g_bStopSound[client] ? "{red}disabled{default}" : "{green}enabled{default}"); - CheckHooks(); return Plugin_Handled; } -public void OnClientAuthorized(int client, const char[] auth) +public Action Command_StopMusic(int client, int args) { - g_hWepSounds.Rewind(); - - if(KvJumpToKey(g_hWepSounds, auth, false)) + if (client == 0) { - int disabled = g_hWepSounds.GetNum("disabled", 0); - if(disabled) - g_bStopSound[client] = true; + ReplyToCommand(client, "[SM] Cannot use command from server console."); + return Plugin_Handled; } - CheckHooks(); + 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(); + } + else + { + SetClientCookie(client, g_hCookieStopMapMusic, "0"); + CReplyToCommand(client, "%t %t", "Chat Prefix", "Map music enabled"); + } + + return Plugin_Handled; +} + +public void OnClientCookiesCached(int client) +{ + char sBuffer[2]; + int iValue = 0; + + // Weapon Sounds cookie + GetClientCookie(client, g_hCookieStopSound, sBuffer, sizeof(sBuffer)); + + iValue = StringToInt(sBuffer); + if (iValue == 1) + { + g_bStopWeaponSounds[client] = true; + g_bStopWeaponSoundsHooked = true; + } + else + { + g_bStopWeaponSounds[client] = BackwardCapabilityCheck(client); + + if (iValue != 0) + { + SetClientCookie(client, g_hCookieStopSound, "0"); + } + } + + // Map Music cookie + GetClientCookie(client, g_hCookieStopMapMusic, sBuffer, sizeof(sBuffer)); + + iValue = StringToInt(sBuffer); + if (iValue == 1) + { + g_bStopMapMusic[client] = true; + g_bStopMapMusicHooked = true; + } + else + { + g_bStopMapMusic[client] = false; + + if (iValue != 0) + { + SetClientCookie(client, g_hCookieStopMapMusic, "0"); + } + } +} + +// Because we have some players, whose settings are saved to KV file. We want to save this data. +bool BackwardCapabilityCheck(int client) +{ + char sSteamId[32]; + GetClientAuthId(client, AuthId_Steam2, sSteamId, sizeof(sSteamId)); + g_hWepSounds.Rewind(); + + if (!g_hWepSounds.JumpToKey(sSteamId, false)) + { + return false; + } + + int disabled = g_hWepSounds.GetNum("disabled", 0); + g_hWepSounds.DeleteThis(); + g_hWepSounds.Rewind(); + + return (disabled == 1); } public void OnClientDisconnect_Post(int client) { - g_bStopSound[client] = false; - CheckHooks(); + g_bStopWeaponSounds[client] = false; + g_bStopMapMusic[client] = false; + + CheckWeaponSoundsHooks(); + CheckMapMusicHooks(); } -void CheckHooks() +void CheckWeaponSoundsHooks() { bool bShouldHook = false; - for(int i = 1; i <= MaxClients; i++) + for (int i = 1; i <= MaxClients; i++) { - if(g_bStopSound[i]) + if (g_bStopWeaponSounds[i]) { bShouldHook = true; break; @@ -208,25 +395,202 @@ void CheckHooks() } // Fake (un)hook because toggling actual hooks will cause server instability. - g_bHooked = bShouldHook; + g_bStopWeaponSoundsHooked = bShouldHook; } -public Action Hook_NormalSound(int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], +void CheckMapMusicHooks() +{ + bool bShouldHook = false; + + for (int i = 1; i <= MaxClients; i++) + { + if (g_bStopMapMusic[i]) + { + bShouldHook = true; + break; + } + } + + // Fake (un)hook because toggling actual hooks will cause server instability. + g_bStopMapMusicHooked = bShouldHook; +} + +void StopMapMusic() +{ + char sSound[PLATFORM_MAX_PATH]; + int entity = INVALID_ENT_REFERENCE; + + for (int i = 0; i < g_iNumSounds; i++) + { + entity = EntRefToEntIndex(g_iMapMusicEntities[i]); + + if (entity != INVALID_ENT_REFERENCE) + { + GetEntPropString(entity, Prop_Data, "m_iszSound", sSound, sizeof(sSound)); + + StopSoundFromEntity(sSound, entity); + } + } +} + +void StopSoundFromEntity(const char[] sSample, int entity) +{ + for (int i = 1; i <= MaxClients; i++) + { + if (g_bStopMapMusic[i] && IsClientInGame(i)) + { + Client_StopSound(i, entity, SNDCHAN_STATIC, sSample); + } + } +} + +bool IsEntityInMapMusicEntities(int entity) +{ + for (int i = 0; i < g_iNumSounds; i++) + { + if (entity == EntRefToEntIndex(g_iMapMusicEntities[i])) + { + return true; + } + } + + return false; +} + +// I guess this is from SMLib +void Client_StopSound(int client, int entity, int channel, const char[] name) +{ + EmitSoundToClient(client, name, entity, channel, SNDLEVEL_NONE, SND_STOP, 0.0, SNDPITCH_NORMAL, _, _, _, true); +} + +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, "0"); + 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(); + } + else + { + SetClientCookie(client, g_hCookieStopMapMusic, "0"); + CPrintToChat(client, "%t %t", "Chat Prefix", "Map music enabled"); + } + } + + ShowStopSoundsSettingsMenu(client); + } + 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) { // Ignore non-weapon sounds. - if(!g_bHooked || !(strncmp(sample, "weapons", 7) == 0 || strncmp(sample[1], "weapons", 7) == 0)) + if (!g_bStopWeaponSoundsHooked || channel != SNDCHAN_WEAPON) + { return Plugin_Continue; + } - for(int i = 0; i < numClients; i++) + for (int i = 0; i < numClients; i++) { int client = clients[i]; - if(g_bStopSound[client]) + if (g_bStopWeaponSounds[client]) { // Remove the client from the array. - for(int j = i; j < numClients - 1; j++) + for (int j = i; j < numClients - 1; j++) { clients[j] = clients[j + 1]; + } + + numClients--; + i--; + } + } + + 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) +{ + // Ignore non-weapon sounds. + if (!g_bStopWeaponSoundsHooked || (channel != SNDCHAN_WEAPON && !(channel == SNDCHAN_AUTO && strncmp(sample, "physics/flesh", 13) == 0) && !(channel == SNDCHAN_STATIC && StrContains(sample, "player/headshot", true) != -1))) + { + return Plugin_Continue; + } + + for (int i = 0; i < numClients; i++) + { + int client = clients[i]; + if (g_bStopWeaponSounds[client] || !IsClientConnected(client)) + { + // Remove the client from the array. + for (int j = i; j < numClients - 1; j++) { + clients[j] = clients[j + 1]; + } numClients--; i--; @@ -238,25 +602,33 @@ public Action Hook_NormalSound(int clients[MAXPLAYERS], int &numClients, char sa public Action CSS_Hook_ShotgunShot(const char[] te_name, const int[] Players, int numClients, float delay) { - if(!g_bHooked) + 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++) + for (int i = 0; i < numClients; i++) { - int client = Players[i]; - if(!g_bStopSound[client]) - newClients[newTotal++] = client; + if (!g_bStopWeaponSounds[Players[i]]) + { + newClients[newTotal++] = Players[i]; + } } // No clients were excluded. - if(newTotal == numClients) + if (newTotal == numClients) + { return Plugin_Continue; - else if(newTotal == 0) // All clients were excluded and there is no need to broadcast. + } + 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. float vTemp[3]; @@ -276,75 +648,94 @@ public Action CSS_Hook_ShotgunShot(const char[] te_name, const int[] Players, in return Plugin_Stop; } -public Action DODS_Hook_FireBullets(const char[] te_name, const int[] Players, int numClients, float delay) +public Action Hook_ReloadEffect_CSS(UserMsg msg_id, BfRead msg, const int[] players, int playersNum, bool reliable, bool init) { - if(!g_bHooked) - 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_bStopWeaponSoundsHooked) { - int client = Players[i]; - if(!g_bStopSound[client]) - newClients[newTotal++] = client; + return Plugin_Continue; } - // No clients were excluded. - if(newTotal == numClients) - 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. - float vTemp[3]; - TE_Start("FireBullets"); - 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_flSpread", TE_ReadFloat("m_flSpread")); - TE_Send(newClients, newTotal, delay); - - return Plugin_Stop; -} - -public Action Hook_ReloadEffect(UserMsg msg_id, BfRead msg, const int[] players, int playersNum, bool reliable, bool init) -{ - if(!g_bHooked) - 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++) + for (int i = 0; i < playersNum; i++) { int client_ = players[i]; - if(IsClientInGame(client_) && !g_bStopSound[client_]) + if (IsClientInGame(client_) && !g_bStopWeaponSounds[client_]) + { newClients[newTotal++] = client_; + } } - // No clients were excluded. - if(newTotal == playersNum) + 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. + } + 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++) + 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); @@ -360,18 +751,40 @@ public void OnReloadEffect(DataPack pack) int[] players = new int[newTotal]; int playersNum = 0; - for(int i = 0; i < newTotal; i++) + for (int i = 0; i < newTotal; i++) { int client_ = pack.ReadCell(); - if(IsClientInGame(client_)) + 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) + 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) +{ + if (g_bStopMapMusicHooked && IsEntityInMapMusicEntities(entity)) + { + DataPack datapack; + CreateDataTimer(0.0, Timer_DelayedStopForEntity, datapack, TIMER_FLAG_NO_MAPCHANGE); + + datapack.WriteString(sample); + datapack.WriteCell(entity); + } + + return Plugin_Continue; +} diff --git a/StopSound/scripting/include/morecolors.inc b/StopSound/scripting/include/morecolors.inc deleted file mode 120000 index cd0d80e6..00000000 --- a/StopSound/scripting/include/morecolors.inc +++ /dev/null @@ -1 +0,0 @@ -../../../includes/morecolors.inc \ No newline at end of file diff --git a/StopSound/scripting/include/multicolors.inc b/StopSound/scripting/include/multicolors.inc new file mode 100644 index 00000000..cb69a30d --- /dev/null +++ b/StopSound/scripting/include/multicolors.inc @@ -0,0 +1 @@ +../../../includes/multicolors.inc \ No newline at end of file diff --git a/StopSound/translations/plugin.stopsound.phrases.txt b/StopSound/translations/plugin.stopsound.phrases.txt new file mode 100644 index 00000000..5f28ef2e --- /dev/null +++ b/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