/*
* CSB Admin HP & Armor
* Copyright (C) 2026 counter-strike-boost.com
*
* amx_hp and amx_armor set (or add, with a leading +) health/armour on a target,
* clamped by cvars. amx_hpmenu opens a player list and a preset-amount menu. Every
* change is announced to admins and written to the AMXX log.
*
* 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
#include
new const PLUGIN[] = "CSB Admin HP & Armor"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new const g_iPresets[] = { 25, 50, 100, 150, 200, 255 }
new g_pMaxHp, g_pMaxArmor
new g_iMenuTarget[33] /* userid stored while the amount menu is open */
new bool:g_bMenuArmor[33] /* false = HP menu, true = armour menu */
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pMaxHp = register_cvar("csb_hp_max", "1000")
g_pMaxArmor = register_cvar("csb_armor_max", "255")
register_concmd("amx_hp", "cmdHp", ADMIN_LEVEL_A, " <[+]amount> - set or add health")
register_concmd("amx_armor", "cmdArmor", ADMIN_LEVEL_A, " <[+]amount> - set or add armour")
register_concmd("amx_hpmenu", "cmdMenu", ADMIN_LEVEL_A, "- open the HP/armour menu")
}
applyValue(id, target, bool:armor, const arg[])
{
new bool:add = (arg[0] == '+')
new offset = add ? 1 : 0
new amount = str_to_num(arg[offset])
new cur = armor ? get_user_armor(target) : get_user_health(target)
new value = add ? cur + amount : amount
new maxVal = armor ? get_pcvar_num(g_pMaxArmor) : get_pcvar_num(g_pMaxHp)
if (value < 1)
value = 1
if (value > maxVal)
value = maxVal
if (armor)
set_user_armor(target, value)
else
set_user_health(target, value)
new aname[32], tname[32]
getName(id, aname, charsmax(aname))
get_user_name(target, tname, charsmax(tname))
announceAdmins("^x04[CSB]^x03 %s^x01 set^x04 %s^x01 %s to^x03 %d^x01.",
aname, tname, armor ? "armour" : "HP", value)
log_amx("[CSB HP/Armor] %s set %s %s to %d", aname, tname, armor ? "armor" : "hp", value)
}
public cmdHp(id, level, cid)
{
return genericSetCmd(id, level, cid, false)
}
public cmdArmor(id, level, cid)
{
return genericSetCmd(id, level, cid, true)
}
genericSetCmd(id, level, cid, bool:armor)
{
if (!cmd_access(id, level, cid, 3))
return PLUGIN_HANDLED
new arg[32]
read_argv(1, arg, charsmax(arg))
new target = cmd_target(id, arg, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF)
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 amt[16]
read_argv(2, amt, charsmax(amt))
applyValue(id, target, armor, amt)
return PLUGIN_HANDLED
}
public cmdMenu(id, level, cid)
{
if (!cmd_access(id, level, cid, 1))
return PLUGIN_HANDLED
showPlayerMenu(id)
return PLUGIN_HANDLED
}
showPlayerMenu(id)
{
new menu = menu_create("\yCSB HP/Armor\w^nPick a player", "menuPlayer")
new players[32], num, pid, name[32], info[8]
get_players(players, num, "h") /* skip HLTV */
for (new i = 0; i < num; i++)
{
pid = players[i]
get_user_name(pid, name, charsmax(name))
num_to_str(get_user_userid(pid), info, charsmax(info))
menu_additem(menu, name, info, 0)
}
menu_display(id, menu, 0)
}
public menuPlayer(id, menu, item)
{
if (item == MENU_EXIT || item < 0)
{
menu_destroy(menu)
return PLUGIN_HANDLED
}
new info[8], name[32], access, callback
menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
menu_destroy(menu)
g_iMenuTarget[id] = str_to_num(info)
showAmountMenu(id)
return PLUGIN_HANDLED
}
showAmountMenu(id)
{
new target = find_player("k", g_iMenuTarget[id])
if (!target)
{
client_print(id, print_chat, "[CSB] That player has left.")
return
}
new title[64], tname[32]
get_user_name(target, tname, charsmax(tname))
formatex(title, charsmax(title), "\yTarget: %s^n\wChoose amount", tname)
new menu = menu_create(title, "menuAmount")
new line[32], info[8]
for (new i = 0; i < sizeof(g_iPresets); i++)
{
formatex(line, charsmax(line), "%s: %d", g_bMenuArmor[id] ? "Armour" : "HP", g_iPresets[i])
num_to_str(g_iPresets[i], info, charsmax(info))
menu_additem(menu, line, info, 0)
}
menu_additem(menu, g_bMenuArmor[id] ? "\ySwitch to HP" : "\ySwitch to Armour", "toggle", 0)
menu_display(id, menu, 0)
}
public menuAmount(id, menu, item)
{
if (item == MENU_EXIT || item < 0)
{
menu_destroy(menu)
return PLUGIN_HANDLED
}
new info[8], name[32], access, callback
menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback)
menu_destroy(menu)
if (equal(info, "toggle"))
{
g_bMenuArmor[id] = !g_bMenuArmor[id]
showAmountMenu(id)
return PLUGIN_HANDLED
}
new target = find_player("k", g_iMenuTarget[id])
if (!target || !is_user_alive(target))
{
client_print(id, print_chat, "[CSB] Target is gone or dead.")
return PLUGIN_HANDLED
}
applyValue(id, target, g_bMenuArmor[id], info)
showAmountMenu(id)
return PLUGIN_HANDLED
}
announceAdmins(const fmt[], any:...)
{
new msg[192]
vformat(msg, charsmax(msg), fmt, 2)
new players[32], num, pid, msgid = get_user_msgid("SayText")
get_players(players, num, "ch")
for (new i = 0; i < num; i++)
{
pid = players[i]
if (!(get_user_flags(pid) & ADMIN_LEVEL_A))
continue
message_begin(MSG_ONE, msgid, _, pid)
write_byte(pid)
write_string(msg)
message_end()
}
}
getName(id, name[], len)
{
if (id)
get_user_name(id, name, len)
else
copy(name, len, "CONSOLE")
}