/* * CSB Earthquake * Copyright (C) 2026 counter-strike-boost.com * * Shakes everyone's screen with the ScreenShake message, either on an admin * command (amx_earthquake) or automatically at random intervals. While the * quake runs it can also give grounded players a small random push and plays an * optional rumble sound. Duration, amplitude and the push are cvar-controlled. * * 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 #include new const PLUGIN[] = "CSB Earthquake" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define TASK_AUTO 9100 #define TASK_SHAKE 9101 new g_pEnabled, g_pAuto, g_pMinInt, g_pMaxInt new g_pDuration, g_pAmp, g_pPush, g_pSound new bool:g_bQuaking = false new g_iTicks = 0 new g_szSound[64] new g_msgShake public plugin_precache() { g_pSound = register_cvar("csb_quake_sound", "") get_pcvar_string(g_pSound, g_szSound, charsmax(g_szSound)) if (g_szSound[0]) precache_sound(g_szSound) } public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_quake_enabled", "1") g_pAuto = register_cvar("csb_quake_auto", "1") g_pMinInt = register_cvar("csb_quake_min_interval", "120") g_pMaxInt = register_cvar("csb_quake_max_interval", "300") g_pDuration = register_cvar("csb_quake_duration", "5") g_pAmp = register_cvar("csb_quake_amplitude", "8") g_pPush = register_cvar("csb_quake_push", "1") register_concmd("amx_earthquake", "cmdQuake", ADMIN_LEVEL_A, "[seconds] - trigger an earthquake") g_msgShake = get_user_msgid("ScreenShake") scheduleNext() } scheduleNext() { remove_task(TASK_AUTO) if (!get_pcvar_num(g_pAuto)) return new mn = get_pcvar_num(g_pMinInt) new mx = get_pcvar_num(g_pMaxInt) if (mn < 10) mn = 10 if (mx < mn) mx = mn set_task(float(random_num(mn, mx)), "taskAutoQuake", TASK_AUTO) } public taskAutoQuake() { if (get_pcvar_num(g_pEnabled) && get_pcvar_num(g_pAuto)) startQuake(get_pcvar_num(g_pDuration)) scheduleNext() } public cmdQuake(id, level, cid) { if (!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED if (!get_pcvar_num(g_pEnabled)) { console_print(id, "[CSB] Earthquake is disabled (csb_quake_enabled 0).") return PLUGIN_HANDLED } new secs = get_pcvar_num(g_pDuration) if (read_argc() > 1) { new arg[8] read_argv(1, arg, charsmax(arg)) new n = str_to_num(arg) if (n > 0) secs = n } new aname[32] if (id) get_user_name(id, aname, charsmax(aname)) else copy(aname, charsmax(aname), "CONSOLE") log_amx("[CSB Quake] %s triggered an earthquake (%d s)", aname, secs) startQuake(secs) return PLUGIN_HANDLED } startQuake(secs) { if (g_bQuaking) return if (secs < 1) secs = 1 g_bQuaking = true g_iTicks = secs * 4 client_print(0, print_chat, "^x04[CSB]^x01 The ground is shaking! EARTHQUAKE!") if (g_szSound[0]) { new players[32], num get_players(players, num, "c") for (new i = 0; i < num; i++) emit_sound(players[i], CHAN_STATIC, g_szSound, VOL_NORM, ATTN_NORM, 0, PITCH_NORM) } set_task(0.25, "taskShake", TASK_SHAKE, _, _, "b") } public taskShake() { if (!g_bQuaking) { remove_task(TASK_SHAKE) return } g_iTicks-- new amp = get_pcvar_num(g_pAmp) new push = get_pcvar_num(g_pPush) new players[32], num, pid get_players(players, num, "a") for (new i = 0; i < num; i++) { pid = players[i] message_begin(MSG_ONE, g_msgShake, _, pid) write_short(amp << 12) // amplitude write_short(1 << 12) // duration write_short(amp << 12) // frequency message_end() if (push && (pev(pid, pev_flags) & FL_ONGROUND)) { new Float:vel[3] pev(pid, pev_velocity, vel) vel[0] += random_float(-90.0, 90.0) vel[1] += random_float(-90.0, 90.0) vel[2] += random_float(70.0, 160.0) set_pev(pid, pev_velocity, vel) } } if (g_iTicks <= 0) { g_bQuaking = false remove_task(TASK_SHAKE) } }