/* * CSB Surf Helper * Copyright (C) 2026 counter-strike-boost.com * * Quality-of-life for surf servers. Fall damage is cancelled, buying is blocked, * a sensible sv_airaccelerate is set, a live speed HUD shows horizontal velocity, * /stuck teleports a wedged player to a spawn point, and death triggers an * instant respawn so a surf map never leaves anyone waiting. * * 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 Surf Helper" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_pEnabled, g_pNoFall, g_pNoBuy, g_pAirAccel, g_pRespawn, g_pStuckCd new Float:g_fLastStuck[33] new g_iHudSync public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_surf_enabled", "1") g_pNoFall = register_cvar("csb_surf_nofall", "1") g_pNoBuy = register_cvar("csb_surf_nobuy", "1") g_pAirAccel = register_cvar("csb_surf_airaccel", "100") g_pRespawn = register_cvar("csb_surf_respawn", "1") g_pStuckCd = register_cvar("csb_surf_stuck_cooldown", "5.0") RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage", 0) register_event("DeathMsg", "eventDeath", "a", "1>0") register_clcmd("say /stuck", "cmdStuck") register_clcmd("say_team /stuck", "cmdStuck") register_clcmd("buy", "blockBuy") register_clcmd("buyammo", "blockBuy") g_iHudSync = CreateHudSyncObj() set_task(0.3, "taskSpeed", 0, _, _, "b") } public plugin_cfg() { if (get_pcvar_num(g_pEnabled)) { new pAir = get_cvar_pointer("sv_airaccelerate") if (pAir) set_pcvar_num(pAir, get_pcvar_num(g_pAirAccel)) } } public client_putinserver(id) { g_fLastStuck[id] = 0.0 } public fwTakeDamage(victim, inflictor, attacker, Float:damage, damagebits) { if (!get_pcvar_num(g_pEnabled) || !get_pcvar_num(g_pNoFall)) return HAM_IGNORED if (damagebits & DMG_FALL) { SetHamParamFloat(4, 0.0) return HAM_SUPERCEDE } return HAM_IGNORED } public cmdStuck(id) { if (!get_pcvar_num(g_pEnabled) || !is_user_alive(id)) return PLUGIN_HANDLED if (get_gametime() - g_fLastStuck[id] < get_pcvar_float(g_pStuckCd)) { client_print(id, print_chat, "[CSB] /stuck is on cooldown.") return PLUGIN_HANDLED } new spawn = engfunc(EngFunc_FindEntityByString, 0, "classname", "info_player_start") if (spawn <= 0) spawn = engfunc(EngFunc_FindEntityByString, 0, "classname", "info_player_deathmatch") if (spawn <= 0) { client_print(id, print_chat, "[CSB] No spawn point found.") return PLUGIN_HANDLED } static Float:fPos[3] pev(spawn, pev_origin, fPos) engfunc(EngFunc_SetOrigin, id, fPos) static Float:fZero[3] set_pev(id, pev_velocity, fZero) g_fLastStuck[id] = get_gametime() client_print(id, print_chat, "[CSB] Teleported to a spawn point.") return PLUGIN_HANDLED } public blockBuy(id) { if (get_pcvar_num(g_pEnabled) && get_pcvar_num(g_pNoBuy)) return PLUGIN_HANDLED return PLUGIN_CONTINUE } public eventDeath() { new victim = read_data(2) if (!get_pcvar_num(g_pEnabled) || !get_pcvar_num(g_pRespawn)) return if (victim >= 1 && victim <= 32) set_task(2.0, "taskRespawn", victim) } public taskRespawn(id) { if (!is_user_connected(id) || is_user_alive(id)) return if (get_user_team(id) == 1 || get_user_team(id) == 2) ExecuteHamB(Ham_CS_RoundRespawn, id) } public taskSpeed() { if (!get_pcvar_num(g_pEnabled)) return new players[32], num get_players(players, num, "a") for (new i = 0; i < num; i++) { new id = players[i] static Float:fVel[3] pev(id, pev_velocity, fVel) new speed = floatround(floatsqroot(fVel[0]*fVel[0] + fVel[1]*fVel[1])) set_hudmessage(0, 255, 200, 0.45, 0.80, 0, 0.0, 0.4, 0.0, 0.0, -1) ShowSyncHudMsg(id, g_iHudSync, "%d u/s", speed) } }