/*
* CSB Jetpack
* Copyright (C) 2026 counter-strike-boost.com
*
* A fuel-limited jetpack. Bind a key to +jetpack: while held, the player is
* pushed along their aim direction with a little lift, a thrust light burns at
* their feet and the fuel bar drains. Standing on the ground refills the fuel.
* Access can be restricted to a flag so it becomes a VIP perk.
*
* Inspired by VEN's classic Jetpack plugin for AMX Mod X. This is an
* independent GPL re-implementation; no original code is reused.
*
* 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
#include
new const PLUGIN[] = "CSB Jetpack"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define SVC_TEMPENTITY 23
#define TE_DLIGHT 27
#define TASK_THINK 5500
new g_pEnabled, g_pPower, g_pLift, g_pDrain, g_pRegen, g_pAccess, g_pSound
new bool:g_bThrust[33]
new Float:g_fFuel[33]
new g_szSound[64]
new g_iSyncHud
public plugin_precache()
{
g_pSound = register_cvar("csb_jet_sound", "")
get_pcvar_string(g_pSound, g_szSound, charsmax(g_szSound))
if (g_szSound[0])
precache_sound(g_szSound)
}
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_jet_enabled", "1")
g_pPower = register_cvar("csb_jet_power", "320") // forward speed
g_pLift = register_cvar("csb_jet_lift", "170.0") // upward push
g_pDrain = register_cvar("csb_jet_drain", "1.5") // fuel per tick
g_pRegen = register_cvar("csb_jet_regen", "2.0") // fuel per tick on ground
g_pAccess = register_cvar("csb_jet_flag", "") // required admin flag(s), empty = everyone
register_clcmd("+jetpack", "cmdThrustOn")
register_clcmd("-jetpack", "cmdThrustOff")
g_iSyncHud = CreateHudSyncObj()
set_task(0.1, "taskThink", TASK_THINK, _, _, "b")
}
public client_putinserver(id)
{
g_bThrust[id] = false
g_fFuel[id] = 100.0
}
public client_disconnected(id)
{
g_bThrust[id] = false
}
bool:hasAccess(id)
{
new flags[8]
get_pcvar_string(g_pAccess, flags, charsmax(flags))
if (!flags[0])
return true
return (get_user_flags(id) & read_flags(flags)) ? true : false
}
public cmdThrustOn(id)
{
if (!get_pcvar_num(g_pEnabled))
return PLUGIN_HANDLED
if (!hasAccess(id))
{
client_print(id, print_chat, "[CSB] The jetpack is reserved for VIP players.")
return PLUGIN_HANDLED
}
g_bThrust[id] = true
return PLUGIN_HANDLED
}
public cmdThrustOff(id)
{
g_bThrust[id] = false
return PLUGIN_HANDLED
}
public taskThink()
{
new Float:power = float(get_pcvar_num(g_pPower))
new Float:lift = get_pcvar_float(g_pLift)
new Float:drain = get_pcvar_float(g_pDrain)
new Float:regen = get_pcvar_float(g_pRegen)
new players[32], num, pid, origin[3]
get_players(players, num, "a")
for (new i = 0; i < num; i++)
{
pid = players[i]
new bool:onGround = (pev(pid, pev_flags) & FL_ONGROUND) ? true : false
if (g_bThrust[pid] && g_fFuel[pid] > 0.0 && get_pcvar_num(g_pEnabled))
{
new Float:aim[3]
velocity_by_aim(pid, floatround(power), aim)
new Float:vel[3]
pev(pid, pev_velocity, vel)
vel[0] = aim[0]
vel[1] = aim[1]
vel[2] = aim[2] + lift
set_pev(pid, pev_velocity, vel)
g_fFuel[pid] -= drain
if (g_fFuel[pid] < 0.0)
g_fFuel[pid] = 0.0
/* thrust light at the feet */
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] - 20)
write_byte(6)
write_byte(255)
write_byte(random_num(120, 200))
write_byte(0)
write_byte(2)
write_byte(4)
message_end()
if (g_szSound[0])
emit_sound(pid, CHAN_STATIC, g_szSound, 0.4, ATTN_NORM, 0, PITCH_NORM)
}
else if (onGround && g_fFuel[pid] < 100.0)
{
g_fFuel[pid] += regen
if (g_fFuel[pid] > 100.0)
g_fFuel[pid] = 100.0
}
showFuel(pid)
}
}
showFuel(id)
{
/* only bother while flying or when the tank is not full */
if (!g_bThrust[id] && g_fFuel[id] >= 100.0)
return
new pct = floatround(g_fFuel[id])
new bar[11], filled = pct / 10
for (new i = 0; i < 10; i++)
bar[i] = (i < filled) ? '|' : '.'
bar[10] = 0
set_hudmessage(0, 180, 255, 0.02, 0.85, 0, 0.0, 0.3, 0.0, 0.0, -1)
ShowSyncHudMsg(id, g_iSyncHud, "Jetpack [%s] %d%%", bar, pct)
}