/*
* CSB HUD Clock
* Copyright (C) 2026 counter-strike-boost.com
*
* Shows the real server clock in a small HUD corner, in 12h or 24h format
* (cvar), and can show the elapsed map time next to it. A per-player cvar-driven
* offset lets a player nudge the shown time to their own timezone with /clock.
*
* 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
new const PLUGIN[] = "CSB HUD Clock"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new g_pEnabled, g_pFormat, g_pElapsed
new g_iSync
new Float:g_fMapStart
new bool:g_bShow[33]
new g_iOffset[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_clock_enabled", "1")
g_pFormat = register_cvar("csb_clock_24h", "1")
g_pElapsed = register_cvar("csb_clock_elapsed", "1")
register_clcmd("say /clock", "cmdClock")
register_clcmd("say_team /clock", "cmdClock")
g_iSync = CreateHudSyncObj()
g_fMapStart = get_gametime()
set_task(1.0, "taskClock", 55, _, _, "b")
}
public client_putinserver(id)
{
g_bShow[id] = true
g_iOffset[id] = 0
}
public cmdClock(id)
{
new args[32]
read_args(args, charsmax(args))
remove_quotes(args)
/* "/clock" toggles; "/clock +2" or "/clock -3" sets an hour offset */
new tok[16]
strtok(args, tok, charsmax(tok), tok, charsmax(tok), ' ')
if (containi(args, " ") != -1)
{
new rest[16]
copy(rest, charsmax(rest), args[7])
trim(rest)
new off = str_to_num(rest)
if (off < -12)
off = -12
if (off > 14)
off = 14
g_iOffset[id] = off
client_print(id, print_chat, "[CSB] Clock offset set to %+d hour(s).", off)
return PLUGIN_HANDLED
}
g_bShow[id] = !g_bShow[id]
client_print(id, print_chat, "[CSB] HUD clock %s.", g_bShow[id] ? "shown" : "hidden")
return PLUGIN_HANDLED
}
public taskClock()
{
if (!get_pcvar_num(g_pEnabled))
return
new bool:elapsed = get_pcvar_num(g_pElapsed) != 0
new bool:h24 = get_pcvar_num(g_pFormat) != 0
new mapMin = floatround((get_gametime() - g_fMapStart) / 60.0, floatround_floor)
new players[32], num
get_players(players, num, "ch")
set_hudmessage(120, 220, 255, 0.82, 0.02, 0, 0.0, 1.2, 0.0, 0.0, -1)
for (new i = 0; i < num; i++)
{
new id = players[i]
if (!g_bShow[id])
continue
new hh, mm, ss
serverClock(g_iOffset[id], hh, mm, ss)
new line[64]
if (h24)
{
formatex(line, charsmax(line), "%02d:%02d:%02d", hh, mm, ss)
}
else
{
new ampm = (hh >= 12) ? 'P' : 'A'
new h12 = hh % 12
if (h12 == 0)
h12 = 12
formatex(line, charsmax(line), "%d:%02d:%02d %cM", h12, mm, ss, ampm)
}
if (elapsed)
{
new full[80]
formatex(full, charsmax(full), "%s (map %d min)", line, mapMin)
ShowSyncHudMsg(id, g_iSync, "%s", full)
}
else
{
ShowSyncHudMsg(id, g_iSync, "%s", line)
}
}
}
serverClock(offsetHours, &hh, &mm, &ss)
{
new t[16]
get_time("%H", t, charsmax(t))
hh = str_to_num(t)
get_time("%M", t, charsmax(t))
mm = str_to_num(t)
get_time("%S", t, charsmax(t))
ss = str_to_num(t)
hh = (hh + offsetHours) % 24
if (hh < 0)
hh += 24
}