/* * CSB Admin Grab * Copyright (C) 2026 counter-strike-boost.com * * Lets an admin grab a player (or a physics entity) with +grab: while the key is * held the target is pinned in the air at a fixed distance along the admin's aim * direction, updated every frame in PlayerPreThink. invnext / invprev change the * hold distance, and releasing +grab throws the target with velocity along the * aim vector. * * Inspired by Admin Grab by KRoTaL. 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 new const PLUGIN[] = "CSB Admin Grab" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" #define ACCESS_FLAG ADMIN_BAN new g_pEnabled, g_pThrow, g_pMaxDist new g_iTarget[33] new Float:g_fDist[33] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) g_pEnabled = register_cvar("csb_grab_enabled", "1") g_pThrow = register_cvar("csb_grab_throw", "900") g_pMaxDist = register_cvar("csb_grab_maxdist", "800") register_clcmd("+grab", "cmdGrabStart") register_clcmd("-grab", "cmdGrabStop") register_clcmd("invnext", "cmdNext") register_clcmd("invprev", "cmdPrev") register_forward(FM_PlayerPreThink, "fwPreThink") } public client_putinserver(id) { g_iTarget[id] = 0 g_fDist[id] = 120.0 } public client_disconnected(id) { g_iTarget[id] = 0 } bool:hasAccess(id) { return (get_user_flags(id) & ACCESS_FLAG) != 0 } public cmdGrabStart(id) { if (!get_pcvar_num(g_pEnabled) || !hasAccess(id) || !is_user_alive(id)) return PLUGIN_HANDLED new ent, body get_user_aiming(id, ent, body, 4096) if (ent < 1 || !pev_valid(ent)) { client_print(id, print_chat, "[CSB] Nothing grabbable in your crosshair.") return PLUGIN_HANDLED } /* set the hold distance to the current distance to the target */ static Float:fMe[3], Float:fThem[3] pev(id, pev_origin, fMe) pev(ent, pev_origin, fThem) g_fDist[id] = vector_distance(fMe, fThem) g_iTarget[id] = ent new cap = get_pcvar_num(g_pMaxDist) if (g_fDist[id] > float(cap)) g_fDist[id] = float(cap) client_print(id, print_chat, "[CSB] Grabbed entity %d. Use mouse wheel to push/pull, release to throw.", ent) return PLUGIN_HANDLED } public cmdGrabStop(id) { new ent = g_iTarget[id] g_iTarget[id] = 0 if (ent < 1 || !pev_valid(ent)) return PLUGIN_HANDLED /* throw along the admin aim vector */ static Float:fAng[3], Float:fFwd[3] pev(id, pev_v_angle, fAng) angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd) new Float:speed = get_pcvar_float(g_pThrow) static Float:fVel[3] fVel[0] = fFwd[0] * speed fVel[1] = fFwd[1] * speed fVel[2] = fFwd[2] * speed + 100.0 set_pev(ent, pev_velocity, fVel) return PLUGIN_HANDLED } public cmdNext(id) { if (g_iTarget[id] > 0) { g_fDist[id] += 30.0 new cap = get_pcvar_num(g_pMaxDist) if (g_fDist[id] > float(cap)) g_fDist[id] = float(cap) return PLUGIN_HANDLED } return PLUGIN_CONTINUE } public cmdPrev(id) { if (g_iTarget[id] > 0) { g_fDist[id] -= 30.0 if (g_fDist[id] < 40.0) g_fDist[id] = 40.0 return PLUGIN_HANDLED } return PLUGIN_CONTINUE } public fwPreThink(id) { new ent = g_iTarget[id] if (ent < 1) return FMRES_IGNORED if (!is_user_alive(id) || !pev_valid(ent)) { g_iTarget[id] = 0 return FMRES_IGNORED } static Float:fEye[3], Float:fOfs[3], Float:fAng[3], Float:fFwd[3] pev(id, pev_origin, fEye) pev(id, pev_view_ofs, fOfs) fEye[0] += fOfs[0] fEye[1] += fOfs[1] fEye[2] += fOfs[2] pev(id, pev_v_angle, fAng) angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd) static Float:fDest[3] fDest[0] = fEye[0] + fFwd[0] * g_fDist[id] fDest[1] = fEye[1] + fFwd[1] * g_fDist[id] fDest[2] = fEye[2] + fFwd[2] * g_fDist[id] /* hold it in place: zero velocity and set origin each frame */ static Float:fZero[3] fZero[0] = 0.0 fZero[1] = 0.0 fZero[2] = 0.0 set_pev(ent, pev_velocity, fZero) engfunc(EngFunc_SetOrigin, ent, fDest) return FMRES_IGNORED }