3 * =============================================================================
4 * SourceMod Basefuncommands Plugin
5 * Provides freeze and freezebomb functionality
7 * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
8 * =============================================================================
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License, version 3.0, as published by the
12 * Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
22 * As a special exception, AlliedModders LLC gives you permission to link the
23 * code of this program (as well as its derivative works) to "Half-Life 2," the
24 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
25 * by the Valve Corporation. You must obey the GNU General Public License in
26 * all respects for all other code used. Additionally, AlliedModders LLC grants
27 * this exception to all derivative works. AlliedModders LLC defines further
28 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
29 * or <http://www.sourcemod.net/license.php>.
34 new g_FreezeSerial[MAXPLAYERS+1] = { 0, ... };
35 new g_FreezeBombSerial[MAXPLAYERS+1] = { 0, ... };
36 new g_FreezeTime[MAXPLAYERS+1] = { 0, ... };
37 new g_FreezeBombTime[MAXPLAYERS+1] = { 0, ... };
39 new Handle:g_Cvar_FreezeDuration = INVALID_HANDLE;
40 new Handle:g_Cvar_FreezeBombTicks = INVALID_HANDLE;
41 new Handle:g_Cvar_FreezeBombRadius = INVALID_HANDLE;
42 new Handle:g_Cvar_FreezeBombMode = INVALID_HANDLE;
44 FreezeClient(client, time)
46 if (g_FreezeSerial[client] != 0)
48 UnfreezeClient(client);
51 SetEntityMoveType(client, MOVETYPE_NONE);
52 SetEntityRenderColor(client, 0, 128, 255, 192);
55 GetClientEyePosition(client, vec);
56 EmitAmbientSound(SOUND_FREEZE, vec, client, SNDLEVEL_RAIDSIREN);
58 g_FreezeTime[client] = time;
59 g_FreezeSerial[client] = ++ g_Serial_Gen;
60 CreateTimer(1.0, Timer_Freeze, client | (g_Serial_Gen << 7), DEFAULT_TIMER_FLAGS);
63 UnfreezeClient(client)
65 g_FreezeSerial[client] = 0;
66 g_FreezeTime[client] = 0;
68 if (IsClientInGame(client))
71 GetClientAbsOrigin(client, vec);
74 GetClientEyePosition(client, vec);
75 EmitAmbientSound(SOUND_FREEZE, vec, client, SNDLEVEL_RAIDSIREN);
77 SetEntityMoveType(client, MOVETYPE_WALK);
79 SetEntityRenderColor(client, 255, 255, 255, 255);
83 CreateFreezeBomb(client)
85 if (g_FreezeBombSerial[client] != 0)
87 KillFreezeBomb(client);
90 g_FreezeBombTime[client] = GetConVarInt(g_Cvar_FreezeBombTicks);
91 g_FreezeBombSerial[client] = ++g_Serial_Gen;
92 CreateTimer(1.0, Timer_FreezeBomb, client | (g_Serial_Gen << 7), DEFAULT_TIMER_FLAGS);
95 KillFreezeBomb(client)
97 g_FreezeBombSerial[client] = 0;
98 g_FreezeBombTime[client] = 0;
100 if (IsClientInGame(client))
102 SetEntityRenderColor(client, 255, 255, 255, 255);
108 for(new i = 1; i <= MaxClients; i++)
110 if (g_FreezeSerial[i] != 0)
115 if (g_FreezeBombSerial[i] != 0)
122 PerformFreeze(client, target, time)
124 FreezeClient(target, time);
125 LogAction(client, target, "\"%L\" froze \"%L\"", client, target);
128 PerformFreezeBomb(client, target)
130 if (g_FreezeBombSerial[target] != 0)
132 KillFreezeBomb(target);
133 LogAction(client, target, "\"%L\" removed a FreezeBomb on \"%L\"", client, target);
137 CreateFreezeBomb(target);
138 LogAction(client, target, "\"%L\" set a FreezeBomb on \"%L\"", client, target);
142 public Action:Timer_Freeze(Handle:timer, any:value)
144 new client = value & 0x7f;
145 new serial = value >> 7;
147 if (!IsClientInGame(client)
148 || !IsPlayerAlive(client)
149 || g_FreezeSerial[client] != serial)
151 UnfreezeClient(client);
155 if (g_FreezeTime[client] == 0)
157 UnfreezeClient(client);
159 /* HintText doesn't work on Dark Messiah */
160 if (g_GameEngine != SOURCE_SDK_DARKMESSIAH)
162 PrintHintText(client, "%t", "Unfrozen");
166 PrintCenterText(client, "%t", "Unfrozen");
172 if (g_GameEngine != SOURCE_SDK_DARKMESSIAH)
174 PrintHintText(client, "%t", "You will be unfrozen", g_FreezeTime[client]);
178 PrintCenterText(client, "%t", "You will be unfrozen", g_FreezeTime[client]);
181 g_FreezeTime[client]--;
182 SetEntityMoveType(client, MOVETYPE_NONE);
183 SetEntityRenderColor(client, 0, 128, 255, 135);
186 GetClientAbsOrigin(client, vec);
189 if (g_GlowSprite > -1)
191 TE_SetupGlowSprite(vec, g_GlowSprite, 0.95, 1.5, 50);
195 TE_SetupGlowSprite(vec, g_HaloSprite, 0.95, 1.5, 50);
200 return Plugin_Continue;
203 public Action:Timer_FreezeBomb(Handle:timer, any:value)
205 new client = value & 0x7f;
206 new serial = value >> 7;
208 if (!IsClientInGame(client)
209 || !IsPlayerAlive(client)
210 || g_FreezeBombSerial[client] != serial)
212 KillFreezeBomb(client);
217 GetClientEyePosition(client, vec);
218 g_FreezeBombTime[client]--;
220 if (g_FreezeBombTime[client] > 0)
224 if (g_FreezeBombTime[client] > 1)
226 color = RoundToFloor(g_FreezeBombTime[client] * (255.0 / GetConVarFloat(g_Cvar_FreezeBombTicks)));
227 EmitAmbientSound(SOUND_BEEP, vec, client, SNDLEVEL_RAIDSIREN);
232 EmitAmbientSound(SOUND_FINAL, vec, client, SNDLEVEL_RAIDSIREN);
235 SetEntityRenderColor(client, color, color, 255, 255);
237 decl String:name[64];
238 GetClientName(client, name, sizeof(name));
239 PrintCenterTextAll("%t", "Till Explodes", name, g_FreezeBombTime[client]);
241 GetClientAbsOrigin(client, vec);
244 TE_SetupBeamRingPoint(vec, 10.0, GetConVarFloat(g_Cvar_FreezeBombRadius) / 3.0, g_BeamSprite, g_HaloSprite, 0, 15, 0.5, 5.0, 0.0, greyColor, 10, 0);
246 TE_SetupBeamRingPoint(vec, 10.0, GetConVarFloat(g_Cvar_FreezeBombRadius) / 3.0, g_BeamSprite, g_HaloSprite, 0, 10, 0.6, 10.0, 0.5, whiteColor, 10, 0);
248 return Plugin_Continue;
252 if (g_ExplosionSprite > -1)
254 TE_SetupExplosion(vec, g_ExplosionSprite, 5.0, 1, 0, GetConVarInt(g_Cvar_FreezeBombRadius), 5000);
258 EmitAmbientSound(SOUND_BOOM, vec, client, SNDLEVEL_RAIDSIREN);
260 KillFreezeBomb(client);
261 FreezeClient(client, GetConVarInt(g_Cvar_FreezeDuration));
263 if (GetConVarInt(g_Cvar_FreezeBombMode) > 0)
265 new bool:teamOnly = ((GetConVarInt(g_Cvar_FreezeBombMode) == 1) ? true : false);
267 for (new i = 1; i <= MaxClients; i++)
269 if (!IsClientInGame(i) || !IsPlayerAlive(i) || i == client)
274 if (teamOnly && GetClientTeam(i) != GetClientTeam(client))
280 GetClientEyePosition(i, pos);
282 new Float:distance = GetVectorDistance(vec, pos);
284 if (distance > GetConVarFloat(g_Cvar_FreezeBombRadius))
289 if (g_BeamSprite2 > -1)
291 TE_SetupBeamPoints(vec, pos, g_BeamSprite2, g_HaloSprite, 0, 1, 0.7, 20.0, 50.0, 1, 1.5, blueColor, 10);
295 TE_SetupBeamPoints(vec, pos, g_BeamSprite, g_HaloSprite, 0, 1, 0.7, 20.0, 50.0, 1, 1.5, blueColor, 10);
299 FreezeClient(i, GetConVarInt(g_Cvar_FreezeDuration));
306 public AdminMenu_Freeze(Handle:topmenu,
307 TopMenuAction:action,
308 TopMenuObject:object_id,
313 if (action == TopMenuAction_DisplayOption)
315 Format(buffer, maxlength, "%T", "Freeze player", param);
317 else if (action == TopMenuAction_SelectOption)
319 DisplayFreezeMenu(param);
323 public AdminMenu_FreezeBomb(Handle:topmenu,
324 TopMenuAction:action,
325 TopMenuObject:object_id,
330 if (action == TopMenuAction_DisplayOption)
332 Format(buffer, maxlength, "%T", "FreezeBomb player", param);
334 else if (action == TopMenuAction_SelectOption)
336 DisplayFreezeBombMenu(param);
340 DisplayFreezeMenu(client)
342 new Handle:menu = CreateMenu(MenuHandler_Freeze);
344 decl String:title[100];
345 Format(title, sizeof(title), "%T:", "Freeze player", client);
346 SetMenuTitle(menu, title);
347 SetMenuExitBackButton(menu, true);
349 AddTargetsToMenu(menu, client, true, true);
351 DisplayMenu(menu, client, MENU_TIME_FOREVER);
354 DisplayFreezeBombMenu(client)
356 new Handle:menu = CreateMenu(MenuHandler_FreezeBomb);
358 decl String:title[100];
359 Format(title, sizeof(title), "%T:", "FreezeBomb player", client);
360 SetMenuTitle(menu, title);
361 SetMenuExitBackButton(menu, true);
363 AddTargetsToMenu(menu, client, true, true);
365 DisplayMenu(menu, client, MENU_TIME_FOREVER);
368 public MenuHandler_Freeze(Handle:menu, MenuAction:action, param1, param2)
370 if (action == MenuAction_End)
374 else if (action == MenuAction_Cancel)
376 if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
378 DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory);
381 else if (action == MenuAction_Select)
383 decl String:info[32];
386 GetMenuItem(menu, param2, info, sizeof(info));
387 userid = StringToInt(info);
389 if ((target = GetClientOfUserId(userid)) == 0)
391 PrintToChat(param1, "[SM] %t", "Player no longer available");
393 else if (!CanUserTarget(param1, target))
395 PrintToChat(param1, "[SM] %t", "Unable to target");
400 GetClientName(target, name, sizeof(name));
402 PerformFreeze(param1, target, GetConVarInt(g_Cvar_FreezeDuration));
403 ShowActivity2(param1, "[SM] ", "%t", "Froze target", "_s", name);
406 /* Re-draw the menu if they're still valid */
407 if (IsClientInGame(param1) && !IsClientInKickQueue(param1))
409 DisplayFreezeMenu(param1);
414 public MenuHandler_FreezeBomb(Handle:menu, MenuAction:action, param1, param2)
416 if (action == MenuAction_End)
420 else if (action == MenuAction_Cancel)
422 if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
424 DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory);
427 else if (action == MenuAction_Select)
429 decl String:info[32];
432 GetMenuItem(menu, param2, info, sizeof(info));
433 userid = StringToInt(info);
435 if ((target = GetClientOfUserId(userid)) == 0)
437 PrintToChat(param1, "[SM] %t", "Player no longer available");
439 else if (!CanUserTarget(param1, target))
441 PrintToChat(param1, "[SM] %t", "Unable to target");
446 GetClientName(target, name, sizeof(name));
448 PerformFreezeBomb(param1, target);
449 ShowActivity2(param1, "[SM] ", "%t", "Toggled FreezeBomb on target", "_s", name);
452 /* Re-draw the menu if they're still valid */
453 if (IsClientInGame(param1) && !IsClientInKickQueue(param1))
455 DisplayFreezeBombMenu(param1);
460 public Action:Command_Freeze(client, args)
464 ReplyToCommand(client, "[SM] Usage: sm_freeze <#userid|name> [time]");
465 return Plugin_Handled;
469 GetCmdArg(1, arg, sizeof(arg));
471 new seconds = GetConVarInt(g_Cvar_FreezeDuration);
475 decl String:time[20];
476 GetCmdArg(2, time, sizeof(time));
477 if (StringToIntEx(time, seconds) == 0)
479 ReplyToCommand(client, "[SM] %t", "Invalid Amount");
480 return Plugin_Handled;
484 decl String:target_name[MAX_TARGET_LENGTH];
485 decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml;
487 if ((target_count = ProcessTargetString(
492 COMMAND_FILTER_ALIVE,
497 ReplyToTargetError(client, target_count);
498 return Plugin_Handled;
501 for (new i = 0; i < target_count; i++)
503 PerformFreeze(client, target_list[i], seconds);
508 ShowActivity2(client, "[SM] ", "%t", "Froze target", target_name);
512 ShowActivity2(client, "[SM] ", "%t", "Froze target", "_s", target_name);
515 return Plugin_Handled;
518 public Action:Command_FreezeBomb(client, args)
522 ReplyToCommand(client, "[SM] Usage: sm_freezebomb <#userid|name>");
523 return Plugin_Handled;
527 GetCmdArg(1, arg, sizeof(arg));
529 decl String:target_name[MAX_TARGET_LENGTH];
530 decl target_list[MAXPLAYERS], target_count, bool:tn_is_ml;
532 if ((target_count = ProcessTargetString(
537 COMMAND_FILTER_ALIVE,
542 ReplyToTargetError(client, target_count);
543 return Plugin_Handled;
546 for (new i = 0; i < target_count; i++)
548 PerformFreezeBomb(client, target_list[i]);
553 ShowActivity2(client, "[SM] ", "%t", "Toggled FreezeBomb on target", target_name);
557 ShowActivity2(client, "[SM] ", "%t", "Toggled FreezeBomb on target", "_s", target_name);
560 return Plugin_Handled;