/*
* CSB Anti Camp
* Copyright (C) 2026 counter-strike-boost.com
*
* Detects camping by tracking how long a player stays inside a small radius of
* an anchor point (sampled in a task). Campers first get a HUD warning and a
* bright glow that exposes them, then take escalating damage until they move.
* Radius, time and damage are cvars; bomb carriers are exempt so the objective
* is never punished.
*
* Inspired by the classic Anti Camp plugins for AMX Mod X. 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 Anti Camp"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define CSW_C4 6
new g_pEnabled, g_pRadius, g_pWarn, g_pPunish, g_pDamage
new Float:g_fAnchor[33][3]
new g_iCampTime[33]
new bool:g_bGlowing[33]
new g_iSync
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_camp_enabled", "1")
g_pRadius = register_cvar("csb_camp_radius", "120")
g_pWarn = register_cvar("csb_camp_warn", "6")
g_pPunish = register_cvar("csb_camp_punish", "10")
g_pDamage = register_cvar("csb_camp_damage", "8")
register_event("ResetHUD", "eventSpawn", "b")
g_iSync = CreateHudSyncObj()
set_task(1.0, "taskScan", 0, _, _, "b")
}
public client_putinserver(id)
{
g_iCampTime[id] = 0
g_bGlowing[id] = false
}
public eventSpawn(id)
{
g_iCampTime[id] = 0
clearGlow(id)
if (is_user_alive(id))
pev(id, pev_origin, g_fAnchor[id])
}
public taskScan()
{
if (!get_pcvar_num(g_pEnabled))
return
new Float:radius = get_pcvar_float(g_pRadius)
new warn = get_pcvar_num(g_pWarn)
new punish = get_pcvar_num(g_pPunish)
new players[32], num
get_players(players, num, "ah")
for (new i = 0; i < num; i++)
{
new id = players[i]
/* bomb carrier is doing their job -> never punish */
if (user_has_weapon(id, CSW_C4))
{
g_iCampTime[id] = 0
clearGlow(id)
continue
}
static Float:pos[3]
pev(id, pev_origin, pos)
if (get_distance_f(pos, g_fAnchor[id]) <= radius)
{
g_iCampTime[id]++
}
else
{
g_iCampTime[id] = 0
clearGlow(id)
g_fAnchor[id][0] = pos[0]
g_fAnchor[id][1] = pos[1]
g_fAnchor[id][2] = pos[2]
}
if (g_iCampTime[id] == warn)
{
setGlow(id)
set_hudmessage(255, 60, 60, -1.0, 0.65, 0, 0.0, 2.0, 0.0, 0.0, -1)
ShowSyncHudMsg(id, g_iSync, "STOP CAMPING - move or take damage!")
}
if (g_iCampTime[id] >= punish)
{
new dmg = get_pcvar_num(g_pDamage)
new hp = get_user_health(id)
if (hp - dmg <= 0)
user_kill(id, 1)
else
set_user_health(id, hp - dmg)
client_print(id, print_chat, "[CSB] Camping penalty: -%d HP.", dmg)
}
}
}
setGlow(id)
{
if (g_bGlowing[id])
return
g_bGlowing[id] = true
set_user_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 160)
}
clearGlow(id)
{
if (!g_bGlowing[id])
return
g_bGlowing[id] = false
set_user_rendering(id, kRenderFxNone, 0, 0, 0, kRenderNormal, 0)
}