Sunucu tanitimi
csb-playtime-tracker / addons / amxmodx / scripting / csb_playtime_tracker.sma
205 lines 4.7 KiB Pawn Raw Permalink History
/*
 * 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 <https://www.gnu.org/licenses/> for details.
 */

#include <amxmodx>
#include <amxmisc>
#include <nvault>

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)
}