/*
* CSB Scrolling Hostname
* Copyright (C) 2026 counter-strike-boost.com
*
* Animates the server hostname with a scrolling marquee effect. The base text
* supports dynamic placeholders - {players}, {map} and {time} - which are
* substituted live, and a sliding window is written to the hostname cvar on a
* timer to make it scroll. The original hostname is restored when the plugin
* ends so nothing is left mangled on map change.
*
* 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 Scrolling Hostname"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new g_szOriginal[128]
new g_iOffset
new g_pEnabled, g_pText, g_pWidth, g_pInterval
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_host_enabled", "1")
g_pText = register_cvar("csb_host_text", "*** Welcome to {map} - {players} players - {time} left ***")
g_pWidth = register_cvar("csb_host_width", "32")
g_pInterval = register_cvar("csb_host_interval", "0.6")
/* remember the real hostname so we can put it back */
get_cvar_string("hostname", g_szOriginal, charsmax(g_szOriginal))
}
public plugin_cfg()
{
new Float:interval = get_pcvar_float(g_pInterval)
if (interval < 0.2)
interval = 0.2
set_task(interval, "taskScroll", 1337, _, _, "b")
}
public plugin_end()
{
/* restore the original hostname on map end / unload */
if (g_szOriginal[0])
set_cvar_string("hostname", g_szOriginal)
}
expandPlaceholders(out[], len)
{
get_pcvar_string(g_pText, out, len)
new map[32]
get_mapname(map, charsmax(map))
new players[32], num
get_players(players, num, "ch")
new count[8]
num_to_str(num, count, charsmax(count))
new timeStr[16]
new tl = get_timeleft()
if (tl > 0)
formatex(timeStr, charsmax(timeStr), "%d:%02d", tl / 60, tl % 60)
else
copy(timeStr, charsmax(timeStr), "--:--")
replace_string(out, len, "{map}", map)
replace_string(out, len, "{players}", count)
replace_string(out, len, "{time}", timeStr)
}
public taskScroll()
{
if (!get_pcvar_num(g_pEnabled))
return
new full[160]
expandPlaceholders(full, charsmax(full))
/* pad with spaces so the marquee wraps cleanly */
new padded[192]
formatex(padded, charsmax(padded), "%s ", full)
new total = strlen(padded)
if (total < 1)
return
new width = get_pcvar_num(g_pWidth)
if (width < 8)
width = 8
if (width > 63)
width = 63
g_iOffset = (g_iOffset + 1) % total
new view[80]
new w = 0
for (new i = 0; i < width; i++)
{
new src = (g_iOffset + i) % total
view[w++] = padded[src]
}
view[w] = 0
set_cvar_string("hostname", view)
}