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