/*
* CSB Extend Map
* Copyright (C) 2026 counter-strike-boost.com
*
* amx_extendmap adds N minutes to mp_timelimit and re-broadcasts the new time
* left. Players can also start a vote (say /extend) to extend the current map
* once, capped by a max-extensions cvar so a map can never run forever.
*
* Inspired by the map-extension commands from the AMX Mod X map management
* plugin (AMX Mod X Development Team). Independent GPL re-implementation.
*
* 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 Extend Map"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new g_pTimeLimit
new g_pDefaultMin, g_pMaxExtends, g_pVoteMin
new g_iExtends = 0
new bool:g_bVoteRunning = false
new g_iYes, g_iNo
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pTimeLimit = get_cvar_pointer("mp_timelimit")
g_pDefaultMin = register_cvar("csb_extend_minutes", "15")
g_pMaxExtends = register_cvar("csb_extend_max", "3")
g_pVoteMin = register_cvar("csb_extend_votemin", "15")
register_concmd("amx_extendmap", "cmdExtend", ADMIN_MAP, "[minutes] - add time to mp_timelimit")
register_clcmd("say /extend", "cmdVote")
register_clcmd("say_team /extend", "cmdVote")
}
public plugin_cfg()
{
g_iExtends = 0
}
extendBy(minutes)
{
new cur = g_pTimeLimit ? get_pcvar_num(g_pTimeLimit) : get_cvar_num("mp_timelimit")
new next = cur + minutes
if (g_pTimeLimit)
set_pcvar_num(g_pTimeLimit, next)
else
set_cvar_num("mp_timelimit", next)
g_iExtends++
new left = get_timeleft() / 60
client_print(0, print_chat, "[CSB] Map extended by %d minute(s). New limit: %d min, about %d min left.",
minutes, next, left)
}
public cmdExtend(id, level, cid)
{
if (!cmd_access(id, level, cid, 1))
return PLUGIN_HANDLED
new minutes = get_pcvar_num(g_pDefaultMin)
if (read_argc() > 1)
{
new arg[8]
read_argv(1, arg, charsmax(arg))
new n = str_to_num(arg)
if (n > 0)
minutes = n
}
extendBy(minutes)
new aname[32]
if (id)
get_user_name(id, aname, charsmax(aname))
else
copy(aname, charsmax(aname), "CONSOLE")
log_amx("[CSB Extend] %s extended the map by %d min", aname, minutes)
return PLUGIN_HANDLED
}
public cmdVote(id)
{
if (g_bVoteRunning)
{
client_print(id, print_chat, "[CSB] A vote is already running.")
return PLUGIN_HANDLED
}
if (g_iExtends >= get_pcvar_num(g_pMaxExtends))
{
client_print(id, print_chat, "[CSB] This map has already been extended the maximum number of times.")
return PLUGIN_HANDLED
}
g_bVoteRunning = true
g_iYes = 0
g_iNo = 0
new menu = menu_create("\yExtend the map?^n\wIt will add time to the current map.", "voteHandler")
menu_additem(menu, "\wYes, extend", "1", 0)
menu_additem(menu, "\wNo", "2", 0)
menu_setprop(menu, MPROP_EXIT, MEXIT_NEVER)
new players[32], num, pid
get_players(players, num, "ch")
for (new i = 0; i < num; i++)
{
pid = players[i]
menu_display(pid, menu, 0)
}
client_print(0, print_chat, "[CSB] Vote started: extend the current map?")
set_task(15.0, "voteEnd")
return PLUGIN_HANDLED
}
public voteHandler(id, menu, item)
{
if (item == MENU_EXIT || item < 0)
{
menu_destroy(menu)
return PLUGIN_HANDLED
}
new info[4], name[32], access, callback
menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
menu_destroy(menu)
if (str_to_num(info) == 1)
g_iYes++
else
g_iNo++
return PLUGIN_HANDLED
}
public voteEnd()
{
g_bVoteRunning = false
if (g_iYes > g_iNo)
{
client_print(0, print_chat, "[CSB] Vote passed (%d yes / %d no). Extending the map.", g_iYes, g_iNo)
extendBy(get_pcvar_num(g_pVoteMin))
log_amx("[CSB Extend] player vote passed (%d/%d), map extended", g_iYes, g_iNo)
}
else
{
client_print(0, print_chat, "[CSB] Vote failed (%d yes / %d no). The map will not be extended.", g_iYes, g_iNo)
}
}