· 8 years ago · Jun 07, 2018, 05:14 AM
1#pragma semicolon 1
2#include <sourcemod>
3#include <cstrike>
4#include <sdktools>
5#include <clientprefs>
6#include <smlib>
7
8#undef REQUIRE_PLUGIN
9#include <updater>
10
11public Plugin:myinfo =
12{
13 name = "Retakes",
14 author = "Ofir",
15 description = "Retake Simulation",
16 version = "1.5",
17 url = "https://forums.alliedmods.net/member.php?u=190571"
18};
19
20//Enums and Contstants
21#define PREFIX " \x05[RETAKES]\x04 "
22#define UPDATE_URL "https://www.dropbox.com/s/gfbtaoo902cftpy/update_info.txt"
23#define SITEA 0
24#define SITEB 1
25#define MAXSPAWNS 64
26
27#define FL_USED_Ct (1 << 0)
28#define FL_USED_T (1 << 1)
29#define GRENADESSETCOUNT 6
30
31enum SpawnType
32{
33 None,
34 Bomb,
35 T,
36 Ct
37};
38
39enum Spawn
40{
41 Id,
42 SpawnType:Type,
43 Float:Location[3],
44 Float:Angles[3],
45 Site,
46 bool:Used
47};
48
49new const String:gs_GrenadeSets[][][64] = {
50 {"weapon_hegrenade", "weapon_flashbang"},
51 {"weapon_flashbang", "weapon_flashbang"},
52 {"weapon_flashbang", "none"},
53 {"weapon_smokegrenade", "none"},
54 {"moli", "none"},
55 {"none", "none"}
56};
57
58new gi_GrenadeSetsFlags[GRENADESSETCOUNT];
59
60//Cvars Handlers
61new Handle:gh_PistolRoundsCount = INVALID_HANDLE;
62new Handle:gh_WinRowScramble = INVALID_HANDLE;
63new Handle:gh_StrongPistolChance = INVALID_HANDLE;
64new Handle:gh_DidntPlant = INVALID_HANDLE;
65
66//Cvars Vars
67new gi_PistolRoundsCount;
68new gi_WinRowScramble;
69new gi_StrongPistolChance;
70new gi_DidntPlant;
71
72//Players Arrays
73new bool:gb_PreferenceLoaded[MAXPLAYERS+1] = {false, ...};
74new gi_PistolPrefence[MAXPLAYERS+1] = {0, ...};
75new gi_WantAwp[MAXPLAYERS+1] = {0, ...};
76new bool:gb_WantSilencer[MAXPLAYERS+1] = {false, ...};
77new gi_ChoosedSite[MAXPLAYERS+1];
78new gi_DamageCount[MAXPLAYERS+1];
79new gi_NextRoundTeam[MAXPLAYERS+1] = {-1, ...};
80new bool:gb_Warnned[MAXPLAYERS+1] = {false, ...};
81new bool:gb_PluginSwitchingTeam[MAXPLAYERS+1] = {false, ...};
82new bool:gb_Voted[MAXPLAYERS+1] = {false, ...};
83new Float:gf_UsedVP[MAXPLAYERS+1];
84
85//Global Vars
86new bool:gb_EditMode = false;
87new bool:gb_Scrambling = false;
88new bool:gb_WaitForPlayers = true;
89new bool:gb_WarmUp = false;
90new bool:gb_balancedTeams = false;
91new bool:gb_newClientsJoined = false;
92new bool:gb_BombPlanted = false;
93new bool:gb_OnlyPistols = false;
94new String:gs_CurrentMap[64];
95new gi_MoneyOffset;
96new gi_HelmetOffset;
97new g_precacheLaser;
98new g_precacheGlow;
99new g_Spawns[MAXSPAWNS][Spawn];
100new g_SpawnsCount = 0;
101new gi_WinRowCounter = 0;
102new gi_PlayerQueue[MAXPLAYERS+1];
103new gi_QueueCounter;
104new Float:gf_MapLoadTime;
105new Float:gf_StartRoundTime;
106new Handle:gh_MapLoadTimer;
107new gi_Bomber;
108new gi_Voters = 0; // Total voters connected. Doesn't include fake clients.
109new gi_Votes = 0; // Total number of "say rtv" votes
110new gi_VotesNeeded = 0; // Necessary votes before map vote begins. (voters * percent_needed)
111
112//Cookies
113new Handle:gh_SilencedM4 = INVALID_HANDLE;
114new Handle:gh_WantAwp = INVALID_HANDLE;
115new Handle:gh_PistolPrefence = INVALID_HANDLE;
116
117//Sql
118new Handle:gh_Sql = INVALID_HANDLE;
119new gi_ReconncetCounter = 0;
120
121public OnPluginStart()
122{
123 //Convars
124 gh_PistolRoundsCount = CreateConVar("retakes_pistols", "5", "How much Pistols Rounds should be. 0 to disable", _, true, 0.0);
125 gh_WinRowScramble = CreateConVar("retakes_winrow", "7", "How much row the T's need to win for scramble. 0 to disable", _, true, 0.0);
126 gh_StrongPistolChance = CreateConVar("retakes_strongchance", "33", "How much percent to give a awper a strong pistol by his choice. 0 to disable", _, true, 0.0, true, 100.0);
127 gh_DidntPlant = CreateConVar("retakes_didntplant", "0", "How much time player should be banned if he didnt planted twice. -1 - Do nothing, 0 - Kick client", _, true, -1.0);
128
129 gi_PistolRoundsCount = GetConVarInt(gh_PistolRoundsCount);
130 gi_WinRowScramble = GetConVarInt(gh_WinRowScramble);
131 gi_StrongPistolChance = GetConVarInt(gh_StrongPistolChance);
132 gi_DidntPlant = GetConVarInt(gh_DidntPlant);
133
134 HookConVarChange(gh_PistolRoundsCount, Action_OnSettingsChange);
135 HookConVarChange(gh_WinRowScramble, Action_OnSettingsChange);
136 HookConVarChange(gh_StrongPistolChance, Action_OnSettingsChange);
137 HookConVarChange(gh_DidntPlant, Action_OnSettingsChange);
138
139 AutoExecConfig(true, "retakes");
140 //Admin Commands
141 RegAdminCmd("sm_start", Command_Start, ADMFLAG_ROOT);
142 RegAdminCmd("sm_scramble", Command_Scramble, ADMFLAG_ROOT);
143 RegAdminCmd("sm_pistols", Command_OnlyPistols, ADMFLAG_ROOT);
144 RegAdminCmd("sm_del", Command_DeleteSpawn, ADMFLAG_ROOT);
145 RegAdminCmd("sm_delete", Command_DeleteSpawn, ADMFLAG_ROOT);
146 RegAdminCmd("sm_add", Command_AddSpawn, ADMFLAG_ROOT);
147 RegAdminCmd("sm_edit", Command_Edit, ADMFLAG_ROOT);
148 RegAdminCmd("sm_spawns", Command_Spawns, ADMFLAG_ROOT);
149 //Client Commands
150 RegConsoleCmd("sm_guns", Command_Guns);
151 RegConsoleCmd("sm_awp", Command_Guns);
152 RegConsoleCmd("sm_m4", Command_Guns);
153 RegConsoleCmd("sm_m4a1", Command_Guns);
154 RegConsoleCmd("sm_m4a4", Command_Guns);
155 RegConsoleCmd("sm_vp", Command_VotePistols);
156 AddCommandListener(Command_Say, "say");
157 AddCommandListener(Command_Say, "say_team");
158 //Events
159 HookEvent("round_prestart", Event_OnRoundPreStart);
160 HookEvent("round_poststart", Event_OnRoundPostStart);
161 HookEvent("round_end", Event_OnRoundEnd);
162 HookEvent("player_connect_full", Event_OnFullConnect);
163 HookEvent("player_team", Event_OnPlayerChangeTeam, EventHookMode_Pre);
164 HookEvent("player_hurt", Event_OnPlayerDamged);
165 HookEvent("bomb_defused", Event_OnBombDefused);
166 HookEvent("bomb_planted", Event_OnBombPlanted);
167 HookEvent("round_freeze_end", Event_OnFreezeTimeEnd);
168 //Listeners
169 AddCommandListener(Hook_ChangeTeam, "jointeam");
170 //Offsets
171 gi_MoneyOffset = FindSendPropOffs("CCSPlayer", "m_iAccount");
172 gi_HelmetOffset = FindSendPropOffs("CCSPlayer", "m_bHasHelmet");
173 //Coockies
174 gh_WantAwp = RegClientCookie("retakes_awp", "Retakes allow player play with awp", CookieAccess_Protected);
175 gh_SilencedM4 = RegClientCookie("retakes_m4", "Retakes play with m4a1s or m4a4", CookieAccess_Protected);
176 gh_PistolPrefence = RegClientCookie("retakes_pistol", "Retakes pistol prefernce", CookieAccess_Protected);
177
178 //Sql
179 ConnectSQL();
180 //Add Tag
181 AddServerTag("retakes");
182
183 if (LibraryExists("updater"))
184 {
185 Updater_AddPlugin(UPDATE_URL);
186 }
187
188 if(GetClientCountFix() >= 2)
189 {
190 gb_WaitForPlayers = false;
191 SetConfig(false);
192 }
193}
194
195public OnLibraryAdded(const String:name[])
196{
197 if (StrEqual(name, "updater"))
198 {
199 Updater_AddPlugin(UPDATE_URL);
200 }
201}
202
203public Action_OnSettingsChange(Handle:cvar, const String:oldvalue[], const String:newvalue[])
204{
205 if (cvar == gh_PistolRoundsCount)
206 {
207 gi_PistolRoundsCount = StringToInt(newvalue);
208 }
209 else if(cvar == gh_WinRowScramble)
210 {
211 gi_WinRowScramble = StringToInt(newvalue);
212 }
213 else if(cvar == gh_StrongPistolChance)
214 {
215 gi_StrongPistolChance = StringToInt(newvalue);
216 }
217 else if(cvar == gh_DidntPlant)
218 {
219 gi_DidntPlant = StringToInt(newvalue);
220 }
221}
222
223
224public OnMapStart()
225{
226 //Map String to LowerCase
227 GetCurrentMap(gs_CurrentMap, sizeof(gs_CurrentMap));
228 new len = strlen(gs_CurrentMap);
229 for(new i=0;i < len;i++)
230 {
231 gs_CurrentMap[i] = CharToLower(gs_CurrentMap[i]);
232 }
233 gb_EditMode = false;
234 gb_OnlyPistols = false;
235 LoadSpawns(true); // Load Spawns
236 //Precahche models for edit mode
237 g_precacheLaser = PrecacheModel("materials/sprites/laserbeam.vmt");
238 g_precacheGlow = PrecacheModel("materials/sprites/blueflare1.vmt");
239 SetConfig(true);
240 gi_QueueCounter = 0;
241 for (new i = 1; i < MaxClients; i++)
242 {
243 if(IsClientInGame(i))
244 {
245 LoadClientCoockies(i);
246 if(GetClientTeam(i) == 1)
247 {
248 AddPlayerToQueue(i);
249 }
250 }
251 }
252
253 gb_WarmUp = true;
254 PrintToChatAll("%sRetakes will start in 30 seconds", PREFIX);
255 gh_MapLoadTimer = CreateTimer(30.0, Timer_MapLoadDelay, _);
256 gf_MapLoadTime = GetEngineTime();
257 CreateTimer(0.1, Timer_PrintHintWarmup, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
258
259 gi_WinRowCounter = 0;
260 gi_Voters = 0;
261 gi_Votes = 0;
262 gi_VotesNeeded = 0;
263
264 for (new i=1; i<=MaxClients; i++)
265 {
266 if (IsClientConnected(i))
267 {
268 OnClientConnected(i);
269 }
270 }
271}
272
273public OnClientConnected(client)
274{
275 if(IsFakeClient(client))
276 return;
277
278 gb_Voted[client] = false;
279
280 gi_Voters++;
281 gi_VotesNeeded = RoundToFloor(float(gi_Voters) * 0.5);
282 gf_UsedVP[client] = -100.0;
283 return;
284}
285
286public OnClientDisconnect(client)
287{
288 if(IsFakeClient(client))
289 return;
290
291 if(gb_Voted[client])
292 {
293 gi_Votes--;
294 }
295
296 gi_Voters--;
297
298 gi_VotesNeeded = RoundToFloor(float(gi_Voters) * 0.5);
299
300 if (gi_VotesNeeded < 1)
301 {
302 return;
303 }
304
305 if (gi_Votes &&
306 gi_Voters &&
307 gi_Votes >= gi_VotesNeeded
308 )
309 {
310 ToggleVP();
311 }
312}
313
314LoadClientCoockies(client)
315{
316 if(IsFakeClient(client))
317 return;
318 decl String:buffer[16];
319 new bool:openGunsMenu = false;
320
321 GetClientCookie(client, gh_WantAwp, buffer, sizeof(buffer));
322 if(!StrEqual(buffer, ""))
323 gi_WantAwp[client] = StringToInt(buffer);
324 else
325 openGunsMenu = true;
326
327 GetClientCookie(client, gh_SilencedM4, buffer, sizeof(buffer));
328 if(!StrEqual(buffer, ""))
329 gb_WantSilencer[client] = bool:StringToInt(buffer);
330 else
331 openGunsMenu = true;
332
333 GetClientCookie(client, gh_PistolPrefence, buffer, sizeof(buffer));
334 if(!StrEqual(buffer, ""))
335 gi_PistolPrefence[client] = bool:StringToInt(buffer);
336 else
337 openGunsMenu = true;
338
339 gb_PreferenceLoaded[client] = !openGunsMenu;
340}
341
342public OnClientCookiesCached(client)
343{
344 LoadClientCoockies(client);
345}
346
347public Event_OnFullConnect(Handle:event, const String:name[], bool:dontBroadcast)
348{
349 if(!gb_EditMode && !gb_WarmUp)
350 {
351 new client = GetClientOfUserId(GetEventInt(event, "userid"));
352 if(GetClientCountFix() > 1)
353 {
354 SetEntPropFloat(client, Prop_Send, "m_fForceTeam", 3600.0);
355 }
356 if(!gb_PreferenceLoaded[client])
357 {
358 Command_Guns(client, 0);
359 }
360 }
361}
362
363AddPlayerToQueue(client)
364{
365 if(IsClientSourceTV(client))
366 return;
367
368 for (new i = 0; i < gi_QueueCounter; i++)
369 {
370 if(client == gi_PlayerQueue[i])
371 {
372 return;
373 }
374 }
375 gi_PlayerQueue[gi_QueueCounter] = client;
376 gi_QueueCounter++;
377 PrintToChat(client, "%sYou are now \x02%d\x04 place in the queue", PREFIX, gi_QueueCounter);
378 if(gi_QueueCounter == MAXPLAYERS)
379 {
380 gi_QueueCounter = 0;
381 }
382 return;
383}
384
385public OnClientDisconnect_Post(client)
386{
387 gb_Warnned[client] = false;
388 gi_NextRoundTeam[client] = -1;
389 if(!gb_WaitForPlayers && GetClientCountFix() < 2)
390 {
391 gb_WaitForPlayers = true;
392 SetConfig(true);
393 }
394 gb_PreferenceLoaded[client] = false;
395 new index = -1;
396 for (new i = 0; i < gi_QueueCounter; i++)
397 {
398 if(client == gi_PlayerQueue[i])
399 {
400 index = i;
401 break;
402 }
403 }
404 if(index != -1)
405 {
406 DeletePlayerFromQueue(client);
407 }
408}
409
410public Action:Event_OnPlayerChangeTeam(Handle:event, const String:name[], bool:dontBroadcast)
411{
412 dontBroadcast = true;
413 if(!gb_WarmUp && gb_WaitForPlayers)
414 {
415 if(GetClientCountFix() >= 2)
416 {
417 gb_WaitForPlayers = false;
418 ServerCommand("mp_restartgame 5");
419 SetConfig(false);
420 }
421 else
422 {
423 PrintToChatAll("%sWaiting for players to join", PREFIX);
424 }
425 }
426 return Plugin_Changed;
427}
428
429public Action:Event_OnPlayerDamged(Handle:event, const String:name[],bool:dontBroadcast)
430{
431 new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
432 new dhealth = GetEventInt(event, "dmg_health");
433 gi_DamageCount[attacker] += dhealth;
434}
435
436public Action:Event_OnBombDefused(Handle:event, const String:name[],bool:dontBroadcast)
437{
438 new defuser = GetClientOfUserId(GetEventInt(event, "userid"));
439 if(GetTeamAliveClientCount(2) > 0)
440 {
441 PrintToChatAll("%sNINJA DEFUSE", PREFIX);
442 gi_DamageCount[defuser] += 100;
443 }
444}
445
446public Action:Event_OnBombPlanted(Handle:event, const String:name[],bool:dontBroadcast)
447{
448 gb_BombPlanted = true;
449}
450
451public Event_OnFreezeTimeEnd(Handle:event, const String:name[], bool:dontBroadcast)
452{
453}
454
455public Action:Hook_ChangeTeam(client, const String:command[], args)
456{
457 if (args < 1)
458 return Plugin_Handled;
459
460 char arg[4];
461 GetCmdArg(1, arg, sizeof(arg));
462 int team_to = StringToInt(arg);
463 int team_from = GetClientTeam(client);
464
465 if ((team_from == team_to && team_from != CS_TEAM_NONE) || gb_PluginSwitchingTeam[client] || IsFakeClient(client) || gb_EditMode || gb_WaitForPlayers || gb_WarmUp)
466 {
467 return Plugin_Continue;
468 }
469
470 if ((team_from == CS_TEAM_CT && team_to == CS_TEAM_T )
471 || (team_from == CS_TEAM_T && team_to == CS_TEAM_CT))
472 {
473 return Plugin_Handled;
474 }
475
476 SwitchPlayerTeam(client, 1);
477 AddPlayerToQueue(client);
478 return Plugin_Handled;
479}
480
481public Event_OnRoundPreStart(Handle:event, const String:name[], bool:dontBroadcast)
482{
483 if(!gb_EditMode)
484 {
485 if(!gb_balancedTeams)
486 {
487 SetQueueClients();
488 gb_balancedTeams = true;
489 }
490 else
491 {
492 gb_balancedTeams = false;
493 }
494 if(!gb_newClientsJoined)
495 {
496 for (new i = 1; i <= MaxClients; i++)
497 {
498 if(IsClientInGame(i) && gi_NextRoundTeam[i] == -1)
499 {
500 gi_NextRoundTeam[i] = GetClientTeam(i);
501 }
502 }
503 BalanceTeams();
504 }
505 gb_newClientsJoined = false;
506 for (new i = 1; i <= MaxClients; i++)
507 {
508 if(IsClientInGame(i) && !IsClientSourceTV(i) && gi_NextRoundTeam[i] != -1)
509 {
510 if(gi_NextRoundTeam[i] == 1)
511 {
512 SwitchPlayerTeam(i, 1);
513 }
514 else
515 {
516 SwitchPlayerTeam(i, gi_NextRoundTeam[i], false);
517 CS_UpdateClientModel(i);
518 }
519 }
520 }
521 for (new i = 0; i < MAXPLAYERS; i++)
522 {
523 gi_NextRoundTeam[i] = -1;
524 }
525 }
526}
527
528public Event_OnRoundPostStart(Handle:event, const String:name[], bool:dontBroadcast)
529{
530 gi_Bomber = -1;
531 gb_BombPlanted = false;
532 if(!gb_EditMode && !gb_WaitForPlayers && !gb_WarmUp)
533 {
534 new site = GetRandomInt(0, 1);
535 PrintToChatAll("%sRetake on Site:\x02%s", PREFIX, site == SITEA ? "A":"B");
536 gf_StartRoundTime = GetEngineTime();
537 CreateTimer(0.1, Timer_PrintHintSite, site, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
538 //Reset spawn use and roundkills
539 for (new i = 0; i < GRENADESSETCOUNT; i++)
540 {
541 gi_GrenadeSetsFlags[i] = 0;
542 }
543 for (new i = 0; i < g_SpawnsCount; i++)
544 {
545 g_Spawns[i][Used] = false;
546 }
547 for (new i = 0; i < MAXPLAYERS; i++)
548 {
549 gi_DamageCount[i] = 0;
550 }
551
552 //Random awper for each team
553 new awpCt = GetRandomAwpPlayer(3);
554 new awpT = GetRandomAwpPlayer(2);
555
556 //Get Bomber
557 gi_Bomber = GetRandomPlayerFromTeam(2);
558 new randomSpawn = -1;
559 new randomGrenadeSet = -1;
560 new Float:loc[3], Float:ang[3];
561 new bool:pistols = CS_GetTeamScore(3) + CS_GetTeamScore(2) < gi_PistolRoundsCount || gb_OnlyPistols;
562 for (new i = 1; i <= MaxClients; i++)
563 {
564 if(IsClientInGame(i) && !IsClientSourceTV(i) && GetClientTeam(i) != 1)
565 {
566 //Set Money to 0$
567 SetEntData(i, gi_MoneyOffset, 0);
568 SetEntProp(i, Prop_Data, "m_ArmorValue", 100);
569 Client_RemoveAllWeapons(i);
570 randomSpawn = -1;
571 if(i != gi_Bomber)
572 {
573 randomSpawn = GetRandomSpawn(GetClientTeam(i) == 3 ? Ct : T, site);
574 if(randomSpawn != -1)
575 {
576 Array_Copy(g_Spawns[randomSpawn][Location], loc, 3);
577 Array_Copy(g_Spawns[randomSpawn][Angles], ang, 3);
578 g_Spawns[randomSpawn][Used] = true;
579 TeleportEntity(i, loc, ang, NULL_VECTOR);
580 }
581 }
582 else
583 {
584 randomSpawn = GetRandomSpawn(Bomb, site);
585 if(randomSpawn != -1)
586 {
587 Array_Copy(g_Spawns[randomSpawn][Location], loc, 3);
588 Array_Copy(g_Spawns[randomSpawn][Angles], ang, 3);
589 g_Spawns[randomSpawn][Used] = true;
590 TeleportEntity(i, loc, ang, NULL_VECTOR);
591 }
592 GivePlayerItem(i, "weapon_c4");
593 }
594 //Give Grenades
595 if(!pistols)
596 {
597 SetEntData(i, gi_HelmetOffset, 1);
598 randomGrenadeSet = GetRandomGrenadeSet(GetClientTeam(i));
599 if(randomGrenadeSet != -1)
600 {
601 if(GetClientTeam(i) == 3)
602 gi_GrenadeSetsFlags[randomGrenadeSet] = gi_GrenadeSetsFlags[randomGrenadeSet] | FL_USED_Ct;
603 else if(GetClientTeam(i) == 2)
604 gi_GrenadeSetsFlags[randomGrenadeSet] = gi_GrenadeSetsFlags[randomGrenadeSet] | FL_USED_T;
605 for (new k = 0; k < 2; k++)
606 {
607 if(!StrEqual("none", gs_GrenadeSets[randomGrenadeSet][k]))
608 {
609 if(!StrEqual("moli", gs_GrenadeSets[randomGrenadeSet][k]))
610 GivePlayerItem(i, gs_GrenadeSets[randomGrenadeSet][k]);
611 else if(GetClientTeam(i) == 3)
612 GivePlayerItem(i, "weapon_incgrenade");
613 else
614 GivePlayerItem(i, "weapon_molotov");
615
616 }
617 }
618 }
619 }
620 if(pistols)
621 {
622 SetEntData(i, gi_HelmetOffset, 0);
623 }
624 //Give Weapons
625 GivePlayerItem(i, "weapon_knife");
626 if((awpCt == i || awpT == i) && !pistols)
627 {
628 GivePlayerItem(i, "weapon_awp");
629 if(gi_PistolPrefence[i] == 0)
630 {
631 if(GetClientTeam(i) == 3)
632 GivePlayerItem(i, "weapon_hkp2000");
633 else
634 GivePlayerItem(i, "weapon_glock");
635 }
636 else if(gi_PistolPrefence[i] == 1)
637 {
638 if(GetRandomInt(1, 100) <= gi_StrongPistolChance)
639 {
640 if(GetClientTeam(i) == 3)
641 GivePlayerItem(i, "weapon_fiveseven");
642 else
643 GivePlayerItem(i, "weapon_tec9");
644 }
645 else
646 GivePlayerItem(i, "weapon_p250");
647 }
648 else if(gi_PistolPrefence[i] == 2)
649 GivePlayerItem(i, "weapon_p250");
650 }
651 else
652 {
653 if(GetClientTeam(i) == 3)
654 {
655 if(!pistols)
656 {
657 if(!gb_WantSilencer[i])
658 GivePlayerItem(i, "weapon_m4a1");
659 else
660 GivePlayerItem(i, "weapon_m4a1_silencer");
661 }
662 GivePlayerItem(i, "weapon_hkp2000");
663 }
664 else
665 {
666 if(!pistols)
667 {
668 GivePlayerItem(i, "weapon_ak47");
669 }
670 GivePlayerItem(i, "weapon_glock");
671 }
672 }
673 }
674 }
675 if(gi_Bomber != -1)
676 if(IsClientInGame(gi_Bomber))
677 FakeClientCommand(gi_Bomber, "use weapon_c4");
678 }
679}
680
681public Event_OnRoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
682{
683 new bool:queueplayers = true;
684 if(!gb_EditMode)
685 {
686 gb_balancedTeams = true;
687 if(!gb_BombPlanted && gi_Bomber != -1 && GetEventInt(event, "winner") == 3 && IsClientInGame(gi_Bomber))
688 {
689 new DamageList[MaxClients];
690 new IndexList[MaxClients];
691 new count = 0;
692 for (new i = 1; i <= MaxClients; i++)
693 {
694 if(IsClientInGame(i))
695 {
696 if(GetClientTeam(i) == 3)
697 {
698 DamageList[count] = GetClientFrags(i);
699 IndexList[count] = i;
700 count++;
701 }
702 }
703 }
704 new temp;
705 new temp2;
706 for (new i = 0; i < count; i++)
707 {
708 for (new j = i+1; j < count; j++)
709 {
710 if(DamageList[i] < DamageList[j])
711 {
712 temp = DamageList[i];
713 temp2 = IndexList[i];
714 DamageList[i] = DamageList[j];
715 IndexList[i] = IndexList[j];
716 DamageList[j] = temp;
717 IndexList[j] = temp2;
718 }
719 }
720 }
721 gi_NextRoundTeam[gi_Bomber] = 3;
722 gi_NextRoundTeam[IndexList[0]] = 2;
723 new String:sName[64];
724 GetClientName(gi_Bomber, sName, 64);
725 PrintToChatAll("%s%s Failed to plant to bomb.He will be swap to \x02CT\x04", PREFIX, sName);
726 if(gb_Warnned[gi_Bomber])
727 {
728 if(gi_DidntPlant > 0)
729 {
730 BanClient(gi_Bomber, gi_DidntPlant, BANFLAG_AUTO, "Didnt planted the bomb 2 times", "You didnt planted the bomb 2 times");
731 }
732 else if(gi_DidntPlant == 0)
733 {
734 KickClient(gi_Bomber, "Didnt planted the bomb twice");
735 }
736 gb_Warnned[gi_Bomber] = false;
737 }
738 else
739 {
740 gb_Warnned[gi_Bomber] = true;
741 }
742 for (new i = 1; i < MaxClients; i++)
743 {
744 if(IsClientInGame(i) && gi_NextRoundTeam[i] == -1)
745 {
746 gi_NextRoundTeam[i] = GetClientTeam(i);
747 }
748 }
749 }
750 else
751 {
752 if(GetEventInt(event, "winner") == 3)
753 {
754 gi_WinRowCounter = 0;
755 //Move top Killers to T
756 new DamageList[MaxClients];
757 new IndexList[MaxClients];
758 new count = 0;
759 new terrorCount = RoundToFloor(GetClientCountFix(false) / 2.0);
760 if(terrorCount > 4)
761 terrorCount = 4;
762 for (new i = 1; i <= MaxClients; i++)
763 {
764 if(IsClientInGame(i))
765 {
766 if(GetClientTeam(i) == 3)
767 {
768 DamageList[count] = gi_DamageCount[i];
769 IndexList[count] = i;
770 count++;
771 }
772 else if (GetClientTeam(i) == 2)
773 {
774 gi_NextRoundTeam[i] = 3;
775 }
776 }
777 }
778 new temp;
779 new temp2;
780 for (new i = 0; i < count; i++)
781 {
782 for (new j = i+1; j < count; j++)
783 {
784 if(DamageList[i] < DamageList[j])
785 {
786 temp = DamageList[i];
787 temp2 = IndexList[i];
788 DamageList[i] = DamageList[j];
789 IndexList[i] = IndexList[j];
790 DamageList[j] = temp;
791 IndexList[j] = temp2;
792 }
793 }
794 }
795 for (new i = 0; i < terrorCount; i++)
796 {
797 gi_NextRoundTeam[IndexList[i]] = 2;
798 }
799 }
800 else if (GetEventInt(event, "winner") == 2)
801 {
802 gi_WinRowCounter++;
803 if(gi_WinRowCounter == gi_WinRowScramble || gb_Scrambling)
804 {
805 //Scramble Players
806 gi_WinRowCounter = 0;
807 gb_Scrambling = false;
808 queueplayers = false;
809 ScrambleTeams(false);
810 }
811 else
812 {
813 for (new i = 1; i < MaxClients; i++)
814 {
815 if(IsClientInGame(i) && gi_NextRoundTeam[i] == -1)
816 {
817 gi_NextRoundTeam[i] = GetClientTeam(i);
818 }
819 }
820 if(gi_WinRowCounter > gi_WinRowScramble - 3)
821 PrintToChatAll("%sThe Terror need to take \x02%d\x04 more rounds in a row to scramble", PREFIX, gi_WinRowScramble - gi_WinRowCounter);
822 }
823 }
824 }
825 if(queueplayers)
826 SetQueueClients();
827 }
828}
829
830BalanceTeams()
831{
832 //Balance Team if not Balanced
833 new terrorCount = RoundToFloor(GetClientCountFix(false) / 2.0);
834 if(terrorCount > 4)
835 terrorCount = 4;
836 if(terrorCount < GetNextTeamCount(2, true))
837 {
838 new DamageList[MaxClients];
839 new IndexList[MaxClients];
840 new count = 0;
841 for (new i = 1; i <= MaxClients; i++)
842 {
843 if(IsClientInGame(i) && GetClientTeam(i) == 2)
844 {
845 DamageList[count] = GetClientFrags(i);
846 IndexList[count] = i;
847 count++;
848 }
849 }
850 new temp;
851 new temp2;
852 for (new i = 0; i < count; i++)
853 {
854 for (new j = i+1; j < count; j++)
855 {
856 if(DamageList[i] < DamageList[j])
857 {
858 temp = DamageList[i];
859 temp2 = IndexList[i];
860 DamageList[i] = DamageList[j];
861 IndexList[i] = IndexList[j];
862 DamageList[j] = temp;
863 IndexList[j] = temp2;
864 }
865 }
866 }
867 for (new i = 0; i < GetNextTeamCount(2, true) - terrorCount; i++)
868 {
869 gi_NextRoundTeam[IndexList[i]] = 3;
870 }
871 }
872 else if(terrorCount > GetNextTeamCount(2, true))
873 {
874 new DamageList[MaxClients];
875 new IndexList[MaxClients];
876 new count = 0;
877 for (new i = 1; i <= MaxClients; i++)
878 {
879 if(IsClientInGame(i) && GetClientTeam(i) == 3)
880 {
881 DamageList[count] = GetClientFrags(i);
882 IndexList[count] = i;
883 count++;
884 }
885 }
886 new temp;
887 new temp2;
888 for (new i = 0; i < count; i++)
889 {
890 for (new j = i+1; j < count; j++)
891 {
892 if(DamageList[i] > DamageList[j])
893 {
894 temp = DamageList[i];
895 temp2 = IndexList[i];
896 DamageList[i] = DamageList[j];
897 IndexList[i] = IndexList[j];
898 DamageList[j] = temp;
899 IndexList[j] = temp2;
900 }
901 }
902 }
903 for (new i = 0; i < terrorCount - GetNextTeamCount(2, true); i++)
904 {
905 gi_NextRoundTeam[IndexList[i]] = 2;
906 }
907 }
908}
909
910ScrambleTeams(bool:includespec)
911{
912 PrintToChatAll("%sScrambling Teams", PREFIX);
913 new terrorCount = RoundToFloor(GetClientCountFix(includespec) / 2.0);
914 if(terrorCount > 4)
915 terrorCount = 4;
916 new randomPlayer = -1;
917 for (new i = 0; i < MAXPLAYERS; i++)
918 {
919 gi_NextRoundTeam[i] = -1;
920 }
921 for (new i = 0; i < terrorCount; i++)
922 {
923 randomPlayer = GetRandomPlayer(includespec);
924 if(randomPlayer != -1)
925 {
926 gi_NextRoundTeam[randomPlayer] = 2;
927 if(GetClientTeam(randomPlayer) == 1)
928 {
929 DeletePlayerFromQueue(i);
930 }
931 }
932 }
933 new ctCount = GetClientCountFix(true) - terrorCount;
934 if(ctCount > 5)
935 ctCount = 5;
936 for (int i = 0; i < ctCount; i++)
937 {
938 randomPlayer = GetRandomPlayer(includespec);
939 if(randomPlayer != -1)
940 {
941 gi_NextRoundTeam[randomPlayer] = 3;
942 if(GetClientTeam(randomPlayer) == 1)
943 {
944 DeletePlayerFromQueue(i);
945 }
946 }
947 }
948
949 for (int i = 1; i <= MaxClients; i++)
950 {
951 if(IsClientInGame(i) && gi_NextRoundTeam[i] == -1)
952 {
953 gi_NextRoundTeam[i] = 1;
954 AddPlayerToQueue(i);
955 }
956 }
957 gb_balancedTeams = true;
958}
959
960SetQueueClients()
961{
962 for (new i = 1; i <= MaxClients; i++)
963 {
964 if(IsClientInGame(i) && gi_NextRoundTeam[i] == -1 && GetClientTeam(i) != 1)
965 {
966 gi_NextRoundTeam[i] = GetClientTeam(i);
967 }
968 }
969 new terror = GetNextTeamCount(2);
970 new ct = GetNextTeamCount(3);
971 if(terror == 0)
972 {
973 terror = GetTeamClientCountFix(2);
974 }
975 if(ct == 0)
976 {
977 ct = GetTeamClientCountFix(3);
978 }
979 new counter = gi_QueueCounter;
980 new queue[counter];
981 for (new i = 0; i < counter; i++)
982 {
983 queue[i] = gi_PlayerQueue[i];
984 }
985 for (new i = 0; i < counter; i++)
986 {
987 if(IsClientInGame(queue[i]))
988 {
989 if(ct > terror && terror < 4)
990 {
991 SwitchPlayerTeam(queue[i], 2);
992 gi_NextRoundTeam[queue[i]] = 2;
993 terror++;
994 DeletePlayerFromQueue(queue[i]);
995 gb_newClientsJoined = true;
996 }
997 else if(ct < 5)
998 {
999 SwitchPlayerTeam(queue[i], 3);
1000 gi_NextRoundTeam[queue[i]] = 3;
1001 ct++;
1002 DeletePlayerFromQueue(queue[i]);
1003 gb_newClientsJoined = true;
1004 }
1005 }
1006 }
1007}
1008
1009DeletePlayerFromQueue(client)
1010{
1011 new index = -1;
1012 for (new i = 0; i < gi_QueueCounter; i++)
1013 {
1014 if(client == gi_PlayerQueue[i])
1015 {
1016 index = i;
1017 break;
1018 }
1019 }
1020 if(index != -1)
1021 {
1022 for (new i = index+1; i < gi_QueueCounter; i++)
1023 {
1024 gi_PlayerQueue[i-1] = gi_PlayerQueue[i];
1025 }
1026 gi_QueueCounter--;
1027 if(gi_QueueCounter < 0)
1028 {
1029 gi_QueueCounter = 0;
1030 }
1031 }
1032}
1033
1034public Action:Command_Start(client, args)
1035{
1036 gf_MapLoadTime -= 50;
1037 TriggerTimer(gh_MapLoadTimer, false);
1038 return Plugin_Handled;
1039}
1040
1041public Action:Command_Spawns(client, args)
1042{
1043 new aCt, bCt;
1044 new aT, bT;
1045 new aB, bB;
1046 for (new i = 0; i < g_SpawnsCount; i++)
1047 {
1048 if(g_Spawns[i][Type] == Ct && g_Spawns[i][Site] == SITEA)
1049 aCt++;
1050 if(g_Spawns[i][Type] == Ct && g_Spawns[i][Site] == SITEB)
1051 bCt++;
1052 if(g_Spawns[i][Type] == T && g_Spawns[i][Site] == SITEA)
1053 aT++;
1054 if(g_Spawns[i][Type] == T && g_Spawns[i][Site] == SITEB)
1055 bT++;
1056 if(g_Spawns[i][Type] == Bomb && g_Spawns[i][Site] == SITEA)
1057 aB++;
1058 if(g_Spawns[i][Type] == Bomb && g_Spawns[i][Site] == SITEB)
1059 bB++;
1060 }
1061 PrintToChatAll("A:Ct:%d, T:%d, Bomb:%d", aCt, aT, aB);
1062 PrintToChatAll("B:Ct:%d, T:%d, Bomb:%d", bCt, bT, bB);
1063 return Plugin_Handled;
1064}
1065
1066public Action:Command_Scramble(client, args)
1067{
1068 gb_Scrambling = true;
1069 return Plugin_Handled;
1070}
1071
1072public Action:Command_OnlyPistols(client, args)
1073{
1074 gb_OnlyPistols = !gb_OnlyPistols;
1075 PrintToChatAll("%sPistols Only is now \x02%s", PREFIX, gb_OnlyPistols ? "Enabled":"Disabled");
1076 return Plugin_Handled;
1077}
1078
1079public Action:Command_VotePistols(int client, int args)
1080{
1081 if(GetEngineTime() - gf_UsedVP[client] < 5)
1082 {
1083 PrintToChat(client, "%s\x02sm_vp\x04 is allowed once in 5 seconds", PREFIX);
1084 return Plugin_Handled;
1085 }
1086
1087 gf_UsedVP[client] = GetEngineTime();
1088
1089 if(CS_GetTeamScore(3) + CS_GetTeamScore(2) < gi_PistolRoundsCount)
1090 {
1091 PrintToChat(client, "%ssm_vp is allowed after \x02%d\x04 rounds", PREFIX, gi_PistolRoundsCount);
1092 return Plugin_Handled;
1093 }
1094
1095 new String:name[64];
1096 GetClientName(client, name, sizeof(name));
1097 if(!gb_Voted[client])
1098 {
1099 gi_Votes++;
1100 PrintToChatAll("%s\x02%s\x04 wants to \x02%s%\x04 Only Pistols (%d votes, %d required)", PREFIX, name, gb_OnlyPistols ? "Disable":"Enable", gi_Votes, gi_VotesNeeded);
1101 }
1102 else
1103 {
1104 gi_Votes--;
1105 PrintToChatAll("%s\x02%s\x04 devoted (%d votes, %d required)", PREFIX, name, gi_Votes, gi_VotesNeeded);
1106 }
1107
1108 gb_Voted[client] = !gb_Voted[client];
1109
1110 if (gi_Votes >= gi_VotesNeeded)
1111 {
1112 ToggleVP();
1113 }
1114
1115 return Plugin_Handled;
1116}
1117
1118ToggleVP()
1119{
1120 for (int i = 0; i < MAXPLAYERS; i++)
1121 {
1122 gb_Voted[i] = false;
1123 }
1124 gi_Votes = 0;
1125 gi_VotesNeeded = RoundToFloor(float(gi_Voters) * 0.5);
1126
1127 gb_OnlyPistols = !gb_OnlyPistols;
1128 PrintToChatAll("%sPistols Only is now \x02%s", PREFIX, gb_OnlyPistols ? "Enabled":"Disabled");
1129}
1130
1131
1132public Action:Command_Edit(client, args)
1133{
1134 gb_EditMode = !gb_EditMode;
1135 PrintToChatAll("%sEdit mode is now %s", PREFIX, gb_EditMode ? "Enabled":"Disabled");
1136 if(gb_EditMode)
1137 {
1138 CreateTimer(0.1, DrawSpawns, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
1139 }
1140 SetConfig(gb_EditMode);
1141 ServerCommand("mp_restartgame 1");
1142 return Plugin_Handled;
1143}
1144
1145stock GetNextTeamCount(team, bool:next = true)
1146{
1147 if(!next)
1148 return GetTeamClientCountFix(team);
1149 new count = 0;
1150 for (new i = 1; i < MaxClients; i++)
1151 {
1152 if(gi_NextRoundTeam[i] == team)
1153 count++;
1154 }
1155 return count;
1156}
1157
1158stock GetTeamClientCountFix(team)
1159{
1160 new count = 0;
1161 for (int i = 1; i <= MaxClients; i++)
1162 {
1163 if(IsClientInGame(i) && GetClientTeam(i) == team)
1164 {
1165 count++;
1166 }
1167 }
1168 return count;
1169}
1170
1171stock GetTeamAliveClientCount(team)
1172{
1173 new count = 0;
1174 for (new i = 1; i < MaxClients; i++)
1175 {
1176 if(IsClientInGame(i) && GetClientTeam(i) == team && IsPlayerAlive(i))
1177 count++;
1178 }
1179 return count;
1180}
1181
1182stock GetRandomAwpPlayer(team)
1183{
1184 new iClients[MaxClients];
1185 new numClients;
1186
1187 for (new i = 1; i < MaxClients; i++)
1188 {
1189 if(IsClientInGame(i) && !IsClientSourceTV(i) && gi_WantAwp[i] > 0 && GetClientTeam(i) == team)
1190 {
1191 iClients[numClients] = i;
1192 numClients++;
1193 }
1194 }
1195
1196 if(numClients)
1197 {
1198 new awp = iClients[GetRandomInt(0, numClients-1)];
1199 if(gi_WantAwp[awp] == 2 && GetRandomInt(0, 1) == 1)
1200 {
1201 numClients = 0;
1202 for (new i = 1; i < MaxClients; i++)
1203 {
1204 if(IsClientInGame(i) && !IsClientSourceTV(i) && gi_WantAwp[i] == 1 && GetClientTeam(i) == team)
1205 {
1206 iClients[numClients] = i;
1207 numClients++;
1208 }
1209 }
1210 if(numClients)
1211 {
1212 return iClients[GetRandomInt(0, numClients-1)];
1213 }
1214 return -1;
1215 }
1216 return awp;
1217 }
1218 return -1;
1219}
1220
1221stock GetRandomSpawn(SpawnType:type, site)
1222{
1223 decl iSpawns[MaxClients];
1224 new numSpawns;
1225
1226 for (new i = 0; i < g_SpawnsCount; i++)
1227 {
1228 if(!g_Spawns[i][Used] && g_Spawns[i][Type] == type && g_Spawns[i][Site] == site)
1229 {
1230 iSpawns[numSpawns] = i;
1231 numSpawns++;
1232 }
1233 }
1234
1235 if (numSpawns)
1236 {
1237 return iSpawns[GetRandomInt(0, numSpawns-1)];
1238 }
1239 return -1;
1240}
1241
1242stock GetRandomPlayer(bool:includespec = false)
1243{
1244 decl iClients[MaxClients];
1245 new numClients;
1246
1247 for (new i = 1; i < MaxClients; i++)
1248 {
1249 if(IsClientInGame(i) && !IsClientSourceTV(i) && gi_NextRoundTeam[i] == -1 && (includespec || GetClientTeam(i) != 1))
1250 {
1251 iClients[numClients] = i;
1252 numClients++;
1253 }
1254 }
1255
1256 if (numClients)
1257 {
1258 return iClients[GetRandomInt(0, numClients-1)];
1259 }
1260 return -1;
1261}
1262
1263stock GetRandomPlayerFromTeam(team)
1264{
1265 decl iClients[MaxClients];
1266 new numClients = 0;
1267
1268 for (new i = 1; i < MaxClients; i++)
1269 {
1270 if(IsClientInGame(i) && !IsClientSourceTV(i) && GetClientTeam(i) == team)
1271 {
1272 iClients[numClients] = i;
1273 numClients++;
1274 }
1275 }
1276
1277 if (numClients)
1278 {
1279 return iClients[GetRandomInt(0, numClients-1)];
1280 }
1281 return -1;
1282}
1283
1284stock GetRandomGrenadeSet(team)
1285{
1286 decl iSets[MaxClients];
1287 new numSets;
1288 new flag = FL_USED_Ct;
1289 if(team == 2)
1290 flag = FL_USED_T;
1291
1292 for (new i = 0; i < GRENADESSETCOUNT; i++)
1293 {
1294 if(!(gi_GrenadeSetsFlags[i] & flag))
1295 {
1296 iSets[numSets] = i;
1297 numSets++;
1298 }
1299 }
1300
1301 if (numSets)
1302 {
1303 return iSets[GetRandomInt(0, numSets-1)];
1304 }
1305 return -1;
1306}
1307
1308public Action:Command_Say(client, const String:command[], argc)
1309{
1310 decl String:sText[192];
1311 GetCmdArgString(sText, sizeof(sText));
1312 StripQuotes(sText);
1313 if(StrEqual(sText, "guns") || StrEqual(sText, "weapons") || StrEqual(sText, "weps"))
1314 {
1315 Command_Guns(client, 0);
1316 return Plugin_Handled;
1317 }
1318 return Plugin_Continue;
1319}
1320
1321public Action:Command_Guns(client, args)
1322{
1323 new Handle:menu = CreateMenu(MenuHandler_M4, MENU_ACTIONS_ALL);
1324 SetMenuTitle(menu, "Choose Ct Weapon:");
1325 AddMenuItem(menu, "0", "M4A4");
1326 AddMenuItem(menu, "1", "M4A1-S");
1327 DisplayMenu(menu, client, MENU_TIME_FOREVER);
1328 return Plugin_Handled;
1329}
1330
1331public MenuHandler_M4(Handle:menu, MenuAction:action, param1, param2)
1332{
1333 if(action == MenuAction_Select)
1334 {
1335 new String:sArg[6];
1336 GetMenuItem(menu, param2, sArg, sizeof(sArg));
1337 gb_WantSilencer[param1] = bool:StringToInt(sArg);
1338 new convInt = gb_WantSilencer[param1] ? 1 : 0;
1339 decl String:buffer[16];
1340 IntToString(convInt, buffer, sizeof(buffer));
1341 SetClientCookie(param1, gh_SilencedM4, buffer);
1342
1343 new Handle:hmenu = CreateMenu(MenuHandler_Awp, MENU_ACTIONS_ALL);
1344 SetMenuTitle(hmenu, "Do you want to play with Awp:");
1345 AddMenuItem(hmenu, "1", "Always");
1346 AddMenuItem(hmenu, "2", "Sometimes");
1347 AddMenuItem(hmenu, "0", "Never");
1348 DisplayMenu(hmenu, param1, MENU_TIME_FOREVER);
1349 }
1350}
1351
1352public MenuHandler_Awp(Handle:menu, MenuAction:action, param1, param2)
1353{
1354 if(action == MenuAction_Select)
1355 {
1356 new String:sArg[6];
1357 GetMenuItem(menu, param2, sArg, sizeof(sArg));
1358 gi_WantAwp[param1] = StringToInt(sArg);
1359 decl String:buffer[16];
1360 IntToString(gi_WantAwp[param1], buffer, sizeof(buffer));
1361 SetClientCookie(param1, gh_WantAwp, buffer);
1362 if(gi_WantAwp[param1] != 0)
1363 {
1364 new Handle:hmenu = CreateMenu(MenuHandler_Pistol, MENU_ACTIONS_ALL);
1365 SetMenuTitle(hmenu, "Which Pistol you want with Awp:");
1366 AddMenuItem(hmenu, "0", "P2000/Glock");
1367 if(gi_StrongPistolChance == 100)
1368 AddMenuItem(hmenu, "1", "FiveSeven/Tec9");
1369 else if(gi_StrongPistolChance > 0)
1370 AddMenuItem(hmenu, "1", "FiveSeven/Tec9/P250");
1371 AddMenuItem(hmenu, "2", "P250");
1372 DisplayMenu(hmenu, param1, MENU_TIME_FOREVER);
1373 }
1374 }
1375}
1376
1377public MenuHandler_Pistol(Handle:menu, MenuAction:action, param1, param2)
1378{
1379 if(action == MenuAction_Select)
1380 {
1381 new String:sArg[6];
1382 GetMenuItem(menu, param2, sArg, sizeof(sArg));
1383 gi_PistolPrefence[param1] = StringToInt(sArg);
1384 decl String:buffer[16];
1385 IntToString(gi_PistolPrefence[param1], buffer, sizeof(buffer));
1386 SetClientCookie(param1, gh_PistolPrefence, buffer);
1387 }
1388}
1389
1390public Action:Command_DeleteSpawn(client, args)
1391{
1392 new Handle:hmenu = CreateMenu(MenuHandler_Teleport);
1393 SetMenuTitle(hmenu, "Select Spawn");
1394 if(g_SpawnsCount > 0)
1395 {
1396 decl String:sDisplay[64];
1397 decl String:sInfo[64];
1398 for (new i = 0; i < g_SpawnsCount; i++)
1399 {
1400 FormatEx(sDisplay, sizeof(sDisplay), "Site:%s, Type:", g_Spawns[i][Site] == SITEA ? "A":"B");
1401 if(g_Spawns[i][Type] == Bomb)
1402 FormatEx(sDisplay, sizeof(sDisplay), "%sBomb", sDisplay);
1403 else if(g_Spawns[i][Type] == T)
1404 FormatEx(sDisplay, sizeof(sDisplay), "%sT", sDisplay);
1405 else if(g_Spawns[i][Type] == Ct)
1406 FormatEx(sDisplay, sizeof(sDisplay), "%sCt", sDisplay);
1407 FormatEx(sInfo, sizeof(sInfo), "%d", i);
1408 AddMenuItem(hmenu, sInfo, sDisplay);
1409 }
1410 SetMenuExitButton(hmenu, true);
1411 }
1412 else
1413 {
1414 return Plugin_Handled;
1415 }
1416 DisplayMenu(hmenu, client, MENU_TIME_FOREVER);
1417 return Plugin_Handled;
1418}
1419
1420public MenuHandler_Teleport(Handle:menu, MenuAction:action, param1, param2)
1421{
1422 if (action == MenuAction_End)
1423 {
1424 CloseHandle(menu);
1425 }
1426 else if (action == MenuAction_Select)
1427 {
1428 decl String:sInfo[32];
1429 GetMenuItem(menu, param2, sInfo, sizeof(sInfo));
1430 new spawnNum = StringToInt(sInfo);
1431 new Float:loc[3], Float:ang[3];
1432 Array_Copy(g_Spawns[spawnNum][Location], loc, 3);
1433 Array_Copy(g_Spawns[spawnNum][Angles], ang, 3);
1434 TeleportEntity(param1, loc, ang, NULL_VECTOR);
1435 new Handle:hmenu = CreateMenu(MenuHandler_Delete);
1436 SetMenuTitle(hmenu, "Delete this spawn:");
1437 FormatEx(sInfo, sizeof(sInfo), "%d", g_Spawns[spawnNum][Id]);
1438 AddMenuItem(hmenu, sInfo, "Yes");
1439 AddMenuItem(hmenu, "-1", "No");
1440 DisplayMenu(hmenu, param1, MENU_TIME_FOREVER);
1441 }
1442}
1443
1444public MenuHandler_Delete(Handle:menu, MenuAction:action, param1, param2)
1445{
1446 if (action == MenuAction_End)
1447 {
1448 CloseHandle(menu);
1449 }
1450 else if (action == MenuAction_Select)
1451 {
1452 decl String:sInfo[32];
1453 GetMenuItem(menu, param2, sInfo, sizeof(sInfo));
1454 new spawnNum = StringToInt(sInfo);
1455 if(spawnNum == -1)
1456 {
1457 Command_DeleteSpawn(param1, 0);
1458 }
1459 else
1460 {
1461 decl String:sQuery[64];
1462 FormatEx(sQuery, sizeof(sQuery), "DELETE FROM spawns WHERE id = %d", spawnNum);
1463 SQL_TQuery(gh_Sql, DeleteSpawnCallBack, sQuery, param1, DBPrio_High);
1464 }
1465 }
1466}
1467
1468public DeleteSpawnCallBack(Handle:owner, Handle:hndl, const String:error[], any:data)
1469{
1470 if (hndl == INVALID_HANDLE)
1471 {
1472 LogError("SQL Error on DeleteSpawn: %s", error);
1473 return;
1474 }
1475
1476 LoadSpawns();
1477
1478 if (IsClientInGame(data))
1479 {
1480 PrintToChat(data, "%sDeleted spawn", PREFIX);
1481 }
1482}
1483
1484public Action:Command_AddSpawn(client, args)
1485{
1486 new Handle:menu = CreateMenu(MenuHandler_Site, MENU_ACTIONS_ALL);
1487 SetMenuTitle(menu, "Choose Site:");
1488 AddMenuItem(menu, "0", "A");
1489 AddMenuItem(menu, "1", "B");
1490 DisplayMenu(menu, client, MENU_TIME_FOREVER);
1491 return Plugin_Handled;
1492}
1493
1494public MenuHandler_Site(Handle:menu, MenuAction:action, param1, param2)
1495{
1496 if(action == MenuAction_Select)
1497 {
1498 new String:sArg[6];
1499 GetMenuItem(menu, param2, sArg, sizeof(sArg));
1500 gi_ChoosedSite[param1] = StringToInt(sArg);
1501 new Handle:hmenu = CreateMenu(MenuHandler_Type, MENU_ACTIONS_ALL);
1502 SetMenuTitle(hmenu, "Choose Spawn Type:");
1503 AddMenuItem(hmenu, "1", "Bomber");
1504 AddMenuItem(hmenu, "2", "T");
1505 AddMenuItem(hmenu, "3", "CT");
1506 SetMenuExitBackButton(hmenu, true);
1507 DisplayMenu(hmenu, param1, MENU_TIME_FOREVER);
1508
1509 }
1510}
1511
1512public MenuHandler_Type(Handle:menu, MenuAction:action, param1, param2)
1513{
1514 if(action == MenuAction_Select)
1515 {
1516 new String:sArg[6];
1517 GetMenuItem(menu, param2, sArg, sizeof(sArg));
1518 new type = StringToInt(sArg);
1519
1520 decl String:sQuery[512];
1521 new Float:loc[3], Float:ang[3];
1522 GetClientAbsOrigin(param1, loc);
1523 GetClientEyeAngles(param1, ang);
1524 FormatEx(sQuery, sizeof(sQuery), "INSERT INTO spawns (map, type, site, posx, posy, posz, angx) VALUES ('%s', '%d', '%d', %f, %f, %f, %f);", gs_CurrentMap, type, gi_ChoosedSite[param1], loc[0], loc[1], loc[2], ang[1]);
1525 SQL_TQuery(gh_Sql, AddSpawnCallback, sQuery, param1, DBPrio_Normal);
1526 }
1527 else if(action == MenuAction_Cancel)
1528 {
1529 Command_AddSpawn(param1, 0);
1530 }
1531}
1532
1533public AddSpawnCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
1534{
1535 if (hndl == INVALID_HANDLE)
1536 {
1537 LogError("SQL Error on AddSpawn: %s", error);
1538 return;
1539 }
1540
1541 Command_AddSpawn(data, 0);
1542 LoadSpawns();
1543}
1544
1545stock GetClientCountFix(bool:includespec = true)
1546{
1547 new counter = 0;
1548 for (new i = 1; i <= MaxClients; i++)
1549 {
1550 if(IsClientInGame(i) && !IsClientSourceTV(i) && (includespec || GetClientTeam(i) != 1))
1551 {
1552 counter++;
1553 }
1554 }
1555 return counter;
1556}
1557
1558//Sql
1559ConnectSQL()
1560{
1561 if (gh_Sql != INVALID_HANDLE)
1562 {
1563 CloseHandle(gh_Sql);
1564 }
1565
1566 gh_Sql = INVALID_HANDLE;
1567
1568 if (SQL_CheckConfig("retakes"))
1569 {
1570 SQL_TConnect(ConnectSQLCallback, "retakes");
1571 }
1572 else
1573 {
1574 SetFailState("PLUGIN STOPPED - Reason: no config entry found for 'retakes' in databases.cfg - PLUGIN STOPPED");
1575 }
1576}
1577
1578public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
1579{
1580 if (gi_ReconncetCounter >= 5)
1581 {
1582 LogError("PLUGIN STOPPED - Reason: reconnect counter reached max - PLUGIN STOPPED");
1583 return;
1584 }
1585
1586 if (hndl == INVALID_HANDLE)
1587 {
1588 LogError("Connection to SQL database has failed, Reason: %s", error);
1589
1590 gi_ReconncetCounter++;
1591 ConnectSQL();
1592
1593 return;
1594 }
1595
1596 decl String:sDriver[16];
1597 SQL_GetDriverIdent(owner, sDriver, sizeof(sDriver));
1598
1599 gh_Sql = CloneHandle(hndl);
1600
1601 if (StrEqual(sDriver, "mysql", false))
1602 {
1603 SQL_TQuery(gh_Sql, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `spawns` (`id` int(11) NOT NULL AUTO_INCREMENT, `type` int(11) NOT NULL, `site` int(11) NOT NULL, `map` varchar(32) NOT NULL, `posx` float NOT NULL, `posy` float NOT NULL, `posz` float NOT NULL, `angx` float NOT NULL, PRIMARY KEY (`id`));");
1604 //SQL_TQuery(gh_Sql, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `players` (`auth` varchar(24) NOT NULL PRIMARY KEY, `kills` int(11) NOT NULL, `deaths` int(11) NOT NULL);");
1605 }
1606 else if (StrEqual(sDriver, "sqlite", false))
1607 {
1608 SQL_TQuery(gh_Sql, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `spawns` (`id` INTEGER PRIMARY KEY, `type` INTEGER NOT NULL, `site` INTEGER NOT NULL, `map` varchar(32) NOT NULL, `posx` float NOT NULL, `posy` float NOT NULL, `posz` float NOT NULL, `angx` float NOT NULL);");
1609 }
1610
1611 gi_ReconncetCounter = 1;
1612}
1613
1614public CreateSQLTableCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
1615{
1616 if (owner == INVALID_HANDLE)
1617 {
1618 LogError("SQL:Reconnect");
1619 gi_ReconncetCounter++;
1620 ConnectSQL();
1621
1622 return;
1623 }
1624
1625 if (hndl == INVALID_HANDLE)
1626 {
1627 LogError("SQL CreateTable:%s", error);
1628 return;
1629 }
1630
1631 LoadSpawns();
1632}
1633
1634LoadSpawns(bool:mapstart = false)
1635{
1636 if (gh_Sql == INVALID_HANDLE)
1637 {
1638 ConnectSQL();
1639 }
1640 else
1641 {
1642 decl String:sQuery[384];
1643 FormatEx(sQuery, sizeof(sQuery), "SELECT id, type, site, posx, posy, posz, angx FROM spawns WHERE map = '%s'", gs_CurrentMap);
1644 SQL_TQuery(gh_Sql, LoadSpawnsCallBack, sQuery, mapstart, DBPrio_High);
1645 }
1646}
1647
1648public LoadSpawnsCallBack(Handle:owner, Handle:hndl, const String:error[], any:data)
1649{
1650 if (hndl == INVALID_HANDLE)
1651 {
1652 LogError("SQL Error on LoadDest: %s", error);
1653 return;
1654 }
1655
1656 g_SpawnsCount = 0;
1657 while (SQL_FetchRow(hndl) && g_SpawnsCount < MAXSPAWNS)
1658 {
1659 g_Spawns[g_SpawnsCount][Id] = SQL_FetchInt(hndl, 0);
1660 g_Spawns[g_SpawnsCount][Type] = SpawnType:SQL_FetchInt(hndl, 1);
1661 g_Spawns[g_SpawnsCount][Site] = SQL_FetchInt(hndl, 2);
1662 g_Spawns[g_SpawnsCount][Location][0] = SQL_FetchFloat(hndl, 3);
1663 g_Spawns[g_SpawnsCount][Location][1] = SQL_FetchFloat(hndl, 4);
1664 g_Spawns[g_SpawnsCount][Location][2] = SQL_FetchFloat(hndl, 5);
1665 g_Spawns[g_SpawnsCount][Angles][0] = 0.0;
1666 g_Spawns[g_SpawnsCount][Angles][1] = SQL_FetchFloat(hndl, 6);
1667 g_Spawns[g_SpawnsCount][Angles][2] = 0.0;
1668
1669 g_SpawnsCount++;
1670 }
1671
1672
1673 if(data)
1674 {
1675 if(g_SpawnsCount == 0)
1676 {
1677 gb_EditMode = true;
1678 PrintToChatAll("%sEdit mode is now Enabled becuase there is no spawns", PREFIX);
1679 CreateTimer(0.1, DrawSpawns, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
1680 }
1681 else
1682 {
1683 gb_EditMode = false;
1684 }
1685 }
1686
1687}
1688
1689public Action:DrawSpawns(Handle:timer)
1690{
1691 if (!gb_EditMode)
1692 {
1693 return Plugin_Stop;
1694 }
1695 new g_DrawColor[4];
1696 new Float:Point1[3];
1697 new Float:Point2[3];
1698 for (new i = 0; i < g_SpawnsCount; i++)
1699 {
1700 //Set Color
1701 if(g_Spawns[i][Type] == Ct)
1702 {
1703 g_DrawColor[0] = 0;
1704 g_DrawColor[1] = 255;
1705 g_DrawColor[2] = 255;
1706 }
1707 else if (g_Spawns[i][Type] == T)
1708 {
1709 g_DrawColor[0] = 255;
1710 g_DrawColor[1] = 0;
1711 g_DrawColor[2] = 0;
1712 }
1713 else if (g_Spawns[i][Type] == Bomb)
1714 {
1715 g_DrawColor[0] = 255;
1716 g_DrawColor[1] = 255;
1717 g_DrawColor[2] = 0;
1718 }
1719 g_DrawColor[3] = 255;
1720 //Set Points
1721 Array_Copy(g_Spawns[i][Location], Point1, 3);
1722 Array_Copy(Point1, Point2, 3);
1723 Point2[2] += 100.0;
1724 //Draw Beam
1725 TE_SetupBeamPoints(Point1, Point2, g_precacheLaser, 0, 0, 0, 0.1, 3.0, 3.0, 10, 0.0, g_DrawColor, 0);TE_SendToAll(0.0);
1726 //Draw Light Ball if site == A
1727 if(g_Spawns[i][Site] == SITEA)
1728 {
1729 Point2[0] = 0.0;
1730 Point2[1] = 0.0;
1731 Point2[2] = 0.0;
1732 TE_SetupGlowSprite(Point1, g_precacheGlow, 0.1, 1.0, 255);TE_SendToAll(0.0);
1733 }
1734 }
1735
1736 return Plugin_Continue;
1737}
1738
1739public Action:Timer_MapLoadDelay(Handle:timer)
1740{
1741 if(GetClientCountFix() >= 2)
1742 {
1743 gb_WaitForPlayers = false;
1744 gb_balancedTeams = false;
1745 ScrambleTeams(true);
1746 SetConfig(false);
1747 ServerCommand("mp_restartgame 1");
1748 ServerCommand("mp_warmup_end");
1749 }
1750 else
1751 {
1752 PrintToChatAll("%sWaiting for more players to join", PREFIX);
1753 }
1754 gb_WarmUp = false;
1755}
1756
1757public Action:Timer_PrintHintWarmup(Handle:timer)
1758{
1759 if(GetEngineTime() - gf_MapLoadTime >= 30)
1760 return Plugin_Stop;
1761 PrintHintTextToAll("\n<font size='22'>Retakes will start in:</font><font size='22' color='#E22C56'>%.00f seconds</font>", 30 - (GetEngineTime() - gf_MapLoadTime));
1762 return Plugin_Continue;
1763}
1764
1765public Action:Timer_PrintHintSite(Handle:timer, any:site)
1766{
1767 if(GetEngineTime() - gf_StartRoundTime >= 3)
1768 return Plugin_Stop;
1769 PrintHintTextToAll(" <font size='22'> <font color = '#01A9DB'>%d CT</font> vs <font color = '#FE2E2E'> %d T</font>\n Retake on Site:<font color='#E22C56'>%s</font></font>", GetTeamClientCountFix(3), GetTeamClientCountFix(2), site == SITEA ? "A":"B");
1770 return Plugin_Continue;
1771}
1772
1773SetConfig(bool:warmup)
1774{
1775 ServerCommand("exec retakes.cfg");
1776 if(!warmup)
1777 {
1778 ServerCommand("exec retakes_live.cfg");
1779 ServerCommand("mp_defuser_allocation 2");
1780 }
1781 else
1782 {
1783 ServerCommand("exec retakes_warmup.cfg");
1784 }
1785}
1786
1787stock void SwitchPlayerTeam(int client, int team, bool change = true)
1788{
1789 if (GetClientTeam(client) == team)
1790 return;
1791
1792 gb_PluginSwitchingTeam[client] = true;
1793 if (!change)
1794 {
1795 CS_SwitchTeam(client, team);
1796 CS_UpdateClientModel(client);
1797 }
1798 else
1799 {
1800 ChangeClientTeam(client, team);
1801 }
1802 gb_PluginSwitchingTeam[client] = false;
1803}