/* * CSB Playtime Tracker * Copyright (C) 2026 counter-strike-boost.com * * Accumulates connected seconds per SteamID in nVault (flushed every minute and * on disconnect), prints total hours with say /time and a say /toptime ladder, * and exposes a native csb_get_playtime(id) that the VIP / rewards plugins can * read to gate perks by hours played. * * 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 Playtime Tracker" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define NO_VAULT (-1) new g_iVault = NO_VAULT new g_iTotal[33] /* total accumulated seconds, loaded from the vault */ new g_iSince[33] /* systime of the last flush / connect */ new g_szAuth[33][35] new g_szName[33][32] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) register_clcmd("say /time", "cmdTime") register_clcmd("say_team /time", "cmdTime") register_clcmd("say /toptime", "cmdTopTime") register_clcmd("say_team /toptime", "cmdTopTime") set_task(60.0, "taskFlush", 0, _, _, "b") } public plugin_natives() { register_native("csb_get_playtime", "native_get_playtime") } public plugin_cfg() { g_iVault = nvault_open("csb_playtime") if (g_iVault == NO_VAULT) log_amx("[CSB Playtime] could not open nVault 'csb_playtime' - tracking disabled.") } public plugin_end() { new players[32], num get_players(players, num, "c") for (new i = 0; i < num; i++) flushPlayer(players[i]) if (g_iVault != NO_VAULT) nvault_close(g_iVault) } public client_authorized(id) { g_iTotal[id] = 0 g_iSince[id] = get_systime() g_szAuth[id][0] = 0 g_szName[id][0] = 0 if (is_user_bot(id) || is_user_hltv(id)) return get_user_authid(id, g_szAuth[id], charsmax(g_szAuth[])) get_user_name(id, g_szName[id], charsmax(g_szName[])) if (g_iVault == NO_VAULT) return new value[16] if (nvault_get(g_iVault, g_szAuth[id], value, charsmax(value))) g_iTotal[id] = str_to_num(value) } public client_disconnected(id) { flushPlayer(id) g_iSince[id] = 0 } flushPlayer(id) { if (!g_szAuth[id][0]) return new now = get_systime() if (g_iSince[id] > 0 && now > g_iSince[id]) { g_iTotal[id] += (now - g_iSince[id]) g_iSince[id] = now } if (g_iVault != NO_VAULT) { new value[16] num_to_str(g_iTotal[id], value, charsmax(value)) nvault_pset(g_iVault, g_szAuth[id], value) } } public taskFlush() { new players[32], num get_players(players, num, "c") for (new i = 0; i < num; i++) flushPlayer(players[i]) } seconds(id) { new extra = 0 if (g_iSince[id] > 0) extra = get_systime() - g_iSince[id] return g_iTotal[id] + extra } public cmdTime(id) { new secs = seconds(id) new hours = secs / 3600 new mins = (secs % 3600) / 60 client_print(id, print_chat, "[CSB] You have played %d hour(s) and %d minute(s) on this server.", hours, mins) return PLUGIN_HANDLED } public cmdTopTime(id) { new players[32], num get_players(players, num, "c") /* simple selection sort of the connected players by playtime */ new order[32] for (new i = 0; i < num; i++) order[i] = players[i] for (new i = 0; i < num; i++) { new best = i for (new j = i + 1; j < num; j++) { if (seconds(order[j]) > seconds(order[best])) best = j } if (best != i) { new tmp = order[i] order[i] = order[best] order[best] = tmp } } client_print(id, print_chat, "[CSB] --- Top playtime (online players) ---") new shown = num < 5 ? num : 5 for (new i = 0; i < shown; i++) { new pid = order[i] new secs = seconds(pid) new name[32] get_user_name(pid, name, charsmax(name)) client_print(id, print_chat, "[CSB] %d. %s - %dh %dm", i + 1, name, secs / 3600, (secs % 3600) / 60) } return PLUGIN_HANDLED } /* native csb_get_playtime(id) -> total seconds played, live */ public native_get_playtime(plugin, params) { new id = get_param(1) if (id < 1 || id > 32 || !is_user_connected(id)) return 0 return seconds(id) }