/*
* CSB Zombie Core
* Copyright (C) 2026 counter-strike-boost.com
*
* A Zombie Plague style infection core. After a short countdown a random
* player is turned into the first zombie: knife only, scaled health, speed and
* gravity, and a zombie model. Zombies are Terrorists, humans are Counter-
* Terrorists, so the round ends naturally when one side is wiped out. Knifing
* a human converts them. Other plugins hook in through the exposed natives
* (csb_is_zombie, csb_infect, csb_make_human).
*
* Inspired by Zombie Plague by MeRcyLeZZ. 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 Zombie Core"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define TASK_RELEASE 4321
new g_pEnabled, g_pReleaseDelay, g_pZombieHp, g_pZombieSpeed, g_pZombieGravity, g_pModel
new bool:g_bZombie[33]
new bool:g_bRoundActive
new g_iMaxPlayers
new Forward:g_fwInfected
public plugin_precache()
{
// Zombie model must be installed as models/player/zombie_source/*.
// Nothing to precache for the player model itself here.
}
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_zm_enabled", "1")
g_pReleaseDelay = register_cvar("csb_zm_release_delay", "15.0")
g_pZombieHp = register_cvar("csb_zm_zombie_hp", "1500")
g_pZombieSpeed = register_cvar("csb_zm_zombie_speed", "270")
g_pZombieGravity = register_cvar("csb_zm_zombie_gravity", "0.80")
g_pModel = register_cvar("csb_zm_model", "zombie_source")
RegisterHam(Ham_Spawn, "player", "fwSpawnPost", 1)
RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage", 0)
register_event("HLTV", "evNewRound", "a", "1=0", "2=0")
g_iMaxPlayers = get_maxplayers()
// csb_zombie_infected(id, infector) -- infector is 0 for the first zombie
g_fwInfected = CreateMultiForward("csb_zombie_infected", ET_IGNORE, FP_CELL, FP_CELL)
set_task(1.0, "taskHud", _, _, _, "b")
}
public plugin_natives()
{
register_native("csb_is_zombie", "native_is_zombie", 1)
register_native("csb_infect", "native_infect", 1)
register_native("csb_make_human", "native_make_human", 1)
}
public native_is_zombie(plugin, params)
{
new id = get_param(1)
if (id < 1 || id > g_iMaxPlayers)
return 0
return g_bZombie[id] ? 1 : 0
}
public native_infect(plugin, params)
{
new id = get_param(1)
if (!is_user_alive(id))
return 0
makeZombie(id, 0)
return 1
}
public native_make_human(plugin, params)
{
new id = get_param(1)
if (!is_user_connected(id))
return 0
makeHuman(id)
return 1
}
public client_disconnected(id)
{
g_bZombie[id] = false
}
public evNewRound()
{
if (!get_pcvar_num(g_pEnabled))
return
g_bRoundActive = false
remove_task(TASK_RELEASE)
// Everyone starts human this round.
for (new id = 1; id <= g_iMaxPlayers; id++)
{
if (!is_user_connected(id))
continue
g_bZombie[id] = false
}
set_task(get_pcvar_float(g_pReleaseDelay), "taskFirstZombie", TASK_RELEASE)
client_print(0, print_chat, "[Zombie] The infection begins in %d seconds. Run!", get_pcvar_num(g_pReleaseDelay))
}
public taskFirstZombie()
{
new candidates[32], num = 0
for (new id = 1; id <= g_iMaxPlayers; id++)
{
if (is_user_alive(id))
candidates[num++] = id
}
if (num < 2)
{
client_print(0, print_chat, "[Zombie] Not enough players to start the infection.")
return
}
g_bRoundActive = true
new pick = candidates[random_num(0, num - 1)]
makeZombie(pick, 0)
new name[32]
get_user_name(pick, name, charsmax(name))
client_print(0, print_chat, "[Zombie] %s is the first zombie!", name)
}
public fwSpawnPost(id)
{
if (!get_pcvar_num(g_pEnabled) || !is_user_alive(id))
return
// Freshly spawned players are human until infected.
makeHuman(id)
}
public fwTakeDamage(victim, inflictor, attacker, Float:damage, damagebits)
{
if (!get_pcvar_num(g_pEnabled) || !g_bRoundActive)
return HAM_IGNORED
if (attacker < 1 || attacker > g_iMaxPlayers || attacker == victim)
return HAM_IGNORED
// Only a zombie's knife infects, and only a living human can be infected.
if (!g_bZombie[attacker] || g_bZombie[victim] || !is_user_alive(victim))
return HAM_IGNORED
makeZombie(victim, attacker)
return HAM_SUPERCEDE // absorb the hit; infection replaces the damage
}
makeZombie(id, infector)
{
g_bZombie[id] = true
if (cs_get_user_team(id) != CS_TEAM_T)
cs_set_user_team(id, CS_TEAM_T)
strip_user_weapons(id)
give_item(id, "weapon_knife")
set_user_health(id, get_pcvar_num(g_pZombieHp))
set_user_gravity(id, get_pcvar_float(g_pZombieGravity))
set_user_maxspeed(id, get_pcvar_float(g_pZombieSpeed))
set_user_rendering(id, kRenderFxNone, 60, 120, 60, kRenderNormal, 20)
new model[32]
get_pcvar_string(g_pModel, model, charsmax(model))
if (model[0])
cs_set_user_model(id, model)
new ret
ExecuteForward(g_fwInfected, ret, id, infector)
checkRoundBalance()
}
makeHuman(id)
{
g_bZombie[id] = false
if (is_user_alive(id) && cs_get_user_team(id) != CS_TEAM_CT)
cs_set_user_team(id, CS_TEAM_CT)
set_user_gravity(id, 1.0)
set_user_maxspeed(id, 240.0)
set_user_rendering(id, kRenderFxNone, 0, 0, 0, kRenderNormal, 16)
cs_reset_user_model(id)
if (is_user_alive(id))
{
give_item(id, "weapon_knife")
give_item(id, "weapon_usp")
cs_set_user_bpammo(id, CSW_USP, 24)
}
}
checkRoundBalance()
{
new zombies, humans
for (new id = 1; id <= g_iMaxPlayers; id++)
{
if (!is_user_alive(id))
continue
if (g_bZombie[id]) zombies++
else humans++
}
if (zombies == 0 && humans > 0)
client_print(0, print_chat, "[Zombie] Humans have survived the outbreak!")
else if (humans == 0 && zombies > 0)
client_print(0, print_chat, "[Zombie] The zombies have consumed everyone!")
}
public taskHud()
{
if (!get_pcvar_num(g_pEnabled))
return
new zombies, humans
for (new id = 1; id <= g_iMaxPlayers; id++)
{
if (!is_user_alive(id))
continue
if (g_bZombie[id]) zombies++
else humans++
}
set_hudmessage(60, 200, 60, 0.02, 0.90, 0, 0.0, 1.1, 0.0, 0.0, -1)
show_hudmessage(0, "Zombies: %d Humans: %d", zombies, humans)
}