Daemon666 / CSB Base Builder Öffentlich

A build phase where builders grab, carry, rotate and lock map props, followed by a fight phase where the other team must break in.

v1.0.0 178 Downloads GPL-3.0 Zuletzt aktualisiert Aug 23, 2026
csb_base_builder.sma v1.0.0 304 Zeilen · 7.6 KB Rohtext
1 /*
2 * CSB Base Builder
3 * Copyright (C) 2026 counter-strike-boost.com
4 *
5 * Base Builder core. Each round opens with a build phase in which the builder
6 * team can grab, carry, rotate and lock map props: /grab pins whatever brush
7 * prop your crosshair is on in front of you (moved every frame in
8 * PlayerPreThink), /rotate spins it, /lock freezes it in place, /drop releases
9 * it. Each builder is limited to a number of locked props. When the build timer
10 * expires the fight phase starts, every prop is frozen and the attacking team
11 * must break in.
12 *
13 * Inspired by Base Builder (ConnorMcLeod / Kreedz community). Independent GPL
14 * re-implementation.
15 *
16 * This program is free software: you can redistribute it and/or modify it under
17 * the terms of the GNU General Public License as published by the Free Software
18 * Foundation, either version 3 of the License, or (at your option) any later
19 * version. It is distributed in the hope that it will be useful, but WITHOUT
20 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
22 */
23
24 #include <amxmodx>
25 #include <fakemeta>
26
27 new const PLUGIN[] = "CSB Base Builder"
28 new const VERSION[] = "1.0.0"
29 new const AUTHOR[] = "counter-strike-boost.com"
30
31 #define PHASE_BUILD 0
32 #define PHASE_FIGHT 1
33
34 new g_pEnabled, g_pBuildTime, g_pBuilderTeam, g_pPropLimit
35
36 new g_iPhase
37 new g_iGrab[33]
38 new Float:g_fGrabDist[33]
39 new Float:g_fGrabYaw[33]
40 new g_iLockedCount[33]
41 new g_iHudSync
42
43 public plugin_init()
44 {
45 register_plugin(PLUGIN, VERSION, AUTHOR)
46
47 g_pEnabled = register_cvar("csb_bb_enabled", "1")
48 g_pBuildTime = register_cvar("csb_bb_buildtime", "45")
49 g_pBuilderTeam = register_cvar("csb_bb_builderteam", "2") /* 1=T 2=CT */
50 g_pPropLimit = register_cvar("csb_bb_proplimit", "6")
51
52 register_clcmd("say /grab", "cmdGrab")
53 register_clcmd("say /drop", "cmdDrop")
54 register_clcmd("say /rotate", "cmdRotate")
55 register_clcmd("say /lock", "cmdLock")
56
57 register_forward(FM_PlayerPreThink, "fwPreThink")
58 register_logevent("eventRoundStart", 2, "1=Round_Start")
59
60 g_iHudSync = CreateHudSyncObj()
61
62 set_task(1.0, "taskHud", 0, _, _, "b")
63 }
64
65 public client_putinserver(id)
66 {
67 g_iGrab[id] = 0
68 g_iLockedCount[id] = 0
69 }
70
71 public client_disconnected(id)
72 {
73 g_iGrab[id] = 0
74 }
75
76 public eventRoundStart()
77 {
78 if (!get_pcvar_num(g_pEnabled))
79 return
80
81 g_iPhase = PHASE_BUILD
82
83 for (new id = 1; id <= 32; id++)
84 {
85 g_iGrab[id] = 0
86 g_iLockedCount[id] = 0
87 }
88
89 client_print(0, print_chat, "[CSB] BUILD PHASE - %d seconds. Builders: /grab /rotate /lock /drop", get_pcvar_num(g_pBuildTime))
90
91 set_task(float(get_pcvar_num(g_pBuildTime)), "taskFightPhase", 9911)
92 }
93
94 public taskFightPhase()
95 {
96 g_iPhase = PHASE_FIGHT
97
98 /* drop and freeze everything */
99 for (new id = 1; id <= 32; id++)
100 {
101 if (g_iGrab[id] > 0)
102 {
103 freezeProp(g_iGrab[id])
104 g_iGrab[id] = 0
105 }
106 }
107
108 client_print(0, print_chat, "[CSB] FIGHT PHASE - break into the base!")
109 }
110
111 bool:isBuilder(id)
112 {
113 return get_user_team(id) == get_pcvar_num(g_pBuilderTeam)
114 }
115
116 bool:isGrabbable(ent)
117 {
118 if (ent <= 32 || !pev_valid(ent))
119 return false
120
121 static cls[32]
122 pev(ent, pev_classname, cls, charsmax(cls))
123
124 if (equal(cls, "worldspawn") || equal(cls, "player"))
125 return false
126
127 /* brush props and pushables only */
128 if (equal(cls, "func_pushable") || equal(cls, "func_breakable")
129 || equal(cls, "func_wall") || equal(cls, "func_door")
130 || containi(cls, "func_") == 0)
131 return true
132
133 return false
134 }
135
136 public cmdGrab(id)
137 {
138 if (!get_pcvar_num(g_pEnabled) || g_iPhase != PHASE_BUILD)
139 {
140 client_print(id, print_chat, "[CSB] You can only build during the build phase.")
141 return PLUGIN_HANDLED
142 }
143
144 if (!isBuilder(id) || !is_user_alive(id))
145 return PLUGIN_HANDLED
146
147 if (g_iGrab[id] > 0)
148 {
149 client_print(id, print_chat, "[CSB] You are already carrying a prop. /drop or /lock first.")
150 return PLUGIN_HANDLED
151 }
152
153 new ent, body
154 get_user_aiming(id, ent, body, 700)
155
156 if (!isGrabbable(ent))
157 {
158 client_print(id, print_chat, "[CSB] No movable prop in your crosshair.")
159 return PLUGIN_HANDLED
160 }
161
162 static Float:fMe[3], Float:fProp[3]
163 pev(id, pev_origin, fMe)
164 pev(ent, pev_origin, fProp)
165
166 g_iGrab[id] = ent
167 g_fGrabDist[id] = vector_distance(fMe, fProp)
168
169 if (g_fGrabDist[id] > 200.0)
170 g_fGrabDist[id] = 200.0
171 else if (g_fGrabDist[id] < 80.0)
172 g_fGrabDist[id] = 80.0
173
174 static Float:fAng[3]
175 pev(ent, pev_angles, fAng)
176 g_fGrabYaw[id] = fAng[1]
177
178 /* make it float freely while carried */
179 set_pev(ent, pev_movetype, MOVETYPE_NOCLIP)
180
181 client_print(id, print_chat, "[CSB] Prop grabbed. /rotate to spin, /lock to place.")
182 return PLUGIN_HANDLED
183 }
184
185 public cmdDrop(id)
186 {
187 if (g_iGrab[id] > 0)
188 {
189 set_pev(g_iGrab[id], pev_movetype, MOVETYPE_TOSS)
190 g_iGrab[id] = 0
191 client_print(id, print_chat, "[CSB] Prop dropped.")
192 }
193
194 return PLUGIN_HANDLED
195 }
196
197 public cmdRotate(id)
198 {
199 if (g_iGrab[id] > 0)
200 {
201 g_fGrabYaw[id] += 45.0
202
203 if (g_fGrabYaw[id] >= 360.0)
204 g_fGrabYaw[id] -= 360.0
205
206 client_print(id, print_chat, "[CSB] Rotated to %d degrees.", floatround(g_fGrabYaw[id]))
207 }
208
209 return PLUGIN_HANDLED
210 }
211
212 public cmdLock(id)
213 {
214 if (g_iGrab[id] <= 0)
215 return PLUGIN_HANDLED
216
217 if (g_iLockedCount[id] >= get_pcvar_num(g_pPropLimit))
218 {
219 client_print(id, print_chat, "[CSB] You reached your prop limit (%d).", get_pcvar_num(g_pPropLimit))
220 return PLUGIN_HANDLED
221 }
222
223 new ent = g_iGrab[id]
224 freezeProp(ent)
225 set_pev(ent, pev_owner, id)
226
227 g_iGrab[id] = 0
228 g_iLockedCount[id]++
229
230 client_print(id, print_chat, "[CSB] Prop locked in place (%d/%d).", g_iLockedCount[id], get_pcvar_num(g_pPropLimit))
231 return PLUGIN_HANDLED
232 }
233
234 freezeProp(ent)
235 {
236 if (!pev_valid(ent))
237 return
238
239 static Float:fZero[3]
240 set_pev(ent, pev_velocity, fZero)
241 set_pev(ent, pev_movetype, MOVETYPE_PUSHSTEP)
242 }
243
244 public fwPreThink(id)
245 {
246 new ent = g_iGrab[id]
247
248 if (ent <= 0)
249 return
250
251 if (!is_user_alive(id) || !pev_valid(ent))
252 {
253 g_iGrab[id] = 0
254 return
255 }
256
257 static Float:fEye[3], Float:fOfs[3], Float:fAng[3], Float:fFwd[3], Float:fDest[3]
258 pev(id, pev_origin, fEye)
259 pev(id, pev_view_ofs, fOfs)
260 fEye[0] += fOfs[0]
261 fEye[1] += fOfs[1]
262 fEye[2] += fOfs[2]
263
264 pev(id, pev_v_angle, fAng)
265 angle_vector(fAng, ANGLEVECTOR_FORWARD, fFwd)
266
267 fDest[0] = fEye[0] + fFwd[0] * g_fGrabDist[id]
268 fDest[1] = fEye[1] + fFwd[1] * g_fGrabDist[id]
269 fDest[2] = fEye[2] + fFwd[2] * g_fGrabDist[id]
270
271 static Float:fZero[3]
272 set_pev(ent, pev_velocity, fZero)
273 engfunc(EngFunc_SetOrigin, ent, fDest)
274
275 static Float:fSet[3]
276 fSet[0] = 0.0
277 fSet[1] = g_fGrabYaw[id]
278 fSet[2] = 0.0
279 set_pev(ent, pev_angles, fSet)
280 }
281
282 public taskHud()
283 {
284 if (!get_pcvar_num(g_pEnabled))
285 return
286
287 new players[32], num
288 get_players(players, num, "ch")
289
290 for (new i = 0; i < num; i++)
291 {
292 new id = players[i]
293
294 set_hudmessage(255, 180, 0, 0.02, 0.12, 0, 0.0, 1.1, 0.0, 0.0, -1)
295
296 if (g_iPhase == PHASE_BUILD && isBuilder(id))
297 ShowSyncHudMsg(id, g_iHudSync, "BUILD PHASE | props %d/%d", g_iLockedCount[id], get_pcvar_num(g_pPropLimit))
298 else if (g_iPhase == PHASE_BUILD)
299 ShowSyncHudMsg(id, g_iHudSync, "BUILD PHASE | wait for the fight")
300 else
301 ShowSyncHudMsg(id, g_iHudSync, "FIGHT PHASE")
302 }
303 }
304