Daemon666 / CSB Admin Grab Публичен

Admins grab a player or entity with +grab, push/pull it with the mouse wheel and throw it on release.

v1.0.0 141 изтегляния GPL-3.0 Последна актуализация Aug 24, 2026
csb_admin_grab.sma v1.0.0 191 реда · 4.7 KB Суров
1 /*
2 * CSB Admin Grab
3 * Copyright (C) 2026 counter-strike-boost.com
4 *
5 * Lets an admin grab a player (or a physics entity) with +grab: while the key is
6 * held the target is pinned in the air at a fixed distance along the admin's aim
7 * direction, updated every frame in PlayerPreThink. invnext / invprev change the
8 * hold distance, and releasing +grab throws the target with velocity along the
9 * aim vector.
10 *
11 * Inspired by Admin Grab by KRoTaL. Independent GPL re-implementation; no
12 * original code is reused.
13 *
14 * This program is free software: you can redistribute it and/or modify it under
15 * the terms of the GNU General Public License as published by the Free Software
16 * Foundation, either version 3 of the License, or (at your option) any later
17 * version. It is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
20 */
21
22 #include <amxmodx>
23 #include <fakemeta>
24
25 new const PLUGIN[] = "CSB Admin Grab"
26 new const VERSION[] = "1.0.0"
27 new const AUTHOR[] = "counter-strike-boost.com"
28
29 #define ACCESS_FLAG ADMIN_BAN
30
31 new g_pEnabled, g_pThrow, g_pMaxDist
32
33 new g_iTarget[33]
34 new Float:g_fDist[33]
35
36 public plugin_init()
37 {
38 register_plugin(PLUGIN, VERSION, AUTHOR)
39
40 g_pEnabled = register_cvar("csb_grab_enabled", "1")
41 g_pThrow = register_cvar("csb_grab_throw", "900")
42 g_pMaxDist = register_cvar("csb_grab_maxdist", "800")
43
44 register_clcmd("+grab", "cmdGrabStart")
45 register_clcmd("-grab", "cmdGrabStop")
46 register_clcmd("invnext", "cmdNext")
47 register_clcmd("invprev", "cmdPrev")
48
49 register_forward(FM_PlayerPreThink, "fwPreThink")
50 }
51
52 public client_putinserver(id)
53 {
54 g_iTarget[id] = 0
55 g_fDist[id] = 120.0
56 }
57
58 public client_disconnected(id)
59 {
60 g_iTarget[id] = 0
61 }
62
63 bool:hasAccess(id)
64 {
65 return (get_user_flags(id) & ACCESS_FLAG) != 0
66 }
67
68 public cmdGrabStart(id)
69 {
70 if (!get_pcvar_num(g_pEnabled) || !hasAccess(id) || !is_user_alive(id))
71 return PLUGIN_HANDLED
72
73 new ent, body
74 get_user_aiming(id, ent, body, 4096)
75
76 if (ent < 1 || !pev_valid(ent))
77 {
78 client_print(id, print_chat, "[CSB] Nothing grabbable in your crosshair.")
79 return PLUGIN_HANDLED
80 }
81
82 /* set the hold distance to the current distance to the target */
83 static Float:fMe[3], Float:fThem[3]
84 pev(id, pev_origin, fMe)
85 pev(ent, pev_origin, fThem)
86
87 g_fDist[id] = vector_distance(fMe, fThem)
88 g_iTarget[id] = ent
89
90 new cap = get_pcvar_num(g_pMaxDist)
91 if (g_fDist[id] > float(cap))
92 g_fDist[id] = float(cap)
93
94 client_print(id, print_chat, "[CSB] Grabbed entity %d. Use mouse wheel to push/pull, release to throw.", ent)
95 return PLUGIN_HANDLED
96 }
97
98 public cmdGrabStop(id)
99 {
100 new ent = g_iTarget[id]
101 g_iTarget[id] = 0
102
103 if (ent < 1 || !pev_valid(ent))
104 return PLUGIN_HANDLED
105
106 /* throw along the admin aim vector */
107 static Float:fAng[3], Float:fFwd[3]
108 pev(id, pev_v_angle, fAng)
109 angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd)
110
111 new Float:speed = get_pcvar_float(g_pThrow)
112
113 static Float:fVel[3]
114 fVel[0] = fFwd[0] * speed
115 fVel[1] = fFwd[1] * speed
116 fVel[2] = fFwd[2] * speed + 100.0
117
118 set_pev(ent, pev_velocity, fVel)
119 return PLUGIN_HANDLED
120 }
121
122 public cmdNext(id)
123 {
124 if (g_iTarget[id] > 0)
125 {
126 g_fDist[id] += 30.0
127
128 new cap = get_pcvar_num(g_pMaxDist)
129 if (g_fDist[id] > float(cap))
130 g_fDist[id] = float(cap)
131
132 return PLUGIN_HANDLED
133 }
134
135 return PLUGIN_CONTINUE
136 }
137
138 public cmdPrev(id)
139 {
140 if (g_iTarget[id] > 0)
141 {
142 g_fDist[id] -= 30.0
143
144 if (g_fDist[id] < 40.0)
145 g_fDist[id] = 40.0
146
147 return PLUGIN_HANDLED
148 }
149
150 return PLUGIN_CONTINUE
151 }
152
153 public fwPreThink(id)
154 {
155 new ent = g_iTarget[id]
156
157 if (ent < 1)
158 return FMRES_IGNORED
159
160 if (!is_user_alive(id) || !pev_valid(ent))
161 {
162 g_iTarget[id] = 0
163 return FMRES_IGNORED
164 }
165
166 static Float:fEye[3], Float:fOfs[3], Float:fAng[3], Float:fFwd[3]
167 pev(id, pev_origin, fEye)
168 pev(id, pev_view_ofs, fOfs)
169 fEye[0] += fOfs[0]
170 fEye[1] += fOfs[1]
171 fEye[2] += fOfs[2]
172
173 pev(id, pev_v_angle, fAng)
174 angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd)
175
176 static Float:fDest[3]
177 fDest[0] = fEye[0] + fFwd[0] * g_fDist[id]
178 fDest[1] = fEye[1] + fFwd[1] * g_fDist[id]
179 fDest[2] = fEye[2] + fFwd[2] * g_fDist[id]
180
181 /* hold it in place: zero velocity and set origin each frame */
182 static Float:fZero[3]
183 fZero[0] = 0.0
184 fZero[1] = 0.0
185 fZero[2] = 0.0
186 set_pev(ent, pev_velocity, fZero)
187
188 engfunc(EngFunc_SetOrigin, ent, fDest)
189 return FMRES_IGNORED
190 }
191