[Half-Life AMXX] / blockmaker_v3.51.sma Repository:
ViewVC logotype

Annotation of /blockmaker_v3.51.sma

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (view) (download)

1 : ian 1 #include <amxmodx>
2 :     #include <amxmisc>
3 :     #include <engine>
4 :     #include <fun>
5 :     #include <cstrike>
6 :    
7 :     #pragma semicolon 1;
8 :    
9 :     #define PLUGIN "Block Maker"
10 :     #define VERSION "3.51"
11 :     #define AUTHOR "Necro"
12 :     #define MAIN_MENU_KEYS (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)
13 :     #define BLOCKSELECTION_MENU_KEYS (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)
14 :     #define OPTIONS_MENU_KEYS (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)
15 :     #define TELEPORT_MENU_KEYS (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<5)|(1<<6)|(1<<7)|(1<<9)
16 :     #define CHOICE_MENU_KEYS (1<<0)|(1<<1)|(1<<9)
17 :     #define BM_ADMIN_LEVEL ADMIN_MENU //admin access level to use this plugin. ADMIN_MENU = flag 'u'
18 :    
19 :     const Float:gfSnapDistance = 10.0; //blocks snap together when they're within this value + the players snap gap
20 :    
21 :     /* enum for menu option values */
22 :     enum
23 :     {
24 :     N1, N2, N3, N4, N5, N6, N7, N8, N9, N0
25 :     };
26 :    
27 :     /* enum for options with YES/NO confirmation */
28 :     enum
29 :     {
30 :     CHOICE_LOAD,
31 :     CHOICE_DEL_BLOCKS,
32 :     CHOICE_DEL_TELEPORTS
33 :     };
34 :    
35 :     /* hud message values */
36 :     const gHudRed = 10;
37 :     const gHudGreen = 30;
38 :     const gHudBlue = 200;
39 :     const Float:gfTextX = -1.0;
40 :     const Float:gfTextY = 0.84;
41 :     const gHudEffects = 0;
42 :     const Float:gfHudFxTime = 0.0;
43 :     const Float:gfHudHoldTime = 0.25;
44 :     const Float:gfHudFadeInTime = 0.0;
45 :     const Float:gfHudFadeOutTime = 0.0;
46 :     const gHudChannel = 2;
47 :    
48 :     /* Task ID offsets */
49 :     const TASK_GRAB = 1000;
50 :     const TASK_BHOPSOLID = 2000;
51 :     const TASK_BHOPSOLIDNOT = 3000;
52 :     const TASK_INVINCIBLE = 4000;
53 :     const TASK_STEALTH = 5000;
54 :     const TASK_ICE = 6000;
55 :     const TASK_SPRITE = 7000;
56 :     const TASK_CAMOUFLAGE = 8000;
57 :     const TASK_HONEY = 9000;
58 :     const TASK_FIRE = 10000;
59 :     const TASK_BOOTSOFSPEED = 11000;
60 :     const TASK_TELEPORT = 12000;
61 :    
62 :     /* Strings */
63 :     new const gszPrefix[] = "[BM] ";
64 :     new const gszInfoTarget[] = "info_target";
65 :     new const gszHelpFilenameFormat[] = "blockmaker_v%s.txt";
66 :     new gszFile[128];
67 :     new gszNewFile[128];
68 :     new gszMenu[256];
69 :     new gszOptionsMenu[256];
70 :     new gszTeleportMenu[256];
71 :     new gszChoiceMenu[128];
72 :     new gszHelpTitle[64];
73 :     new gszHelpText[1600];
74 :     new gszHelpFilename[32];
75 :     new gszViewModel[33][32];
76 :    
77 :     /* Block dimensions */
78 :     new Float:gfBlockSizeMinForX[3] = {-4.0,-32.0,-32.0};
79 :     new Float:gfBlockSizeMaxForX[3] = { 4.0, 32.0, 32.0};
80 :     new Float:gfBlockSizeMinForY[3] = {-32.0,-4.0,-32.0};
81 :     new Float:gfBlockSizeMaxForY[3] = { 32.0, 4.0, 32.0};
82 :     new Float:gfBlockSizeMinForZ[3] = {-32.0,-32.0,-4.0};
83 :     new Float:gfBlockSizeMaxForZ[3] = { 32.0, 32.0, 4.0};
84 :     new Float:gfDefaultBlockAngles[3] = { 0.0, 0.0, 0.0 };
85 :    
86 :     /* Block models */
87 :     new const gszBlockModelDefault[] = "models/blockmaker/bm_block_default.mdl";
88 :     new const gszBlockModelPlatform[] = "models/blockmaker/bm_block_platform.mdl";
89 :     new const gszBlockModelBhop[] = "models/blockmaker/bm_block_bhop.mdl";
90 :     new const gszBlockModelDamage[] = "models/blockmaker/bm_block_damage.mdl";
91 :     new const gszBlockModelHealer[] = "models/blockmaker/bm_block_healer.mdl";
92 :     new const gszBlockModelInvincibility[] = "models/blockmaker/bm_block_invincibility.mdl";
93 :     new const gszBlockModelSpeedBoost[] = "models/blockmaker/bm_block_speedboost.mdl";
94 :     new const gszBlockModelNoFallDamage[] = "models/blockmaker/bm_block_nofalldamage.mdl";
95 :     new const gszBlockModelIce[] = "models/blockmaker/bm_block_ice.mdl";
96 :     new const gszBlockModelDeath[] = "models/blockmaker/bm_block_death.mdl";
97 :     new const gszBlockModelNuke[] = "models/blockmaker/bm_block_nuke.mdl";
98 :     new const gszBlockModelCamouflage[] = "models/blockmaker/bm_block_camouflage.mdl";
99 :     new const gszBlockModelLowGravity[] = "models/blockmaker/bm_block_lowgravity.mdl";
100 :     new const gszBlockModelFire[] = "models/blockmaker/bm_block_fire.mdl";
101 :     new const gszBlockModelRandom[] = "models/blockmaker/bm_block_random.mdl";
102 :     new const gszBlockModelSlap[] = "models/blockmaker/bm_block_slap.mdl";
103 :     new const gszBlockModelHoney[] = "models/blockmaker/bm_block_honey.mdl";
104 :     new const gszBlockModelBarrierCT[] = "models/blockmaker/bm_block_barrier_ct.mdl";
105 :     new const gszBlockModelBarrierT[] = "models/blockmaker/bm_block_barrier_t.mdl";
106 :     new const gszBlockModelBootsOfSpeed[] = "models/blockmaker/bm_block_bootsofspeed.mdl";
107 :    
108 :     /* Block sprites */
109 :     new const gszBlockSpriteFire[] = "sprites/blockmaker/bm_block_fire.spr"; //custom
110 :     new const gszBlockSpriteTrampoline[] = "sprites/blockmaker/bm_block_trampoline.spr"; //custom
111 :     new const gszBlockSpriteSpeedBoost[] = "sprites/blockmaker/bm_block_speedboost.spr"; //custom
112 :     new const gszFireSprite[] = "sprites/blockmaker/bm_block_fire_flame.spr"; //custom
113 :    
114 :     /* Block sounds */
115 :     new const gszNukeExplosion[] = "weapons/c4_explode1.wav"; //from CS
116 :     new const gszFireSoundFlame[] = "ambience/flameburst1.wav"; //from HL
117 :     new const gszInvincibleSound[] = "warcraft3/divineshield.wav"; //from WC3 plugin
118 :     new const gszCamouflageSound[] = "warcraft3/antend.wav"; //from WC3 plugin
119 :     new const gszStealthSound[] = "warcraft3/levelupcaster.wav"; //from WC3 plugin
120 :     new const gszBootsOfSpeedSound[] = "warcraft3/purgetarget1.wav"; //from WC3 plugin
121 :    
122 :     /* Teleport */
123 :     new const Float:gfTeleportSizeMin[3] = {-16.0,-16.0,-16.0};
124 :     new const Float:gfTeleportSizeMax[3] = { 16.0, 16.0, 16.0};
125 :     new const Float:gfTeleportZOffset = 36.0;
126 :     new const gTeleportStartFrames = 20;
127 :     new const gTeleportEndFrames = 5;
128 :     new const gszTeleportSound[] = "warcraft3/blinkarrival.wav"; //from WC3 plugin
129 :     new const gszTeleportSpriteStart[] = "sprites/flare6.spr"; //from HL
130 :     new const gszTeleportSpriteEnd[] = "sprites/blockmaker/bm_teleport_end.spr"; //custom
131 :    
132 :     /* Variables */
133 :     new gSpriteIdBeam;
134 :     new gSpriteIdFire;
135 :     new gMsgScreenFade;
136 :     new gMenuBeforeOptions[33];
137 :     new gChoiceOption[33];
138 :     new gBlockMenuPage[33];
139 :     new gTeleportStart[33];
140 :     new gGrabbed[33];
141 :     new gGroupedBlocks[33][256];
142 :     new gGroupCount[33];
143 :     new bool:gbSnapping[33];
144 :     new bool:gbNoFallDamage[33];
145 :     new bool:gbOnIce[33];
146 :     new bool:gbLowGravity[33];
147 :     new bool:gbOnFire[33];
148 :     new bool:gbJustDeleted[33];
149 :     new bool:gbAdminGodmode[33];
150 :     new bool:gbAdminNoclip[33];
151 :     new Float:gfSnappingGap[33];
152 :     new Float:gfOldMaxSpeed[33];
153 :     new Float:gfGrabOffset[33][3];
154 :     new Float:gfGrablength[33];
155 :     new Float:gfNextHealTime[33];
156 :     new Float:gfNextDamageTime[33];
157 :     new Float:gfInvincibleNextUse[33];
158 :     new Float:gfInvincibleTimeOut[33];
159 :     new Float:gfStealthNextUse[33];
160 :     new Float:gfStealthTimeOut[33];
161 :     new Float:gfTrampolineTimeout[33];
162 :     new Float:gfSpeedBoostTimeOut[33];
163 :     new Float:gfNukeNextUse[33];
164 :     new Float:gfCamouflageNextUse[33];
165 :     new Float:gfCamouflageTimeOut[33];
166 :     new Float:gfRandomNextUse[33];
167 :     new Float:gfBootsOfSpeedTimeOut[33];
168 :     new Float:gfBootsOfSpeedNextUse[33];
169 :     new gszCamouflageOldModel[33][32];
170 :    
171 :     /* BLOCK & TELEPORT TYPES */
172 :     const gBlockMax = 21;
173 :     new gSelectedBlockType[gBlockMax];
174 :    
175 :     new const gszBlockClassname[] = "bm_block";
176 :     new const gszSpriteClassname[] = "bm_sprite";
177 :     new const gszTeleportStartClassname[32] = "bm_teleportstart";
178 :     new const gszTeleportEndClassname[32] = "bm_teleportend";
179 :    
180 :     enum
181 :     {
182 :     TELEPORT_START,
183 :     TELEPORT_END
184 :     };
185 :    
186 :     enum
187 :     {
188 :     BM_PLATFORM, //A
189 :     BM_BHOP, //B
190 :     BM_DAMAGE, //C
191 :     BM_HEALER, //D
192 :     BM_NOFALLDAMAGE, //I
193 :     BM_ICE, //J
194 :     BM_TRAMPOLINE, //G
195 :     BM_SPEEDBOOST, //H
196 :     BM_INVINCIBILITY, //E
197 :     BM_STEALTH, //F
198 :     BM_DEATH, //K
199 :     BM_NUKE, //L
200 :     BM_CAMOUFLAGE, //M
201 :     BM_LOWGRAVITY, //N
202 :     BM_FIRE, //O
203 :     BM_SLAP, //P
204 :     BM_RANDOM, //Q
205 :     BM_HONEY, //R
206 :     BM_BARRIER_CT, //S
207 :     BM_BARRIER_T, //T
208 :     BM_BOOTSOFSPEED //U
209 :     };
210 :    
211 :     new const gszBlockNames[gBlockMax][32] =
212 :     {
213 :     "Platform",
214 :     "Bunnyhop",
215 :     "Damage",
216 :     "Healer",
217 :     "No Fall Damage",
218 :     "Ice",
219 :     "Trampoline",
220 :     "Speed Boost",
221 :     "Invincibility",
222 :     "Stealth",
223 :     "Death",
224 :     "Nuke",
225 :     "Camouflage",
226 :     "Low Gravity",
227 :     "Fire",
228 :     "Slap",
229 :     "Random",
230 :     "Honey",
231 :     "CT Barrier",
232 :     "T Barrier",
233 :     "Boots Of Speed"
234 :     };
235 :    
236 :     new const gBlockSaveIds[gBlockMax] =
237 :     {
238 :     'A', 'B', 'C', 'D', 'I', 'J', 'G', 'H', 'E', 'F', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U'
239 :     };
240 :    
241 :     //array of blocks that the random block can be
242 :     const gRandomBlocksMax = 6;
243 :    
244 :     new const gRandomBlocks[gRandomBlocksMax] =
245 :     {
246 :     BM_INVINCIBILITY,
247 :     BM_STEALTH,
248 :     BM_DEATH,
249 :     BM_CAMOUFLAGE,
250 :     BM_SLAP,
251 :     BM_BOOTSOFSPEED
252 :     };
253 :    
254 :     //max speed for player when they have the boots of speed
255 :     const Float:gfBootsMaxSpeed = 400.0;
256 :    
257 :     //how many pages for the block selection menu
258 :     new gBlockMenuPagesMax;
259 :    
260 :     /***** PLUGIN START *****/
261 :     public plugin_init()
262 :     {
263 :     register_plugin(PLUGIN, VERSION, AUTHOR);
264 :    
265 :     //register client commands
266 :     register_clcmd("say /bm", "cmdShowMainMenu");
267 :     register_clcmd("+bmgrab", "cmdGrab", BM_ADMIN_LEVEL, "bind a key to +bmgrab");
268 :     register_clcmd("-bmgrab", "cmdRelease", BM_ADMIN_LEVEL);
269 :    
270 :     //register menus
271 :     register_menucmd(register_menuid("bmMainMenu"), MAIN_MENU_KEYS, "handleMainMenu");
272 :     register_menucmd(register_menuid("bmBlockSelectionMenu"), BLOCKSELECTION_MENU_KEYS, "handleBlockSelectionMenu");
273 :     register_menucmd(register_menuid("bmOptionsMenu"), OPTIONS_MENU_KEYS, "handleOptionsMenu");
274 :     register_menucmd(register_menuid("bmTeleportMenu"), TELEPORT_MENU_KEYS, "handleTeleportMenu");
275 :     register_menucmd(register_menuid("bmChoiceMenu"), CHOICE_MENU_KEYS, "handleChoiceMenu");
276 :    
277 :     //register CVARs
278 :     register_cvar("bm_telefrags", "1"); //players near teleport exit die if someone comes through
279 :     register_cvar("bm_firedamageamount", "20.0"); //damage you take per half-second on the fire block
280 :     register_cvar("bm_damageamount", "5.0"); //damage you take per half-second on the damage block
281 :     register_cvar("bm_healamount", "1.0"); //how much hp per half-second you get on the healing block
282 :     register_cvar("bm_invincibletime", "20.0"); //how long a player is invincible
283 :     register_cvar("bm_invinciblecooldown", "60.0"); //time before the invincible block can be used again
284 :     register_cvar("bm_stealthtime", "20.0"); //how long a player is in stealth
285 :     register_cvar("bm_stealthcooldown", "60.0"); //time before the stealth block can be used again
286 :     register_cvar("bm_camouflagetime", "20.0"); //how long a player is in camouflage
287 :     register_cvar("bm_camouflagecooldown", "60.0"); //time before the camouflage block can be used again
288 :     register_cvar("bm_nukecooldown", "60.0"); //someone might have been invincible when it was used
289 :     register_cvar("bm_randomcooldown", "30.0"); //time before the random block can be used again
290 :     register_cvar("bm_bootsofspeedtime", "20.0"); //how long the player has boots of speed
291 :     register_cvar("bm_bootsofspeedcooldown", "60.0"); //time before boots of speed can be used again
292 :    
293 :     //register events
294 :     register_event("DeathMsg", "eventPlayerDeath", "a");
295 :     register_event("TextMsg", "eventRoundRestart", "a", "2&#Game_C", "2&#Game_w");
296 :     register_event("ResetHUD", "eventPlayerSpawn", "b");
297 :     register_event("CurWeapon", "eventCurWeapon", "be");
298 :    
299 :     //make config folder if it doesn't already exist
300 :     new szConfigsDir[64];
301 :     new szMap[32];
302 :     get_configsdir(szConfigsDir, 64);
303 :     add(szConfigsDir, 64, "/blockmaker");
304 :    
305 :     if (!dir_exists(szConfigsDir))
306 :     {
307 :     mkdir(szConfigsDir);
308 :     }
309 :    
310 :     get_mapname(szMap, 32);
311 :     formatex(gszFile, 96, "%s/%s.cfg", szConfigsDir, szMap);
312 :    
313 :     //make save folder in basedir (new saving/loading method)
314 :     new szDir[64];
315 :     get_basedir(szDir, 64);
316 :     add(szDir, 64, "/blockmaker");
317 :    
318 :     if (!dir_exists(szDir))
319 :     {
320 :     mkdir(szDir);
321 :     }
322 :    
323 :     get_mapname(szMap, 32);
324 :     formatex(gszNewFile, 96, "%s/%s.bm", szDir, szMap);
325 :     }
326 :    
327 :     public plugin_precache()
328 :     {
329 :     //precache blocks
330 :     precache_model(gszBlockModelDefault);
331 :     precache_model(gszBlockModelDamage);
332 :     precache_model(gszBlockModelIce);
333 :     precache_model(gszBlockModelInvincibility);
334 :     precache_model(gszBlockModelSpeedBoost);
335 :     precache_model(gszBlockModelBhop);
336 :     precache_model(gszBlockModelHealer);
337 :     precache_model(gszBlockModelPlatform);
338 :     precache_model(gszBlockModelNoFallDamage);
339 :     precache_model(gszBlockModelDeath);
340 :     precache_model(gszBlockModelNuke);
341 :     precache_model(gszBlockModelCamouflage);
342 :     precache_model(gszBlockModelLowGravity);
343 :     precache_model(gszBlockModelFire);
344 :     precache_model(gszBlockModelSlap);
345 :     precache_model(gszBlockModelRandom);
346 :     precache_model(gszBlockModelHoney);
347 :     precache_model(gszBlockModelBarrierCT);
348 :     precache_model(gszBlockModelBarrierT);
349 :     precache_model(gszBlockModelBootsOfSpeed);
350 :    
351 :     //precache sprites
352 :     precache_model(gszBlockSpriteFire);
353 :     precache_model(gszBlockSpriteTrampoline);
354 :     precache_model(gszBlockSpriteSpeedBoost);
355 :     precache_model(gszTeleportSpriteStart);
356 :     precache_model(gszTeleportSpriteEnd);
357 :     gSpriteIdFire = precache_model(gszFireSprite);
358 :     gSpriteIdBeam = precache_model("sprites/zbeam4.spr");
359 :    
360 :     //precache sounds
361 :     precache_sound(gszTeleportSound);
362 :     precache_sound(gszNukeExplosion);
363 :     precache_sound(gszInvincibleSound);
364 :     precache_sound(gszCamouflageSound);
365 :     precache_sound(gszStealthSound);
366 :     precache_sound(gszFireSoundFlame);
367 :     precache_sound(gszBootsOfSpeedSound);
368 :     }
369 :    
370 :     public plugin_cfg()
371 :     {
372 :     //format help text filename
373 :     format(gszHelpFilename, 32, gszHelpFilenameFormat, VERSION);
374 :    
375 :     //create main menu
376 :     new size = sizeof(gszMenu);
377 :     add(gszMenu, size, "\yBlock Maker Menu^n^n");
378 :     add(gszMenu, size, "\r1. \wBlock Type: \y%s^n");
379 :     add(gszMenu, size, "\r2. %sCreate Block^n");
380 :     add(gszMenu, size, "\r3. %sConvert Block^n");
381 :     add(gszMenu, size, "\r4. %sDelete Block^n");
382 :     add(gszMenu, size, "\r5. %sRotate Block^n^n");
383 :     add(gszMenu, size, "\r6. %sNoclip: %s^n");
384 :     add(gszMenu, size, "\r7. %sGodmode: %s^n^n");
385 :     add(gszMenu, size, "\r8. \wOptions Menu^n");
386 :     add(gszMenu, size, "\r9. \wTeleport menu^n^n");
387 :     add(gszMenu, size, "\r0. \wClose");
388 :    
389 :     //calculate maximum number of block menu pages from maximum amount of blocks
390 :     gBlockMenuPagesMax = floatround((float(gBlockMax) / 8.0), floatround_ceil);
391 :    
392 :     //create the options menu
393 :     size = sizeof(gszOptionsMenu);
394 :     add(gszOptionsMenu, size, "\yOptions Menu^n^n");
395 :     add(gszOptionsMenu, size, "\r1. %sSnapping: %s^n");
396 :     add(gszOptionsMenu, size, "\r2. %sSnapping gap: \y%.1f^n");
397 :     add(gszOptionsMenu, size, "\r3. %sAdd to group^n");
398 :     add(gszOptionsMenu, size, "\r4. %sClear group^n^n");
399 :     add(gszOptionsMenu, size, "\r5. %sDelete all blocks^n");
400 :     add(gszOptionsMenu, size, "\r6. %sDelete all teleports^n^n");
401 :     add(gszOptionsMenu, size, "\r7. %sSave to file^n");
402 :     add(gszOptionsMenu, size, "\r8. %sLoad from file^n^n");
403 :     add(gszOptionsMenu, size, "\r9. \wShow help^n");
404 :     add(gszOptionsMenu, size, "\r0. \wBack");
405 :    
406 :     //create teleport menu
407 :     size = sizeof(gszTeleportMenu);
408 :     add(gszTeleportMenu, size, "\yTeleporter Menu^n^n");
409 :     add(gszTeleportMenu, size, "\r1. %sTeleport Start^n");
410 :     add(gszTeleportMenu, size, "\r2. %sTeleport Destination^n");
411 :     add(gszTeleportMenu, size, "\r3. %sShow Teleport Path^n");
412 :     add(gszTeleportMenu, size, "\r4. %sDelete Teleport^n^n^n");
413 :     add(gszTeleportMenu, size, "\r6. %sNoclip: %s^n");
414 :     add(gszTeleportMenu, size, "\r7. %sGodmode: %s^n^n");
415 :     add(gszTeleportMenu, size, "\r8. \wOptions Menu^n^n^n");
416 :     add(gszTeleportMenu, size, "\r0. \wBack");
417 :    
418 :     //create choice (YES/NO) menu
419 :     size = sizeof(gszChoiceMenu);
420 :     add(gszChoiceMenu, size, "\y%s^n^n");
421 :     add(gszChoiceMenu, size, "\r1. \wYes^n");
422 :     add(gszChoiceMenu, size, "\r2. \wNo^n^n^n^n^n^n^n^n^n^n^n");
423 :     add(gszChoiceMenu, size, "\r0. \wBack");
424 :    
425 :     //create help title
426 :     format(gszHelpTitle, sizeof(gszHelpTitle), "%s v%s by %s", PLUGIN, VERSION, AUTHOR);
427 :    
428 :     //read in help text from file
429 :     new szConfigsDir[32];
430 :     new szHelpFilename[64];
431 :     new szLine[128];
432 :     get_configsdir(szConfigsDir, 32);
433 :     format(szHelpFilename, sizeof(szHelpFilename), "%s/%s", szConfigsDir, gszHelpFilename);
434 :    
435 :     //open help file for reading
436 :     new f = fopen(szHelpFilename, "rt");
437 :    
438 :     //iterate through all the lines in the file
439 :     size = sizeof(gszHelpText);
440 :     while (!feof(f))
441 :     {
442 :     fgets(f, szLine, 128);
443 :    
444 :     add(gszHelpText, size, szLine);
445 :     }
446 :    
447 :     //close file
448 :     fclose(f);
449 :    
450 :     //get id for message 'ScreenFade'
451 :     gMsgScreenFade = get_user_msgid("ScreenFade");
452 :    
453 :     //load blocks from file
454 :     loadBlocks(0);
455 :     }
456 :    
457 :     /***** FORWARDS *****/
458 :     public client_connect(id)
459 :     {
460 :     //make sure snapping is on by default
461 :     gbSnapping[id] = true;
462 :    
463 :     //players chosen snapping gap defaults to 0.0 units
464 :     gfSnappingGap[id] = 0.0;
465 :    
466 :     //make sure players can die
467 :     gbNoFallDamage[id] = false;
468 :    
469 :     //players block selection menu is on page 1
470 :     gBlockMenuPage[id] = 1;
471 :    
472 :     //player doesn't have godmode or noclip
473 :     gbAdminGodmode[id] = false;
474 :     gbAdminNoclip[id] = false;
475 :    
476 :     //player doesn't have any block grouped
477 :     gGroupCount[id] = 0;
478 :     }
479 :    
480 :     public client_disconnect(id)
481 :     {
482 :     //clear players group
483 :     groupClear(id);
484 :    
485 :     //if player was grabbing an entity when they disconnected
486 :     if (gGrabbed[id])
487 :     {
488 :     //if entity is valid
489 :     if (is_valid_ent(gGrabbed[id]))
490 :     {
491 :     //set the entity to 'not being grabbed'
492 :     entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
493 :     }
494 :    
495 :     gGrabbed[id] = 0;
496 :     }
497 :     }
498 :    
499 :     public pfn_touch(ent, id)
500 :     {
501 :     //if touch event involves a player
502 :     if (id > 0 && id <= 32)
503 :     {
504 :     //if player is alive
505 :     if (is_user_alive(id))
506 :     {
507 :     //if entity involved is a block
508 :     if (isBlock(ent))
509 :     {
510 :     //get the blocktype
511 :     new blockType = entity_get_int(ent, EV_INT_body);
512 :    
513 :     //if blocktype is a bunnyhop block or barrier
514 :     if (blockType == BM_BHOP || blockType == BM_BARRIER_CT || blockType == BM_BARRIER_T)
515 :     {
516 :     //if task does not already exist for bunnyhop block
517 :     if (!task_exists(TASK_BHOPSOLIDNOT + ent) && !task_exists(TASK_BHOPSOLID + ent))
518 :     {
519 :     //get the players team
520 :     new CsTeams:team = cs_get_user_team(id);
521 :    
522 :     //if players team is different to barrier
523 :     if (blockType == BM_BARRIER_CT && team == CS_TEAM_T)
524 :     {
525 :     //make block SOLID_NOT without any delay
526 :     taskSolidNot(TASK_BHOPSOLIDNOT + ent);
527 :     }
528 :     else if (blockType == BM_BARRIER_T && team == CS_TEAM_CT)
529 :     {
530 :     //make block SOLID_NOT without any delay
531 :     taskSolidNot(TASK_BHOPSOLIDNOT + ent);
532 :     }
533 :     else if (blockType == BM_BHOP)
534 :     {
535 :     //set bhop block to be SOLID_NOT after 0.1 seconds
536 :     set_task(0.1, "taskSolidNot", TASK_BHOPSOLIDNOT + ent);
537 :     }
538 :     }
539 :     }
540 :     }
541 :     }
542 :     }
543 :    
544 :     return PLUGIN_CONTINUE;
545 :     }
546 :    
547 :     public server_frame()
548 :     {
549 :     new ent;
550 :     new Float:vOrigin[3];
551 :     new bool:entNear = false;
552 :     new tele;
553 :    
554 :     //iterate through all players and remove slow down after jumping for any 'on ice'
555 :     for (new i = 1; i <= 32; ++i)
556 :     {
557 :     if (is_user_alive(i) && gbOnIce[i])
558 :     {
559 :     entity_set_float(i, EV_FL_fuser2, 0.0);
560 :     }
561 :     }
562 :    
563 :     //find all teleport start entities in map and if a player is close to one, teleport the player
564 :     while ((ent = find_ent_by_class(ent, gszTeleportStartClassname)))
565 :     {
566 :     new Float:vOrigin[3];
567 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
568 :    
569 :     //teleport players and grenades within a sphere around the teleport start entity
570 :     new entinsphere = -1;
571 :     while ((entinsphere = find_ent_in_sphere(entinsphere, vOrigin, 32.0)))
572 :     {
573 :     //get classname of entity
574 :     new szClassname[32];
575 :     entity_get_string(entinsphere, EV_SZ_classname, szClassname, 32);
576 :    
577 :     //if entity is a player
578 :     if (entinsphere > 0 && entinsphere <= 32)
579 :     {
580 :     //only teleport player if they're alive
581 :     if (is_user_alive(entinsphere))
582 :     {
583 :     //teleport the player
584 :     actionTeleport(entinsphere, ent);
585 :     }
586 :     }
587 :     //or if entity is a grenade
588 :     else if (equal(szClassname, "grenade"))
589 :     {
590 :     //get the end of the teleport
591 :     tele = entity_get_int(ent, EV_INT_iuser1);
592 :    
593 :     //if the end of the teleport exists
594 :     if (tele)
595 :     {
596 :     //set the end of the teleport to be not solid
597 :     entity_set_int(tele, EV_INT_solid, SOLID_NOT); //can't be grabbed or deleted
598 :    
599 :     //teleport the grenade
600 :     actionTeleport(entinsphere, ent);
601 :    
602 :     //set a time in the teleport it will become solid after 2 seconds
603 :     entity_set_float(tele, EV_FL_ltime, halflife_time() + 2.0);
604 :     }
605 :     }
606 :     }
607 :     }
608 :    
609 :     //make teleporters SOLID_NOT when players are near them
610 :     while ((ent = find_ent_by_class(ent, gszTeleportEndClassname)))
611 :     {
612 :     //get the origin of the teleport end entity
613 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
614 :    
615 :     //compare this origin with all player and grenade origins
616 :     new entinsphere = -1;
617 :     while ((entinsphere = find_ent_in_sphere(entinsphere, vOrigin, 64.0)))
618 :     {
619 :     //get classname of entity
620 :     new szClassname[32];
621 :     entity_get_string(entinsphere, EV_SZ_classname, szClassname, 32);
622 :    
623 :     //if entity is a player
624 :     if (entinsphere > 0 && entinsphere <= 32)
625 :     {
626 :     //make sure player is alive
627 :     if (is_user_alive(entinsphere))
628 :     {
629 :     entNear = true;
630 :    
631 :     break;
632 :     }
633 :     }
634 :     //or if entity is a grenade
635 :     else if (equal(szClassname, "grenade"))
636 :     {
637 :     entNear = true;
638 :    
639 :     break;
640 :     }
641 :     }
642 :    
643 :     //set the solid type of the teleport end entity depending on whether or not a player is near
644 :     if (entNear)
645 :     {
646 :     //only do this if it is not being grabbed
647 :     if (entity_get_int(ent, EV_INT_iuser2) == 0)
648 :     {
649 :     entity_set_int(ent, EV_INT_solid, SOLID_NOT); //can't be grabbed or deleted
650 :     }
651 :     }
652 :     else
653 :     {
654 :     //get time from teleport end entity to check if it can go solid
655 :     new Float:fTime = entity_get_float(ent, EV_FL_ltime);
656 :    
657 :     //only set teleport end entity to solid if its 'solid not' time has elapsed
658 :     if (halflife_time() >= fTime)
659 :     {
660 :     entity_set_int(ent, EV_INT_solid, SOLID_BBOX); //CAN be grabbed and deleted
661 :     }
662 :     }
663 :     }
664 :    
665 :     //find all block entities
666 :     while ((ent = find_ent_by_class(ent, gszBlockClassname)))
667 :     {
668 :     //get block type
669 :     new blockType = entity_get_int(ent, EV_INT_body);
670 :    
671 :     //if block is a speed boost
672 :     if (blockType == BM_SPEEDBOOST)
673 :     {
674 :     new Float:vOrigin[3];
675 :     new Float:pOrigin[3];
676 :     new Float:dist = 9999.9;
677 :     new Float:playerDist = 9999.9;
678 :     new nearestPlayer = 0;
679 :    
680 :     //get the origin of the speed boost block
681 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
682 :    
683 :     //compare this origin with all players origins to find the nearest player to the block
684 :     for (new id = 1; id <= 32; ++id)
685 :     {
686 :     //if player is alive
687 :     if (is_user_alive(id))
688 :     {
689 :     //get player origin
690 :     entity_get_vector(id, EV_VEC_origin, pOrigin);
691 :    
692 :     //get the distance from the block to the player
693 :     dist = get_distance_f(vOrigin, pOrigin);
694 :    
695 :     if (dist < playerDist)
696 :     {
697 :     nearestPlayer = id;
698 :     playerDist = dist;
699 :     }
700 :     }
701 :     }
702 :    
703 :     //if we found a player within 100 units of the speed boost block
704 :     if (nearestPlayer > 0 && playerDist < 200.0)
705 :     {
706 :     //get the sprite on top of the speed boost block
707 :     new sprite = entity_get_int(ent, EV_INT_iuser3);
708 :    
709 :     //make sure sprite entity is valid
710 :     if (sprite)
711 :     {
712 :     new Float:vAngles[3];
713 :    
714 :     //get the direction the player is looking
715 :     entity_get_vector(nearestPlayer, EV_VEC_angles, vAngles);
716 :    
717 :     //set the angles of the sprite to be the same as the player
718 :     vAngles[0] = 90.0; //always make sure sprite is flat to the block
719 :     vAngles[1] += 90.0; //rotate the sprite by 90 because it doesnt point up (PAT!)
720 :     entity_set_vector(sprite, EV_VEC_angles, vAngles);
721 :     }
722 :     }
723 :     }
724 :     }
725 :     }
726 :    
727 :     public client_PreThink(id)
728 :     {
729 :     //make sure player is connected
730 :     if (is_user_connected(id))
731 :     {
732 :     //display type of block that player is aiming at
733 :     new ent, body;
734 :     get_user_aiming(id, ent, body, 320);
735 :    
736 :     if (isBlock(ent))
737 :     {
738 :     new blockType = entity_get_int(ent, EV_INT_body);
739 :    
740 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
741 :     show_hudmessage(id, "Block Type: %s", gszBlockNames[blockType]);
742 :     }
743 :    
744 :     //make sure player is alive
745 :     if (is_user_alive(id))
746 :     {
747 :     //if player has low gravity
748 :     if (gbLowGravity[id])
749 :     {
750 :     //get players flags
751 :     new flags = entity_get_int(id, EV_INT_flags);
752 :    
753 :     //if player has feet on the ground, set gravity to normal
754 :     if (flags & FL_ONGROUND)
755 :     {
756 :     set_user_gravity(id);
757 :    
758 :     gbLowGravity[id] = false;
759 :     }
760 :     }
761 :    
762 :     //trace directly down to see if there is a block beneath player
763 :     new Float:pOrigin[3];
764 :     new Float:pSize[3];
765 :     new Float:pMaxs[3];
766 :     new Float:vTrace[3];
767 :     new Float:vReturn[3];
768 :     entity_get_vector(id, EV_VEC_origin, pOrigin);
769 :     entity_get_vector(id, EV_VEC_size, pSize);
770 :     entity_get_vector(id, EV_VEC_maxs, pMaxs);
771 :    
772 :     //calculate position of players feet
773 :     pOrigin[2] = pOrigin[2] - ((pSize[2] - 36.0) - (pMaxs[2] - 36.0));
774 :    
775 :     //make the trace small for some blocks
776 :     vTrace[2] = pOrigin[2] - 1.0;
777 :    
778 :     //do 4 traces for each corner of the player
779 :     for (new i = 0; i < 4; ++i)
780 :     {
781 :     switch (i)
782 :     {
783 :     case 0: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] + 16; }
784 :     case 1: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] + 16; }
785 :     case 2: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] - 16; }
786 :     case 3: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] - 16; }
787 :     }
788 :    
789 :     ent = trace_line(id, pOrigin, vTrace, vReturn);
790 :    
791 :     //if entity found is a block
792 :     if (isBlock(ent))
793 :     {
794 :     new blockType = entity_get_int(ent, EV_INT_body);
795 :    
796 :     switch (blockType)
797 :     {
798 :     case BM_HEALER: actionHeal(id);
799 :     case BM_DAMAGE: actionDamage(id);
800 :     case BM_INVINCIBILITY: actionInvincible(id, false);
801 :     case BM_STEALTH: actionStealth(id, false);
802 :     case BM_TRAMPOLINE: actionTrampoline(id);
803 :     case BM_SPEEDBOOST: actionSpeedBoost(id);
804 :     case BM_DEATH: actionDeath(id);
805 :     case BM_NUKE: actionNuke(id, false);
806 :     case BM_LOWGRAVITY: actionLowGravity(id);
807 :     case BM_CAMOUFLAGE: actionCamouflage(id, false);
808 :     case BM_FIRE: actionFire(id, ent);
809 :     case BM_SLAP: actionSlap(id);
810 :     case BM_RANDOM: actionRandom(id, ent);
811 :     case BM_HONEY: actionHoney(id);
812 :     case BM_BOOTSOFSPEED: actionBootsOfSpeed(id, false);
813 :     }
814 :     }
815 :     }
816 :    
817 :     //make the trace longer for other blocks
818 :     vTrace[2] = pOrigin[2] - 20.0;
819 :    
820 :     //do 4 traces for each corner of the player
821 :     for (new i = 0; i < 4; ++i)
822 :     {
823 :     switch (i)
824 :     {
825 :     case 0: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] + 16; }
826 :     case 1: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] + 16; }
827 :     case 2: { vTrace[0] = pOrigin[0] + 16; vTrace[1] = pOrigin[1] - 16; }
828 :     case 3: { vTrace[0] = pOrigin[0] - 16; vTrace[1] = pOrigin[1] - 16; }
829 :     }
830 :    
831 :     ent = trace_line(id, pOrigin, vTrace, vReturn);
832 :    
833 :     //if entity found is a block
834 :     if (isBlock(ent))
835 :     {
836 :     new blockType = entity_get_int(ent, EV_INT_body);
837 :    
838 :     switch (blockType)
839 :     {
840 :     case BM_TRAMPOLINE: actionTrampoline(id);
841 :     case BM_NOFALLDAMAGE: actionNoFallDamage(id);
842 :     case BM_ICE: actionOnIce(id);
843 :     }
844 :     }
845 :     }
846 :    
847 :     //display amount of invincibility/stealth/camouflage/boots of speed timeleft
848 :     new Float:fTime = halflife_time();
849 :     new Float:fTimeleftInvincible = gfInvincibleTimeOut[id] - fTime;
850 :     new Float:fTimeleftStealth = gfStealthTimeOut[id] - fTime;
851 :     new Float:fTimeleftCamouflage = gfCamouflageTimeOut[id] - fTime;
852 :     new Float:fTimeleftBootsOfSpeed = gfBootsOfSpeedTimeOut[id] - fTime;
853 :     new szTextToShow[256] = "";
854 :     new szText[48];
855 :     new bool:bShowText = false;
856 :    
857 :     if (fTimeleftInvincible >= 0.0)
858 :     {
859 :     format(szText, sizeof(szText), "Invincible: %.1f^n", fTimeleftInvincible);
860 :     add(szTextToShow, sizeof(szTextToShow), szText);
861 :     bShowText = true;
862 :     }
863 :    
864 :     if (fTimeleftStealth >= 0.0)
865 :     {
866 :     format(szText, sizeof(szText), "Stealth: %.1f^n", fTimeleftStealth);
867 :     add(szTextToShow, sizeof(szTextToShow), szText);
868 :     bShowText = true;
869 :     }
870 :    
871 :     if (fTimeleftCamouflage >= 0.0)
872 :     {
873 :     //if player is a CT
874 :     if (get_user_team(id) == 1)
875 :     {
876 :     format(szText, sizeof(szText), "You look like a Counter-Terrorist: %.1f^n", fTimeleftCamouflage);
877 :     }
878 :     else
879 :     {
880 :     format(szText, sizeof(szText), "You look like a Terrorist: %.1f^n", fTimeleftCamouflage);
881 :     }
882 :    
883 :     add(szTextToShow, sizeof(szTextToShow), szText);
884 :     bShowText = true;
885 :     }
886 :    
887 :     if (fTimeleftBootsOfSpeed >= 0.0)
888 :     {
889 :     format(szText, sizeof(szText), "Boots of speed: %.1f^n", fTimeleftBootsOfSpeed);
890 :     add(szTextToShow, sizeof(szTextToShow), szText);
891 :     bShowText = true;
892 :     }
893 :    
894 :     //if there is some text to show then show it
895 :     if (bShowText)
896 :     {
897 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
898 :     show_hudmessage(id, szTextToShow);
899 :     }
900 :     }
901 :    
902 :     //get players buttons
903 :     new buttons = get_user_button(id);
904 :     new oldbuttons = get_user_oldbutton(id);
905 :    
906 :     //if player has grabbed an entity
907 :     if (gGrabbed[id] > 0)
908 :     {
909 :     //check for a single press on the following buttons
910 :     if (buttons & IN_JUMP && !(oldbuttons & IN_JUMP)) cmdJump(id);
911 :     if (buttons & IN_DUCK && !(oldbuttons & IN_DUCK)) cmdDuck(id);
912 :     if (buttons & IN_ATTACK && !(oldbuttons & IN_ATTACK)) cmdAttack(id);
913 :     if (buttons & IN_ATTACK2 && !(oldbuttons & IN_ATTACK2)) cmdAttack2(id);
914 :    
915 :     //prevent player from using attack
916 :     buttons &= ~IN_ATTACK;
917 :     entity_set_int(id, EV_INT_button, buttons);
918 :    
919 :     //if player has grabbed a valid entity
920 :     if (is_valid_ent(gGrabbed[id]))
921 :     {
922 :     //if block the player is grabbing is in their group and group count is larger than 1
923 :     if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
924 :     {
925 :     new Float:vMoveTo[3];
926 :     new Float:vOffset[3];
927 :     new Float:vOrigin[3];
928 :     new block;
929 :    
930 :     //move the block the player has grabbed and get the move vector
931 :     moveGrabbedEntity(id, vMoveTo);
932 :    
933 :     //move the rest of the blocks in the players group using vector for grabbed block
934 :     for (new i = 0; i <= gGroupCount[id]; ++i)
935 :     {
936 :     block = gGroupedBlocks[id][i];
937 :    
938 :     //if block is still in this players group
939 :     if (isBlockInGroup(id, block))
940 :     {
941 :     //get offset vector from block
942 :     entity_get_vector(block, EV_VEC_vuser1, vOffset);
943 :    
944 :     vOrigin[0] = vMoveTo[0] - vOffset[0];
945 :     vOrigin[1] = vMoveTo[1] - vOffset[1];
946 :     vOrigin[2] = vMoveTo[2] - vOffset[2];
947 :    
948 :     //move grouped block
949 :     moveEntity(id, block, vOrigin, false);
950 :     }
951 :     }
952 :     }
953 :     else
954 :     {
955 :     //move the entity the player has grabbed
956 :     moveGrabbedEntity(id);
957 :     }
958 :     }
959 :     else
960 :     {
961 :     cmdRelease(id);
962 :     }
963 :     }
964 :    
965 :     //if player has just deleted something
966 :     if (gbJustDeleted[id])
967 :     {
968 :     //if player is pressing attack2
969 :     if (buttons & IN_ATTACK2)
970 :     {
971 :     //prevent player from using attack2
972 :     buttons &= ~IN_ATTACK2;
973 :     entity_set_int(id, EV_INT_button, buttons);
974 :     }
975 :     else
976 :     {
977 :     //player has now NOT just deleted something
978 :     gbJustDeleted[id] = false;
979 :     }
980 :     }
981 :     }
982 :    
983 :     return PLUGIN_CONTINUE;
984 :     }
985 :    
986 :     public client_PostThink(id)
987 :     {
988 :     //if player is aliev
989 :     if (is_user_alive(id))
990 :     {
991 :     //if player is set no not get fall damage
992 :     if (gbNoFallDamage[id])
993 :     {
994 :     entity_set_int(id, EV_INT_watertype, -3);
995 :     gbNoFallDamage[id] = false;
996 :     }
997 :     }
998 :     }
999 :    
1000 :     /***** EVENTS *****/
1001 :     public eventPlayerDeath()
1002 :     {
1003 :     new id = read_data(2);
1004 :    
1005 :     resetTimers(id);
1006 :     }
1007 :    
1008 :     public eventRoundRestart()
1009 :     {
1010 :     //iterate through all players
1011 :     for (new id = 1; id <= 32; ++id)
1012 :     {
1013 :     //reset all players timers
1014 :     resetTimers(id);
1015 :     }
1016 :     }
1017 :    
1018 :     public eventPlayerSpawn(id)
1019 :     {
1020 :     //if player has godmode enabled
1021 :     if (gbAdminGodmode[id])
1022 :     {
1023 :     //re-enable godmode on player
1024 :     set_user_godmode(id, 1);
1025 :     }
1026 :    
1027 :     //if player has noclip enabled
1028 :     if (gbAdminNoclip[id])
1029 :     {
1030 :     //re-enable noclip on player
1031 :     set_user_noclip(id, 1);
1032 :     }
1033 :     }
1034 :    
1035 :     resetTimers(id)
1036 :     {
1037 :     gfInvincibleTimeOut[id] = 0.0;
1038 :     gfInvincibleNextUse[id] = 0.0;
1039 :     gfStealthTimeOut[id] = 0.0;
1040 :     gfStealthNextUse[id] = 0.0;
1041 :     gfCamouflageTimeOut[id] = 0.0;
1042 :     gfCamouflageNextUse[id] = 0.0;
1043 :     gfNukeNextUse[id] = 0.0;
1044 :     gbOnFire[id] = false;
1045 :     gfRandomNextUse[id] = 0.0;
1046 :     gfBootsOfSpeedTimeOut[id] = 0.0;
1047 :     gfBootsOfSpeedNextUse[id] = 0.0;
1048 :    
1049 :     //remove any task this player might have
1050 :     new taskId = TASK_INVINCIBLE + id;
1051 :     if (task_exists(taskId))
1052 :     {
1053 :     remove_task(taskId);
1054 :     }
1055 :    
1056 :     taskId = TASK_STEALTH + id;
1057 :     if (task_exists(taskId))
1058 :     {
1059 :     remove_task(taskId);
1060 :     }
1061 :    
1062 :     taskId = TASK_CAMOUFLAGE + id;
1063 :     if (task_exists(taskId))
1064 :     {
1065 :     remove_task(taskId);
1066 :    
1067 :     //change back to players old model
1068 :     cs_set_user_model(id, gszCamouflageOldModel[id]);
1069 :     }
1070 :    
1071 :     //make sure player is connected
1072 :     if (is_user_connected(id))
1073 :     {
1074 :     //set players rendering to normal
1075 :     set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 255);
1076 :     }
1077 :     }
1078 :    
1079 :     public eventCurWeapon(id)
1080 :     {
1081 :     new Float:fTime = halflife_time();
1082 :     new Float:fTimeleftBootsOfSpeed = gfBootsOfSpeedTimeOut[id] - fTime;
1083 :    
1084 :     //if the player has the boots of speed
1085 :     if (fTimeleftBootsOfSpeed >= 0.0)
1086 :     {
1087 :     //set their max speed so they obtain their speed after changing weapon
1088 :     set_user_maxspeed(id, gfBootsMaxSpeed);
1089 :     }
1090 :     }
1091 :    
1092 :     /***** BLOCK ACTIONS *****/
1093 :     actionDamage(id)
1094 :     {
1095 :     if (halflife_time() >= gfNextDamageTime[id])
1096 :     {
1097 :     if (get_user_health(id) > 0)
1098 :     {
1099 :     new Float:amount = get_cvar_float("bm_damageamount");
1100 :     fakedamage(id, "damage block", amount, DMG_CRUSH);
1101 :     }
1102 :    
1103 :     gfNextDamageTime[id] = halflife_time() + 0.5;
1104 :     }
1105 :     }
1106 :    
1107 :     actionHeal(id)
1108 :     {
1109 :     if (halflife_time() >= gfNextHealTime[id])
1110 :     {
1111 :     new hp = get_user_health(id);
1112 :     new amount = floatround(get_cvar_float("bm_healamount"), floatround_floor);
1113 :     new sum = (hp + amount);
1114 :    
1115 :     if (sum < 100)
1116 :     {
1117 :     set_user_health(id, sum);
1118 :     }
1119 :     else
1120 :     {
1121 :     set_user_health(id, 100);
1122 :     }
1123 :    
1124 :     gfNextHealTime[id] = halflife_time() + 0.5;
1125 :     }
1126 :     }
1127 :    
1128 :     actionInvincible(id, OverrideTimer)
1129 :     {
1130 :     new Float:fTime = halflife_time();
1131 :    
1132 :     if (fTime >= gfInvincibleNextUse[id] || OverrideTimer)
1133 :     {
1134 :     new Float:fTimeout = get_cvar_float("bm_invincibletime");
1135 :    
1136 :     set_user_godmode(id, 1);
1137 :     set_task(fTimeout, "taskInvincibleRemove", TASK_INVINCIBLE + id, "", 0, "a", 1);
1138 :    
1139 :     //only make player glow white for invincibility if player isn't already stealth
1140 :     if (fTime >= gfStealthTimeOut[id])
1141 :     {
1142 :     set_user_rendering(id, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 16);
1143 :     }
1144 :    
1145 :     //play invincibility sound
1146 :     emit_sound(id, CHAN_STATIC, gszInvincibleSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
1147 :    
1148 :     gfInvincibleTimeOut[id] = fTime + fTimeout;
1149 :     gfInvincibleNextUse[id] = fTime + fTimeout + get_cvar_float("bm_invinciblecooldown");
1150 :     }
1151 :     else
1152 :     {
1153 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1154 :     show_hudmessage(id, "Invincibility next use: %.1f", gfInvincibleNextUse[id] - fTime);
1155 :     }
1156 :     }
1157 :    
1158 :     actionStealth(id, OverrideTimer)
1159 :     {
1160 :     new Float:fTime = halflife_time();
1161 :    
1162 :     //check if player is outside of cooldown time to use stealth
1163 :     if (fTime >= gfStealthNextUse[id] || OverrideTimer)
1164 :     {
1165 :     new Float:fTimeout = get_cvar_float("bm_stealthtime");
1166 :    
1167 :     //set a task to remove stealth after time out amount
1168 :     set_task(fTimeout, "taskStealthRemove", TASK_STEALTH + id, "", 0, "a", 1);
1169 :    
1170 :     //make player invisible
1171 :     set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderTransColor, 0);
1172 :    
1173 :     //play stealth sound
1174 :     emit_sound(id, CHAN_STATIC, gszStealthSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
1175 :    
1176 :     gfStealthTimeOut[id] = fTime + fTimeout;
1177 :     gfStealthNextUse[id] = fTime + fTimeout + get_cvar_float("bm_stealthcooldown");
1178 :     }
1179 :     else
1180 :     {
1181 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1182 :     show_hudmessage(id, "Stealth next use: %.1f", gfStealthNextUse[id] - fTime);
1183 :     }
1184 :     }
1185 :    
1186 :     actionTrampoline(id)
1187 :     {
1188 :     //if trampoline timeout has exceeded (needed to prevent velocity being given multiple times)
1189 :     if (halflife_time() >= gfTrampolineTimeout[id])
1190 :     {
1191 :     new Float:velocity[3];
1192 :    
1193 :     //set player Z velocity to make player bounce
1194 :     entity_get_vector(id, EV_VEC_velocity, velocity);
1195 :     velocity[2] = 500.0; //jump velocity
1196 :     entity_set_vector(id, EV_VEC_velocity, velocity);
1197 :    
1198 :     entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
1199 :    
1200 :     gfTrampolineTimeout[id] = halflife_time() + 0.5;
1201 :     }
1202 :     }
1203 :    
1204 :     actionSpeedBoost(id)
1205 :     {
1206 :     //if speed boost timeout has exceeded (needed to prevent speed boost being given multiple times)
1207 :     if (halflife_time() >= gfSpeedBoostTimeOut[id])
1208 :     {
1209 :     new Float:pAim[3];
1210 :    
1211 :     //set velocity on player in direction they're aiming
1212 :     velocity_by_aim(id, 800, pAim);
1213 :     pAim[2] = 260.0; //make sure Z velocity is only as high as a jump
1214 :     entity_set_vector(id, EV_VEC_velocity, pAim);
1215 :    
1216 :     entity_set_int(id, EV_INT_gaitsequence, 6); //play the Jump Animation
1217 :    
1218 :     gfSpeedBoostTimeOut[id] = halflife_time() + 0.5;
1219 :     }
1220 :     }
1221 :    
1222 :     actionNoFallDamage(id)
1223 :     {
1224 :     //set the player to not receive any fall damage (handled in client_PostThink)
1225 :     gbNoFallDamage[id] = true;
1226 :     }
1227 :    
1228 :     actionOnIce(id)
1229 :     {
1230 :     new taskid = TASK_ICE + id;
1231 :    
1232 :     if (!gbOnIce[id])
1233 :     {
1234 :     //save players maxspeed value
1235 :     gfOldMaxSpeed[id] = get_user_maxspeed(id);
1236 :    
1237 :     //make player feel like they're on ice
1238 :     entity_set_float(id, EV_FL_friction, 0.15);
1239 :     set_user_maxspeed(id, 600.0);
1240 :    
1241 :     //player is now 'on ice'
1242 :     gbOnIce[id] = true;
1243 :     }
1244 :    
1245 :     //remove any existing 'not on ice' task
1246 :     if (task_exists(taskid))
1247 :     {
1248 :     remove_task(taskid);
1249 :     }
1250 :    
1251 :     //set task to remove 'on ice' effect very soon (task replaced if player is still on ice before task time reached)
1252 :     set_task(0.1, "taskNotOnIce", taskid);
1253 :     }
1254 :    
1255 :     actionDeath(id)
1256 :     {
1257 :     //if player does not have godmode enabled (admin godmode or invincibility)
1258 :     if (!get_user_godmode(id))
1259 :     {
1260 :     //kill player by inflicting massive damage
1261 :     fakedamage(id, "the block of death", 10000.0, DMG_GENERIC);
1262 :     }
1263 :     }
1264 :    
1265 :     actionNuke(id, OverrideTimer)
1266 :     {
1267 :     //get game time
1268 :     new Float:fTime = halflife_time();
1269 :    
1270 :     //make sure player is alive
1271 :     if (is_user_alive(id) && (fTime >= gfNukeNextUse[id] || OverrideTimer))
1272 :     {
1273 :     //get players team
1274 :     new CsTeams:playerTeam = cs_get_user_team(id);
1275 :     new CsTeams:team;
1276 :    
1277 :     //iterate through all players
1278 :     for (new i = 1; i <= 32; ++i)
1279 :     {
1280 :     //make sure player is alive
1281 :     if (is_user_alive(i))
1282 :     {
1283 :     team = cs_get_user_team(i);
1284 :    
1285 :     //if this player is on a different team to the player that used the nuke
1286 :     if ((team == CS_TEAM_T && playerTeam == CS_TEAM_CT) || (team == CS_TEAM_CT && playerTeam == CS_TEAM_T))
1287 :     {
1288 :     //slay player
1289 :     fakedamage(i, "a nuke", 10000.0, DMG_BLAST);
1290 :     }
1291 :     }
1292 :    
1293 :     //make sure player is connected
1294 :     if (is_user_connected(i))
1295 :     {
1296 :     //make the screen flash for a nuke effect
1297 :     message_begin(MSG_ONE, gMsgScreenFade, {0, 0, 0}, i);
1298 :     write_short(1024); //duration
1299 :     write_short(1024); //hold time
1300 :     write_short(4096); //type (in / out)
1301 :     write_byte(255); //red
1302 :     write_byte(255); //green
1303 :     write_byte(255); //blue
1304 :     write_byte(255); //alpha
1305 :     message_end();
1306 :     }
1307 :     }
1308 :    
1309 :     //play explosion sound
1310 :     emit_sound(0, CHAN_STATIC, gszNukeExplosion, 1.0, ATTN_NORM, 0, PITCH_NORM);
1311 :    
1312 :     //set the time when the player can use the nuke again (someone might have been invincible)
1313 :     gfNukeNextUse[id] = fTime + get_cvar_float("bm_nukecooldown");
1314 :    
1315 :     //get the name of the player that used the nuke
1316 :     new szPlayerName[32];
1317 :     get_user_name(id, szPlayerName, 32);
1318 :    
1319 :     //setup hud message to show who nuked what team
1320 :     set_hudmessage(255, 255, 0, -1.0, 0.35, 0, 6.0, 10.0, 1.0, 1.0);
1321 :    
1322 :     //show message saying player nuked the other team
1323 :     if (playerTeam == CS_TEAM_T)
1324 :     {
1325 :     show_hudmessage(0, "%s just nuked the Counter-Terrorists", szPlayerName);
1326 :     }
1327 :     else
1328 :     {
1329 :     show_hudmessage(0, "%s just nuked the Terrorists", szPlayerName);
1330 :     }
1331 :     }
1332 :     else
1333 :     {
1334 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1335 :     show_hudmessage(id, "Nuke next use: %.1f", gfNukeNextUse[id] - fTime);
1336 :     }
1337 :     }
1338 :    
1339 :     actionCamouflage(id, OverrideTimer)
1340 :     {
1341 :     new Float:fTime = halflife_time();
1342 :    
1343 :     //check if player is outside of cooldown time to use camouflage
1344 :     if (fTime >= gfCamouflageNextUse[id] || OverrideTimer)
1345 :     {
1346 :     new Float:fTimeout = get_cvar_float("bm_camouflagetime");
1347 :    
1348 :     //get players team and model
1349 :     new szModel[32];
1350 :     new team;
1351 :    
1352 :     cs_get_user_model(id, szModel, 32);
1353 :    
1354 :     team = get_user_team(id);
1355 :    
1356 :     //save current player model
1357 :     gszCamouflageOldModel[id] = szModel;
1358 :    
1359 :     //change player model depending on their current team
1360 :     if (team == 1) //TERRORIST
1361 :     {
1362 :     cs_set_user_model(id, "urban");
1363 :     }
1364 :     else
1365 :     {
1366 :     cs_set_user_model(id, "leet");
1367 :     }
1368 :    
1369 :     //play camouflage sound
1370 :     emit_sound(id, CHAN_STATIC, gszCamouflageSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
1371 :    
1372 :     //set a task to remove camouflage after time out amount
1373 :     set_task(fTimeout, "taskCamouflageRemove", TASK_CAMOUFLAGE + id, "", 0, "a", 1);
1374 :    
1375 :     //set timers to prevent player from using camouflage again so soon
1376 :     gfCamouflageTimeOut[id] = fTime + fTimeout;
1377 :     gfCamouflageNextUse[id] = fTime + fTimeout + get_cvar_float("bm_camouflagecooldown");
1378 :     }
1379 :     else
1380 :     {
1381 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1382 :     show_hudmessage(id, "Camouflage next use: %.1f", gfCamouflageNextUse[id] - fTime);
1383 :     }
1384 :     }
1385 :    
1386 :     actionLowGravity(id)
1387 :     {
1388 :     //set player to have low gravity
1389 :     set_user_gravity(id, 0.25);
1390 :    
1391 :     //set global boolean showing player has low gravity
1392 :     gbLowGravity[id] = true;
1393 :     }
1394 :    
1395 :     actionFire(id, ent)
1396 :     {
1397 :     if (halflife_time() >= gfNextDamageTime[id])
1398 :     {
1399 :     new hp = get_user_health(id);
1400 :    
1401 :     //if players health is greater than 0
1402 :     if (hp > 0)
1403 :     {
1404 :     //if player does not have godmode
1405 :     if (!get_user_godmode(id))
1406 :     {
1407 :     new Float:amount = get_cvar_float("bm_firedamageamount") / 10.0;
1408 :     new Float:newAmount = hp - amount;
1409 :    
1410 :     //if this amount of damage won't kill the player
1411 :     if (newAmount > 0)
1412 :     {
1413 :     set_user_health(id, floatround(newAmount, floatround_floor));
1414 :     }
1415 :     else
1416 :     {
1417 :     //use fakedamage to kill the player
1418 :     fakedamage(id, "fire block", amount, DMG_BURN);
1419 :     }
1420 :     }
1421 :    
1422 :     //get halflife time and time for next fire sound from fire block
1423 :     new Float:fTime = halflife_time();
1424 :     new Float:fNextFireSoundTime = entity_get_float(ent, EV_FL_ltime);
1425 :    
1426 :     //if the current time is greater than or equal to the next time to play the fire sound
1427 :     if (fTime >= fNextFireSoundTime)
1428 :     {
1429 :     //play the fire sound
1430 :     emit_sound(ent, CHAN_ITEM, gszFireSoundFlame, 0.6, ATTN_NORM, 0, PITCH_NORM);
1431 :    
1432 :     //set the fire blocks time
1433 :     entity_set_float(ent, EV_FL_ltime, fTime + 0.75);
1434 :     }
1435 :    
1436 :     //get effects vectors using block origin
1437 :     new Float:origin1[3];
1438 :     new Float:origin2[3];
1439 :     entity_get_vector(ent, EV_VEC_origin, origin1);
1440 :     entity_get_vector(ent, EV_VEC_origin, origin2);
1441 :     origin1[0] -= 32.0;
1442 :     origin1[1] -= 32.0;
1443 :     origin1[2] += 10.0;
1444 :     origin2[0] += 32.0;
1445 :     origin2[1] += 32.0;
1446 :     origin2[2] += 10.0;
1447 :    
1448 :     //get a random height for the flame
1449 :     new randHeight = random_num(0, 32) + 16;
1450 :    
1451 :     //show some effects
1452 :     message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
1453 :     write_byte(TE_BUBBLES);
1454 :     write_coord(floatround(origin1[0], floatround_floor)); //min start position
1455 :     write_coord(floatround(origin1[1], floatround_floor));
1456 :     write_coord(floatround(origin1[2], floatround_floor));
1457 :     write_coord(floatround(origin2[0], floatround_floor)); //max start position
1458 :     write_coord(floatround(origin2[1], floatround_floor));
1459 :     write_coord(floatround(origin2[2], floatround_floor));
1460 :     write_coord(randHeight); //float height
1461 :     write_short(gSpriteIdFire); //model index
1462 :     write_byte(10); //count
1463 :     write_coord(1); //speed
1464 :     message_end();
1465 :     }
1466 :    
1467 :     gfNextDamageTime[id] = halflife_time() + 0.05;
1468 :     }
1469 :     }
1470 :    
1471 :     actionSlap(id)
1472 :     {
1473 :     user_slap(id, 0);
1474 :     user_slap(id, 0);
1475 :     set_hudmessage(255, 255, 255, -1.0, 0.20, 0, 6.0, 12.0, 0.0, 1.0, 3);
1476 :    
1477 :     show_hudmessage(id, "GET OFF MY FACE!!!");
1478 :     }
1479 :    
1480 :     actionRandom(id, ent)
1481 :     {
1482 :     new Float:fTime = halflife_time();
1483 :    
1484 :     //check if player is outside of cooldown time to use camouflage
1485 :     if (fTime >= gfRandomNextUse[id])
1486 :     {
1487 :     //get which type of block this is set to be
1488 :     new blockType = entity_get_int(ent, EV_INT_iuser4);
1489 :    
1490 :     //do the random block action
1491 :     switch (blockType)
1492 :     {
1493 :     case BM_INVINCIBILITY: actionInvincible(id, true);
1494 :     case BM_STEALTH: actionStealth(id, true);
1495 :     case BM_DEATH: actionDeath(id);
1496 :     case BM_CAMOUFLAGE: actionCamouflage(id, true);
1497 :     case BM_SLAP: actionSlap(id);
1498 :     case BM_BOOTSOFSPEED: actionBootsOfSpeed(id, true);
1499 :     }
1500 :    
1501 :     //set timer to prevent player from using the random block again so soon
1502 :     gfRandomNextUse[id] = fTime + get_cvar_float("bm_randomcooldown");
1503 :    
1504 :     //set this random block to another random block!
1505 :     new randNum = random_num(0, gRandomBlocksMax - 1);
1506 :     entity_set_int(ent, EV_INT_iuser4, gRandomBlocks[randNum]);
1507 :     }
1508 :     else
1509 :     {
1510 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1511 :     show_hudmessage(id, "Random block next use: %.1f", gfRandomNextUse[id] - fTime);
1512 :     }
1513 :     }
1514 :    
1515 :     actionHoney(id)
1516 :     {
1517 :     new taskid = TASK_HONEY + id;
1518 :    
1519 :     //make player feel like they're stuck in honey by lowering their maxspeed
1520 :     set_user_maxspeed(id, 50.0);
1521 :    
1522 :     //remove any existing 'in honey' task
1523 :     if (task_exists(taskid))
1524 :     {
1525 :     remove_task(taskid);
1526 :     }
1527 :     else
1528 :     {
1529 :     //half the players velocity the first time they touch it
1530 :     new Float:vVelocity[3];
1531 :     entity_get_vector(id, EV_VEC_velocity, vVelocity);
1532 :     vVelocity[0] = vVelocity[0] / 2.0;
1533 :     vVelocity[1] = vVelocity[1] / 2.0;
1534 :     entity_set_vector(id, EV_VEC_velocity, vVelocity);
1535 :     }
1536 :    
1537 :     //set task to remove 'in honey' effect very soon (task replaced if player is still in honey before task time reached)
1538 :     set_task(0.1, "taskNotInHoney", taskid);
1539 :     }
1540 :    
1541 :     actionBootsOfSpeed(id, bool:OverrideTimer)
1542 :     {
1543 :     new Float:fTime = halflife_time();
1544 :    
1545 :     //check if player is outside of cooldown time to use the boots of speed
1546 :     if (fTime >= gfBootsOfSpeedNextUse[id] || OverrideTimer)
1547 :     {
1548 :     new Float:fTimeout = get_cvar_float("bm_bootsofspeedtime");
1549 :    
1550 :     //set a task to remove the boots of speed after time out amount
1551 :     set_task(fTimeout, "taskBootsOfSpeedRemove", TASK_BOOTSOFSPEED + id, "", 0, "a", 1);
1552 :    
1553 :     //set the players maxspeed to 400 so they run faster!
1554 :     set_user_maxspeed(id, gfBootsMaxSpeed);
1555 :    
1556 :     //play boots of speed sound
1557 :     emit_sound(id, CHAN_STATIC, gszBootsOfSpeedSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
1558 :    
1559 :     gfBootsOfSpeedTimeOut[id] = fTime + fTimeout;
1560 :     gfBootsOfSpeedNextUse[id] = fTime + fTimeout + get_cvar_float("bm_bootsofspeedcooldown");
1561 :     }
1562 :     else
1563 :     {
1564 :     set_hudmessage(gHudRed, gHudGreen, gHudBlue, gfTextX, gfTextY, gHudEffects, gfHudFxTime, gfHudHoldTime, gfHudFadeInTime, gfHudFadeOutTime, gHudChannel);
1565 :     show_hudmessage(id, "Boots of speed next use: %.1f", gfBootsOfSpeedNextUse[id] - fTime);
1566 :     }
1567 :     }
1568 :    
1569 :     actionTeleport(id, ent)
1570 :     {
1571 :     //get end entity id
1572 :     new tele = entity_get_int(ent, EV_INT_iuser1);
1573 :    
1574 :     //if teleport end id is valid
1575 :     if (tele)
1576 :     {
1577 :     //get end entity origin
1578 :     new Float:vTele[3];
1579 :     entity_get_vector(tele, EV_VEC_origin, vTele);
1580 :    
1581 :     //if id of entity being teleported is a player and telefrags CVAR is set then kill any nearby players
1582 :     if ((id > 0 && id <= 32) && get_cvar_num("bm_telefrags") > 0)
1583 :     {
1584 :     new player = -1;
1585 :    
1586 :     do
1587 :     {
1588 :     player = find_ent_in_sphere(player, vTele, 16.0);
1589 :    
1590 :     //if entity found is a player
1591 :     if (player > 0 && player <= 32)
1592 :     {
1593 :     //if player is alive, and is not the player that went through the teleport
1594 :     if (is_user_alive(player) && player != id)
1595 :     {
1596 :     //kill the player
1597 :     user_kill(player, 1);
1598 :     }
1599 :     }
1600 :     }while(player);
1601 :     }
1602 :    
1603 :     //get origin of the start of the teleport
1604 :     new Float:vOrigin[3];
1605 :     new origin[3];
1606 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
1607 :     FVecIVec(vOrigin, origin);
1608 :    
1609 :     //show some teleporting effects
1610 :     message_begin(MSG_PVS, SVC_TEMPENTITY, origin);
1611 :     write_byte(TE_IMPLOSION);
1612 :     write_coord(origin[0]);
1613 :     write_coord(origin[1]);
1614 :     write_coord(origin[2]);
1615 :     write_byte(64); // radius
1616 :     write_byte(100); // count
1617 :     write_byte(6); // life
1618 :     message_end();
1619 :    
1620 :     //teleport player
1621 :     entity_set_vector(id, EV_VEC_origin, vTele);
1622 :    
1623 :     //reverse players Z velocity
1624 :     new Float:vVelocity[3];
1625 :     entity_get_vector(id, EV_VEC_velocity, vVelocity);
1626 :     vVelocity[2] = floatabs(vVelocity[2]);
1627 :     entity_set_vector(id, EV_VEC_velocity, vVelocity);
1628 :    
1629 :     //play teleport sound
1630 :     emit_sound(id, CHAN_STATIC, gszTeleportSound, 1.0, ATTN_NORM, 0, PITCH_NORM);
1631 :     }
1632 :     }
1633 :    
1634 :     /***** TASKS *****/
1635 :     public taskSolidNot(ent)
1636 :     {
1637 :     ent -= TASK_BHOPSOLIDNOT;
1638 :    
1639 :     //make sure entity is valid
1640 :     if (is_valid_ent(ent))
1641 :     {
1642 :     //if block isn't being grabbed
1643 :     if (entity_get_int(ent, EV_INT_iuser2) == 0)
1644 :     {
1645 :     entity_set_int(ent, EV_INT_solid, SOLID_NOT);
1646 :     set_rendering(ent, kRenderFxNone, 255, 255, 255, kRenderTransAdd, 25);
1647 :     set_task(1.0, "taskSolid", TASK_BHOPSOLID + ent);
1648 :     }
1649 :     }
1650 :     }
1651 :    
1652 :     public taskSolid(ent)
1653 :     {
1654 :     ent -= TASK_BHOPSOLID;
1655 :    
1656 :     //make sure entity is valid
1657 :     if (is_valid_ent(ent))
1658 :     {
1659 :     entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
1660 :    
1661 :     //get the player ID of who has the block in a group (if anyone)
1662 :     new player = entity_get_int(ent, EV_INT_iuser1);
1663 :    
1664 :     //if the block is in a group
1665 :     if (player > 0)
1666 :     {
1667 :     //set the block so it is now 'being grouped' (for setting the rendering)
1668 :     groupBlock(0, ent);
1669 :     }
1670 :     else
1671 :     {
1672 :     set_rendering(ent, kRenderFxNone, 0, 0, 0, kRenderNormal, 255);
1673 :     }
1674 :     }
1675 :     }
1676 :    
1677 :     public taskInvincibleRemove(id)
1678 :     {
1679 :     id -= TASK_INVINCIBLE;
1680 :    
1681 :     //make sure player is alive
1682 :     if (is_user_alive(id))
1683 :     {
1684 :     set_user_godmode(id, 0);
1685 :    
1686 :     //only set players rendering back to normal if player is not stealth
1687 :     if (halflife_time() >= gfStealthTimeOut[id])
1688 :     {
1689 :     set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 16);
1690 :     }
1691 :     }
1692 :     }
1693 :    
1694 :     public taskStealthRemove(id)
1695 :     {
1696 :     id -= TASK_STEALTH;
1697 :    
1698 :     //make sure player is connected
1699 :     if (is_user_connected(id))
1700 :     {
1701 :     //only set players rendering back to normal if player is not invincible
1702 :     if (halflife_time() >= gfInvincibleTimeOut[id])
1703 :     {
1704 :     set_user_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 255);
1705 :     }
1706 :     else //if player is invincible then set player to glow white
1707 :     {
1708 :     set_user_rendering(id, kRenderFxGlowShell, 255, 255, 255, kRenderTransColor, 16);
1709 :     }
1710 :     }
1711 :     }
1712 :    
1713 :     public taskNotOnIce(id)
1714 :     {
1715 :     id -= TASK_ICE;
1716 :    
1717 :     //make player run normally
1718 :     entity_set_float(id, EV_FL_friction, 1.0);
1719 :    
1720 :     if (gfOldMaxSpeed[id] > 100.0)
1721 :     {
1722 :     set_user_maxspeed(id, gfOldMaxSpeed[id]);
1723 :     }
1724 :     else
1725 :     {
1726 :     set_user_maxspeed(id, 250.0);
1727 :     }
1728 :    
1729 :     //no longer 'on ice'
1730 :     gbOnIce[id] = false;
1731 :     gfOldMaxSpeed[id] = 0.0;
1732 :     }
1733 :    
1734 :     public taskCamouflageRemove(id)
1735 :     {
1736 :     id -= TASK_CAMOUFLAGE;
1737 :    
1738 :     //if player is still connected
1739 :     if (is_user_connected(id))
1740 :     {
1741 :     //change back to players old model
1742 :     cs_set_user_model(id, gszCamouflageOldModel[id]);
1743 :     }
1744 :     }
1745 :    
1746 :     public taskNotInHoney(id)
1747 :     {
1748 :     id -= TASK_HONEY;
1749 :    
1750 :     //if player is alive
1751 :     if (is_user_alive(id))
1752 :     {
1753 :     //make player move normally
1754 :     set_user_maxspeed(id, 250.0);
1755 :    
1756 :     //this will set the players maxspeed faster if they have the boots of speed!
1757 :     eventCurWeapon(id);
1758 :     }
1759 :     }
1760 :    
1761 :     public taskBootsOfSpeedRemove(id)
1762 :     {
1763 :     id -= TASK_BOOTSOFSPEED;
1764 :    
1765 :     //set players speed back to normal
1766 :     set_user_maxspeed(id, 250.0);
1767 :     }
1768 :    
1769 :     public taskSpriteNextFrame(params[])
1770 :     {
1771 :     new ent = params[0];
1772 :    
1773 :     //make sure entity is valid
1774 :     if (is_valid_ent(ent))
1775 :     {
1776 :     new frames = params[1];
1777 :     new Float:current_frame = entity_get_float(ent, EV_FL_frame);
1778 :    
1779 :     if (current_frame < 0.0 || current_frame >= frames)
1780 :     {
1781 :     entity_set_float(ent, EV_FL_frame, 1.0);
1782 :     }
1783 :     else
1784 :     {
1785 :     entity_set_float(ent, EV_FL_frame, current_frame + 1.0);
1786 :     }
1787 :     }
1788 :     else
1789 :     {
1790 :     remove_task(TASK_SPRITE + ent);
1791 :     }
1792 :     }
1793 :    
1794 :     /***** COMMANDS *****/
1795 :     public cmdJump(id)
1796 :     {
1797 :     //if the object the player is grabbing isn't too close
1798 :     if (gfGrablength[id] > 72.0)
1799 :     {
1800 :     //move the object closer
1801 :     gfGrablength[id] -= 16.0;
1802 :     }
1803 :     }
1804 :    
1805 :     public cmdDuck(id)
1806 :     {
1807 :     //move the object further away
1808 :     gfGrablength[id] += 16.0;
1809 :     }
1810 :    
1811 :     public cmdAttack(id)
1812 :     {
1813 :     //if entity being grabbed is a block
1814 :     if (isBlock(gGrabbed[id]))
1815 :     {
1816 :     //if block the player is grabbing is in their group and group count is larger than 1
1817 :     if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
1818 :     {
1819 :     new block;
1820 :    
1821 :     //move the rest of the blocks in the players group using vector for grabbed block
1822 :     for (new i = 0; i <= gGroupCount[id]; ++i)
1823 :     {
1824 :     block = gGroupedBlocks[id][i];
1825 :    
1826 :     //if this block is in this players group
1827 :     if (isBlockInGroup(id, block))
1828 :     {
1829 :     //only copy the block if it is not stuck
1830 :     if (!isBlockStuck(block))
1831 :     {
1832 :     //copy the block
1833 :     copyBlock(block);
1834 :     }
1835 :     }
1836 :     }
1837 :     }
1838 :     else
1839 :     {
1840 :     //only copy the block the player has grabbed if it is not stuck
1841 :     if (!isBlockStuck(gGrabbed[id]))
1842 :     {
1843 :     //copy the block
1844 :     new newBlock = copyBlock(gGrabbed[id]);
1845 :    
1846 :     //if new block was created successfully
1847 :     if (newBlock)
1848 :     {
1849 :     //set currently grabbed block to 'not being grabbed'
1850 :     entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
1851 :    
1852 :     //set new block to 'being grabbed'
1853 :     entity_set_int(newBlock, EV_INT_iuser2, id);
1854 :    
1855 :     //set player to grabbing new block
1856 :     gGrabbed[id] = newBlock;
1857 :     }
1858 :     }
1859 :     else
1860 :     {
1861 :     //tell the player they can't copy a block when it is in a stuck position
1862 :     client_print(id, print_chat, "%sYou cannot copy a block that is in a stuck position!", gszPrefix);
1863 :     }
1864 :     }
1865 :     }
1866 :     }
1867 :    
1868 :     public cmdAttack2(id)
1869 :     {
1870 :     //if player is grabbing a block
1871 :     if (isBlock(gGrabbed[id]))
1872 :     {
1873 :     //if block the player is grabbing is in their group and group count is larger than 1
1874 :     if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
1875 :     {
1876 :     new block;
1877 :    
1878 :     //iterate through all blocks in the players group
1879 :     for (new i = 0; i <= gGroupCount[id]; ++i)
1880 :     {
1881 :     block = gGroupedBlocks[id][i];
1882 :    
1883 :     //if block is still valid
1884 :     if (is_valid_ent(block))
1885 :     {
1886 :     //if block is still in this players group
1887 :     if (isBlockInGroup(id, block))
1888 :     {
1889 :     //delete the block
1890 :     gbJustDeleted[id] = deleteBlock(block);
1891 :     }
1892 :     }
1893 :     }
1894 :     }
1895 :     else
1896 :     {
1897 :     //delete the block
1898 :     gbJustDeleted[id] = deleteBlock(gGrabbed[id]);
1899 :     }
1900 :     }
1901 :     //if player is grabbing a teleport
1902 :     else if (isTeleport(gGrabbed[id]))
1903 :     {
1904 :     //delete the teleport
1905 :     gbJustDeleted[id] = deleteTeleport(id, gGrabbed[id]);
1906 :     }
1907 :     }
1908 :    
1909 :     public cmdGrab(id)
1910 :     {
1911 :     //make sure player has access to use this command
1912 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
1913 :     {
1914 :     //get the entity the player is aiming at and the length
1915 :     new ent, body;
1916 :     gfGrablength[id] = get_user_aiming(id, ent, body);
1917 :    
1918 :     //get if the entity is a block or a teleport
1919 :     new bool:bIsBlock = isBlock(ent);
1920 :     new bool:bIsTeleport = isTeleport(ent);
1921 :    
1922 :     //if the entity is a block or teleport
1923 :     if (bIsBlock || bIsTeleport)
1924 :     {
1925 :     //get who is currently grabbing the entity (if anyone)
1926 :     new grabber = entity_get_int(ent, EV_INT_iuser2);
1927 :    
1928 :     //if entity is not being grabbed by someone else
1929 :     if (grabber == 0 || grabber == id)
1930 :     {
1931 :     //if entity is a block
1932 :     if (bIsBlock)
1933 :     {
1934 :     //get the player ID of who has the block in a group (if anyone)
1935 :     new player = entity_get_int(ent, EV_INT_iuser1);
1936 :    
1937 :     //if the block is not in a group or is in this players group
1938 :     if (player == 0 || player == id)
1939 :     {
1940 :     //set the block to 'being grabbed'
1941 :     setGrabbed(id, ent);
1942 :    
1943 :     //if this block is in this players group and group count is greater than 1
1944 :     if (player == id && gGroupCount[id] > 1)
1945 :     {
1946 :     new Float:vGrabbedOrigin[3];
1947 :     new Float:vOrigin[3];
1948 :     new Float:vOffset[3];
1949 :     new block;
1950 :    
1951 :     //get origin of the block
1952 :     entity_get_vector(ent, EV_VEC_origin, vGrabbedOrigin);
1953 :    
1954 :     //iterate through all blocks in players group
1955 :     for (new i = 0; i <= gGroupCount[id]; ++i)
1956 :     {
1957 :     block = gGroupedBlocks[id][i];
1958 :    
1959 :     //if block is still valid
1960 :     if (is_valid_ent(block))
1961 :     {
1962 :     player = entity_get_int(ent, EV_INT_iuser1);
1963 :    
1964 :     //if block is still in this players group
1965 :     if (player == id)
1966 :     {
1967 :     //get origin of block in players group
1968 :     entity_get_vector(block, EV_VEC_origin, vOrigin);
1969 :    
1970 :     //calculate offset from grabbed block
1971 :     vOffset[0] = vGrabbedOrigin[0] - vOrigin[0];
1972 :     vOffset[1] = vGrabbedOrigin[1] - vOrigin[1];
1973 :     vOffset[2] = vGrabbedOrigin[2] - vOrigin[2];
1974 :    
1975 :     //save offset value in grouped block
1976 :     entity_set_vector(block, EV_VEC_vuser1, vOffset);
1977 :    
1978 :     //indicate that entity is being grabbed
1979 :     entity_set_int(block, EV_INT_iuser2, id);
1980 :     }
1981 :     }
1982 :     }
1983 :     }
1984 :     }
1985 :     }
1986 :     //if entity is a teleporter
1987 :     else if (bIsTeleport)
1988 :     {
1989 :     //set the teleport to 'being grabbed'
1990 :     setGrabbed(id, ent);
1991 :     }
1992 :     }
1993 :     }
1994 :     }
1995 :    
1996 :     return PLUGIN_HANDLED;
1997 :     }
1998 :    
1999 :     setGrabbed(id, ent)
2000 :     {
2001 :     new Float:fpOrigin[3];
2002 :     new Float:fbOrigin[3];
2003 :     new Float:fAiming[3];
2004 :     new iAiming[3];
2005 :     new bOrigin[3];
2006 :    
2007 :     //get players current view model then clear it
2008 :     entity_get_string(id, EV_SZ_viewmodel, gszViewModel[id], 32);
2009 :     entity_set_string(id, EV_SZ_viewmodel, "");
2010 :    
2011 :     get_user_origin(id, bOrigin, 1); //position from eyes (weapon aiming)
2012 :     get_user_origin(id, iAiming, 3); //end position from eyes (hit point for weapon)
2013 :     entity_get_vector(id, EV_VEC_origin, fpOrigin); //get player position
2014 :     entity_get_vector(ent, EV_VEC_origin, fbOrigin); //get block position
2015 :     IVecFVec(iAiming, fAiming);
2016 :     FVecIVec(fbOrigin, bOrigin);
2017 :    
2018 :     //set gGrabbed
2019 :     gGrabbed[id] = ent;
2020 :     gfGrabOffset[id][0] = fbOrigin[0] - iAiming[0];
2021 :     gfGrabOffset[id][1] = fbOrigin[1] - iAiming[1];
2022 :     gfGrabOffset[id][2] = fbOrigin[2] - iAiming[2];
2023 :    
2024 :     //indicate that entity is being grabbed
2025 :     entity_set_int(ent, EV_INT_iuser2, id);
2026 :     }
2027 :    
2028 :     public cmdRelease(id)
2029 :     {
2030 :     //make sure player has access to use this command
2031 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2032 :     {
2033 :     //if player is grabbing an entity
2034 :     if (gGrabbed[id])
2035 :     {
2036 :     //if entity player is grabbing is a block
2037 :     if (isBlock(gGrabbed[id]))
2038 :     {
2039 :     //if block the player is grabbing is in their group and group count is > 1
2040 :     if (isBlockInGroup(id, gGrabbed[id]) && gGroupCount[id] > 1)
2041 :     {
2042 :     new block;
2043 :     new bool:bGroupIsStuck = true;
2044 :    
2045 :     //iterate through all blocks in the players group
2046 :     for (new i = 0; i <= gGroupCount[id]; ++i)
2047 :     {
2048 :     block = gGroupedBlocks[id][i];
2049 :    
2050 :     //if this block is in this players group
2051 :     if (isBlockInGroup(id, block))
2052 :     {
2053 :     //indicate that entity is no longer being grabbed
2054 :     entity_set_int(block, EV_INT_iuser2, 0);
2055 :    
2056 :     //start off thinking all blocks in group are stuck
2057 :     if (bGroupIsStuck)
2058 :     {
2059 :     //if block is not stuck
2060 :     if (!isBlockStuck(block))
2061 :     {
2062 :     //at least one of the blocks in the group are not stuck
2063 :     bGroupIsStuck = false;
2064 :     }
2065 :     }
2066 :     }
2067 :     }
2068 :    
2069 :     //if all the blocks in the group are stuck
2070 :     if (bGroupIsStuck)
2071 :     {
2072 :     //iterate through all blocks in the players group
2073 :     for (new i = 0; i <= gGroupCount[id]; ++i)
2074 :     {
2075 :     block = gGroupedBlocks[id][i];
2076 :    
2077 :     //if this block is in this players group
2078 :     if (isBlockInGroup(id, block))
2079 :     {
2080 :     //delete the block
2081 :     deleteBlock(block);
2082 :     }
2083 :     }
2084 :    
2085 :     //tell the player all the blocks were deleted because they were stuck
2086 :     client_print(id, print_chat, "%sGroup deleted because all the blocks were stuck!", gszPrefix);
2087 :     }
2088 :     }
2089 :     else
2090 :     {
2091 :     //if block player has grabbed is valid
2092 :     if (is_valid_ent(gGrabbed[id]))
2093 :     {
2094 :     //if the block is stuck
2095 :     if (isBlockStuck(gGrabbed[id]))
2096 :     {
2097 :     //delete the block
2098 :     new bool:bDeleted = deleteBlock(gGrabbed[id]);
2099 :    
2100 :     //if the block was deleted successfully
2101 :     if (bDeleted)
2102 :     {
2103 :     //tell the player the block was deleted and why
2104 :     client_print(id, print_chat, "%sBlock deleted because it was stuck!", gszPrefix);
2105 :     }
2106 :     }
2107 :     else
2108 :     {
2109 :     //indicate that the block is no longer being grabbed
2110 :     entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
2111 :     }
2112 :     }
2113 :     }
2114 :     }
2115 :     else if (isTeleport(gGrabbed[id]))
2116 :     {
2117 :     //indicate that the teleport is no longer being grabbed
2118 :     entity_set_int(gGrabbed[id], EV_INT_iuser2, 0);
2119 :     }
2120 :    
2121 :     //set the players view model back to what it was
2122 :     entity_set_string(id, EV_SZ_viewmodel, gszViewModel[id]);
2123 :    
2124 :     //indicate that player is not grabbing an object
2125 :     gGrabbed[id] = 0;
2126 :     }
2127 :     }
2128 :    
2129 :     return PLUGIN_HANDLED;
2130 :     }
2131 :    
2132 :     /* MENUS */
2133 :     public cmdShowMainMenu(id)
2134 :     {
2135 :     new col[3];
2136 :     new szMenu[256];
2137 :     new szGodmode[6];
2138 :     new szNoclip[6];
2139 :     col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
2140 :     szGodmode = (get_user_godmode(id) ? "\yOn" : "\rOff");
2141 :     szNoclip = (get_user_noclip(id) ? "\yOn" : "\rOff");
2142 :    
2143 :     //format the main menu
2144 :     format(szMenu, 256, gszMenu, gszBlockNames[gSelectedBlockType[id]], col, col, col, col, col, szNoclip, col, szGodmode);
2145 :    
2146 :     //show the main menu to the player
2147 :     show_menu(id, MAIN_MENU_KEYS, szMenu, -1, "bmMainMenu");
2148 :    
2149 :     return PLUGIN_HANDLED;
2150 :     }
2151 :    
2152 :     showBlockSelectionMenu(id)
2153 :     {
2154 :     //create block selection menu 1 (first 8 blocks)
2155 :     new szBlockMenu[256];
2156 :     new szTitle[32];
2157 :     new szEntry[32];
2158 :     new num;
2159 :     new startBlock;
2160 :    
2161 :     //format the page number into the menu title
2162 :     format(szTitle, sizeof(szTitle), "\yBlock Selection %d^n^n", gBlockMenuPage[id]);
2163 :    
2164 :     //add the title to the menu
2165 :     add(szBlockMenu, sizeof(szBlockMenu), szTitle);
2166 :    
2167 :     //calculate the block that the menu will start on
2168 :     startBlock = (gBlockMenuPage[id] - 1) * 8;
2169 :    
2170 :     //iterate through 8 blocks to add to the menu
2171 :     for (new i = startBlock; i < startBlock + 8; ++i)
2172 :     {
2173 :     //make sure the loop doesn't go above the maximum number of blocks
2174 :     if (i < gBlockMax)
2175 :     {
2176 :     //calculate the menu item number
2177 :     num = (i - startBlock) + 1;
2178 :    
2179 :     //format the block name into the menu entry
2180 :     format(szEntry, sizeof(szEntry), "\r%d. \w%s^n", num, gszBlockNames[i]);
2181 :     }
2182 :     else
2183 :     {
2184 :     //format a blank menu entry
2185 :     format(szEntry, sizeof(szEntry), "^n");
2186 :     }
2187 :    
2188 :     //add the entry to the menu
2189 :     add(szBlockMenu, sizeof(szBlockMenu), szEntry);
2190 :     }
2191 :    
2192 :     //if the block selection page the player is on is less than the maximum page
2193 :     if (gBlockMenuPage[id] < gBlockMenuPagesMax)
2194 :     {
2195 :     add(szBlockMenu, sizeof(szBlockMenu), "^n\r9. \wMore");
2196 :     }
2197 :     else
2198 :     {
2199 :     add(szBlockMenu, sizeof(szBlockMenu), "^n");
2200 :     }
2201 :    
2202 :     //add a back option to the menu
2203 :     add(szBlockMenu, sizeof(szBlockMenu), "^n\r0. \wBack");
2204 :    
2205 :     //display the block selection menu
2206 :     show_menu(id, BLOCKSELECTION_MENU_KEYS, szBlockMenu, -1, "bmBlockSelectionMenu");
2207 :     }
2208 :    
2209 :     showOptionsMenu(id, oldMenu)
2210 :     {
2211 :     //set the oldmenu global variable so when the back key is pressed it goes back to the previous menu
2212 :     gMenuBeforeOptions[id] = oldMenu;
2213 :    
2214 :     new col[3];
2215 :     new szSnapping[6];
2216 :     new szMenu[256];
2217 :     col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
2218 :     szSnapping = (gbSnapping[id] ? "\yOn" : "\rOff");
2219 :    
2220 :     //format the options menu
2221 :     format(szMenu, sizeof(szMenu), gszOptionsMenu, col, szSnapping, col, gfSnappingGap[id], col, col, col, col, col, col);
2222 :    
2223 :     //show the options menu to player
2224 :     show_menu(id, OPTIONS_MENU_KEYS, szMenu, -1, "bmOptionsMenu");
2225 :     }
2226 :    
2227 :     showTeleportMenu(id)
2228 :     {
2229 :     new col[3];
2230 :     new szMenu[256];
2231 :     new szGodmode[6];
2232 :     new szNoclip[6];
2233 :     col = (get_user_flags(id) & BM_ADMIN_LEVEL ? "\w" : "\d");
2234 :     szGodmode = (get_user_godmode(id) ? "\yOn" : "\rOff");
2235 :     szNoclip = (get_user_noclip(id) ? "\yOn" : "\rOff");
2236 :    
2237 :     //format teleport menu
2238 :     format(szMenu, sizeof(szMenu), gszTeleportMenu, col, (gTeleportStart[id] ? "\w" : "\d"), col, col, col, szNoclip, col, szGodmode);
2239 :    
2240 :     show_menu(id, TELEPORT_MENU_KEYS, szMenu, -1, "bmTeleportMenu");
2241 :     }
2242 :    
2243 :     showChoiceMenu(id, gChoice, const szTitle[96])
2244 :     {
2245 :     gChoiceOption[id] = gChoice;
2246 :    
2247 :     //format choice menu using given title
2248 :     new szMenu[128];
2249 :     format(szMenu, sizeof(szMenu), gszChoiceMenu, szTitle);
2250 :    
2251 :     //show the choice menu to the player
2252 :     show_menu(id, TELEPORT_MENU_KEYS, szMenu, -1, "bmChoiceMenu");
2253 :     }
2254 :    
2255 :     public handleMainMenu(id, num)
2256 :     {
2257 :     switch (num)
2258 :     {
2259 :     case N1: { showBlockSelectionMenu(id); }
2260 :     case N2: { createBlockAiming(id, gSelectedBlockType[id]); }
2261 :     case N3: { convertBlockAiming(id, gSelectedBlockType[id]); }
2262 :     case N4: { deleteBlockAiming(id); }
2263 :     case N5: { rotateBlockAiming(id); }
2264 :     case N6: { toggleNoclip(id); }
2265 :     case N7: { toggleGodmode(id); }
2266 :     case N8: { showOptionsMenu(id, 1); }
2267 :     case N9: { showTeleportMenu(id); }
2268 :     case N0: { return; }
2269 :     }
2270 :    
2271 :     //selections 1, 8 and 9 show different menus
2272 :     if (num != N1 && num != N8 && num != N9)
2273 :     {
2274 :     //display menu again
2275 :     cmdShowMainMenu(id);
2276 :     }
2277 :     }
2278 :    
2279 :     public handleBlockSelectionMenu(id, num)
2280 :     {
2281 :     switch (num)
2282 :     {
2283 :     case N9:
2284 :     {
2285 :     //goto next block selection menu page
2286 :     ++gBlockMenuPage[id];
2287 :    
2288 :     //make sure the player can't go above the maximum block selection page
2289 :     if (gBlockMenuPage[id] > gBlockMenuPagesMax)
2290 :     {
2291 :     gBlockMenuPage[id] = gBlockMenuPagesMax;
2292 :     }
2293 :    
2294 :     //show block selection menu again
2295 :     showBlockSelectionMenu(id);
2296 :     }
2297 :    
2298 :     case N0:
2299 :     {
2300 :     //goto previous block selection menu page
2301 :     --gBlockMenuPage[id];
2302 :    
2303 :     //show main menu if player goes back too far
2304 :     if (gBlockMenuPage[id] < 1)
2305 :     {
2306 :     cmdShowMainMenu(id);
2307 :     gBlockMenuPage[id] = 1;
2308 :     }
2309 :     else
2310 :     {
2311 :     //show block selection menu again
2312 :     showBlockSelectionMenu(id);
2313 :     }
2314 :     }
2315 :    
2316 :     default:
2317 :     {
2318 :     //offset the num value using the players block selection page number
2319 :     num += (gBlockMenuPage[id] - 1) * 8;
2320 :    
2321 :     //if block number is within range
2322 :     if (num < gBlockMax)
2323 :     {
2324 :     gSelectedBlockType[id] = num;
2325 :     cmdShowMainMenu(id);
2326 :     }
2327 :     else
2328 :     {
2329 :     showBlockSelectionMenu(id);
2330 :     }
2331 :     }
2332 :     }
2333 :     }
2334 :    
2335 :     public handleOptionsMenu(id, num)
2336 :     {
2337 :     switch (num)
2338 :     {
2339 :     case N1: { toggleSnapping(id); }
2340 :     case N2: { toggleSnappingGap(id); }
2341 :     case N3: { groupBlockAiming(id); }
2342 :     case N4: { groupClear(id); }
2343 :     case N5: { showChoiceMenu(id, CHOICE_DEL_BLOCKS, "Are you sure you want to erase all blocks on the map?"); }
2344 :     case N6: { showChoiceMenu(id, CHOICE_DEL_TELEPORTS, "Are you sure you want to erase all teleports on the map?"); }
2345 :     case N7: { saveBlocks(id); }
2346 :     case N8: { showChoiceMenu(id, CHOICE_LOAD, "Loading will erase all blocks and teleports, do you want to continue?"); }
2347 :     case N9: { showHelp(id); }
2348 :    
2349 :     case N0:
2350 :     {
2351 :     if (gMenuBeforeOptions[id] == 1)
2352 :     {
2353 :     cmdShowMainMenu(id);
2354 :     }
2355 :     else if (gMenuBeforeOptions[id] == 2)
2356 :     {
2357 :     showTeleportMenu(id);
2358 :     }
2359 :     else
2360 :     {
2361 :     //for some reason the players 'gMenuBeforeOptions' number is invalid
2362 :     log_amx("%sPlayer ID: %d has an invalid gMenuBeforeOptions: %d", gszPrefix, id, gMenuBeforeOptions[id]);
2363 :     }
2364 :     }
2365 :     }
2366 :    
2367 :     //these selections show a different menu
2368 :     if (num != N5 && num != N6 && num != N8 && num != N0)
2369 :     {
2370 :     //display menu again
2371 :     showOptionsMenu(id, gMenuBeforeOptions[id]);
2372 :     }
2373 :     }
2374 :    
2375 :     public handleTeleportMenu(id, num)
2376 :     {
2377 :     switch (num)
2378 :     {
2379 :     case N1: { createTeleportAiming(id, TELEPORT_START); }
2380 :     case N2: { createTeleportAiming(id, TELEPORT_END); }
2381 :     case N3: { showTeleportPath(id); }
2382 :     case N4: { deleteTeleportAiming(id); }
2383 :     case N6: { toggleNoclip(id); }
2384 :     case N7: { toggleGodmode(id); }
2385 :     case N8: { showOptionsMenu(id, 2); }
2386 :     case N0: { cmdShowMainMenu(id); }
2387 :     }
2388 :    
2389 :     //selections 6, 8 and 9 show different menus
2390 :     if (num != N6 && num != N8 && num != N0)
2391 :     {
2392 :     showTeleportMenu(id);
2393 :     }
2394 :     }
2395 :    
2396 :     public handleChoiceMenu(id, num)
2397 :     {
2398 :     switch (num)
2399 :     {
2400 :     case N1: //YES
2401 :     {
2402 :     switch (gChoiceOption[id])
2403 :     {
2404 :     case CHOICE_LOAD: loadBlocks(id);
2405 :     case CHOICE_DEL_BLOCKS: deleteAllBlocks(id, true);
2406 :     case CHOICE_DEL_TELEPORTS: deleteAllTeleports(id, true);
2407 :    
2408 :     default:
2409 :     {
2410 :     log_amx("%sInvalid choice in handleChoiceMenu()", gszPrefix);
2411 :     }
2412 :     }
2413 :     }
2414 :     }
2415 :    
2416 :     //show options menu again
2417 :     showOptionsMenu(id, gMenuBeforeOptions[id]);
2418 :     }
2419 :    
2420 :     toggleGodmode(id)
2421 :     {
2422 :     //make sure player has access to this command
2423 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2424 :     {
2425 :     //if player has godmode
2426 :     if (get_user_godmode(id))
2427 :     {
2428 :     //turn off godmode for player
2429 :     set_user_godmode(id, 0);
2430 :     gbAdminGodmode[id] = false;
2431 :     }
2432 :     else
2433 :     {
2434 :     //turn on godmode for player
2435 :     set_user_godmode(id, 1);
2436 :     gbAdminGodmode[id] = true;
2437 :     }
2438 :     }
2439 :     }
2440 :    
2441 :     toggleNoclip(id)
2442 :     {
2443 :     //make sure player has access to this command
2444 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2445 :     {
2446 :     //if player has noclip
2447 :     if (get_user_noclip(id))
2448 :     {
2449 :     //turn off noclip for player
2450 :     set_user_noclip(id, 0);
2451 :     gbAdminNoclip[id] = false;
2452 :     }
2453 :     else
2454 :     {
2455 :     //turn on noclip for player
2456 :     set_user_noclip(id, 1);
2457 :     gbAdminNoclip[id] = true;
2458 :     }
2459 :     }
2460 :     }
2461 :    
2462 :     toggleSnapping(id)
2463 :     {
2464 :     //make sure player has access to this command
2465 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2466 :     {
2467 :     gbSnapping[id] = !gbSnapping[id];
2468 :     }
2469 :     }
2470 :    
2471 :     toggleSnappingGap(id)
2472 :     {
2473 :     //make sure player has access to this command
2474 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2475 :     {
2476 :     //increment this players snapping gap by 5
2477 :     gfSnappingGap[id] += 4.0;
2478 :    
2479 :     //if this players snapping gap gets too big then loop it back to 0
2480 :     if (gfSnappingGap[id] > 40.0)
2481 :     {
2482 :     gfSnappingGap[id] = 0.0;
2483 :     }
2484 :     }
2485 :     }
2486 :    
2487 :     showHelp(id)
2488 :     {
2489 :     //get cvar values
2490 :     new szHelpText[1600];
2491 :    
2492 :     new Telefrags = get_cvar_num("bm_telefrags");
2493 :     new Float:fFireDamageAmount = get_cvar_float("bm_firedamageamount");
2494 :     new Float:fDamageAmount = get_cvar_float("bm_damageamount");
2495 :     new Float:fHealAmount = get_cvar_float("bm_healamount");
2496 :     new Float:fInvincibleTime = get_cvar_float("bm_invincibletime");
2497 :     new Float:fInvincibleCooldown = get_cvar_float("bm_invinciblecooldown");
2498 :     new Float:fStealthTime = get_cvar_float("bm_stealthtime");
2499 :     new Float:fStealthCooldown = get_cvar_float("bm_stealthcooldown");
2500 :     new Float:fCamouflageTime = get_cvar_float("bm_camouflagetime");
2501 :     new Float:fCamouflageCooldown = get_cvar_float("bm_camouflagecooldown");
2502 :     new Float:fNukeCooldown = get_cvar_float("bm_nukecooldown");
2503 :     new Float:fRandomCooldown = get_cvar_float("bm_randomcooldown");
2504 :     new Float:fBootsOfSpeedTime = get_cvar_float("bm_bootsofspeedtime");
2505 :     new Float:fBootsOfSpeedCooldown = get_cvar_float("bm_bootsofspeedcooldown");
2506 :    
2507 :     //format the help text
2508 :     format(szHelpText, sizeof(szHelpText), gszHelpText, Telefrags, fFireDamageAmount, fDamageAmount, fHealAmount, fInvincibleTime, fInvincibleCooldown, fStealthTime, fStealthCooldown, fCamouflageTime, fCamouflageCooldown, fNukeCooldown, fRandomCooldown, fBootsOfSpeedTime, fBootsOfSpeedCooldown);
2509 :    
2510 :     //show the help
2511 :     show_motd(id, szHelpText, gszHelpTitle);
2512 :     }
2513 :    
2514 :     showTeleportPath(id)
2515 :     {
2516 :     //get the entity the player is aiming at
2517 :     new ent, body;
2518 :     get_user_aiming(id, ent, body);
2519 :    
2520 :     //if entity found is a teleport
2521 :     if (isTeleport(ent))
2522 :     {
2523 :     //get other side of teleport
2524 :     new tele = entity_get_int(ent, EV_INT_iuser1);
2525 :    
2526 :     //if there is another end to the teleport
2527 :     if (tele)
2528 :     {
2529 :     //get origins of the start and end teleport entities
2530 :     new life = 50;
2531 :     new Float:vOrigin1[3];
2532 :     new Float:vOrigin2[3];
2533 :     entity_get_vector(ent, EV_VEC_origin, vOrigin1);
2534 :     entity_get_vector(tele, EV_VEC_origin, vOrigin2);
2535 :    
2536 :     //draw a line in between the 2 origins
2537 :     drawLine(vOrigin1, vOrigin2, life);
2538 :    
2539 :     //get the distance between the points
2540 :     new Float:fDist = get_distance_f(vOrigin1, vOrigin2);
2541 :    
2542 :     //notify that a line has been drawn between the start and end of the teleport
2543 :     client_print(id, print_chat, "%sA line has been drawn to show the teleport path. Distance: %f units.", gszPrefix, fDist);
2544 :     }
2545 :     }
2546 :     }
2547 :    
2548 :     /* GROUPING BLOCKS */
2549 :     groupBlockAiming(id)
2550 :     {
2551 :     //get the entity the player is aiming at
2552 :     new ent, body;
2553 :     get_user_aiming(id, ent, body);
2554 :    
2555 :     //is entity is a block
2556 :     if (isBlock(ent))
2557 :     {
2558 :     //get whether or not block is already being grouped
2559 :     new player = entity_get_int(ent, EV_INT_iuser1);
2560 :    
2561 :     //if block is not in a group
2562 :     if (player == 0)
2563 :     {
2564 :     //increment group value
2565 :     ++gGroupCount[id];
2566 :    
2567 :     //add this entity to the players group
2568 :     gGroupedBlocks[id][gGroupCount[id]] = ent;
2569 :    
2570 :     //set the block so it is now 'being grouped'
2571 :     groupBlock(id, ent);
2572 :    
2573 :     }
2574 :     //if block is in this players group
2575 :     else if (player == id)
2576 :     {
2577 :     //remove block from being grouped
2578 :     groupRemoveBlock(ent);
2579 :     }
2580 :     //if another player has the block grouped
2581 :     else
2582 :     {
2583 :     //get id and name of who has the block grouped
2584 :     new szName[32];
2585 :     new player = entity_get_int(ent, EV_INT_iuser1);
2586 :     get_user_name(player, szName, 32);
2587 :    
2588 :     //notify player who the block is being grouped by
2589 :     client_print(id, print_chat, "%sBlock is already in a group by: %s", gszPrefix, szName);
2590 :     }
2591 :     }
2592 :     }
2593 :    
2594 :     groupBlock(id, ent)
2595 :     {
2596 :     //if entity is valid
2597 :     if (is_valid_ent(ent))
2598 :     {
2599 :     //if id passed in is a player
2600 :     if (id > 0 && id <= 32)
2601 :     {
2602 :     //set block so it is now being grouped
2603 :     entity_set_int(ent, EV_INT_iuser1, id);
2604 :     }
2605 :    
2606 :     //get block type
2607 :     new blockType = entity_get_int(ent, EV_INT_body);
2608 :    
2609 :     //if block is a stealth block
2610 :     if (blockType == BM_STEALTH)
2611 :     {
2612 :     //make block transparent and red
2613 :     set_rendering(ent, kRenderFxGlowShell, 255, 0, 0, kRenderTransAdd, 16);
2614 :     }
2615 :     else
2616 :     {
2617 :     //make block glow red to show it is grouped
2618 :     set_rendering(ent, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 16);
2619 :     }
2620 :     }
2621 :     }
2622 :    
2623 :     groupRemoveBlock(ent)
2624 :     {
2625 :     //make sure entity is a block
2626 :     if (isBlock(ent))
2627 :     {
2628 :     //remove block from being grouped (stays in players gGroupedBlocks[id][] array
2629 :     entity_set_int(ent, EV_INT_iuser1, 0);
2630 :    
2631 :     //get block type
2632 :     new blockType = entity_get_int(ent, EV_INT_body);
2633 :    
2634 :     //if block is an invincibility block
2635 :     if (blockType == BM_INVINCIBILITY)
2636 :     {
2637 :     //set block to glow white
2638 :     set_rendering(ent, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 16);
2639 :     }
2640 :     else if (blockType == BM_STEALTH)
2641 :     {
2642 :     //set block to be transparent
2643 :     set_rendering(ent, kRenderFxNone, 255, 255, 255, kRenderTransAdd, 180);
2644 :     }
2645 :     else
2646 :     {
2647 :     //remove glow on block
2648 :     set_rendering(ent, kRenderFxNone, 0, 0, 0, kRenderNormal, 255);
2649 :     }
2650 :     }
2651 :     }
2652 :    
2653 :     groupClear(id)
2654 :     {
2655 :     new blockCount = 0;
2656 :     new blocksDeleted = 0;
2657 :     new block;
2658 :    
2659 :     //remove all players blocks from being grouped
2660 :     for (new i = 0; i <= gGroupCount[id]; ++i)
2661 :     {
2662 :     block = gGroupedBlocks[id][i];
2663 :    
2664 :     //if block is in this players group
2665 :     if (isBlockInGroup(id, block))
2666 :     {
2667 :     //if block is stuck
2668 :     if (isBlockStuck(block))
2669 :     {
2670 :     //delete the stuck block
2671 :     deleteBlock(block);
2672 :    
2673 :     //count how many blocks have been deleted
2674 :     ++blocksDeleted;
2675 :     }
2676 :     else
2677 :     {
2678 :     //remove block from being grouped
2679 :     groupRemoveBlock(block);
2680 :    
2681 :     //count how many blocks have been removed from group
2682 :     ++blockCount;
2683 :     }
2684 :     }
2685 :     }
2686 :    
2687 :     //set players group count to 0
2688 :     gGroupCount[id] = 0;
2689 :    
2690 :     //if player is connected
2691 :     if (is_user_connected(id))
2692 :     {
2693 :     //if some blocks were deleted
2694 :     if (blocksDeleted > 0)
2695 :     {
2696 :     //notify player how many blocks were cleared from group and deleted
2697 :     client_print(id, print_chat, "%sRemoved %d blocks from group, deleted %d stuck blocks", gszPrefix, blockCount, blocksDeleted);
2698 :     }
2699 :     else
2700 :     {
2701 :     //notify player how many blocks were cleared from group
2702 :     client_print(id, print_chat, "%sRemoved %d blocks from group", gszPrefix, blockCount);
2703 :     }
2704 :     }
2705 :     }
2706 :    
2707 :     /* BLOCK & TELEPORT OPERATIONS */
2708 :     moveGrabbedEntity(id, Float:vMoveTo[3] = {0.0, 0.0, 0.0})
2709 :     {
2710 :     new iOrigin[3], iLook[3];
2711 :     new Float:fOrigin[3], Float:fLook[3], Float:fDirection[3], Float:fLength;
2712 :    
2713 :     get_user_origin(id, iOrigin, 1); //Position from eyes (weapon aiming)
2714 :     get_user_origin(id, iLook, 3); //End position from eyes (hit point for weapon)
2715 :     IVecFVec(iOrigin, fOrigin);
2716 :     IVecFVec(iLook, fLook);
2717 :    
2718 :     fDirection[0] = fLook[0] - fOrigin[0];
2719 :     fDirection[1] = fLook[1] - fOrigin[1];
2720 :     fDirection[2] = fLook[2] - fOrigin[2];
2721 :     fLength = get_distance_f(fLook, fOrigin);
2722 :    
2723 :     if (fLength == 0.0) fLength = 1.0; //avoid division by 0
2724 :    
2725 :     //calculate the position to move the block
2726 :     vMoveTo[0] = (fOrigin[0] + fDirection[0] * gfGrablength[id] / fLength) + gfGrabOffset[id][0];
2727 :     vMoveTo[1] = (fOrigin[1] + fDirection[1] * gfGrablength[id] / fLength) + gfGrabOffset[id][1];
2728 :     vMoveTo[2] = (fOrigin[2] + fDirection[2] * gfGrablength[id] / fLength) + gfGrabOffset[id][2];
2729 :     vMoveTo[2] = float(floatround(vMoveTo[2], floatround_floor));
2730 :    
2731 :     //move the block and its sprite (if it has one)
2732 :     moveEntity(id, gGrabbed[id], vMoveTo, true);
2733 :     }
2734 :    
2735 :     moveEntity(id, ent, Float:vMoveTo[3], bool:bDoSnapping)
2736 :     {
2737 :     //do snapping for entity if snapping boolean passed in is true
2738 :     if (bDoSnapping)
2739 :     {
2740 :     doSnapping(id, ent, vMoveTo);
2741 :     }
2742 :    
2743 :     //set the position of the block
2744 :     entity_set_origin(ent, vMoveTo);
2745 :    
2746 :     //get the sprite that sits above the block (if any)
2747 :     new sprite = entity_get_int(ent, EV_INT_iuser3);
2748 :    
2749 :     //if sprite entity is valid
2750 :     if (sprite)
2751 :     {
2752 :     //get size of block
2753 :     new Float:vSizeMax[3];
2754 :     entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
2755 :    
2756 :     //move the sprite onto the top of the block
2757 :     vMoveTo[2] += vSizeMax[2] + 0.15;
2758 :     entity_set_origin(sprite, vMoveTo);
2759 :     }
2760 :     }
2761 :    
2762 :     /* TELEPORTS */
2763 :     createTeleportAiming(id, teleportType)
2764 :     {
2765 :     //make sure player has access to this command
2766 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2767 :     {
2768 :     //get where player is aiming for origin of teleport entity
2769 :     new pOrigin[3], Float:vOrigin[3];
2770 :     get_user_origin(id, pOrigin, 3);
2771 :     IVecFVec(pOrigin, vOrigin);
2772 :     vOrigin[2] += gfTeleportZOffset;
2773 :    
2774 :     //create the teleport of the given type
2775 :     createTeleport(id, teleportType, vOrigin);
2776 :     }
2777 :     }
2778 :    
2779 :     createTeleport(id, teleportType, Float:vOrigin[3])
2780 :     {
2781 :     new ent = create_entity(gszInfoTarget);
2782 :    
2783 :     if (is_valid_ent(ent))
2784 :     {
2785 :     switch (teleportType)
2786 :     {
2787 :     case TELEPORT_START:
2788 :     {
2789 :     //if player has already created a teleport start entity then delete it
2790 :     if (gTeleportStart[id])
2791 :     {
2792 :     remove_entity(gTeleportStart[id]);
2793 :     }
2794 :    
2795 :     //set teleport properties
2796 :     entity_set_string(ent, EV_SZ_classname, gszTeleportStartClassname);
2797 :     entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
2798 :     entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
2799 :     entity_set_model(ent, gszTeleportSpriteStart);
2800 :     entity_set_size(ent, gfTeleportSizeMin, gfTeleportSizeMax);
2801 :     entity_set_origin(ent, vOrigin);
2802 :    
2803 :     //set the rendermode and transparency
2804 :     entity_set_int(ent, EV_INT_rendermode, 5); //rendermode
2805 :     entity_set_float(ent, EV_FL_renderamt, 255.0); //visable
2806 :    
2807 :     //set task for animating sprite
2808 :     new params[2];
2809 :     params[0] = ent;
2810 :     params[1] = gTeleportStartFrames;
2811 :     set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + ent, params, 2, "b");
2812 :    
2813 :     //store teleport start entity to a global variable so it can be linked to the end entity
2814 :     gTeleportStart[id] = ent;
2815 :     }
2816 :    
2817 :     case TELEPORT_END:
2818 :     {
2819 :     //make sure there is a teleport start entity
2820 :     if (gTeleportStart[id])
2821 :     {
2822 :     //set teleport properties
2823 :     entity_set_string(ent, EV_SZ_classname, gszTeleportEndClassname);
2824 :     entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
2825 :     entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
2826 :     entity_set_model(ent, gszTeleportSpriteEnd);
2827 :     entity_set_size(ent, gfTeleportSizeMin, gfTeleportSizeMax);
2828 :     entity_set_origin(ent, vOrigin);
2829 :    
2830 :     //set the rendermode and transparency
2831 :     entity_set_int(ent, EV_INT_rendermode, 5); //rendermode
2832 :     entity_set_float(ent, EV_FL_renderamt, 255.0); //visable
2833 :    
2834 :     //link up teleport start and end entities
2835 :     entity_set_int(ent, EV_INT_iuser1, gTeleportStart[id]);
2836 :     entity_set_int(gTeleportStart[id], EV_INT_iuser1, ent);
2837 :    
2838 :     //set task for animating sprite
2839 :     new params[2];
2840 :     params[0] = ent;
2841 :     params[1] = gTeleportEndFrames;
2842 :     set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + ent, params, 2, "b");
2843 :    
2844 :     //indicate that this player has no teleport start entity waiting for an end
2845 :     gTeleportStart[id] = 0;
2846 :     }
2847 :     else
2848 :     {
2849 :     //delete entity that was created because there is no start entity
2850 :     remove_entity(ent);
2851 :     }
2852 :     }
2853 :     }
2854 :     }
2855 :     else
2856 :     {
2857 :     log_amx("%sCouldn't create 'env_sprite' entity", gszPrefix);
2858 :     }
2859 :     }
2860 :    
2861 :     deleteTeleportAiming(id)
2862 :     {
2863 :     //make sure player has access to this command
2864 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2865 :     {
2866 :     //get entity that player is aiming at
2867 :     new ent, body;
2868 :     get_user_aiming(id, ent, body, 9999);
2869 :    
2870 :     //delete block that player is aiming at
2871 :     new bool:deleted = deleteTeleport(id, ent);
2872 :    
2873 :     if (deleted)
2874 :     {
2875 :     client_print(id, print_chat, "%sTeleport deleted!", gszPrefix);
2876 :     }
2877 :     }
2878 :     }
2879 :    
2880 :     bool:deleteTeleport(id, ent)
2881 :     {
2882 :     //iterate through the different types of teleport (start and end)
2883 :     for (new i = 0; i < 2; ++i)
2884 :     {
2885 :     //if entity is a teleport then delete both the start and the end of the teleport
2886 :     if (isTeleport(ent))
2887 :     {
2888 :     //get entity id of the other side of the teleport
2889 :     new tele = entity_get_int(ent, EV_INT_iuser1);
2890 :    
2891 :     //clear teleport start entity if it was just deleted
2892 :     if (gTeleportStart[id] == ent || gTeleportStart[id] == tele)
2893 :     {
2894 :     gTeleportStart[id] = 0;
2895 :     }
2896 :    
2897 :     //remove tasks that exist to animate the teleport sprites
2898 :     if (task_exists(TASK_SPRITE + ent))
2899 :     {
2900 :     remove_task(TASK_SPRITE + ent);
2901 :     }
2902 :    
2903 :     if (task_exists(TASK_SPRITE + tele))
2904 :     {
2905 :     remove_task(TASK_SPRITE + tele);
2906 :     }
2907 :    
2908 :     //delete both the start and end positions of the teleporter
2909 :     if (tele)
2910 :     {
2911 :     remove_entity(tele);
2912 :     }
2913 :    
2914 :     remove_entity(ent);
2915 :    
2916 :     //delete was deleted
2917 :     return true;
2918 :     }
2919 :     }
2920 :    
2921 :     //teleport was not deleted
2922 :     return false;
2923 :     }
2924 :    
2925 :     deleteAllBlocks(id, bool:bNotify)
2926 :     {
2927 :     //make sure player has access to this command
2928 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2929 :     {
2930 :     new bool:bDeleted;
2931 :     new blockCount = 0;
2932 :     new ent = -1;
2933 :    
2934 :     //find all blocks in the map
2935 :     while ((ent = find_ent_by_class(ent, gszBlockClassname)))
2936 :     {
2937 :     //delete the block
2938 :     bDeleted = deleteBlock(ent);
2939 :    
2940 :     //if block was successfully deleted
2941 :     if (bDeleted)
2942 :     {
2943 :     //increment counter for how many blocks have been deleted
2944 :     ++blockCount;
2945 :     }
2946 :     }
2947 :    
2948 :     //get players name
2949 :     new szName[32];
2950 :     get_user_name(id, szName, 32);
2951 :    
2952 :     //iterate through all players
2953 :     for (new i = 1; i <= 32; ++i)
2954 :     {
2955 :     //make sure nobody is grabbing a block because they've all been deleted!
2956 :     gGrabbed[id] = 0;
2957 :    
2958 :     //make sure player is connected
2959 :     if (is_user_connected(i))
2960 :     {
2961 :     //notify all admins that the player deleted all the blocks
2962 :     if (bNotify && get_user_flags(i) & BM_ADMIN_LEVEL)
2963 :     {
2964 :     client_print(i, print_chat, "%s'%s' deleted all the blocks from the map. Total blocks: %d", gszPrefix, szName, blockCount);
2965 :     }
2966 :     }
2967 :     }
2968 :     }
2969 :     }
2970 :    
2971 :     deleteAllTeleports(id, bool:bNotify)
2972 :     {
2973 :     //make sure player has access to this command
2974 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
2975 :     {
2976 :     new bool:bDeleted;
2977 :     new teleCount = 0;
2978 :     new ent = -1;
2979 :    
2980 :     //find all teleport start entities in the map
2981 :     while ((ent = find_ent_by_class(ent, gszTeleportStartClassname)))
2982 :     {
2983 :     //delete the block
2984 :     bDeleted = deleteTeleport(id, ent);
2985 :    
2986 :     //if block was successfully deleted
2987 :     if (bDeleted)
2988 :     {
2989 :     //increment counter for how many blocks have been deleted
2990 :     ++teleCount;
2991 :     }
2992 :     }
2993 :    
2994 :     //get players name
2995 :     new szName[32];
2996 :     get_user_name(id, szName, 32);
2997 :    
2998 :     //iterate through all players
2999 :     for (new i = 1; i <= 32; ++i)
3000 :     {
3001 :     //make sure nobody has a teleport start set
3002 :     gTeleportStart[id] = 0;
3003 :    
3004 :     //make sure player is connected
3005 :     if (is_user_connected(i))
3006 :     {
3007 :     //notify all admins that the player deleted all the teleports
3008 :     if (bNotify && get_user_flags(i) & BM_ADMIN_LEVEL)
3009 :     {
3010 :     client_print(i, print_chat, "%s'%s' deleted all the teleports from the map. Total teleports: %d", gszPrefix, szName, teleCount);
3011 :     }
3012 :     }
3013 :     }
3014 :     }
3015 :     }
3016 :    
3017 :     /***** BLOCKS *****/
3018 :     createBlockAiming(const id, const blockType)
3019 :     {
3020 :     //make sure player has access to this command
3021 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
3022 :     {
3023 :     new origin[3];
3024 :     new Float:vOrigin[3];
3025 :    
3026 :     //get the origin of the player and add Z offset
3027 :     get_user_origin(id, origin, 3);
3028 :     IVecFVec(origin, vOrigin);
3029 :     vOrigin[2] += gfBlockSizeMaxForZ[2];
3030 :    
3031 :     //create the block
3032 :     createBlock(id, blockType, vOrigin, gfDefaultBlockAngles, gfBlockSizeMinForZ, gfBlockSizeMaxForZ);
3033 :     }
3034 :     }
3035 :    
3036 :     createBlock(const id, const blockType, Float:vOrigin[3], Float:vAngles[3], Float:vSizeMin[3], Float:vSizeMax[3])
3037 :     {
3038 :     new ent = create_entity(gszInfoTarget);
3039 :    
3040 :     //make sure entity was created successfully
3041 :     if (is_valid_ent(ent))
3042 :     {
3043 :     //set block properties
3044 :     entity_set_string(ent, EV_SZ_classname, gszBlockClassname);
3045 :     entity_set_int(ent, EV_INT_solid, SOLID_BBOX);
3046 :     entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE);
3047 :    
3048 :     switch (blockType)
3049 :     {
3050 :     case BM_PLATFORM: entity_set_model(ent, gszBlockModelPlatform);
3051 :     case BM_BHOP: entity_set_model(ent, gszBlockModelBhop);
3052 :     case BM_DAMAGE: entity_set_model(ent, gszBlockModelDamage);
3053 :     case BM_HEALER: entity_set_model(ent, gszBlockModelHealer);
3054 :     case BM_INVINCIBILITY: entity_set_model(ent, gszBlockModelInvincibility);
3055 :     case BM_STEALTH: entity_set_model(ent, gszBlockModelDefault);
3056 :     case BM_TRAMPOLINE: entity_set_model(ent, gszBlockModelDefault);
3057 :     case BM_SPEEDBOOST: entity_set_model(ent, gszBlockModelSpeedBoost);
3058 :     case BM_NOFALLDAMAGE: entity_set_model(ent, gszBlockModelNoFallDamage);
3059 :     case BM_ICE: entity_set_model(ent, gszBlockModelIce);
3060 :     case BM_DEATH: entity_set_model(ent, gszBlockModelDeath);
3061 :     case BM_NUKE: entity_set_model(ent, gszBlockModelNuke);
3062 :     case BM_CAMOUFLAGE: entity_set_model(ent, gszBlockModelCamouflage);
3063 :     case BM_LOWGRAVITY: entity_set_model(ent, gszBlockModelLowGravity);
3064 :     case BM_FIRE: entity_set_model(ent, gszBlockModelFire);
3065 :     case BM_SLAP: entity_set_model(ent, gszBlockModelSlap);
3066 :     case BM_RANDOM: entity_set_model(ent, gszBlockModelRandom);
3067 :     case BM_HONEY: entity_set_model(ent, gszBlockModelHoney);
3068 :     case BM_BARRIER_CT: entity_set_model(ent, gszBlockModelBarrierCT);
3069 :     case BM_BARRIER_T: entity_set_model(ent, gszBlockModelBarrierT);
3070 :     case BM_BOOTSOFSPEED: entity_set_model(ent, gszBlockModelBootsOfSpeed);
3071 :     default: entity_set_model(ent, gszBlockModelDefault);
3072 :     }
3073 :    
3074 :     entity_set_vector(ent, EV_VEC_angles, vAngles);
3075 :     entity_set_size(ent, vSizeMin, vSizeMax);
3076 :     entity_set_int(ent, EV_INT_body, blockType);
3077 :    
3078 :     //if a player is creating the block
3079 :     if (id > 0 && id <= 32)
3080 :     {
3081 :     //do snapping for new block
3082 :     doSnapping(id, ent, vOrigin);
3083 :     }
3084 :    
3085 :     //set origin of new block
3086 :     entity_set_origin(ent, vOrigin);
3087 :    
3088 :     //setup special properties on some blocks
3089 :     switch (blockType)
3090 :     {
3091 :     case BM_STEALTH: set_rendering(ent, kRenderFxNone, 255, 255, 255, kRenderTransAdd, 180);
3092 :     case BM_INVINCIBILITY: set_rendering(ent, kRenderFxGlowShell, 255, 255, 255, kRenderNormal, 16);
3093 :    
3094 :     case BM_RANDOM:
3095 :     {
3096 :     //set this random block to a random block!
3097 :     new randNum = random_num(0, gRandomBlocksMax - 1);
3098 :     entity_set_int(ent, EV_INT_iuser4, gRandomBlocks[randNum]);
3099 :     }
3100 :     }
3101 :    
3102 :     //if blocktype is one which requires an additional sprite
3103 :     if (blockType == BM_FIRE || blockType == BM_TRAMPOLINE || blockType == BM_SPEEDBOOST)
3104 :     {
3105 :     //add sprite on top of the block
3106 :     new sprite = create_entity(gszInfoTarget);
3107 :    
3108 :     //make sure entity was created successfully
3109 :     if (sprite)
3110 :     {
3111 :     //create angle vector and rotate it so its horizontal
3112 :     new Float:vAngles[3];
3113 :     vAngles[0] = 90.0;
3114 :     vAngles[1] = 0.0;
3115 :     vAngles[2] = 0.0;
3116 :    
3117 :     //move the sprite up onto the top of the block, adding 0.15 to prevent flickering
3118 :     vOrigin[2] += vSizeMax[2] + 0.15;
3119 :    
3120 :     //set block properties
3121 :     entity_set_string(sprite, EV_SZ_classname, gszSpriteClassname);
3122 :     entity_set_int(sprite, EV_INT_solid, SOLID_NOT);
3123 :     entity_set_int(sprite, EV_INT_movetype, MOVETYPE_NONE);
3124 :     entity_set_vector(sprite, EV_VEC_angles, vAngles);
3125 :    
3126 :     //set sprite model depending on block type
3127 :     switch (blockType)
3128 :     {
3129 :     case BM_TRAMPOLINE: entity_set_model(sprite, gszBlockSpriteTrampoline);
3130 :     case BM_SPEEDBOOST: entity_set_model(sprite, gszBlockSpriteSpeedBoost);
3131 :     case BM_FIRE: entity_set_model(sprite, gszBlockSpriteFire);
3132 :     }
3133 :    
3134 :     //set the rendermode to additive and set the transparency
3135 :     entity_set_int(sprite, EV_INT_rendermode, 5);
3136 :     entity_set_float(sprite, EV_FL_renderamt, 255.0);
3137 :    
3138 :     //set origin of new sprite
3139 :     entity_set_origin(sprite, vOrigin);
3140 :    
3141 :     //link this sprite to the block
3142 :     entity_set_int(ent, EV_INT_iuser3, sprite);
3143 :    
3144 :     //set task for animating the sprite
3145 :     if (blockType == BM_FIRE || blockType == BM_TRAMPOLINE)
3146 :     {
3147 :     new params[2];
3148 :     params[0] = sprite;
3149 :     params[1] = 8; //both the fire and trampoline sprites have 8 frames
3150 :     set_task(0.1, "taskSpriteNextFrame", TASK_SPRITE + sprite, params, 2, "b");
3151 :     }
3152 :     }
3153 :     }
3154 :    
3155 :     return ent;
3156 :     }
3157 :    
3158 :     return 0;
3159 :     }
3160 :    
3161 :     convertBlockAiming(id, const convertTo)
3162 :     {
3163 :     //make sure player has access to this command
3164 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
3165 :     {
3166 :     //get entity that player is aiming at
3167 :     new ent, body;
3168 :     get_user_aiming(id, ent, body);
3169 :    
3170 :     //if player is aiming at a block
3171 :     if (isBlock(ent))
3172 :     {
3173 :     //get who is currently grabbing the block (if anyone)
3174 :     new grabber = entity_get_int(ent, EV_INT_iuser2);
3175 :    
3176 :     //if entity is not being grabbed by someone else
3177 :     if (grabber == 0 || grabber == id)
3178 :     {
3179 :     //get the player ID of who has the block in a group (if anyone)
3180 :     new player = entity_get_int(ent, EV_INT_iuser1);
3181 :    
3182 :     //if the block is not in a group or is in this players group
3183 :     if (player == 0 || player == id)
3184 :     {
3185 :     new newBlock;
3186 :    
3187 :     //if block is in the players group and group count is larger than 1
3188 :     if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
3189 :     {
3190 :     new block;
3191 :     new blockCount = 0;
3192 :    
3193 :     //iterate through all blocks in the players group
3194 :     for (new i = 0; i <= gGroupCount[id]; ++i)
3195 :     {
3196 :     block = gGroupedBlocks[id][i];
3197 :    
3198 :     //if this block is in this players group
3199 :     if (isBlockInGroup(id, block))
3200 :     {
3201 :     //convert the block
3202 :     newBlock = convertBlock(id, block, convertTo);
3203 :    
3204 :     //if block was converted
3205 :     if (newBlock != 0)
3206 :     {
3207 :     //new block is now in the group
3208 :     gGroupedBlocks[id][i] = newBlock;
3209 :    
3210 :     //set the block so it is now 'being grouped'
3211 :     groupBlock(id, newBlock);
3212 :     }
3213 :     //count how many blocks could NOT be converted
3214 :     else
3215 :     {
3216 :     ++blockCount;
3217 :     }
3218 :     }
3219 :     }
3220 :    
3221 :     //if some blocks could NOT be converted
3222 :     if (blockCount > 1)
3223 :     {
3224 :     client_print(id, print_chat, "%sCouldn't convert %d blocks!", gszPrefix, blockCount);
3225 :     }
3226 :     }
3227 :     else
3228 :     {
3229 :     newBlock = convertBlock(id, ent, convertTo);
3230 :    
3231 :     //if block was not converted
3232 :     if (newBlock == 0)
3233 :     {
3234 :     //get the block type
3235 :     new blockType = entity_get_int(ent, EV_INT_body);
3236 :    
3237 :     client_print(id, print_chat, "%sYou cannot convert a %s block into a %s block while it is rotated!", gszPrefix, gszBlockNames[blockType], gszBlockNames[convertTo]);
3238 :     }
3239 :     }
3240 :     }
3241 :     else
3242 :     {
3243 :     //get name of player who has this block in their group
3244 :     new szName[32];
3245 :     get_user_name(player, szName, 32);
3246 :    
3247 :     //notify player who has this block in their group
3248 :     client_print(id, print_chat, "%s%s currently has this block in their group!", gszPrefix, szName);
3249 :     }
3250 :     }
3251 :     }
3252 :     }
3253 :     }
3254 :    
3255 :     convertBlock(id, ent, const convertTo)
3256 :     {
3257 :    
3258 :     new blockType = entity_get_int(ent, EV_INT_body);
3259 :    
3260 :     //if block to convert to is different to block to convert
3261 :     if (blockType != convertTo)
3262 :     {
3263 :     new Float:vOrigin[3];
3264 :     new Float:vAngles[3];
3265 :     new Float:vSizeMin[3];
3266 :     new Float:vSizeMax[3];
3267 :    
3268 :     //get block information from block player is aiming at
3269 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
3270 :     entity_get_vector(ent, EV_VEC_angles, vAngles);
3271 :     entity_get_vector(ent, EV_VEC_mins, vSizeMin);
3272 :     entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
3273 :    
3274 :     //if block is rotated and we're trying to convert it to a block that cannot be rotated
3275 :     if (vAngles[0] == 90.0 && (convertTo == BM_FIRE || convertTo == BM_TRAMPOLINE || convertTo == BM_SPEEDBOOST))
3276 :     {
3277 :     return 0;
3278 :     }
3279 :     else
3280 :     {
3281 :     //delete old block and create new one of given type
3282 :     deleteBlock(ent);
3283 :     return createBlock(id, convertTo, vOrigin, vAngles, vSizeMin, vSizeMax);
3284 :     }
3285 :     }
3286 :    
3287 :     return ent;
3288 :     }
3289 :    
3290 :     deleteBlockAiming(id)
3291 :     {
3292 :     //make sure player has access to this command
3293 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
3294 :     {
3295 :     //get entity that player is aiming at
3296 :     new ent, body;
3297 :     get_user_aiming(id, ent, body);
3298 :    
3299 :     //if entity player is aiming at is a block
3300 :     if (isBlock(ent))
3301 :     {
3302 :     //get who is currently grabbing the block (if anyone)
3303 :     new grabber = entity_get_int(ent, EV_INT_iuser2);
3304 :    
3305 :     //if entity is not being grabbed by someone else
3306 :     if (grabber == 0 || grabber == id)
3307 :     {
3308 :     //get the player ID of who has the block in a group (if anyone)
3309 :     new player = entity_get_int(ent, EV_INT_iuser1);
3310 :    
3311 :     //if the block is not in a group or is in this players group
3312 :     if (player == 0 || player == id)
3313 :     {
3314 :     //if block is not being grabbed
3315 :     if (entity_get_int(ent, EV_INT_iuser2) == 0)
3316 :     {
3317 :     //if block is in the players group and group count is larger than 1
3318 :     if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
3319 :     {
3320 :     new block;
3321 :    
3322 :     //iterate through all blocks in the players group
3323 :     for (new i = 0; i <= gGroupCount[id]; ++i)
3324 :     {
3325 :     block = gGroupedBlocks[id][i];
3326 :    
3327 :     //if block is still valid
3328 :     if (is_valid_ent(block))
3329 :     {
3330 :     //get player id of who has this block in their group
3331 :     new player = entity_get_int(block, EV_INT_iuser1);
3332 :    
3333 :     //if block is still in this players group
3334 :     if (player == id)
3335 :     {
3336 :     //delete the block
3337 :     deleteBlock(block);
3338 :     }
3339 :     }
3340 :     }
3341 :     }
3342 :     else
3343 :     {
3344 :     //delete the block
3345 :     deleteBlock(ent);
3346 :     }
3347 :     }
3348 :     }
3349 :     else
3350 :     {
3351 :     //get name of player who has this block in their group
3352 :     new szName[32];
3353 :     get_user_name(player, szName, 32);
3354 :    
3355 :     //notify player who has this block in their group
3356 :     client_print(id, print_chat, "%s%s currently has this block in their group!", gszPrefix, szName);
3357 :     }
3358 :     }
3359 :     }
3360 :     }
3361 :     }
3362 :    
3363 :     bool:deleteBlock(ent)
3364 :     {
3365 :     //if entity is a block
3366 :     if (isBlock(ent))
3367 :     {
3368 :     //get the sprite attached to the top of the block
3369 :     new sprite = entity_get_int(ent, EV_INT_iuser3);
3370 :    
3371 :     //if sprite entity is valid
3372 :     if (sprite)
3373 :     {
3374 :     //remove the task for the animation of the sprite (if one exists)
3375 :     if (task_exists(TASK_SPRITE + sprite))
3376 :     {
3377 :     remove_task(TASK_SPRITE + sprite);
3378 :     }
3379 :    
3380 :     //delete the sprite
3381 :     remove_entity(sprite);
3382 :     }
3383 :    
3384 :     //delete the block
3385 :     remove_entity(ent);
3386 :    
3387 :     //block was deleted
3388 :     return true;
3389 :     }
3390 :    
3391 :     //block was not deleted
3392 :     return false;
3393 :     }
3394 :    
3395 :     rotateBlockAiming(id)
3396 :     {
3397 :     //make sure player has access to this command
3398 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
3399 :     {
3400 :     //get block that player is aiming at
3401 :     new ent, body;
3402 :     get_user_aiming(id, ent, body);
3403 :    
3404 :     //if entity found is a block
3405 :     if (isBlock(ent))
3406 :     {
3407 :     //get who is currently grabbing the block (if anyone)
3408 :     new grabber = entity_get_int(ent, EV_INT_iuser2);
3409 :    
3410 :     //if entity is not being grabbed by someone else
3411 :     if (grabber == 0 || grabber == id)
3412 :     {
3413 :     //get the player ID of who has the block in a group (if anyone)
3414 :     new player = entity_get_int(ent, EV_INT_iuser1);
3415 :    
3416 :     //if the block is not in a group or is in this players group
3417 :     if (player == 0 || player == id)
3418 :     {
3419 :     //if block is in the players group and group count is larger than 1
3420 :     if (isBlockInGroup(id, ent) && gGroupCount[id] > 1)
3421 :     {
3422 :     new block;
3423 :     new bool:bRotateGroup = true;
3424 :    
3425 :     //iterate through all blocks in the players group
3426 :     for (new i = 0; i <= gGroupCount[id]; ++i)
3427 :     {
3428 :     block = gGroupedBlocks[id][i];
3429 :    
3430 :     //if block is in players group
3431 :     if (isBlockInGroup(id, block))
3432 :     {
3433 :     //get block type
3434 :     new blockType = entity_get_int(block, EV_INT_body);
3435 :    
3436 :     //if block cannot be rotated
3437 :     if (!isBlockTypeRotatable(blockType))
3438 :     {
3439 :     //found a block that cannot be rotated
3440 :     bRotateGroup = false;
3441 :    
3442 :     break;
3443 :     }
3444 :     }
3445 :     }
3446 :    
3447 :     //if we can rotate the group
3448 :     if (bRotateGroup)
3449 :     {
3450 :     //iterate through all blocks in the players group
3451 :     for (new i = 0; i <= gGroupCount[id]; ++i)
3452 :     {
3453 :     block = gGroupedBlocks[id][i];
3454 :    
3455 :     //if block is still valid
3456 :     if (isBlockInGroup(id, block))
3457 :     {
3458 :     //rotate the block
3459 :     rotateBlock(block);
3460 :     }
3461 :     }
3462 :     }
3463 :     else
3464 :     {
3465 :     //notify player that their group cannot be rotated
3466 :     client_print(id, print_chat, "%sYour group contains blocks that cannot be rotated!", gszPrefix);
3467 :     }
3468 :     }
3469 :     else
3470 :     {
3471 :     //rotate the block and get rotated block ID
3472 :     new bool:bRotatedBlock = rotateBlock(ent);
3473 :    
3474 :     //if block did not rotate successfully
3475 :     if (!bRotatedBlock)
3476 :     {
3477 :     //get block type
3478 :     new blockType = entity_get_int(ent, EV_INT_body);
3479 :    
3480 :     //notify player block couldn't rotate
3481 :     client_print(id, print_chat, "%s%s blocks cannot be rotated!", gszPrefix, gszBlockNames[blockType]);
3482 :     }
3483 :     }
3484 :     }
3485 :     else
3486 :     {
3487 :     //get name of player who has this block in their group
3488 :     new szName[32];
3489 :     get_user_name(player, szName, 32);
3490 :    
3491 :     //notify player who has this block in their group
3492 :     client_print(id, print_chat, "%s%s currently has this block in their group!", gszPrefix, szName);
3493 :     }
3494 :     }
3495 :     }
3496 :     }
3497 :     }
3498 :    
3499 :     bool:rotateBlock(ent)
3500 :     {
3501 :     //if entity is valid
3502 :     if (is_valid_ent(ent))
3503 :     {
3504 :     //get block type
3505 :     new blockType = entity_get_int(ent, EV_INT_body);
3506 :    
3507 :     //if block is a type that can be rotated (a block without a sprite, makes it easier!)
3508 :     if (isBlockTypeRotatable(blockType))
3509 :     {
3510 :     new Float:vAngles[3];
3511 :     new Float:vSizeMin[3];
3512 :     new Float:vSizeMax[3];
3513 :    
3514 :     //get block information
3515 :     entity_get_vector(ent, EV_VEC_angles, vAngles);
3516 :    
3517 :     //create new block using current block information with new angles and sizes
3518 :     if (vAngles[0] == 0.0 && vAngles[2] == 0.0)
3519 :     {
3520 :     vAngles[0] = 90.0;
3521 :     vSizeMin = gfBlockSizeMinForX;
3522 :     vSizeMax = gfBlockSizeMaxForX;
3523 :     }
3524 :     else if (vAngles[0] == 90.0 && vAngles[2] == 0.0)
3525 :     {
3526 :     vAngles[0] = 90.0;
3527 :     vAngles[2] = 90.0;
3528 :     vSizeMin = gfBlockSizeMinForY;
3529 :     vSizeMax = gfBlockSizeMaxForY;
3530 :     }
3531 :     else
3532 :     {
3533 :     vAngles = gfDefaultBlockAngles;
3534 :     vSizeMin = gfBlockSizeMinForZ;
3535 :     vSizeMax = gfBlockSizeMaxForZ;
3536 :     }
3537 :    
3538 :     entity_set_vector(ent, EV_VEC_angles, vAngles);
3539 :     entity_set_size(ent, vSizeMin, vSizeMax);
3540 :    
3541 :     return true;
3542 :     }
3543 :     }
3544 :    
3545 :     return false;
3546 :     }
3547 :    
3548 :     copyBlock(ent)
3549 :     {
3550 :     //if entity is valid
3551 :     if (is_valid_ent(ent))
3552 :     {
3553 :     new Float:vOrigin[3];
3554 :     new Float:vAngles[3];
3555 :     new Float:vSizeMin[3];
3556 :     new Float:vSizeMax[3];
3557 :     new blockType;
3558 :    
3559 :     //get blocktype and origin of currently grabbed block
3560 :     blockType = entity_get_int(ent, EV_INT_body);
3561 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
3562 :     entity_get_vector(ent, EV_VEC_angles, vAngles);
3563 :     entity_get_vector(ent, EV_VEC_mins, vSizeMin);
3564 :     entity_get_vector(ent, EV_VEC_maxs, vSizeMax);
3565 :    
3566 :     //create a block of the same type in the same location
3567 :     return createBlock(0, blockType, vOrigin, vAngles, vSizeMin, vSizeMax);
3568 :     }
3569 :    
3570 :     return 0;
3571 :     }
3572 :    
3573 :     /* BLOCK TESTS */
3574 :     bool:isBlockInGroup(id, ent)
3575 :     {
3576 :     //is entity valid
3577 :     if (is_valid_ent(ent))
3578 :     {
3579 :     //get player who has this block in their group (if anyone)
3580 :     new player = entity_get_int(ent, EV_INT_iuser1);
3581 :    
3582 :     if (player == id)
3583 :     {
3584 :     return true;
3585 :     }
3586 :     }
3587 :    
3588 :     return false;
3589 :     }
3590 :    
3591 :     bool:isBlockTypeRotatable(blockType)
3592 :     {
3593 :     if (blockType != BM_FIRE && blockType != BM_TRAMPOLINE && blockType != BM_SPEEDBOOST)
3594 :     {
3595 :     return true;
3596 :     }
3597 :    
3598 :     return false;
3599 :     }
3600 :    
3601 :     bool:isBlock(ent)
3602 :     {
3603 :     //is it a valid entity
3604 :     if (is_valid_ent(ent))
3605 :     {
3606 :     //get classname of entity
3607 :     new szClassname[32];
3608 :     entity_get_string(ent, EV_SZ_classname, szClassname, 32);
3609 :    
3610 :     //if classname of entity matches global block classname
3611 :     if (equal(szClassname, gszBlockClassname) || equal(szClassname, "bcm"))
3612 :     {
3613 :     //entity is a block
3614 :     return true;
3615 :     }
3616 :     }
3617 :    
3618 :     //entity is not a block
3619 :     return false;
3620 :     }
3621 :    
3622 :     bool:isBlockStuck(ent)
3623 :     {
3624 :     //first make sure the entity is valid
3625 :     if (is_valid_ent(ent))
3626 :     {
3627 :     new content;
3628 :     new Float:vOrigin[3];
3629 :     new Float:vPoint[3];
3630 :     new Float:fSizeMin[3];
3631 :     new Float:fSizeMax[3];
3632 :    
3633 :     //get the size of the block being grabbed
3634 :     entity_get_vector(ent, EV_VEC_mins, fSizeMin);
3635 :     entity_get_vector(ent, EV_VEC_maxs, fSizeMax);
3636 :    
3637 :     //get the origin of the block
3638 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
3639 :    
3640 :     //decrease the size values of the block
3641 :     fSizeMin[0] += 1.0;
3642 :     fSizeMax[0] -= 1.0;
3643 :     fSizeMin[1] += 1.0;
3644 :     fSizeMax[1] -= 1.0;
3645 :     fSizeMin[2] += 1.0;
3646 :     fSizeMax[2] -= 1.0;
3647 :    
3648 :     //get the contents of the centre of all 6 faces of the block
3649 :     for (new i = 0; i < 14; ++i)
3650 :     {
3651 :     //start by setting the point to the origin of the block (the middle)
3652 :     vPoint = vOrigin;
3653 :    
3654 :     //set the values depending on the loop number
3655 :     switch (i)
3656 :     {
3657 :     //corners
3658 :     case 0: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMax[2]; }
3659 :     case 1: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMax[2]; }
3660 :     case 2: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMax[2]; }
3661 :     case 3: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMax[2]; }
3662 :     case 4: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMin[2]; }
3663 :     case 5: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMax[1]; vPoint[2] += fSizeMin[2]; }
3664 :     case 6: { vPoint[0] += fSizeMax[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMin[2]; }
3665 :     case 7: { vPoint[0] += fSizeMin[0]; vPoint[1] += fSizeMin[1]; vPoint[2] += fSizeMin[2]; }
3666 :    
3667 :     //centre of faces
3668 :     case 8: { vPoint[0] += fSizeMax[0]; }
3669 :     case 9: { vPoint[0] += fSizeMin[0]; }
3670 :     case 10: { vPoint[1] += fSizeMax[1]; }
3671 :     case 11: { vPoint[1] += fSizeMin[1]; }
3672 :     case 12: { vPoint[2] += fSizeMax[2]; }
3673 :     case 13: { vPoint[2] += fSizeMin[2]; }
3674 :     }
3675 :    
3676 :     //get the contents of the point on the block
3677 :     content = point_contents(vPoint);
3678 :    
3679 :     //if the point is out in the open
3680 :     if (content == CONTENTS_EMPTY || content == 0)
3681 :     {
3682 :     //block is not stuck
3683 :     return false;
3684 :     }
3685 :     }
3686 :     }
3687 :     else
3688 :     {
3689 :     //entity is invalid but don't say its stuck
3690 :     return false;
3691 :     }
3692 :    
3693 :     //block is stuck
3694 :     return true;
3695 :     }
3696 :    
3697 :     bool:isTeleport(ent)
3698 :     {
3699 :     if (is_valid_ent(ent))
3700 :     {
3701 :     //get classname of entity
3702 :     new szClassname[32];
3703 :     entity_get_string(ent, EV_SZ_classname, szClassname, 32);
3704 :    
3705 :     //compare classnames
3706 :     if (equal(szClassname, gszTeleportStartClassname) || equal(szClassname, gszTeleportEndClassname))
3707 :     {
3708 :     //entity is a teleport
3709 :     return true;
3710 :     }
3711 :     }
3712 :    
3713 :     //entity is not a teleport
3714 :     return false;
3715 :     }
3716 :    
3717 :     doSnapping(id, ent, Float:fMoveTo[3])
3718 :     {
3719 :     //if player has snapping enabled
3720 :     if (gbSnapping[id])
3721 :     {
3722 :     new Float:fSnapSize = gfSnapDistance + gfSnappingGap[id];
3723 :     new Float:vReturn[3];
3724 :     new Float:dist;
3725 :     new Float:distOld = 9999.9;
3726 :     new Float:vTraceStart[3];
3727 :     new Float:vTraceEnd[3];
3728 :     new tr;
3729 :     new trClosest = 0;
3730 :     new blockFace;
3731 :    
3732 :     //get the size of the block being grabbed
3733 :     new Float:fSizeMin[3];
3734 :     new Float:fSizeMax[3];
3735 :     entity_get_vector(ent, EV_VEC_mins, fSizeMin);
3736 :     entity_get_vector(ent, EV_VEC_maxs, fSizeMax);
3737 :    
3738 :     //do 6 traces out from each face of the block
3739 :     for (new i = 0; i < 6; ++i)
3740 :     {
3741 :     //setup the start of the trace
3742 :     vTraceStart = fMoveTo;
3743 :    
3744 :     switch (i)
3745 :     {
3746 :     case 0: vTraceStart[0] += fSizeMin[0]; //edge of block on -X
3747 :     case 1: vTraceStart[0] += fSizeMax[0]; //edge of block on +X
3748 :     case 2: vTraceStart[1] += fSizeMin[1]; //edge of block on -Y
3749 :     case 3: vTraceStart[1] += fSizeMax[1]; //edge of block on +Y
3750 :     case 4: vTraceStart[2] += fSizeMin[2]; //edge of block on -Z
3751 :     case 5: vTraceStart[2] += fSizeMax[2]; //edge of block on +Z
3752 :     }
3753 :    
3754 :     //setup the end of the trace
3755 :     vTraceEnd = vTraceStart;
3756 :    
3757 :     switch (i)
3758 :     {
3759 :     case 0: vTraceEnd[0] -= fSnapSize;
3760 :     case 1: vTraceEnd[0] += fSnapSize;
3761 :     case 2: vTraceEnd[1] -= fSnapSize;
3762 :     case 3: vTraceEnd[1] += fSnapSize;
3763 :     case 4: vTraceEnd[2] -= fSnapSize;
3764 :     case 5: vTraceEnd[2] += fSnapSize;
3765 :     }
3766 :    
3767 :     //trace a line out from one of the block faces
3768 :     tr = trace_line(ent, vTraceStart, vTraceEnd, vReturn);
3769 :    
3770 :     //if the trace found a block and block is not in group or block to snap to is not in group
3771 :     if (isBlock(tr) && (!isBlockInGroup(id, tr) || !isBlockInGroup(id, ent)))
3772 :     {
3773 :     //get the distance from the grabbed block to the found block
3774 :     dist = get_distance_f(vTraceStart, vReturn);
3775 :    
3776 :     //if distance to found block is less than the previous block
3777 :     if (dist < distOld)
3778 :     {
3779 :     trClosest = tr;
3780 :     distOld = dist;
3781 :    
3782 :     //save the block face where the trace came from
3783 :     blockFace = i;
3784 :     }
3785 :     }
3786 :     }
3787 :    
3788 :     //if there is a block within the snapping range
3789 :     if (is_valid_ent(trClosest))
3790 :     {
3791 :     //get origin of closest block
3792 :     new Float:vOrigin[3];
3793 :     entity_get_vector(trClosest, EV_VEC_origin, vOrigin);
3794 :    
3795 :     //get sizes of closest block
3796 :     new Float:fTrSizeMin[3];
3797 :     new Float:fTrSizeMax[3];
3798 :     entity_get_vector(trClosest, EV_VEC_mins, fTrSizeMin);
3799 :     entity_get_vector(trClosest, EV_VEC_maxs, fTrSizeMax);
3800 :    
3801 :     //move the subject block to the origin of the closest block
3802 :     fMoveTo = vOrigin;
3803 :    
3804 :     //offset the block to be on the side where the trace hit the closest block
3805 :     if (blockFace == 0) fMoveTo[0] += (fTrSizeMax[0] + fSizeMax[0]) + gfSnappingGap[id];
3806 :     if (blockFace == 1) fMoveTo[0] += (fTrSizeMin[0] + fSizeMin[0]) - gfSnappingGap[id];
3807 :     if (blockFace == 2) fMoveTo[1] += (fTrSizeMax[1] + fSizeMax[1]) + gfSnappingGap[id];
3808 :     if (blockFace == 3) fMoveTo[1] += (fTrSizeMin[1] + fSizeMin[1]) - gfSnappingGap[id];
3809 :     if (blockFace == 4) fMoveTo[2] += (fTrSizeMax[2] + fSizeMax[2]) + gfSnappingGap[id];
3810 :     if (blockFace == 5) fMoveTo[2] += (fTrSizeMin[2] + fSizeMin[2]) - gfSnappingGap[id];
3811 :     }
3812 :     }
3813 :     }
3814 :    
3815 :     /***** FILE HANDLING *****/
3816 :     saveBlocks(id)
3817 :     {
3818 :     //make sure player has access to this command
3819 :     if (get_user_flags(id) & BM_ADMIN_LEVEL)
3820 :     {
3821 :     new file = fopen(gszNewFile, "wt");
3822 :     new ent = -1;
3823 :     new blockType;
3824 :     new Float:vOrigin[3];
3825 :     new Float:vAngles[3];
3826 :     new Float:vStart[3];
3827 :     new Float:vEnd[3];
3828 :     new blockCount = 0;
3829 :     new teleCount = 0;
3830 :     new szData[128];
3831 :    
3832 :     while ((ent = find_ent_by_class(ent, gszBlockClassname)))
3833 :     {
3834 :     //get block info
3835 :     blockType = entity_get_int(ent, EV_INT_body);
3836 :     entity_get_vector(ent, EV_VEC_origin, vOrigin);
3837 :     entity_get_vector(ent, EV_VEC_angles, vAngles);
3838 :    
3839 :     //format block info and save it to file
3840 :     formatex(szData, 128, "%c %f %f %f %f %f %f^n", gBlockSaveIds[blockType], vOrigin[0], vOrigin[1], vOrigin[2], vAngles[0], vAngles[1], vAngles[2]);
3841 :     fputs(file, szData);
3842 :    
3843 :     //increment block count
3844 :     ++blockCount;
3845 :     }
3846 :    
3847 :     //iterate through teleport end entities because you can't have an end without a start
3848 :     ent = -1;
3849 :    
3850 :     while ((ent = find_ent_by_class(ent, gszTeleportEndClassname)))
3851 :     {
3852 :     //get the id of the start of the teleporter
3853 :     new tele = entity_get_int(ent, EV_INT_iuser1);
3854 :    
3855 :     //check that start of teleport is a valid entity
3856 :     if (tele)
3857 :     {
3858 :     //get the origin of the start of the teleport and save it to file
3859 :     entity_get_vector(tele, EV_VEC_origin, vStart);
3860 :     entity_get_vector(ent, EV_VEC_origin, vEnd);
3861 :    
3862 :     formatex(szData, 128, "%s %f %f %f %f %f %f^n", "*", vStart[0], vStart[1], vStart[2], vEnd[0], vEnd[1], vEnd[2]);
3863 :     fputs(file, szData);
3864 :    
3865 :     //2 teleport entities count as 1 teleporter
3866 :     ++teleCount;
3867 :     }
3868 :     }
3869 :    
3870 :     //get players name
3871 :     new szName[32];
3872 :     get_user_name(id, szName, 32);
3873 :    
3874 :     //notify all admins that the player saved blocks to file
3875 :     for (new i = 1; i <= 32; ++i)
3876 :     {
3877 :     //make sure player is connected
3878 :     if (is_user_connected(i))
3879 :     {
3880 :     if (get_user_flags(i) & BM_ADMIN_LEVEL)
3881 :     {
3882 :     client_print(i, print_chat, "%s'%s' saved %d block%s and %d teleporter%s to file! Total entites in map: %d", gszPrefix, szName, blockCount, (blockCount == 1 ? "" : "s"), teleCount, (teleCount == 1 ? "" : "s"), entity_count());
3883 :     }
3884 :     }
3885 :     }
3886 :    
3887 :     //close file
3888 :     fclose(file);
3889 :     }
3890 :     }
3891 :    
3892 :     loadBlocks(id)
3893 :     {
3894 :     new bool:bAccess = false;
3895 :    
3896 :     //if this function was called on map load, ID is 0
3897 :     if (id == 0)
3898 :     {
3899 :     bAccess = true;
3900 :     }
3901 :     //make sure user calling this function has access
3902 :     else if (get_user_flags(id) & BM_ADMIN_LEVEL)
3903 :     {
3904 :     bAccess = true;
3905 :     }
3906 :    
3907 :     if (bAccess)
3908 :     {
3909 :     //if map file exists
3910 :     if (file_exists(gszNewFile))
3911 :     {
3912 :     //if a player is loading the blocks then first delete all the old blocks and teleports
3913 :     if (id > 0 && id <= 32)
3914 :     {
3915 :     deleteAllBlocks(id, false);
3916 :     deleteAllTeleports(id, false);
3917 :     }
3918 :    
3919 :     new szData[128];
3920 :     new szType[2];
3921 :     new sz1[16], sz2[16], sz3[16], sz4[16], sz5[16], sz6[16];
3922 :     new Float:vVec1[3];
3923 :     new Float:vVec2[3];
3924 :     new Float:fSizeMin[3];
3925 :     new Float:fSizeMax[3];
3926 :     new f = fopen(gszNewFile, "rt");
3927 :     new blockCount = 0;
3928 :     new teleCount = 0;
3929 :    
3930 :     //iterate through all the lines in the file
3931 :     while (!feof(f))
3932 :     {
3933 :     szType = "";
3934 :     fgets(f, szData, 128);
3935 :     parse(szData, szType, 1, sz1, 16, sz2, 16, sz3, 16, sz4, 16, sz5, 16, sz6, 16);
3936 :    
3937 :     vVec1[0] = str_to_float(sz1);
3938 :     vVec1[1] = str_to_float(sz2);
3939 :     vVec1[2] = str_to_float(sz3);
3940 :     vVec2[0] = str_to_float(sz4);
3941 :     vVec2[1] = str_to_float(sz5);
3942 :     vVec2[2] = str_to_float(sz6);
3943 :    
3944 :     if (strlen(szType) > 0)
3945 :     {
3946 :     //if type is not a teleport
3947 :     if (szType[0] != '*')
3948 :     {
3949 :     //set block size depending on block angles
3950 :     if (vVec2[0] == 90.0 && vVec2[1] == 0.0 && vVec2[2] == 0.0)
3951 :     {
3952 :     fSizeMin = gfBlockSizeMinForX;
3953 :     fSizeMax = gfBlockSizeMaxForX;
3954 :     }
3955 :     else if (vVec2[0] == 90.0 && vVec2[1] == 0.0 && vVec2[2] == 90.0)
3956 :     {
3957 :     fSizeMin = gfBlockSizeMinForY;
3958 :     fSizeMax = gfBlockSizeMaxForY;
3959 :     }
3960 :     else
3961 :     {
3962 :     fSizeMin = gfBlockSizeMinForZ;
3963 :     fSizeMax = gfBlockSizeMaxForZ;
3964 :     }
3965 :    
3966 :     //increment block counter
3967 :     ++blockCount;
3968 :     }
3969 :    
3970 :     //create block or teleport depending on type
3971 :     switch (szType[0])
3972 :     {
3973 :     case 'A': createBlock(0, BM_PLATFORM, vVec1, vVec2, fSizeMin, fSizeMax);
3974 :     case 'B': createBlock(0, BM_BHOP, vVec1, vVec2, fSizeMin, fSizeMax);
3975 :     case 'C': createBlock(0, BM_DAMAGE, vVec1, vVec2, fSizeMin, fSizeMax);
3976 :     case 'D': createBlock(0, BM_HEALER, vVec1, vVec2, fSizeMin, fSizeMax);
3977 :     case 'E': createBlock(0, BM_INVINCIBILITY, vVec1, vVec2, fSizeMin, fSizeMax);
3978 :     case 'F': createBlock(0, BM_STEALTH, vVec1, vVec2, fSizeMin, fSizeMax);
3979 :     case 'G': createBlock(0, BM_TRAMPOLINE, vVec1, vVec2, fSizeMin, fSizeMax);
3980 :     case 'H': createBlock(0, BM_SPEEDBOOST, vVec1, vVec2, fSizeMin, fSizeMax);
3981 :     case 'I': createBlock(0, BM_NOFALLDAMAGE, vVec1, vVec2, fSizeMin, fSizeMax);
3982 :     case 'J': createBlock(0, BM_ICE, vVec1, vVec2, fSizeMin, fSizeMax);
3983 :     case 'K': createBlock(0, BM_DEATH, vVec1, vVec2, fSizeMin, fSizeMax);
3984 :     case 'L': createBlock(0, BM_NUKE, vVec1, vVec2, fSizeMin, fSizeMax);
3985 :     case 'M': createBlock(0, BM_CAMOUFLAGE, vVec1, vVec2, fSizeMin, fSizeMax);
3986 :     case 'N': createBlock(0, BM_LOWGRAVITY, vVec1, vVec2, fSizeMin, fSizeMax);
3987 :     case 'O': createBlock(0, BM_FIRE, vVec1, vVec2, fSizeMin, fSizeMax);
3988 :     case 'P': createBlock(0, BM_SLAP, vVec1, vVec2, fSizeMin, fSizeMax);
3989 :     case 'Q': createBlock(0, BM_RANDOM, vVec1, vVec2, fSizeMin, fSizeMax);
3990 :     case 'R': createBlock(0, BM_HONEY, vVec1, vVec2, fSizeMin, fSizeMax);
3991 :     case 'S': createBlock(0, BM_BARRIER_CT, vVec1, vVec2, fSizeMin, fSizeMax);
3992 :     case 'T': createBlock(0, BM_BARRIER_T, vVec1, vVec2, fSizeMin, fSizeMax);
3993 :     case 'U': createBlock(0, BM_BOOTSOFSPEED, vVec1, vVec2, fSizeMin, fSizeMax);
3994 :    
3995 :     case '*':
3996 :     {
3997 :     createTeleport(0, TELEPORT_START, vVec1);
3998 :     createTeleport(0, TELEPORT_END, vVec2);
3999 :    
4000 :     //increment teleport count
4001 :     ++teleCount;
4002 :     }
4003 :    
4004 :     default:
4005 :     {
4006 :     log_amx("%sInvalid block type: %c in: %s", gszPrefix, szType[0], gszFile);
4007 :    
4008 :     //decrement block counter because a block was not created
4009 :     --blockCount;
4010 :     }
4011 :     }
4012 :     }
4013 :     }
4014 :    
4015 :     fclose(f);
4016 :    
4017 :     //if a player is loading the blocks
4018 :     if (id > 0 && id <= 32)
4019 :     {
4020 :     //get players name
4021 :     new szName[32];
4022 :     get_user_name(id, szName, 32);
4023 :    
4024 :     //notify all admins that the player loaded blocks from file
4025 :     for (new i = 1; i <= 32; ++i)
4026 :     {
4027 :     //make sure player is connected
4028 :     if (is_user_connected(i))
4029 :     {
4030 :     if (get_user_flags(i) & BM_ADMIN_LEVEL)
4031 :     {
4032 :     client_print(i, print_chat, "%s'%s' loaded %d block%s and %d teleporter%s from file! Total entites in map: %d", gszPrefix, szName, blockCount, (blockCount == 1 ? "" : "s"), teleCount, (teleCount == 1 ? "" : "s"), entity_count());
4033 :     }
4034 :     }
4035 :     }
4036 :     }
4037 :     }
4038 :     else
4039 :     {
4040 :     //if a player is loading the blocks
4041 :     if (id > 0 && id <= 32)
4042 :     {
4043 :     //notify player that the file could not be found
4044 :     client_print(id, print_chat, "%sCouldn't find file: %s", gszPrefix, gszNewFile);
4045 :     }
4046 :     else
4047 :     {
4048 :     log_amx("%sCant find blocks file. Trying old save/load method...", gszPrefix);
4049 :     }
4050 :    
4051 :     //check old saving/loading method
4052 :     loadBlocksOld();
4053 :     }
4054 :     }
4055 :     }
4056 :    
4057 :     loadBlocksOld()
4058 :     {
4059 :     if (!file_exists(gszFile))
4060 :     {
4061 :     return;
4062 :     }
4063 :    
4064 :     new szData[128];
4065 :     new szType[2];
4066 :     new oX[13], oY[13], oZ[13];
4067 :     new aX[13], aY[13], aZ[13];
4068 :     new Float:vOrigin[3];
4069 :     new Float:vAngles[3];
4070 :     new f = fopen(gszFile, "rt");
4071 :     new blockType;
4072 :    
4073 :     //iterate through all the lines in the file
4074 :     while (!feof(f))
4075 :     {
4076 :     szType = "";
4077 :     fgets(f, szData, 128);
4078 :     parse(szData, szType, 2, oX, 12, oY, 12, oZ, 12, aX, 12, aY, 12, aZ, 12);
4079 :    
4080 :     vOrigin[0] = str_to_float(oX);
4081 :     vOrigin[1] = str_to_float(oY);
4082 :     vOrigin[2] = str_to_float(oZ);
4083 :     vAngles[0] = str_to_float(aX);
4084 :     vAngles[1] = str_to_float(aY);
4085 :     vAngles[2] = str_to_float(aZ);
4086 :    
4087 :     blockType = -1;
4088 :    
4089 :     if (strlen(szType) > 0)
4090 :     {
4091 :     //first check if type is a teleporter
4092 :     if (szType[0] == 'S')
4093 :     {
4094 :     createTeleport(0, TELEPORT_START, vOrigin);
4095 :     }
4096 :     else if (szType[0] == 'D')
4097 :     {
4098 :     createTeleport(0, TELEPORT_END, vOrigin);
4099 :     }
4100 :     else
4101 :     {
4102 :     blockType = str_to_num(szType);
4103 :    
4104 :     //if blockType number is valid, create the block
4105 :     if (blockType >= 0 && blockType < gBlockMax)
4106 :     {
4107 :     //create clipping vectors from angles
4108 :     if (vAngles[0] == 90.0 && vAngles[1] == 0.0 && vAngles[2] == 0.0)
4109 :     {
4110 :     createBlock(0, blockType, vOrigin, vAngles, gfBlockSizeMinForX, gfBlockSizeMaxForX);
4111 :     }
4112 :     else if (vAngles[0] == 90.0 && vAngles[1] == 0.0 && vAngles[2] == 90.0)
4113 :     {
4114 :     createBlock(0, blockType, vOrigin, vAngles, gfBlockSizeMinForY, gfBlockSizeMaxForY);
4115 :     }
4116 :     else
4117 :     {
4118 :     createBlock(0, blockType, vOrigin, gfDefaultBlockAngles, gfBlockSizeMinForZ, gfBlockSizeMaxForZ);
4119 :     }
4120 :     }
4121 :     else
4122 :     {
4123 :     log_amx("%sInvalid box type: %c in: %s", gszPrefix, szType[0], gszFile);
4124 :     }
4125 :     }
4126 :     }
4127 :     }
4128 :    
4129 :     fclose(f);
4130 :     }
4131 :    
4132 :     /* MISC */
4133 :     drawLine(Float:vOrigin1[3], Float:vOrigin2[3], life)
4134 :     {
4135 :     message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
4136 :     write_byte(TE_BEAMPOINTS);
4137 :     write_coord(floatround(vOrigin1[0], floatround_floor));
4138 :     write_coord(floatround(vOrigin1[1], floatround_floor));
4139 :     write_coord(floatround(vOrigin1[2], floatround_floor));
4140 :     write_coord(floatround(vOrigin2[0], floatround_floor));
4141 :     write_coord(floatround(vOrigin2[1], floatround_floor));
4142 :     write_coord(floatround(vOrigin2[2], floatround_floor));
4143 :     write_short(gSpriteIdBeam); //sprite index
4144 :     write_byte(0); //starting frame
4145 :     write_byte(1); //frame rate in 0.1's
4146 :     write_byte(life); //life in 0.1's
4147 :     write_byte(5); //line width in 0.1's
4148 :     write_byte(0); //noise amplitude in 0.01's
4149 :     write_byte(255); //red
4150 :     write_byte(255); //green
4151 :     write_byte(255); //blue
4152 :     write_byte(255); //brightness
4153 :     write_byte(0); //scroll speed in 0.1's
4154 :     message_end();
4155 :     }

Contact
ViewVC Help
Powered by ViewVC 1.0.4