/*
* CSB Disco Lights
* Copyright (C) 2026 counter-strike-boost.com
*
* Admin-triggered party mode: cycles the map light style through a set of
* flicker patterns and spawns coloured dynamic lights (TE_DLIGHT) around every
* player for a configurable duration, then restores the normal lighting.
*
* 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
new const PLUGIN[] = "CSB Disco Lights"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define SVC_TEMPENTITY 23
#define SVC_LIGHTSTYLE 12
#define TE_DLIGHT 27
#define TASK_DISCO 7411
setLightStyle(const pattern[])
{
message_begin(MSG_ALL, SVC_LIGHTSTYLE)
write_byte(0) // light style 0 = the map's main lighting
write_string(pattern)
message_end()
}
new const g_szStyles[][] = {
"mmnmmommommnonmmonqnmmo",
"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba",
"mamamamamamamama",
"nmonqnmomnmomomno",
"aaaaaaaazzzzzzzz"
}
new bool:g_bActive = false
new g_iTicks = 0
new g_iStyle = 0
new g_pEnabled, g_pDuration
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_disco_enabled", "1")
g_pDuration = register_cvar("csb_disco_duration", "30")
register_concmd("amx_disco", "cmdDisco", ADMIN_LEVEL_A, "[0|1] - start or stop disco party mode")
}
public plugin_end()
{
if (g_bActive)
setLightStyle("m")
}
public cmdDisco(id, level, cid)
{
if (!cmd_access(id, level, cid, 1))
return PLUGIN_HANDLED
if (!get_pcvar_num(g_pEnabled))
{
console_print(id, "[CSB] Disco mode is disabled (csb_disco_enabled 0).")
return PLUGIN_HANDLED
}
new want
if (read_argc() > 1)
{
new arg[4]
read_argv(1, arg, charsmax(arg))
want = str_to_num(arg)
}
else
{
want = g_bActive ? 0 : 1
}
if (want && !g_bActive)
startDisco(id)
else if (!want && g_bActive)
stopDisco()
else
console_print(id, "[CSB] Disco is already %s.", g_bActive ? "running" : "stopped")
return PLUGIN_HANDLED
}
startDisco(id)
{
g_bActive = true
g_iTicks = 0
g_iStyle = 0
new aname[32]
if (id)
get_user_name(id, aname, charsmax(aname))
else
copy(aname, charsmax(aname), "CONSOLE")
client_print(0, print_chat, "^x04[CSB]^x01 %s started^x04 DISCO PARTY^x01 mode! Get on the floor.", aname)
log_amx("[CSB Disco] %s started disco mode", aname)
set_task(0.5, "taskDisco", TASK_DISCO, _, _, "b")
}
stopDisco()
{
g_bActive = false
remove_task(TASK_DISCO)
setLightStyle("m")
client_print(0, print_chat, "^x04[CSB]^x01 The disco is over. Lights back to normal.")
}
public taskDisco()
{
if (!g_bActive)
{
remove_task(TASK_DISCO)
return
}
g_iTicks++
new maxTicks = get_pcvar_num(g_pDuration) * 2
if (maxTicks < 2)
maxTicks = 2
if (g_iTicks > maxTicks)
{
stopDisco()
return
}
/* rotate the map light style */
g_iStyle = (g_iStyle + 1) % sizeof g_szStyles
setLightStyle(g_szStyles[g_iStyle])
/* one coloured dynamic light over each alive player */
new players[32], num, pid, origin[3]
get_players(players, num, "a")
for (new i = 0; i < num; i++)
{
pid = players[i]
get_user_origin(pid, origin)
message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
write_byte(TE_DLIGHT)
write_coord(origin[0])
write_coord(origin[1])
write_coord(origin[2] + 48)
write_byte(random_num(10, 22)) // radius / 10
write_byte(random_num(0, 255)) // r
write_byte(random_num(0, 255)) // g
write_byte(random_num(0, 255)) // b
write_byte(6) // life * 10
write_byte(8) // decay * 10
message_end()
}
}