/*
* CSB Anti Team Attack
* Copyright (C) 2026 counter-strike-boost.com
*
* Blocks or punishes team damage. With csb_atac_block on, a Ham_TakeDamage hook
* zeroes damage between teammates. Otherwise it counts team damage and team
* kills per map and auto-slays, kicks or bans a player who crosses the
* configured threshold.
*
* Inspired by ATAC by BAILOPAN. 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 Team Attack"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new g_pEnabled, g_pBlock, g_pTkLimit, g_pDmgLimit, g_pAction, g_pBanTime
new g_iTeamDmg[33]
new g_iTeamKills[33]
new bool:g_bPunished[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_atac_enabled", "1")
g_pBlock = register_cvar("csb_atac_block", "1")
g_pTkLimit = register_cvar("csb_atac_tk_limit", "3")
g_pDmgLimit = register_cvar("csb_atac_dmg_limit", "300")
g_pAction = register_cvar("csb_atac_action", "1")
g_pBanTime = register_cvar("csb_atac_bantime", "30")
RegisterHam(Ham_TakeDamage, "player", "fwdTakeDamage")
register_event("DeathMsg", "eventDeath", "a", "1>0")
register_logevent("eventNewMap", 2, "1=Round_Start")
}
public client_putinserver(id)
{
g_iTeamDmg[id] = 0
g_iTeamKills[id] = 0
g_bPunished[id] = false
}
public eventNewMap()
{
/* nothing per-round; counters persist across the map on purpose */
}
public fwdTakeDamage(victim, inflictor, attacker, Float:damage, damagebits)
{
if (!get_pcvar_num(g_pEnabled))
return HAM_IGNORED
if (attacker < 1 || attacker > 32 || attacker == victim)
return HAM_IGNORED
if (!is_user_connected(victim) || get_user_team(victim) != get_user_team(attacker))
return HAM_IGNORED
if (get_pcvar_num(g_pBlock))
{
SetHamParamFloat(4, 0.0)
return HAM_IGNORED
}
g_iTeamDmg[attacker] += floatround(damage)
if (!g_bPunished[attacker] && g_iTeamDmg[attacker] >= get_pcvar_num(g_pDmgLimit))
punish(attacker, "team damage")
return HAM_IGNORED
}
public eventDeath()
{
if (!get_pcvar_num(g_pEnabled) || get_pcvar_num(g_pBlock))
return
new killer = read_data(1)
new victim = read_data(2)
if (killer < 1 || killer > 32 || killer == victim || !is_user_connected(victim))
return
if (get_user_team(killer) != get_user_team(victim))
return
g_iTeamKills[killer]++
new kname[32], vname[32]
get_user_name(killer, kname, charsmax(kname))
get_user_name(victim, vname, charsmax(vname))
client_print(0, print_chat, "[CSB] %s team-killed %s (%d/%d this map).",
kname, vname, g_iTeamKills[killer], get_pcvar_num(g_pTkLimit))
log_amx("[CSB ATAC] %s team-killed %s", kname, vname)
if (!g_bPunished[killer] && g_iTeamKills[killer] >= get_pcvar_num(g_pTkLimit))
punish(killer, "team kills")
}
punish(id, const reason[])
{
g_bPunished[id] = true
new name[32], authid[35]
get_user_name(id, name, charsmax(name))
get_user_authid(id, authid, charsmax(authid))
new action = get_pcvar_num(g_pAction)
switch (action)
{
case 1:
{
if (is_user_alive(id))
user_kill(id)
client_print(0, print_chat, "[CSB ATAC] %s was slain for %s.", name, reason)
}
case 2:
{
client_print(0, print_chat, "[CSB ATAC] %s was kicked for %s.", name, reason)
server_cmd("kick #%d ^"Kicked by ATAC: %s^"", get_user_userid(id), reason)
}
case 3:
{
new mins = get_pcvar_num(g_pBanTime)
client_print(0, print_chat, "[CSB ATAC] %s was banned for %d min for %s.", name, mins, reason)
server_cmd("banid %d #%d kick", mins, get_user_userid(id))
server_cmd("writeid")
}
default:
{
client_print(0, print_chat, "[CSB ATAC] %s crossed the %s threshold.", name, reason)
}
}
log_amx("[CSB ATAC] punished %s <%s> for %s (action %d)", name, authid, reason, action)
}