/* * CSB Quake Sounds * Copyright (C) 2026 counter-strike-boost.com * * The classic Quake announcer for CS 1.6. A DeathMsg hook tracks kill timings * and streaks and plays firstblood, doublekill, multikill, ultrakill, godlike, * headshot and humiliation (knife-kill) sounds. Each player can turn the sounds * off for themselves with /qsounds, and the choice is saved in nVault. * * Inspired by the original "Quake Sounds" plugin (Vexd / the AMXX community). * This is an independent GPL re-implementation; no original code is reused. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. It is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See for details. */ #include #include #include new const PLUGIN[] = "CSB Quake Sounds" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define NO_VAULT (-1) enum _:Snd { SND_FIRSTBLOOD = 0, SND_DOUBLE, SND_MULTI, SND_ULTRA, SND_GODLIKE, SND_HEADSHOT, SND_HUMILIATION } new const g_szSounds[Snd][] = { "csb_quake/firstblood.wav", "csb_quake/doublekill.wav", "csb_quake/multikill.wav", "csb_quake/ultrakill.wav", "csb_quake/godlike.wav", "csb_quake/headshot.wav", "csb_quake/humiliation.wav" } new bool:g_bSoundOk[Snd] new g_iCombo[33] new Float:g_fLastKill[33] new bool:g_bEnabled[33] new g_szAuth[33][35] new bool:g_bFirstBlood new g_iVault = NO_VAULT new g_pEnabled, g_pComboWindow public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_quake_enabled", "1") g_pComboWindow = register_cvar("csb_quake_window", "3.0") register_event("DeathMsg", "fwDeath", "a") register_event("HLTV", "eNewRound", "a", "1=0", "2=0") register_clcmd("say /qsounds", "cmdToggle") register_clcmd("say_team /qsounds", "cmdToggle") } public plugin_precache() { new full[128] for (new i = 0; i < Snd; i++) { formatex(full, charsmax(full), "sound/%s", g_szSounds[i]) if (file_exists(full)) { precache_sound(g_szSounds[i]) g_bSoundOk[i] = true } else { log_amx("[CSB Quake] missing sound %s - that announce is disabled.", full) } } } public plugin_cfg() { g_iVault = nvault_open("csb_quake_sounds") if (g_iVault == NO_VAULT) log_amx("[CSB Quake] could not open nVault - toggles will not persist.") } public plugin_end() { if (g_iVault != NO_VAULT) nvault_close(g_iVault) } public client_authorized(id) { g_iCombo[id] = 0 g_fLastKill[id] = 0.0 g_bEnabled[id] = true if (is_user_bot(id) || is_user_hltv(id)) return get_user_authid(id, g_szAuth[id], charsmax(g_szAuth[])) if (g_iVault == NO_VAULT) return new value[4] if (nvault_get(g_iVault, g_szAuth[id], value, charsmax(value))) g_bEnabled[id] = (str_to_num(value) != 0) } public cmdToggle(id) { g_bEnabled[id] = !g_bEnabled[id] client_print(id, print_chat, "[CSB] Quake sounds are now %s for you.", g_bEnabled[id] ? "ON" : "OFF") if (g_iVault != NO_VAULT && g_szAuth[id][0]) { new value[4] num_to_str(g_bEnabled[id] ? 1 : 0, value, charsmax(value)) nvault_set(g_iVault, g_szAuth[id], value) } return PLUGIN_HANDLED } public eNewRound() { g_bFirstBlood = false for (new i = 1; i <= 32; i++) { g_iCombo[i] = 0 g_fLastKill[i] = 0.0 } } public fwDeath() { if (!get_pcvar_num(g_pEnabled)) return new killer = read_data(1) new victim = read_data(2) new headshot = read_data(3) /* reset the victim's streak */ if (victim >= 1 && victim <= 32) g_iCombo[victim] = 0 if (killer < 1 || killer > 32 || killer == victim || !is_user_connected(killer)) return /* humiliation: killed with the knife -> tell the victim */ if (get_user_weapon(killer) == CSW_KNIFE) playToOne(victim, SND_HUMILIATION) /* first blood of the round */ if (!g_bFirstBlood) { g_bFirstBlood = true playToAll(SND_FIRSTBLOOD) } /* headshot announce goes to the killer */ if (headshot) playToOne(killer, SND_HEADSHOT) /* combo window */ new Float:now = get_gametime() new Float:window = get_pcvar_float(g_pComboWindow) if (g_fLastKill[killer] > 0.0 && (now - g_fLastKill[killer]) <= window) g_iCombo[killer]++ else g_iCombo[killer] = 1 g_fLastKill[killer] = now switch (g_iCombo[killer]) { case 2: playToAll(SND_DOUBLE) case 3: playToAll(SND_MULTI) case 4: playToAll(SND_ULTRA) } if (g_iCombo[killer] >= 5) playToAll(SND_GODLIKE) } playToAll(snd) { if (!g_bSoundOk[snd]) return new players[32], num, pid get_players(players, num, "c") for (new i = 0; i < num; i++) { pid = players[i] if (g_bEnabled[pid]) emit_sound(pid, CHAN_STATIC, g_szSounds[snd], 1.0, 0.0, 0, PITCH_NORM) } } playToOne(id, snd) { if (!g_bSoundOk[snd] || id < 1 || id > 32 || !is_user_connected(id) || !g_bEnabled[id]) return emit_sound(id, CHAN_STATIC, g_szSounds[snd], 1.0, 0.0, 0, PITCH_NORM) }