/*
* CSB Bad Spawn Fixer
* Copyright (C) 2026 counter-strike-boost.com
*
* Prevents spawning inside another player. On spawn the plugin runs a human-hull
* trace at the spawn origin; if it is solid (a body is already there) it nudges
* the player up and then outward in a ring of directions until a free spot is
* found, avoiding the classic deathmatch spawn-stuck and telefrag problem.
*
* 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 Bad Spawn Fixer"
new const VERSION[] = "1.0.0"
new const AUTHOR[] = "counter-strike-boost.com"
#define HULL_HUMAN 1
new g_pEnabled
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_pEnabled = register_cvar("csb_badspawn_enabled", "1")
RegisterHam(Ham_Spawn, "player", "fwSpawnPost", 1)
}
public fwSpawnPost(id)
{
if (!get_pcvar_num(g_pEnabled) || !is_user_alive(id))
return
static Float:origin[3]
pev(id, pev_origin, origin)
if (!isStuck(id, origin))
return
static Float:test[3]
/* first try lifting straight up in small steps */
for (new z = 8; z <= 40; z += 8)
{
test[0] = origin[0]
test[1] = origin[1]
test[2] = origin[2] + float(z)
if (!isStuck(id, test))
{
moveTo(id, test)
return
}
}
/* then a ring of directions at growing radius */
new const dirs = 8
for (new r = 32; r <= 96; r += 32)
{
for (new d = 0; d < dirs; d++)
{
new Float:ang = float(d) * (360.0 / float(dirs))
new Float:rad = ang * 3.14159265 / 180.0
test[0] = origin[0] + floatcos(rad, radian) * float(r)
test[1] = origin[1] + floatsin(rad, radian) * float(r)
test[2] = origin[2] + 16.0
if (!isStuck(id, test))
{
moveTo(id, test)
return
}
}
}
}
bool:isStuck(id, const Float:pos[3])
{
engfunc(EngFunc_TraceHull, pos, pos, 0, HULL_HUMAN, id, 0)
new startsolid = get_tr2(0, TR_StartSolid)
new allsolid = get_tr2(0, TR_AllSolid)
return (startsolid != 0 || allsolid != 0)
}
moveTo(id, const Float:pos[3])
{
engfunc(EngFunc_SetOrigin, id, pos)
static Float:zero[3]
zero[0] = 0.0
zero[1] = 0.0
zero[2] = 0.0
set_pev(id, pev_velocity, zero)
}