/*
* CSB GunGame
* Copyright (C) 2026 counter-strike-boost.com
*
* Level-based GunGame. Every kill made with your current level weapon bumps
* you up the ladder; the ladder ends on HE grenade and then the knife. First
* player to score a knife kill wins the map. A HUD shows every player's level.
*
* Inspired by GunGame by Avalanche and the many CS 1.6 GunGame ports that
* followed. This is an 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. Distributed WITHOUT ANY WARRANTY. See the GNU General
* Public License for more details: .
*/
#include
#include
#include
#include
new const PLUGIN[] = "CSB GunGame"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
// The weapon ladder, from level 0 up. Knife level is the final level.
new const g_iLadder[] =
{
CSW_GALIL, CSW_FAMAS, CSW_MP5NAVY, CSW_UMP45, CSW_P90,
CSW_M4A1, CSW_AK47, CSW_SG552, CSW_AUG, CSW_M249,
CSW_AWP, CSW_SCOUT, CSW_DEAGLE, CSW_USP, CSW_HEGRENADE, CSW_KNIFE
}
new g_pEnabled, g_pKnifeSteal
new g_iLevel[33]
new g_iMaxLevel
new bool:g_bEnded
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_gg_enabled", "1")
g_pKnifeSteal = register_cvar("csb_gg_knife_steal", "1")
g_iMaxLevel = sizeof(g_iLadder) - 1
RegisterHam(Ham_Killed, "player", "fwPlayerKilled", 1)
RegisterHam(Ham_Spawn, "player", "fwPlayerSpawnPost", 1)
register_clcmd("say /level", "cmdLevel")
set_task(1.0, "taskHud", _, _, _, "b")
}
public client_putinserver(id)
{
g_iLevel[id] = 0
}
public fwPlayerSpawnPost(id)
{
if (!get_pcvar_num(g_pEnabled) || g_bEnded || !is_user_alive(id))
return
if (cs_get_user_team(id) != CS_TEAM_T && cs_get_user_team(id) != CS_TEAM_CT)
return
giveLevelWeapon(id)
}
public fwPlayerKilled(victim, attacker, shouldgib)
{
if (!get_pcvar_num(g_pEnabled) || g_bEnded)
return
if (attacker < 1 || attacker > 32 || attacker == victim || !is_user_connected(attacker))
return
new needed = g_iLadder[g_iLevel[attacker]]
new killWeapon = get_user_weapon(attacker)
// Grenade level can't be verified by the active weapon after the throw,
// so a kill on that level always counts. Everything else must match.
new bool:counts
if (needed == CSW_HEGRENADE)
counts = true
else
counts = (killWeapon == needed)
if (!counts)
return
// Knife-stealing a level back down, classic GunGame humiliation rule.
if (get_pcvar_num(g_pKnifeSteal) && killWeapon == CSW_KNIFE && needed != CSW_KNIFE)
{
if (g_iLevel[victim] > 0)
{
g_iLevel[victim]--
client_print(victim, print_center, "You were knifed! Level down.")
if (is_user_alive(victim))
giveLevelWeapon(victim)
}
}
advanceLevel(attacker)
}
advanceLevel(id)
{
// Winning happens when a player scores the KILL on the final (knife) level.
if (g_iLadder[g_iLevel[id]] == CSW_KNIFE)
{
declareWinner(id)
return
}
g_iLevel[id]++
if (g_iLevel[id] > g_iMaxLevel)
{
declareWinner(id)
return
}
client_print(id, print_center, "Level up! %d / %d", g_iLevel[id] + 1, g_iMaxLevel + 1)
emit_sound(id, CHAN_ITEM, "items/gunpickup2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
if (is_user_alive(id))
giveLevelWeapon(id)
}
declareWinner(id)
{
if (g_bEnded)
return
g_bEnded = true
new name[32]
get_user_name(id, name, charsmax(name))
new msg[128]
formatex(msg, charsmax(msg), "^x04[GunGame]^x03 %s^x01 completed the ladder and won the map!", name)
sendChatAll(msg)
set_hudmessage(0, 200, 0, -1.0, 0.30, 0, 0.0, 6.0, 0.0, 0.0, -1)
show_hudmessage(0, "%s WINS GUNGAME!", name)
set_task(6.0, "taskEndMap")
}
public taskEndMap()
{
new mapname[64]
get_mapname(mapname, charsmax(mapname))
server_cmd("changelevel %s", mapname)
}
giveLevelWeapon(id)
{
new level = g_iLevel[id]
if (level < 0) level = 0
if (level > g_iMaxLevel) level = g_iMaxLevel
new csw = g_iLadder[level]
strip_user_weapons(id)
give_item(id, "weapon_knife")
if (csw == CSW_KNIFE)
return
new wname[32], ammo
weaponInfo(csw, wname, charsmax(wname), ammo)
give_item(id, wname)
if (csw == CSW_HEGRENADE)
return
cs_set_user_bpammo(id, csw, ammo)
}
weaponInfo(csw, wname[], len, &ammo)
{
ammo = 90
switch (csw)
{
case CSW_GALIL: { copy(wname, len, "weapon_galil"); ammo = 90; }
case CSW_FAMAS: { copy(wname, len, "weapon_famas"); ammo = 90; }
case CSW_MP5NAVY: { copy(wname, len, "weapon_mp5navy"); ammo = 120; }
case CSW_UMP45: { copy(wname, len, "weapon_ump45"); ammo = 100; }
case CSW_P90: { copy(wname, len, "weapon_p90"); ammo = 100; }
case CSW_M4A1: { copy(wname, len, "weapon_m4a1"); ammo = 90; }
case CSW_AK47: { copy(wname, len, "weapon_ak47"); ammo = 90; }
case CSW_SG552: { copy(wname, len, "weapon_sg552"); ammo = 90; }
case CSW_AUG: { copy(wname, len, "weapon_aug"); ammo = 90; }
case CSW_M249: { copy(wname, len, "weapon_m249"); ammo = 200; }
case CSW_AWP: { copy(wname, len, "weapon_awp"); ammo = 30; }
case CSW_SCOUT: { copy(wname, len, "weapon_scout"); ammo = 90; }
case CSW_DEAGLE: { copy(wname, len, "weapon_deagle"); ammo = 35; }
case CSW_USP: { copy(wname, len, "weapon_usp"); ammo = 24; }
case CSW_HEGRENADE:{ copy(wname, len, "weapon_hegrenade"); ammo = 1; }
default: { copy(wname, len, "weapon_knife"); ammo = 0; }
}
}
public cmdLevel(id)
{
client_print(id, print_chat, "[GunGame] You are on level %d of %d.", g_iLevel[id] + 1, g_iMaxLevel + 1)
return PLUGIN_HANDLED
}
public taskHud()
{
if (!get_pcvar_num(g_pEnabled) || g_bEnded)
return
new players[32], num
get_players(players, num, "ch")
for (new i = 0; i < num; i++)
{
new id = players[i]
set_hudmessage(0, 160, 255, 0.02, 0.35, 0, 0.0, 1.1, 0.0, 0.0, -1)
show_hudmessage(id, "GunGame Level %d / %d", g_iLevel[id] + 1, g_iMaxLevel + 1)
}
}
sendChatAll(const msg[])
{
new players[32], num, msgid = get_user_msgid("SayText")
get_players(players, num, "ch")
for (new i = 0; i < num; i++)
{
message_begin(MSG_ONE, msgid, _, players[i])
write_byte(players[i])
write_string(msg)
message_end()
}
}