/*
* CSB Top 15
* Copyright (C) 2026 counter-strike-boost.com
*
* Builds an HTML scoreboard of the 15 highest-ranked players from the CSX
* ranked storage and shows it in a MOTD window on /top15. The list is cached
* and refreshed on a timer so the query never runs on the game frame that the
* player pressed the key.
*
* Inspired by the classic "Top15" / CSStats plugin shipped with 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 the GNU General
* Public License for more details: .
*/
#include
#include
new const PLUGIN[] = "CSB Top 15"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define MAX_TOP 15
new g_szName[MAX_TOP][32]
new g_iKills[MAX_TOP]
new g_iDeaths[MAX_TOP]
new g_iHeadshots[MAX_TOP]
new g_iCount = 0
new g_pEnabled, g_pRefresh
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_top15_enabled", "1")
g_pRefresh = register_cvar("csb_top15_refresh", "120")
register_clcmd("say /top15", "cmdTop")
register_clcmd("say_team /top15", "cmdTop")
register_clcmd("say /top", "cmdTop")
register_clcmd("csb_top15", "cmdTop")
}
public plugin_cfg()
{
refreshCache()
scheduleRefresh()
}
scheduleRefresh()
{
remove_task(918237)
new Float:delay = float(get_pcvar_num(g_pRefresh))
if (delay < 15.0)
delay = 15.0
set_task(delay, "taskRefresh", 918237, _, _, "b")
}
public taskRefresh()
{
refreshCache()
}
refreshCache()
{
g_iCount = 0
new total = get_statsnum()
if (total > MAX_TOP)
total = MAX_TOP
new stats[8], body[8], name[32], authid[35]
for (new i = 0; i < total; i++)
{
/* get_stats reads the i-th entry of the rank-sorted storage */
get_stats(i, stats, body, name, charsmax(name), authid, charsmax(authid))
copy(g_szName[g_iCount], charsmax(g_szName[]), name)
g_iKills[g_iCount] = stats[0]
g_iDeaths[g_iCount] = stats[1]
g_iHeadshots[g_iCount] = stats[2]
g_iCount++
}
}
public cmdTop(id)
{
if (!get_pcvar_num(g_pEnabled))
{
client_print(id, print_chat, "[CSB] The Top 15 board is disabled.")
return PLUGIN_HANDLED
}
if (!g_iCount)
{
refreshCache()
if (!g_iCount)
{
client_print(id, print_chat, "[CSB] No ranked players yet - go make some frags.")
return PLUGIN_HANDLED
}
}
new motd[1800], len = 0
len += formatex(motd[len], charsmax(motd) - len,
"")
len += formatex(motd[len], charsmax(motd) - len,
"Top %d Players
", g_iCount)
len += formatex(motd[len], charsmax(motd) - len,
"")
len += formatex(motd[len], charsmax(motd) - len,
"| # | Player | Kills | Deaths | K/D | HS%% |
")
for (new i = 0; i < g_iCount && len < charsmax(motd) - 260; i++)
{
new Float:kd = g_iDeaths[i] ? float(g_iKills[i]) / float(g_iDeaths[i]) : float(g_iKills[i])
new hspct = g_iKills[i] ? (g_iHeadshots[i] * 100) / g_iKills[i] : 0
new bg[8]
copy(bg, charsmax(bg), (i % 2) ? "#202020" : "#181818")
len += formatex(motd[len], charsmax(motd) - len,
"| %d | %s | %d | %d | %.2f | %d%% |
",
bg, i + 1, g_szName[i], g_iKills[i], g_iDeaths[i], kd, hspct)
}
len += formatex(motd[len], charsmax(motd) - len, "
")
show_motd(id, motd, "Top 15")
return PLUGIN_HANDLED
}