/* * CSB Zombie Knockback * Copyright (C) 2026 counter-strike-boost.com * * Pushes a zombie backwards when it is shot. On Ham_TakeDamage the plugin adds * a velocity vector along the attacker's aim, scaled by the damage, the weapon * and the zombie's speed. This is the core "feel" plugin of any zombie server. * * Inspired by the knockback found in the classic Zombie Plague mod. This is an * independent GPL re-implementation; no original code is reused. It has no hard * dependency on a specific zombie mod: a zombie is simply any player on the team * chosen by csb_kb_zombie_team. * * 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. See for details. */ #include #include #include new const PLUGIN[] = "CSB Zombie Knockback" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_pEnabled, g_pPower, g_pZombieTeam, g_pAirMul, g_pMaxSpeed /* per-weapon multipliers, indexed by CSW_* id (0..30) */ new Float:g_fWeaponMul[31] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_kb_enabled", "1") g_pPower = register_cvar("csb_kb_power", "6.0") g_pZombieTeam = register_cvar("csb_kb_zombie_team", "1") /* 1 = T, 2 = CT */ g_pAirMul = register_cvar("csb_kb_air_mul", "1.4") g_pMaxSpeed = register_cvar("csb_kb_max_speed", "1200.0") RegisterHam(Ham_TakeDamage, "player", "fwTakeDamage") setupWeaponMultipliers() } setupWeaponMultipliers() { /* default 1.0 for everything, then tune the ones that feel wrong */ for (new i = 0; i < sizeof(g_fWeaponMul); i++) g_fWeaponMul[i] = 1.0 g_fWeaponMul[CSW_KNIFE] = 4.0 g_fWeaponMul[CSW_AWP] = 2.0 g_fWeaponMul[CSW_SCOUT] = 1.8 g_fWeaponMul[CSW_M3] = 0.6 g_fWeaponMul[CSW_XM1014] = 0.5 g_fWeaponMul[CSW_DEAGLE] = 1.6 g_fWeaponMul[CSW_M249] = 0.7 } public fwTakeDamage(victim, inflictor, attacker, Float:damage, damagebits) { if (!get_pcvar_num(g_pEnabled)) return HAM_IGNORED if (attacker < 1 || attacker > get_maxplayers() || attacker == victim) return HAM_IGNORED if (!is_user_alive(victim) || !is_user_connected(attacker)) return HAM_IGNORED /* only push players who are on the zombie team */ if (get_user_team(victim) != get_pcvar_num(g_pZombieTeam)) return HAM_IGNORED new weapon = get_user_weapon(attacker) new Float:mul = (weapon >= 0 && weapon < sizeof(g_fWeaponMul)) ? g_fWeaponMul[weapon] : 1.0 /* direction: from attacker's aim, so grenades/knife still shove correctly */ new Float:vAngle[3], Float:vForward[3] pev(attacker, pev_v_angle, vAngle) angle_vector(vAngle, ANGLEVECTOR_FORWARD, vForward) new Float:power = damage * get_pcvar_float(g_pPower) * mul /* zombies get shoved harder in the air, it looks better */ new flags = pev(victim, pev_flags) if (!(flags & FL_ONGROUND)) power *= get_pcvar_float(g_pAirMul) new Float:vel[3] pev(victim, pev_velocity, vel) vel[0] += vForward[0] * power vel[1] += vForward[1] * power vel[2] += vForward[2] * power * 0.35 /* a little lift, not a launch */ /* clamp so a burst does not fling a zombie across the map */ new Float:maxSpeed = get_pcvar_float(g_pMaxSpeed) new Float:speed = vector_length(vel) if (speed > maxSpeed && speed > 0.0) { new Float:scale = maxSpeed / speed vel[0] *= scale vel[1] *= scale vel[2] *= scale } set_pev(victim, pev_velocity, vel) return HAM_IGNORED }