/*
* CSB Admin Freeze
* Copyright (C) 2026 counter-strike-boost.com
*
* amx_freeze <target> [seconds] locks a player in place by raising the engine
* FL_FROZEN flag and pinning pev_maxspeed to 1.0, with a blue screen fade and a
* timed automatic unfreeze. amx_unfreeze restores the stored maxspeed at once.
*
* Inspired by the freeze command from the AMX Mod X Admin Commands 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 <https://www.gnu.org/licenses/> for details.
*/
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
new const PLUGIN[] = "CSB Admin Freeze"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define FL_FROZEN (1<<16)
#define TASK_UNFREEZE 7100
new bool:g_bFrozen[33]
new Float:g_fOldSpeed[33]
new g_pDefault, g_pMax
new g_msgScreenFade
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pDefault = register_cvar("csb_freeze_default", "5")
g_pMax = register_cvar("csb_freeze_max", "60")
register_concmd("amx_freeze", "cmdFreeze", ADMIN_SLAY, "<target> [seconds] - freeze a player in place")
register_concmd("amx_unfreeze", "cmdUnfreeze", ADMIN_SLAY, "<target> - unfreeze a player")
g_msgScreenFade = get_user_msgid("ScreenFade")
}
public client_disconnected(id)
{
if (g_bFrozen[id])
{
g_bFrozen[id] = false
remove_task(id + TASK_UNFREEZE)
}
}
doFreeze(target)
{
if (g_bFrozen[target])
return
g_fOldSpeed[target] = pev(target, pev_maxspeed)
g_bFrozen[target] = true
set_pev(target, pev_maxspeed, 1.0)
set_pev(target, pev_flags, pev(target, pev_flags) | FL_FROZEN)
message_begin(MSG_ONE, g_msgScreenFade, _, target)
write_short(1 << 12)
write_short(1 << 12)
write_short(0x0004)
write_byte(20)
write_byte(20)
write_byte(180)
write_byte(160)
message_end()
}
doUnfreeze(target)
{
if (!g_bFrozen[target])
return
g_bFrozen[target] = false
remove_task(target + TASK_UNFREEZE)
if (!is_user_connected(target))
return
set_pev(target, pev_flags, pev(target, pev_flags) & ~FL_FROZEN)
new Float:restore = g_fOldSpeed[target]
if (restore < 1.0)
restore = 250.0
set_pev(target, pev_maxspeed, restore)
}
public taskUnfreeze(taskid)
{
new target = taskid - TASK_UNFREEZE
if (target >= 1 && target <= 32)
{
doUnfreeze(target)
if (is_user_connected(target))
client_print(target, print_chat, "[CSB] You have been unfrozen.")
}
}
public cmdFreeze(id, level, cid)
{
if (!cmd_access(id, level, cid, 2))
return PLUGIN_HANDLED
new arg[32]
read_argv(1, arg, charsmax(arg))
new target = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY)
if (!target)
return PLUGIN_HANDLED
if (!is_user_alive(target))
{
client_print(id, print_chat, "[CSB] That player is not alive.")
return PLUGIN_HANDLED
}
new seconds = get_pcvar_num(g_pDefault)
if (read_argc() > 2)
{
new sArg[8]
read_argv(2, sArg, charsmax(sArg))
new n = str_to_num(sArg)
if (n > 0)
seconds = n
}
new maxSec = get_pcvar_num(g_pMax)
if (maxSec > 0 && seconds > maxSec)
seconds = maxSec
doFreeze(target)
remove_task(target + TASK_UNFREEZE)
set_task(float(seconds), "taskUnfreeze", target + TASK_UNFREEZE)
new aname[32], tname[32]
getName(id, aname, charsmax(aname))
get_user_name(target, tname, charsmax(tname))
client_print(0, print_chat, "[CSB] %s froze %s for %d second(s).", aname, tname, seconds)
log_amx("[CSB Freeze] %s froze %s for %d s", aname, tname, seconds)
return PLUGIN_HANDLED
}
public cmdUnfreeze(id, level, cid)
{
if (!cmd_access(id, level, cid, 2))
return PLUGIN_HANDLED
new arg[32]
read_argv(1, arg, charsmax(arg))
new target = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
if (!target)
return PLUGIN_HANDLED
if (!g_bFrozen[target])
{
client_print(id, print_chat, "[CSB] That player is not frozen.")
return PLUGIN_HANDLED
}
doUnfreeze(target)
new aname[32], tname[32]
getName(id, aname, charsmax(aname))
get_user_name(target, tname, charsmax(tname))
client_print(0, print_chat, "[CSB] %s unfroze %s.", aname, tname)
log_amx("[CSB Freeze] %s unfroze %s", aname, tname)
return PLUGIN_HANDLED
}
getName(id, name[], len)
{
if (id)
get_user_name(id, name, len)
else
copy(name, len, "CONSOLE")
}