/*
* CSB Hot Potato Bomb
* Copyright (C) 2026 counter-strike-boost.com
*
* The bomb becomes a hot potato. At round start a random player is handed the
* potato and a countdown starts; whoever is holding it when the timer expires
* explodes. Touching another living player passes the potato to them (a Ham_Touch
* check), a glow shell marks the current carrier, and a HUD shows the countdown
* to everyone.
*
* 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 Hot Potato Bomb"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
new g_pEnabled, g_pTime
new g_iCarrier
new Float:g_fExplodeAt
new Float:g_fLastPass
new g_iHudSync
new g_iExplSpr
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_potato_enabled", "1")
g_pTime = register_cvar("csb_potato_time", "30")
RegisterHam(Ham_Touch, "player", "fwTouch")
register_logevent("eventRoundStart", 2, "1=Round_Start")
register_event("DeathMsg", "eventDeath", "a", "1>0")
g_iHudSync = CreateHudSyncObj()
set_task(0.3, "taskTick", 0, _, _, "b")
}
public plugin_precache()
{
g_iExplSpr = precache_model("sprites/zerogxplode.spr")
}
public client_disconnected(id)
{
if (g_iCarrier == id)
g_iCarrier = 0
}
public eventRoundStart()
{
g_iCarrier = 0
if (!get_pcvar_num(g_pEnabled))
return
set_task(3.0, "taskAssign", 5566)
}
public taskAssign()
{
new players[32], num
get_players(players, num, "a")
if (num == 0)
return
new pick = players[random_num(0, num - 1)]
giveCarrier(pick)
g_fExplodeAt = get_gametime() + get_pcvar_float(g_pTime)
client_print(0, print_chat, "^x04[Potato]^x01 The hot potato is armed! Pass it before it blows!")
}
giveCarrier(id)
{
/* clear old carrier glow */
if (g_iCarrier && is_user_connected(g_iCarrier))
set_user_rendering(g_iCarrier, kRenderFxNone, 0, 0, 0, kRenderNormal, 0)
g_iCarrier = id
g_fLastPass = get_gametime()
if (is_user_alive(id))
set_user_rendering(id, kRenderFxGlowShell, 255, 60, 0, kRenderNormal, 160)
}
public fwTouch(ent, other)
{
if (!g_iCarrier || ent != g_iCarrier)
return HAM_IGNORED
if (other < 1 || other > 32 || !is_user_alive(other) || other == ent)
return HAM_IGNORED
/* small debounce so it does not bounce back instantly */
if (get_gametime() - g_fLastPass < 0.7)
return HAM_IGNORED
giveCarrier(other)
client_print(other, print_chat, "^x04[Potato]^x01 You caught the hot potato! Pass it, fast!")
return HAM_IGNORED
}
public taskTick()
{
if (!g_iCarrier)
return
if (!is_user_alive(g_iCarrier))
{
g_iCarrier = 0
return
}
new Float:left = g_fExplodeAt - get_gametime()
if (left <= 0.0)
{
blowUp(g_iCarrier)
g_iCarrier = 0
return
}
set_hudmessage(255, 100, 0, -1.0, 0.25, 0, 0.0, 0.4, 0.0, 0.0, -1)
ShowSyncHudMsg(0, g_iHudSync, "HOT POTATO: %d", floatround(left, floatround_ceil))
}
blowUp(id)
{
new origin[3]
get_user_origin(id, origin)
message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
write_byte(TE_EXPLOSION)
write_coord(origin[0])
write_coord(origin[1])
write_coord(origin[2])
write_short(g_iExplSpr)
write_byte(30)
write_byte(15)
write_byte(0)
message_end()
set_user_rendering(id, kRenderFxNone, 0, 0, 0, kRenderNormal, 0)
new name[32]
get_user_name(id, name, charsmax(name))
client_print(0, print_chat, "^x04[Potato]^x01 %s was holding the potato and exploded!", name)
user_kill(id)
}
public eventDeath()
{
new victim = read_data(2)
if (victim == g_iCarrier)
g_iCarrier = 0
}