/* * CSB Match Damage Report * Copyright (C) 2026 counter-strike-boost.com * * Competitive-style damage report. Damage is accumulated in Ham_TakeDamage per * attacker/victim pair with hit counts; when a player dies they see exactly how * much damage they dealt to and took from every opponent, and at round end a * short summary of who traded whom is printed. * * Inspired by the CS:GO-style "Damage Report" plugins for AMX Mod X. 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 new const PLUGIN[] = "CSB Match Damage Report" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_iDmgDealt[33][33] new g_iHitsDealt[33][33] new g_iKilledBy[33] /* attacker who got the last kill on this victim */ new g_iKillTime[33] /* systime of that kill, for trade detection */ new g_pEnabled, g_pShowEnd public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_dmgreport_enabled", "1") g_pShowEnd = register_cvar("csb_dmgreport_roundend", "1") RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage") RegisterHam(Ham_Killed, "player", "fwKilled", 1) register_event("HLTV", "eNewRound", "a", "1=0", "2=0") } public eNewRound() { for (new i = 1; i <= 32; i++) { g_iKilledBy[i] = 0 g_iKillTime[i] = 0 for (new j = 1; j <= 32; j++) { g_iDmgDealt[i][j] = 0 g_iHitsDealt[i][j] = 0 } } } public fwTakeDamage(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(attacker) || !is_user_connected(victim)) return HAM_IGNORED new dmg = floatround(damage) if (dmg < 1) dmg = 1 g_iDmgDealt[attacker][victim] += dmg g_iHitsDealt[attacker][victim]++ return HAM_IGNORED } public fwKilled(victim, attacker, shouldgib) { if (attacker >= 1 && attacker <= 32 && attacker != victim && is_user_connected(attacker)) { g_iKilledBy[victim] = attacker g_iKillTime[victim] = get_systime() } if (get_pcvar_num(g_pEnabled)) showReport(victim) } showReport(id) { if (!is_user_connected(id)) return client_print(id, print_chat, "[CSB] -------- Damage Report --------") new name[32] for (new v = 1; v <= 32; v++) { if (v == id || !is_user_connected(v)) continue new given = g_iDmgDealt[id][v] new givenHits = g_iHitsDealt[id][v] new taken = g_iDmgDealt[v][id] new takenHits = g_iHitsDealt[v][id] if (given == 0 && taken == 0) continue get_user_name(v, name, charsmax(name)) client_print(id, print_chat, "[CSB] to %s: %d dmg / %d hit(s) | from %s: %d dmg / %d hit(s)", name, given, givenHits, name, taken, takenHits) } /* who killed us this round */ new killer = g_iKilledBy[id] if (killer && g_iKillTime[id] && is_user_connected(killer)) { get_user_name(killer, name, charsmax(name)) client_print(id, print_chat, "[CSB] You were killed by %s.", name) } } public plugin_cfg() { register_logevent("onRoundEnd", 2, "1=Round_End") } public onRoundEnd() { if (!get_pcvar_num(g_pEnabled) || !get_pcvar_num(g_pShowEnd)) return new players[32], num, pid get_players(players, num, "ch") for (new i = 0; i < num; i++) { pid = players[i] new best = 0, bestDmg = 0 for (new v = 1; v <= 32; v++) { if (v == pid) continue if (g_iDmgDealt[pid][v] > bestDmg) { bestDmg = g_iDmgDealt[pid][v] best = v } } if (best && bestDmg > 0) { new bname[32] get_user_name(best, bname, charsmax(bname)) client_print(pid, print_chat, "[CSB] Round: most damage to %s (%d dmg).", bname, bestDmg) } } }