· 6 years ago · May 28, 2019, 10:14 AM
1 public PlVers:__version =
2{
3 version = 5,
4 filevers = "1.9.0.6245",
5 date = "10/08/2018",
6 time = "14:58:17"
7};
8new Float:NULL_VECTOR[3];
9new String:NULL_STRING[4];
10public Extension:__ext_core =
11{
12 name = "Core",
13 file = "core",
14 autoload = 0,
15 required = 0,
16};
17new MaxClients;
18new TFHoliday:TFHoliday_Birthday;
19new TFHoliday:TFHoliday_Halloween;
20new TFHoliday:TFHoliday_Christmas;
21new TFHoliday:TFHoliday_EndOfTheLine;
22new TFHoliday:TFHoliday_CommunityUpdate;
23new TFHoliday:TFHoliday_ValentinesDay;
24new TFHoliday:TFHoliday_MeetThePyro;
25new TFHoliday:TFHoliday_FullMoon;
26new TFHoliday:TFHoliday_HalloweenOrFullMoon;
27new TFHoliday:TFHoliday_HalloweenOrFullMoonOrValentines;
28new TFHoliday:TFHoliday_AprilFools;
29public Extension:__ext_tf2 =
30{
31 name = "TF2 Tools",
32 file = "game.tf2.ext",
33 autoload = 0,
34 required = 1,
35};
36public Extension:__ext_sdktools =
37{
38 name = "SDKTools",
39 file = "sdktools.ext",
40 autoload = 1,
41 required = 1,
42};
43new String:TFResourceNames[18][];
44public Extension:__ext_regex =
45{
46 name = "Regex Extension",
47 file = "regex.ext",
48 autoload = 1,
49 required = 1,
50};
51new bool:CSkipList[66];
52new Handle:CTrie;
53new CTeamColors[1][3] =
54{
55 {
56 13421772, 5077314, 16728128
57 }
58};
59public Extension:__ext_SteamTools =
60{
61 name = "SteamTools",
62 file = "steamtools.ext",
63 autoload = 1,
64 required = 1,
65};
66public Extension:__ext_sdkhooks =
67{
68 name = "SDKHooks",
69 file = "sdkhooks.ext",
70 autoload = 1,
71 required = 1,
72};
73public SharedPlugin:__pl_tf2items_giveweapon =
74{
75 name = "tf2items_giveweapon",
76 file = "tf2items_giveweapon.smx",
77 required = 1,
78};
79new Float:Flare_Weapon_Knockback_Scale = 1036160860;
80new Float:Flare_Weapon_Knockback_Scale_Multiplier = 1073741824;
81new Handle:g_hCvarEnabled;
82new Handle:g_hCvarEnableCfgFile;
83new Handle:g_hCvarDisableCfgFile;
84new ConVar:g_hCvarVotePercent;
85new ConVar:g_hCvarVoteSpeedEnabled;
86new ConVar:g_hCvarVoteCountEnabled;
87new ConVar:g_hCvarDisableReason;
88new ConVar:g_hCvarEnablePAB;
89new ConVar:g_hCvarTopSpeedHolder;
90new ConVar:g_hCvarTopSpeedMPH;
91new Handle:g_Announce;
92new bool:g_bEnabled;
93new bool:g_bRoundStarted;
94new g_iRoundCount;
95new g_iRocketsFired;
96new Handle:g_hLogicTimer;
97new Float:g_fNextSpawnTime;
98new g_iLastDeadTeam;
99new g_iLastDeadClient;
100new g_iPlayerCount;
101new Handle:g_hHud;
102new g_iRocketSpeed;
103new Handle:g_hTimerHud;
104new Handle:MaxDB_Hud;
105new Float:g_defaultspeed;
106new Float:g_default_turn;
107new Float:g_mph_convert = 1026460677;
108new Float:g_turnrate_convert = 997315565;
109new bool:g_newtarget_bool;
110new g_newtarget_int;
111new g_Voters;
112new g_VotesNeeded;
113new bool:g_VoteInProgress;
114new g_SpeedVotes;
115new g_SpeedVoted[66];
116new g_CountVotes;
117new g_CountVoted[66];
118new Database:db;
119new Menu:TopRocketSpeed;
120new String:Fishy_DisableReason[1000];
121new bool:g_bMusicEnabled;
122new bool:g_bMusic[4];
123new String:g_strMusic[4][256];
124new bool:g_bUseWebPlayer;
125new String:g_strWebPlayerUrl[256];
126new bool:g_bRocketIsValid[1000];
127new g_iRocketEntity[1000];
128new g_iRocketTarget[1000];
129new g_iRocketSpawner[1000];
130new g_iRocketClass[1000];
131new RocketFlags:g_iRocketFlags[1000];
132new Float:g_fRocketSpeed[1000];
133new Float:g_fRocketDirection[1000][3];
134new g_iRocketDeflections[1000];
135new Float:g_fRocketLastDeflectionTime[1000];
136new Float:g_fRocketLastBeepTime[1000];
137new g_iLastCreatedRocket;
138new g_iRocketCount;
139new String:g_strRocketClassName[500][16];
140new String:g_strRocketClassLongName[500][32];
141new BehaviourTypes:g_iRocketClassBehaviour[500];
142new String:g_strRocketClassModel[500][256];
143new RocketFlags:g_iRocketClassFlags[500];
144new Float:g_fRocketClassBeepInterval[500];
145new String:g_strRocketClassSpawnSound[500][256];
146new String:g_strRocketClassBeepSound[500][256];
147new String:g_strRocketClassAlertSound[500][256];
148new Float:g_fRocketClassCritChance[500];
149new Float:g_fRocketClassDamage[500];
150new Float:g_fRocketClassDamageIncrement[500];
151new Float:g_fRocketClassSpeed[500];
152new Float:g_fRocketClassSpeedIncrement[500];
153new Float:g_fRocketClassTurnRate[500];
154new Float:g_fRocketClassTurnRateIncrement[500];
155new Float:g_fRocketClassElevationRate[500];
156new Float:g_fRocketClassElevationLimit[500];
157new Float:g_fRocketClassRocketsModifier[500];
158new Float:g_fRocketClassPlayerModifier[500];
159new Float:g_fRocketClassControlDelay[500];
160new Float:g_fRocketClassTargetWeight[500];
161new Handle:g_hRocketClassCmdsOnSpawn[500];
162new Handle:g_hRocketClassCmdsOnDeflect[500];
163new Handle:g_hRocketClassCmdsOnKill[500];
164new Handle:g_hRocketClassCmdsOnExplode[500];
165new Handle:g_hRocketClassTrie;
166new g_iRocketClassCount;
167new String:g_strSpawnersName[50][32];
168new g_iSpawnersMaxRockets[50];
169new Float:g_fSpawnersInterval[50];
170new Handle:g_hSpawnersChancesTable[50];
171new Handle:g_hSpawnersTrie;
172new g_iSpawnersCount;
173new g_iCurrentRedSpawn;
174new g_iSpawnPointsRedCount;
175new g_iSpawnPointsRedClass[100];
176new g_iSpawnPointsRedEntity[100];
177new g_iCurrentBluSpawn;
178new g_iSpawnPointsBluCount;
179new g_iSpawnPointsBluClass[100];
180new g_iSpawnPointsBluEntity[100];
181new g_iDefaultRedSpawner;
182new g_iDefaultBluSpawner;
183public Plugin:myinfo =
184{
185 name = "[TF2] Dodgeball [Rewritten]",
186 description = "[TF2] Dodgeball [Rewritten]",
187 author = "Fishy",
188 version = "2.1.0",
189 url = "https://keybase.io/rumblefrog"
190};
191public void:__ext_core_SetNTVOptional()
192{
193 MarkNativeAsOptional("GetFeatureStatus");
194 MarkNativeAsOptional("RequireFeature");
195 MarkNativeAsOptional("AddCommandListener");
196 MarkNativeAsOptional("RemoveCommandListener");
197 MarkNativeAsOptional("BfWriteBool");
198 MarkNativeAsOptional("BfWriteByte");
199 MarkNativeAsOptional("BfWriteChar");
200 MarkNativeAsOptional("BfWriteShort");
201 MarkNativeAsOptional("BfWriteWord");
202 MarkNativeAsOptional("BfWriteNum");
203 MarkNativeAsOptional("BfWriteFloat");
204 MarkNativeAsOptional("BfWriteString");
205 MarkNativeAsOptional("BfWriteEntity");
206 MarkNativeAsOptional("BfWriteAngle");
207 MarkNativeAsOptional("BfWriteCoord");
208 MarkNativeAsOptional("BfWriteVecCoord");
209 MarkNativeAsOptional("BfWriteVecNormal");
210 MarkNativeAsOptional("BfWriteAngles");
211 MarkNativeAsOptional("BfReadBool");
212 MarkNativeAsOptional("BfReadByte");
213 MarkNativeAsOptional("BfReadChar");
214 MarkNativeAsOptional("BfReadShort");
215 MarkNativeAsOptional("BfReadWord");
216 MarkNativeAsOptional("BfReadNum");
217 MarkNativeAsOptional("BfReadFloat");
218 MarkNativeAsOptional("BfReadString");
219 MarkNativeAsOptional("BfReadEntity");
220 MarkNativeAsOptional("BfReadAngle");
221 MarkNativeAsOptional("BfReadCoord");
222 MarkNativeAsOptional("BfReadVecCoord");
223 MarkNativeAsOptional("BfReadVecNormal");
224 MarkNativeAsOptional("BfReadAngles");
225 MarkNativeAsOptional("BfGetNumBytesLeft");
226 MarkNativeAsOptional("BfWrite.WriteBool");
227 MarkNativeAsOptional("BfWrite.WriteByte");
228 MarkNativeAsOptional("BfWrite.WriteChar");
229 MarkNativeAsOptional("BfWrite.WriteShort");
230 MarkNativeAsOptional("BfWrite.WriteWord");
231 MarkNativeAsOptional("BfWrite.WriteNum");
232 MarkNativeAsOptional("BfWrite.WriteFloat");
233 MarkNativeAsOptional("BfWrite.WriteString");
234 MarkNativeAsOptional("BfWrite.WriteEntity");
235 MarkNativeAsOptional("BfWrite.WriteAngle");
236 MarkNativeAsOptional("BfWrite.WriteCoord");
237 MarkNativeAsOptional("BfWrite.WriteVecCoord");
238 MarkNativeAsOptional("BfWrite.WriteVecNormal");
239 MarkNativeAsOptional("BfWrite.WriteAngles");
240 MarkNativeAsOptional("BfRead.ReadBool");
241 MarkNativeAsOptional("BfRead.ReadByte");
242 MarkNativeAsOptional("BfRead.ReadChar");
243 MarkNativeAsOptional("BfRead.ReadShort");
244 MarkNativeAsOptional("BfRead.ReadWord");
245 MarkNativeAsOptional("BfRead.ReadNum");
246 MarkNativeAsOptional("BfRead.ReadFloat");
247 MarkNativeAsOptional("BfRead.ReadString");
248 MarkNativeAsOptional("BfRead.ReadEntity");
249 MarkNativeAsOptional("BfRead.ReadAngle");
250 MarkNativeAsOptional("BfRead.ReadCoord");
251 MarkNativeAsOptional("BfRead.ReadVecCoord");
252 MarkNativeAsOptional("BfRead.ReadVecNormal");
253 MarkNativeAsOptional("BfRead.ReadAngles");
254 MarkNativeAsOptional("BfRead.GetNumBytesLeft");
255 MarkNativeAsOptional("PbReadInt");
256 MarkNativeAsOptional("PbReadFloat");
257 MarkNativeAsOptional("PbReadBool");
258 MarkNativeAsOptional("PbReadString");
259 MarkNativeAsOptional("PbReadColor");
260 MarkNativeAsOptional("PbReadAngle");
261 MarkNativeAsOptional("PbReadVector");
262 MarkNativeAsOptional("PbReadVector2D");
263 MarkNativeAsOptional("PbGetRepeatedFieldCount");
264 MarkNativeAsOptional("PbSetInt");
265 MarkNativeAsOptional("PbSetFloat");
266 MarkNativeAsOptional("PbSetBool");
267 MarkNativeAsOptional("PbSetString");
268 MarkNativeAsOptional("PbSetColor");
269 MarkNativeAsOptional("PbSetAngle");
270 MarkNativeAsOptional("PbSetVector");
271 MarkNativeAsOptional("PbSetVector2D");
272 MarkNativeAsOptional("PbAddInt");
273 MarkNativeAsOptional("PbAddFloat");
274 MarkNativeAsOptional("PbAddBool");
275 MarkNativeAsOptional("PbAddString");
276 MarkNativeAsOptional("PbAddColor");
277 MarkNativeAsOptional("PbAddAngle");
278 MarkNativeAsOptional("PbAddVector");
279 MarkNativeAsOptional("PbAddVector2D");
280 MarkNativeAsOptional("PbRemoveRepeatedFieldValue");
281 MarkNativeAsOptional("PbReadMessage");
282 MarkNativeAsOptional("PbReadRepeatedMessage");
283 MarkNativeAsOptional("PbAddMessage");
284 MarkNativeAsOptional("Protobuf.ReadInt");
285 MarkNativeAsOptional("Protobuf.ReadFloat");
286 MarkNativeAsOptional("Protobuf.ReadBool");
287 MarkNativeAsOptional("Protobuf.ReadString");
288 MarkNativeAsOptional("Protobuf.ReadColor");
289 MarkNativeAsOptional("Protobuf.ReadAngle");
290 MarkNativeAsOptional("Protobuf.ReadVector");
291 MarkNativeAsOptional("Protobuf.ReadVector2D");
292 MarkNativeAsOptional("Protobuf.GetRepeatedFieldCount");
293 MarkNativeAsOptional("Protobuf.SetInt");
294 MarkNativeAsOptional("Protobuf.SetFloat");
295 MarkNativeAsOptional("Protobuf.SetBool");
296 MarkNativeAsOptional("Protobuf.SetString");
297 MarkNativeAsOptional("Protobuf.SetColor");
298 MarkNativeAsOptional("Protobuf.SetAngle");
299 MarkNativeAsOptional("Protobuf.SetVector");
300 MarkNativeAsOptional("Protobuf.SetVector2D");
301 MarkNativeAsOptional("Protobuf.AddInt");
302 MarkNativeAsOptional("Protobuf.AddFloat");
303 MarkNativeAsOptional("Protobuf.AddBool");
304 MarkNativeAsOptional("Protobuf.AddString");
305 MarkNativeAsOptional("Protobuf.AddColor");
306 MarkNativeAsOptional("Protobuf.AddAngle");
307 MarkNativeAsOptional("Protobuf.AddVector");
308 MarkNativeAsOptional("Protobuf.AddVector2D");
309 MarkNativeAsOptional("Protobuf.RemoveRepeatedFieldValue");
310 MarkNativeAsOptional("Protobuf.ReadMessage");
311 MarkNativeAsOptional("Protobuf.ReadRepeatedMessage");
312 MarkNativeAsOptional("Protobuf.AddMessage");
313 VerifyCoreVersion();
314 return void:0;
315}
316
317RoundFloat(Float:value)
318{
319 return RoundToNearest(value);
320}
321
322Float:operator*(Float:,_:)(Float:oper1, oper2)
323{
324 return oper1 * float(oper2);
325}
326
327Float:operator*(Float:,_:)(Float:oper1, oper2)
328{
329 return oper1 * float(oper2);
330}
331
332Float:operator/(_:,Float:)(oper1, Float:oper2)
333{
334 return float(oper1) / oper2;
335}
336
337Float:operator/(_:,Float:)(oper1, Float:oper2)
338{
339 return float(oper1) / oper2;
340}
341
342Float:operator+(Float:,_:)(Float:oper1, oper2)
343{
344 return oper1 + float(oper2);
345}
346
347Float:operator+(Float:,_:)(Float:oper1, oper2)
348{
349 return oper1 + float(oper2);
350}
351
352.3132.0<=40000005(oper1, Float:oper2)
353{
354 return float(oper1) <= oper2;
355}
356
357.3132.0<=40000005(oper1, Float:oper2)
358{
359 return float(oper1) <= oper2;
360}
361
362void:ScaleVector(Float:vec[3], Float:scale)
363{
364 new var1 = vec;
365 var1[0] = var1[0] * scale;
366 vec[1] *= scale;
367 vec[2] *= scale;
368 return void:0;
369}
370
371void:MakeVectorFromPoints(Float:pt1[3], Float:pt2[3], Float:output[3])
372{
373 output[0] = pt2[0] - pt1[0];
374 output[1] = pt2[1] - pt1[1];
375 output[2] = pt2[2] - pt1[2];
376 return void:0;
377}
378
379bool:StrEqual(String:str1[], String:str2[], bool:caseSensitive)
380{
381 return strcmp(str1, str2, caseSensitive) == 0;
382}
383
384CharToLower(chr)
385{
386 if (IsCharUpper(chr))
387 {
388 return chr | 32;
389 }
390 return chr;
391}
392
393ExplodeString(String:text[], String:split[], String:buffers[][], maxStrings, maxStringLength, bool:copyRemainder)
394{
395 new reloc_idx;
396 new idx;
397 new total;
398 new var1;
399 if (maxStrings < 1 || !split[0])
400 {
401 return 0;
402 }
403 while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1)
404 {
405 reloc_idx = idx + reloc_idx;
406 total++;
407 if (maxStrings == total)
408 {
409 if (copyRemainder)
410 {
411 strcopy(buffers[total + -1], maxStringLength, text[reloc_idx - idx]);
412 }
413 return total;
414 }
415 }
416 total++;
417 strcopy(buffers[total], maxStringLength, text[reloc_idx]);
418 return total;
419}
420
421Handle:StartMessageOne(String:msgname[], client, flags)
422{
423 new players[1];
424 players[0] = client;
425 return StartMessage(msgname, players, 1, flags);
426}
427
428bool:Menu.DisplayVoteToAll(Menu:this, time, flags)
429{
430 new total;
431 new players[MaxClients];
432 new i = 1;
433 while (i <= MaxClients)
434 {
435 new var1;
436 if (!IsClientInGame(i) || IsFakeClient(i))
437 {
438 }
439 else
440 {
441 total++;
442 players[total] = i;
443 }
444 i++;
445 }
446 return Menu.DisplayVote(this, players, total, time, flags);
447}
448
449void:PrintHintTextToAll(String:format[])
450{
451 new String:buffer[256];
452 new i = 1;
453 while (i <= MaxClients)
454 {
455 if (IsClientInGame(i))
456 {
457 SetGlobalTransTarget(i);
458 VFormat(buffer, 254, format, 2);
459 PrintHintText(i, "%s", buffer);
460 }
461 i++;
462 }
463 return void:0;
464}
465
466void:EmitSoundToClient(client, String:sample[], entity, channel, level, flags, Float:volume, pitch, speakerentity, Float:origin[3], Float:dir[3], bool:updatePos, Float:soundtime)
467{
468 new clients[1];
469 clients[0] = client;
470 new var1;
471 if (entity == -2)
472 {
473 var1 = client;
474 }
475 else
476 {
477 var1 = entity;
478 }
479 entity = var1;
480 EmitSound(clients, 1, sample, entity, channel, level, flags, volume, pitch, speakerentity, origin, dir, updatePos, soundtime);
481 return void:0;
482}
483
484void:EmitSoundToAll(String:sample[], entity, channel, level, flags, Float:volume, pitch, speakerentity, Float:origin[3], Float:dir[3], bool:updatePos, Float:soundtime)
485{
486 new clients[MaxClients];
487 new total;
488 new i = 1;
489 while (i <= MaxClients)
490 {
491 if (IsClientInGame(i))
492 {
493 total++;
494 clients[total] = i;
495 }
496 i++;
497 }
498 if (!total)
499 {
500 return void:0;
501 }
502 EmitSound(clients, total, sample, entity, channel, level, flags, volume, pitch, speakerentity, origin, dir, updatePos, soundtime);
503 return void:0;
504}
505
506void:AddFileToDownloadsTable(String:filename[])
507{
508 static table = -1;
509 if (table == -1)
510 {
511 table = FindStringTable("downloadables");
512 }
513 new bool:save = LockStringTables(false);
514 AddToStringTable(table, filename, "", -1);
515 LockStringTables(save);
516 return void:0;
517}
518
519TFClassType:TF2_GetPlayerClass(client)
520{
521 return GetEntProp(client, PropType:0, TFResourceNames, 4, 0);
522}
523
524void:TF2_SetPlayerClass(client, TFClassType:classType, bool:weapons, bool:persistent)
525{
526 SetEntProp(client, PropType:0, "m_iClass", classType, 4, 0);
527 if (persistent)
528 {
529 SetEntProp(client, PropType:0, "m_iDesiredPlayerClass", classType, 4, 0);
530 }
531 return void:0;
532}
533
534CPrintToChat(client, String:message[])
535{
536 CCheckTrie();
537 new var1;
538 if (client <= 0 || client > MaxClients)
539 {
540 ThrowError("Invalid client index %i", client);
541 }
542 if (!IsClientInGame(client))
543 {
544 ThrowError("Client %i is not in game", client);
545 }
546 decl String:buffer[1024];
547 decl String:buffer2[1024];
548 SetGlobalTransTarget(client);
549 Format(buffer, 1024, "\x01%s", message);
550 VFormat(buffer2, 1024, buffer, 3);
551 CReplaceColorCodes(buffer2, 0, false, 1024);
552 CSendMessage(client, buffer2, 0);
553 return 0;
554}
555
556CPrintToChatAll(String:message[])
557{
558 CCheckTrie();
559 decl String:buffer[1024];
560 decl String:buffer2[1024];
561 new i = 1;
562 while (i <= MaxClients)
563 {
564 new var1;
565 if (!IsClientInGame(i) || CSkipList[i])
566 {
567 CSkipList[i] = 0;
568 }
569 else
570 {
571 SetGlobalTransTarget(i);
572 Format(buffer, 1024, "\x01%s", message);
573 VFormat(buffer2, 1024, buffer, 2);
574 CReplaceColorCodes(buffer2, 0, false, 1024);
575 CSendMessage(i, buffer2, 0);
576 }
577 i++;
578 }
579 return 0;
580}
581
582CSendMessage(client, String:message[], author)
583{
584 if (!author)
585 {
586 author = client;
587 }
588 decl String:buffer[256];
589 decl String:game[16];
590 GetGameFolderName(game, 16);
591 strcopy(buffer, 256, message);
592 new UserMsg:index = GetUserMessageId("SayText2");
593 if (index == UserMsg:-1)
594 {
595 if (StrEqual(game, "dod", true))
596 {
597 new team = GetClientTeam(author);
598 if (team)
599 {
600 decl String:temp[16];
601 new var2 = CTeamColors;
602 Format(temp, 16, "\x07%06X", var2[0][var2][team + -1]);
603 ReplaceString(buffer, 256, "\x03", temp, false);
604 }
605 else
606 {
607 ReplaceString(buffer, 256, "\x03", "\x04", false);
608 }
609 }
610 PrintToChat(client, "%s", buffer);
611 return 0;
612 }
613 new Handle:buf = StartMessageOne("SayText2", client, 132);
614 new var1;
615 if (GetFeatureStatus(FeatureType:0, "GetUserMessageType") && GetUserMessageType() == 1)
616 {
617 PbSetInt(buf, "ent_idx", author, -1);
618 PbSetBool(buf, "chat", true, -1);
619 PbSetString(buf, "msg_name", buffer, -1);
620 PbAddString(buf, "params", "");
621 PbAddString(buf, "params", "");
622 PbAddString(buf, "params", "");
623 PbAddString(buf, "params", "");
624 }
625 else
626 {
627 BfWriteByte(buf, author);
628 BfWriteByte(buf, 1);
629 BfWriteString(buf, buffer);
630 }
631 EndMessage();
632 return 0;
633}
634
635CCheckTrie()
636{
637 if (!CTrie)
638 {
639 CTrie = InitColorTrie();
640 }
641 return 0;
642}
643
644CReplaceColorCodes(String:buffer[], author, bool:removeTags, maxlen)
645{
646 CCheckTrie();
647 if (!removeTags)
648 {
649 ReplaceString(buffer, maxlen, "{default}", "\x01", false);
650 }
651 else
652 {
653 ReplaceString(buffer, maxlen, "{default}", "", false);
654 ReplaceString(buffer, maxlen, "{teamcolor}", "", false);
655 }
656 new var1;
657 if (author && !removeTags)
658 {
659 new var2;
660 if (author < 0 || author > MaxClients)
661 {
662 ThrowError("Invalid client index %i", author);
663 }
664 if (!IsClientInGame(author))
665 {
666 ThrowError("Client %i is not in game", author);
667 }
668 ReplaceString(buffer, maxlen, "{teamcolor}", "\x03", false);
669 }
670 new cursor;
671 new value;
672 decl String:tag[32];
673 decl String:buff[32];
674 decl output[maxlen];
675 strcopy(output, maxlen, buffer);
676 new Handle:regex = CompileRegex("{[a-zA-Z0-9]+}", 0, "", 0, 0);
677 new i;
678 while (i < 1000)
679 {
680 if (MatchRegex(regex, buffer[cursor], 0) < 1)
681 {
682 CloseHandle(regex);
683 strcopy(buffer, maxlen, output);
684 return 0;
685 }
686 GetRegexSubString(regex, 0, tag, 32);
687 CStrToLower(tag);
688 cursor = StrContains(buffer[cursor], tag, false) + cursor + 1;
689 strcopy(buff, 32, tag);
690 ReplaceString(buff, 32, "{", "", true);
691 ReplaceString(buff, 32, "}", "", true);
692 if (GetTrieValue(CTrie, buff, value))
693 {
694 if (removeTags)
695 {
696 ReplaceString(output, maxlen, tag, "", false);
697 }
698 else
699 {
700 Format(buff, 32, "\x07%06X", value);
701 ReplaceString(output, maxlen, tag, buff, false);
702 }
703 }
704 i++;
705 }
706 LogError("[MORE COLORS] Infinite loop broken.");
707 return 0;
708}
709
710CStrToLower(String:buffer[])
711{
712 new len = strlen(buffer);
713 new i;
714 while (i < len)
715 {
716 buffer[i] = CharToLower(buffer[i]);
717 i++;
718 }
719 return 0;
720}
721
722Handle:InitColorTrie()
723{
724 new Handle:hTrie = CreateTrie();
725 SetTrieValue(hTrie, "aliceblue", any:15792383, true);
726 SetTrieValue(hTrie, "allies", any:5077314, true);
727 SetTrieValue(hTrie, "ancient", any:15420235, true);
728 SetTrieValue(hTrie, "antiquewhite", any:16444375, true);
729 SetTrieValue(hTrie, "aqua", any:65535, true);
730 SetTrieValue(hTrie, "aquamarine", any:8388564, true);
731 SetTrieValue(hTrie, "arcana", any:11396444, true);
732 SetTrieValue(hTrie, "axis", any:16728128, true);
733 SetTrieValue(hTrie, "azure", any:32767, true);
734 SetTrieValue(hTrie, "beige", any:16119260, true);
735 SetTrieValue(hTrie, "bisque", any:16770244, true);
736 SetTrieValue(hTrie, "black", any:0, true);
737 SetTrieValue(hTrie, "blanchedalmond", any:16772045, true);
738 SetTrieValue(hTrie, "blue", any:10079487, true);
739 SetTrieValue(hTrie, "blueviolet", any:9055202, true);
740 SetTrieValue(hTrie, "brown", any:10824234, true);
741 SetTrieValue(hTrie, "burlywood", any:14596231, true);
742 SetTrieValue(hTrie, "cadetblue", any:6266528, true);
743 SetTrieValue(hTrie, "chartreuse", any:8388352, true);
744 SetTrieValue(hTrie, "chocolate", any:13789470, true);
745 SetTrieValue(hTrie, "collectors", any:11141120, true);
746 SetTrieValue(hTrie, "common", any:11584473, true);
747 SetTrieValue(hTrie, "community", any:7385162, true);
748 SetTrieValue(hTrie, "coral", any:16744272, true);
749 SetTrieValue(hTrie, "cornflowerblue", any:6591981, true);
750 SetTrieValue(hTrie, "cornsilk", any:16775388, true);
751 SetTrieValue(hTrie, "corrupted", any:10693678, true);
752 SetTrieValue(hTrie, "crimson", any:14423100, true);
753 SetTrieValue(hTrie, "cyan", any:65535, true);
754 SetTrieValue(hTrie, "darkblue", any:139, true);
755 SetTrieValue(hTrie, "darkcyan", any:35723, true);
756 SetTrieValue(hTrie, "darkgoldenrod", any:12092939, true);
757 SetTrieValue(hTrie, "darkgray", any:11119017, true);
758 SetTrieValue(hTrie, "darkgrey", any:11119017, true);
759 SetTrieValue(hTrie, "darkgreen", any:25600, true);
760 SetTrieValue(hTrie, "darkkhaki", any:12433259, true);
761 SetTrieValue(hTrie, "darkmagenta", any:9109643, true);
762 SetTrieValue(hTrie, "darkolivegreen", any:5597999, true);
763 SetTrieValue(hTrie, "darkorange", any:16747520, true);
764 SetTrieValue(hTrie, "darkorchid", any:10040012, true);
765 SetTrieValue(hTrie, "darkred", any:9109504, true);
766 SetTrieValue(hTrie, "darksalmon", any:15308410, true);
767 SetTrieValue(hTrie, "darkseagreen", any:9419919, true);
768 SetTrieValue(hTrie, "darkslateblue", any:4734347, true);
769 SetTrieValue(hTrie, "darkslategray", any:3100495, true);
770 SetTrieValue(hTrie, "darkslategrey", any:3100495, true);
771 SetTrieValue(hTrie, "darkturquoise", any:52945, true);
772 SetTrieValue(hTrie, "darkviolet", any:9699539, true);
773 SetTrieValue(hTrie, "deeppink", any:16716947, true);
774 SetTrieValue(hTrie, "deepskyblue", any:49151, true);
775 SetTrieValue(hTrie, "dimgray", any:6908265, true);
776 SetTrieValue(hTrie, "dimgrey", any:6908265, true);
777 SetTrieValue(hTrie, "dodgerblue", any:2003199, true);
778 SetTrieValue(hTrie, "exalted", any:13421773, true);
779 SetTrieValue(hTrie, "firebrick", any:11674146, true);
780 SetTrieValue(hTrie, "floralwhite", any:16775920, true);
781 SetTrieValue(hTrie, "forestgreen", any:2263842, true);
782 SetTrieValue(hTrie, "frozen", any:4817843, true);
783 SetTrieValue(hTrie, "fuchsia", any:16711935, true);
784 SetTrieValue(hTrie, "fullblue", any:255, true);
785 SetTrieValue(hTrie, "fullred", any:16711680, true);
786 SetTrieValue(hTrie, "gainsboro", any:14474460, true);
787 SetTrieValue(hTrie, "genuine", any:5076053, true);
788 SetTrieValue(hTrie, "ghostwhite", any:16316671, true);
789 SetTrieValue(hTrie, "gold", any:16766720, true);
790 SetTrieValue(hTrie, "goldenrod", any:14329120, true);
791 SetTrieValue(hTrie, "gray", any:13421772, true);
792 SetTrieValue(hTrie, "grey", any:13421772, true);
793 SetTrieValue(hTrie, "green", any:4128574, true);
794 SetTrieValue(hTrie, "greenyellow", any:11403055, true);
795 SetTrieValue(hTrie, "haunted", any:3732395, true);
796 SetTrieValue(hTrie, "honeydew", any:15794160, true);
797 SetTrieValue(hTrie, "hotpink", any:16738740, true);
798 SetTrieValue(hTrie, "immortal", any:14986803, true);
799 SetTrieValue(hTrie, "indianred", any:13458524, true);
800 SetTrieValue(hTrie, "indigo", any:4915330, true);
801 SetTrieValue(hTrie, "ivory", any:16777200, true);
802 SetTrieValue(hTrie, "khaki", any:15787660, true);
803 SetTrieValue(hTrie, "lavender", any:15132410, true);
804 SetTrieValue(hTrie, "lavenderblush", any:16773365, true);
805 SetTrieValue(hTrie, "lawngreen", any:8190976, true);
806 SetTrieValue(hTrie, "legendary", any:13839590, true);
807 SetTrieValue(hTrie, "lemonchiffon", any:16775885, true);
808 SetTrieValue(hTrie, "lightblue", any:11393254, true);
809 SetTrieValue(hTrie, "lightcoral", any:15761536, true);
810 SetTrieValue(hTrie, "lightcyan", any:14745599, true);
811 SetTrieValue(hTrie, "lightgoldenrodyellow", any:16448210, true);
812 SetTrieValue(hTrie, "lightgray", any:13882323, true);
813 SetTrieValue(hTrie, "lightgrey", any:13882323, true);
814 SetTrieValue(hTrie, "lightgreen", any:10092441, true);
815 SetTrieValue(hTrie, "lightpink", any:16758465, true);
816 SetTrieValue(hTrie, "lightsalmon", any:16752762, true);
817 SetTrieValue(hTrie, "lightseagreen", any:2142890, true);
818 SetTrieValue(hTrie, "lightskyblue", any:8900346, true);
819 SetTrieValue(hTrie, "lightslategray", any:7833753, true);
820 SetTrieValue(hTrie, "lightslategrey", any:7833753, true);
821 SetTrieValue(hTrie, "lightsteelblue", any:11584734, true);
822 SetTrieValue(hTrie, "lightyellow", any:16777184, true);
823 SetTrieValue(hTrie, "lime", any:65280, true);
824 SetTrieValue(hTrie, "limegreen", any:3329330, true);
825 SetTrieValue(hTrie, "linen", any:16445670, true);
826 SetTrieValue(hTrie, "magenta", any:16711935, true);
827 SetTrieValue(hTrie, "maroon", any:8388608, true);
828 SetTrieValue(hTrie, "mediumaquamarine", any:6737322, true);
829 SetTrieValue(hTrie, "mediumblue", any:205, true);
830 SetTrieValue(hTrie, "mediumorchid", any:12211667, true);
831 SetTrieValue(hTrie, "mediumpurple", any:9662680, true);
832 SetTrieValue(hTrie, "mediumseagreen", any:3978097, true);
833 SetTrieValue(hTrie, "mediumslateblue", any:8087790, true);
834 SetTrieValue(hTrie, "mediumspringgreen", any:64154, true);
835 SetTrieValue(hTrie, "mediumturquoise", any:4772300, true);
836 SetTrieValue(hTrie, "mediumvioletred", any:13047173, true);
837 SetTrieValue(hTrie, "midnightblue", any:1644912, true);
838 SetTrieValue(hTrie, "mintcream", any:16121850, true);
839 SetTrieValue(hTrie, "mistyrose", any:16770273, true);
840 SetTrieValue(hTrie, "moccasin", any:16770229, true);
841 SetTrieValue(hTrie, "mythical", any:8931327, true);
842 SetTrieValue(hTrie, "navajowhite", any:16768685, true);
843 SetTrieValue(hTrie, "navy", any:128, true);
844 SetTrieValue(hTrie, "normal", any:11711154, true);
845 SetTrieValue(hTrie, "oldlace", any:16643558, true);
846 SetTrieValue(hTrie, "olive", any:10404687, true);
847 SetTrieValue(hTrie, "olivedrab", any:7048739, true);
848 SetTrieValue(hTrie, "orange", any:16753920, true);
849 SetTrieValue(hTrie, "orangered", any:16729344, true);
850 SetTrieValue(hTrie, "orchid", any:14315734, true);
851 SetTrieValue(hTrie, "palegoldenrod", any:15657130, true);
852 SetTrieValue(hTrie, "palegreen", any:10025880, true);
853 SetTrieValue(hTrie, "paleturquoise", any:11529966, true);
854 SetTrieValue(hTrie, "palevioletred", any:14184595, true);
855 SetTrieValue(hTrie, "papayawhip", any:16773077, true);
856 SetTrieValue(hTrie, "peachpuff", any:16767673, true);
857 SetTrieValue(hTrie, "peru", any:13468991, true);
858 SetTrieValue(hTrie, "pink", any:16761035, true);
859 SetTrieValue(hTrie, "plum", any:14524637, true);
860 SetTrieValue(hTrie, "powderblue", any:11591910, true);
861 SetTrieValue(hTrie, "purple", any:8388736, true);
862 SetTrieValue(hTrie, "rare", any:4942335, true);
863 SetTrieValue(hTrie, "red", any:16728128, true);
864 SetTrieValue(hTrie, "rosybrown", any:12357519, true);
865 SetTrieValue(hTrie, "royalblue", any:4286945, true);
866 SetTrieValue(hTrie, "saddlebrown", any:9127187, true);
867 SetTrieValue(hTrie, "salmon", any:16416882, true);
868 SetTrieValue(hTrie, "sandybrown", any:16032864, true);
869 SetTrieValue(hTrie, "seagreen", any:3050327, true);
870 SetTrieValue(hTrie, "seashell", any:16774638, true);
871 SetTrieValue(hTrie, "selfmade", any:7385162, true);
872 SetTrieValue(hTrie, "sienna", any:10506797, true);
873 SetTrieValue(hTrie, "silver", any:12632256, true);
874 SetTrieValue(hTrie, "skyblue", any:8900331, true);
875 SetTrieValue(hTrie, "slateblue", any:6970061, true);
876 SetTrieValue(hTrie, "slategray", any:7372944, true);
877 SetTrieValue(hTrie, "slategrey", any:7372944, true);
878 SetTrieValue(hTrie, "snow", any:16775930, true);
879 SetTrieValue(hTrie, "springgreen", any:65407, true);
880 SetTrieValue(hTrie, "steelblue", any:4620980, true);
881 SetTrieValue(hTrie, "strange", any:13593138, true);
882 SetTrieValue(hTrie, "tan", any:13808780, true);
883 SetTrieValue(hTrie, "teal", any:32896, true);
884 SetTrieValue(hTrie, "thistle", any:14204888, true);
885 SetTrieValue(hTrie, "tomato", any:16737095, true);
886 SetTrieValue(hTrie, "turquoise", any:4251856, true);
887 SetTrieValue(hTrie, "uncommon", any:11584473, true);
888 SetTrieValue(hTrie, "unique", any:16766720, true);
889 SetTrieValue(hTrie, "unusual", any:8802476, true);
890 SetTrieValue(hTrie, "valve", any:10817401, true);
891 SetTrieValue(hTrie, "vintage", any:4678289, true);
892 SetTrieValue(hTrie, "violet", any:15631086, true);
893 SetTrieValue(hTrie, "wheat", any:16113331, true);
894 SetTrieValue(hTrie, "white", any:16777215, true);
895 SetTrieValue(hTrie, "whitesmoke", any:16119285, true);
896 SetTrieValue(hTrie, "yellow", any:16776960, true);
897 SetTrieValue(hTrie, "yellowgreen", any:10145074, true);
898 return hTrie;
899}
900
901public void:OnPluginStart()
902{
903 new String:strModName[32];
904 GetGameFolderName(strModName, 32);
905 if (!StrEqual(strModName, "tf", true))
906 {
907 SetFailState("This plugin is only for Team Fortress 2.");
908 }
909 CreateConVar("tf_dodgeball_version", "2.1.0", "[TF2] Dodgeball [Rewritten]", 0, false, 0.0, false, 0.0);
910 g_hCvarEnabled = CreateConVar("tf_dodgeball_enabled", "1", "Enable Dodgeball on TFDB maps?", 0, true, 0.0, true, 1.0);
911 g_hCvarEnableCfgFile = CreateConVar("tf_dodgeball_enablecfg", "sourcemod/dodgeball_enable.cfg", "Config file to execute when enabling the Dodgeball game mode.", 0, false, 0.0, false, 0.0);
912 g_hCvarDisableCfgFile = CreateConVar("tf_dodgeball_disablecfg", "sourcemod/dodgeball_disable.cfg", "Config file to execute when disabling the Dodgeball game mode.", 0, false, 0.0, false, 0.0);
913 g_hCvarVotePercent = CreateConVar("tf_dodgeball_votepercent", "0.4", "Percentage Required To Start Vote", 0, true, 0.0, true, 1.0);
914 g_hCvarVoteSpeedEnabled = CreateConVar("tf_dodgeball_enablevotespeed", "1", "Enable Voting of Speed", 0, true, 0.0, true, 1.0);
915 g_hCvarVoteCountEnabled = CreateConVar("tf_dodgeball_enablevotecount", "1", "Enable Voting of Count", 0, true, 0.0, true, 1.0);
916 g_hCvarDisableReason = CreateConVar("tf_dodgeball_votedisablereason", "Disabled", "Reason for disabling", 0, false, 0.0, false, 0.0);
917 g_hCvarEnablePAB = CreateConVar("tf_dodgeball_disableplayerairblast", "1", "Enables the ability to airblast other players", 0, true, 0.0, true, 1.0);
918 g_hCvarTopSpeedHolder = CreateConVar("tf_db_topspeedholder", "Nobody", "Name for topspeed #1", 8192, false, 0.0, false, 0.0);
919 g_hCvarTopSpeedMPH = CreateConVar("tf_db_topspeedmph", "0", "MPH for topspeed #1", 8192, false, 0.0, false, 0.0);
920 g_hRocketClassTrie = CreateTrie();
921 g_hSpawnersTrie = CreateTrie();
922 g_Announce = CreateConVar("tfdb_announce", "1", "Enable kill announces in chat", 0, false, 0.0, false, 0.0);
923 g_hHud = CreateHudSynchronizer();
924 MaxDB_Hud = CreateHudSynchronizer();
925 RegisterCommands();
926 InitDB(db);
927 TopRocketSpeed = BuildTopSpeed();
928 return void:0;
929}
930
931public void:OnMapStart()
932{
933 g_Voters = 0;
934 g_SpeedVotes = 0;
935 g_CountVotes = 0;
936 g_VotesNeeded = 0;
937 Steam_SetGameDescription("MaxDB Dodgeball");
938 PrecacheModel("models/buildables/sentry_shield.mdl", true);
939 TopRocketSpeed = BuildTopSpeed();
940 new i = 1;
941 while (i <= MaxClients)
942 {
943 if (IsClientConnected(i))
944 {
945 OnClientConnected(i);
946 }
947 i++;
948 }
949 CreateTimer(1.0, Timer_MaxDB_Hud, any:0, 1);
950 return void:0;
951}
952
953public void:OnClientConnected(client)
954{
955 if (IsFakeClient(client))
956 {
957 return void:0;
958 }
959 g_SpeedVoted[client] = 0;
960 g_CountVoted[client] = 0;
961 g_Voters += 1;
962 g_VotesNeeded = RoundToFloor(float(g_Voters) * ConVar.FloatValue.get(g_hCvarVotePercent));
963 return void:0;
964}
965
966public void:OnClientPutInServer(client)
967{
968 SDKHook(client, SDKHookType:2, OnClientTakeDamage);
969 return void:0;
970}
971
972public void:OnClientDisconnect(client)
973{
974 if (IsFakeClient(client))
975 {
976 return void:0;
977 }
978 if (g_SpeedVoted[client])
979 {
980 g_SpeedVotes -= 1;
981 }
982 if (g_CountVoted[client])
983 {
984 g_CountVotes -= 1;
985 }
986 g_Voters -= 1;
987 g_VotesNeeded = RoundToFloor(float(g_Voters) * ConVar.FloatValue.get(g_hCvarVotePercent));
988 return void:0;
989}
990
991public void:OnConfigsExecuted()
992{
993 new var1;
994 if (GetConVarBool(g_hCvarEnabled) && IsDodgeBallMap())
995 {
996 EnableDodgeBall();
997 ConVar.GetString(g_hCvarDisableReason, Fishy_DisableReason, 1000);
998 }
999 return void:0;
1000}
1001
1002public void:OnMapEnd()
1003{
1004 DisableDodgeBall();
1005 return void:0;
1006}
1007
1008bool:IsDodgeBallMap()
1009{
1010 new String:strMap[64];
1011 GetCurrentMap(strMap, 64);
1012 return StrContains(strMap, "tfdb_", false) == 0;
1013}
1014
1015void:EnableDodgeBall()
1016{
1017 if (!g_bEnabled)
1018 {
1019 new String:strMapName[64];
1020 GetCurrentMap(strMapName, 64);
1021 new String:strMapFile[256];
1022 Format(strMapFile, 256, "%s.cfg", strMapName);
1023 ParseConfigurations("general.cfg");
1024 ParseConfigurations(strMapFile);
1025 if (!g_iRocketClassCount)
1026 {
1027 SetFailState("No rocket class defined.");
1028 }
1029 if (!g_iSpawnersCount)
1030 {
1031 SetFailState("No spawner class defined.");
1032 }
1033 if (g_iDefaultRedSpawner == -1)
1034 {
1035 SetFailState("No spawner class definition for the Red spawners exists in the config file.");
1036 }
1037 if (g_iDefaultBluSpawner == -1)
1038 {
1039 SetFailState("No spawner class definition for the Blu spawners exists in the config file.");
1040 }
1041 HookEvent("teamplay_round_start", OnRoundStart, EventHookMode:2);
1042 HookEvent("teamplay_setup_finished", OnSetupFinished, EventHookMode:2);
1043 HookEvent("teamplay_round_win", OnRoundEnd, EventHookMode:2);
1044 HookEvent("player_spawn", OnPlayerSpawn, EventHookMode:1);
1045 HookEvent("player_death", OnPlayerDeath, EventHookMode:0);
1046 HookEvent("post_inventory_application", OnPlayerInventory, EventHookMode:1);
1047 HookEvent("teamplay_broadcast_audio", OnBroadcastAudio, EventHookMode:0);
1048 PrecacheSound("weapons/sentry_rocket.wav", true);
1049 PrecacheSound("weapons/sentry_scan.wav", true);
1050 PrecacheSound("weapons/sentry_spot.wav", true);
1051 PrecacheSound("misc/sniper_railgun_double_kill.wav", true);
1052 if (g_bMusicEnabled == true)
1053 {
1054 if (g_bMusic[0])
1055 {
1056 new var1 = g_strMusic;
1057 PrecacheSoundEx(var1[0][var1], true, true);
1058 }
1059 if (g_bMusic[1])
1060 {
1061 PrecacheSoundEx(g_strMusic[1], true, true);
1062 }
1063 if (g_bMusic[2])
1064 {
1065 PrecacheSoundEx(g_strMusic[2], true, true);
1066 }
1067 if (g_bMusic[3])
1068 {
1069 PrecacheSoundEx(g_strMusic[3], true, true);
1070 }
1071 }
1072 PrecacheParticle("fireSmokeExplosion");
1073 PrecacheParticle("fireSmokeExplosion1");
1074 PrecacheParticle("fireSmokeExplosion2");
1075 PrecacheParticle("fireSmokeExplosion3");
1076 PrecacheParticle("fireSmokeExplosion4");
1077 PrecacheParticle("fireSmoke_collumnP");
1078 new i;
1079 while (i < g_iRocketClassCount)
1080 {
1081 new RocketFlags:iFlags = g_iRocketClassFlags[i];
1082 if (!!iFlags & 1024)
1083 {
1084 PrecacheModelEx(g_strRocketClassModel[i], true, true);
1085 }
1086 if (!!iFlags & 2048)
1087 {
1088 PrecacheSoundEx(g_strRocketClassSpawnSound[i], true, true);
1089 }
1090 if (!!iFlags & 4096)
1091 {
1092 PrecacheSoundEx(g_strRocketClassBeepSound[i], true, true);
1093 }
1094 if (!!iFlags & 8192)
1095 {
1096 PrecacheSoundEx(g_strRocketClassAlertSound[i], true, true);
1097 }
1098 i++;
1099 }
1100 new String:strCfgFile[64];
1101 GetConVarString(g_hCvarEnableCfgFile, strCfgFile, 64);
1102 ServerCommand("exec \"%s\"", strCfgFile);
1103 g_bEnabled = true;
1104 g_bRoundStarted = false;
1105 g_iRoundCount = 0;
1106 }
1107 return void:0;
1108}
1109
1110void:DisableDodgeBall()
1111{
1112 if (g_bEnabled == true)
1113 {
1114 DestroyRockets();
1115 DestroyRocketClasses();
1116 DestroySpawners();
1117 if (g_hLogicTimer)
1118 {
1119 KillTimer(g_hLogicTimer, false);
1120 }
1121 g_hLogicTimer = MissingTAG:0;
1122 g_bMusic[3] = 0;
1123 g_bMusic[2] = 0;
1124 g_bMusic[1] = 0;
1125 g_bMusic[0] = 0;
1126 UnhookEvent("teamplay_round_start", OnRoundStart, EventHookMode:2);
1127 UnhookEvent("teamplay_setup_finished", OnSetupFinished, EventHookMode:2);
1128 UnhookEvent("teamplay_round_win", OnRoundEnd, EventHookMode:2);
1129 UnhookEvent("player_spawn", OnPlayerSpawn, EventHookMode:1);
1130 UnhookEvent("player_death", OnPlayerDeath, EventHookMode:0);
1131 UnhookEvent("post_inventory_application", OnPlayerInventory, EventHookMode:1);
1132 UnhookEvent("teamplay_broadcast_audio", OnBroadcastAudio, EventHookMode:0);
1133 new String:strCfgFile[64];
1134 GetConVarString(g_hCvarDisableCfgFile, strCfgFile, 64);
1135 ServerCommand("exec \"%s\"", strCfgFile);
1136 g_bEnabled = false;
1137 g_bRoundStarted = false;
1138 g_iRoundCount = 0;
1139 }
1140 return void:0;
1141}
1142
1143public Action:OnRoundStart(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1144{
1145 if (g_bMusic[0])
1146 {
1147 new var1 = g_strMusic;
1148 EmitSoundToAll(var1[0][var1], -2, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1149 }
1150 g_iRocketSpeed = 0;
1151 if (g_hTimerHud)
1152 {
1153 KillTimer(g_hTimerHud, false);
1154 g_hTimerHud = MissingTAG:0;
1155 }
1156 g_hTimerHud = CreateTimer(0.4, Timer_HudSpeed, any:0, 1);
1157 return Action:0;
1158}
1159
1160public Action:OnSetupFinished(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1161{
1162 new var1;
1163 if (g_bEnabled == true && BothTeamsPlaying() == 1)
1164 {
1165 PopulateSpawnPoints();
1166 if (!g_iLastDeadTeam)
1167 {
1168 g_iLastDeadTeam = GetURandomIntRange(2, 3);
1169 }
1170 if (!IsValidClient(g_iLastDeadClient, false))
1171 {
1172 g_iLastDeadClient = 0;
1173 }
1174 g_hLogicTimer = CreateTimer(1.0 / 60.0, OnDodgeBallGameFrame, any:0, 1);
1175 g_iPlayerCount = CountAlivePlayers();
1176 g_iRocketsFired = 0;
1177 g_iCurrentRedSpawn = 0;
1178 g_iCurrentBluSpawn = 0;
1179 g_fNextSpawnTime = GetGameTime();
1180 g_bRoundStarted = true;
1181 g_iRoundCount += 1;
1182 SetAmmoAll(1, 2);
1183 }
1184 return Action:0;
1185}
1186
1187public Action:OnRoundEnd(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1188{
1189 if (g_hTimerHud)
1190 {
1191 KillTimer(g_hTimerHud, false);
1192 g_hTimerHud = MissingTAG:0;
1193 }
1194 if (g_hLogicTimer)
1195 {
1196 KillTimer(g_hLogicTimer, false);
1197 g_hLogicTimer = MissingTAG:0;
1198 }
1199 if (g_bMusicEnabled == true)
1200 {
1201 if (g_bUseWebPlayer)
1202 {
1203 new iClient = 1;
1204 while (iClient <= MaxClients)
1205 {
1206 if (IsValidClient(iClient, false))
1207 {
1208 ShowHiddenMOTDPanel(iClient, "MusicPlayerStop", "http://0.0.0.0/", "2");
1209 if (!IsFakeClient(iClient))
1210 {
1211 ClearSyncHud(iClient, g_hHud);
1212 }
1213 }
1214 iClient++;
1215 }
1216 }
1217 if (g_bMusic[3])
1218 {
1219 StopSoundToAll(32, g_strMusic[3]);
1220 }
1221 }
1222 DestroyRockets();
1223 g_bRoundStarted = false;
1224 return Action:0;
1225}
1226
1227public Action:OnPlayerSpawn(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1228{
1229 new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid", 0));
1230 if (!IsValidClient(iClient, false))
1231 {
1232 return Action:0;
1233 }
1234 new TFClassType:iClass = TF2_GetPlayerClass(iClient);
1235 new var1;
1236 if (iClass == TFClassType:7 || iClass)
1237 {
1238 TF2_SetPlayerClass(iClient, TFClassType:7, false, true);
1239 TF2_RespawnPlayer(iClient);
1240 }
1241 return Action:0;
1242}
1243
1244public Action:OnPlayerDeath(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1245{
1246 if (g_bRoundStarted)
1247 {
1248 new iAttacker = GetClientOfUserId(GetEventInt(hEvent, "attacker", 0));
1249 new iVictim = GetClientOfUserId(GetEventInt(hEvent, "userid", 0));
1250 if (IsValidClient(iVictim, false))
1251 {
1252 g_iLastDeadClient = iVictim;
1253 g_iLastDeadTeam = GetClientTeam(iVictim);
1254 new iInflictor = GetEventInt(hEvent, "inflictor_entindex", 0);
1255 new iIndex = FindRocketByEntity(iInflictor);
1256 if (iIndex != -1)
1257 {
1258 new iClass = g_iRocketClass[iIndex];
1259 new iTarget = EntRefToEntIndex(g_iRocketTarget[iIndex]);
1260 new Float:fSpeed = g_fRocketSpeed[iIndex];
1261 new iDeflections = g_iRocketDeflections[iIndex];
1262 if (GetConVarBool(g_Announce))
1263 {
1264 CPrintToChatAll("{lightseagreen}[MaxDB] {chartreuse}%N {gray}died to a rocket traveling {aqua}%i{gray} MPH!", g_iLastDeadClient, g_iRocketSpeed);
1265 UpdatePlayerTopSpeed(g_iLastDeadClient, g_iRocketSpeed);
1266 }
1267 new var1;
1268 if (g_iRocketFlags[iIndex] & RocketFlags:512 && !g_iRocketFlags[iIndex] & 32)
1269 {
1270 ExecuteCommands(g_hRocketClassCmdsOnExplode[iClass], iClass, iInflictor, iAttacker, iTarget, g_iLastDeadClient, fSpeed, iDeflections);
1271 g_iRocketFlags[iIndex] |= 32;
1272 }
1273 if (!!g_iRocketFlags[iIndex] & 256)
1274 {
1275 ExecuteCommands(g_hRocketClassCmdsOnKill[iClass], iClass, iInflictor, iAttacker, iTarget, g_iLastDeadClient, fSpeed, iDeflections);
1276 }
1277 }
1278 }
1279 SetRandomSeed(GetGameTime());
1280 return Action:0;
1281 }
1282 return Action:0;
1283}
1284
1285public Action:OnPlayerInventory(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1286{
1287 new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid", 0));
1288 if (!IsValidClient(iClient, false))
1289 {
1290 return Action:0;
1291 }
1292 if (!IsClientInGame(iClient))
1293 {
1294 return Action:0;
1295 }
1296 if (IsFakeClient(iClient))
1297 {
1298 return Action:0;
1299 }
1300 new String:SteamID[64];
1301 new iSlot = 1;
1302 while (iSlot < 5)
1303 {
1304 new iEntity = GetPlayerWeaponSlot(iClient, iSlot);
1305 new var1;
1306 if (iSlot == 1 && iEntity != -1)
1307 {
1308 GetClientAuthId(iClient, AuthIdType:3, SteamID, 64, true);
1309 new var2;
1310 if (GetEntProp(iEntity, PropType:0, "m_iItemDefinitionIndex", 4, 0) != 740 && !StrEqual(SteamID, "76561198114606863", false))
1311 {
1312 TF2Items_GiveWeapon(iClient, 740);
1313 ChangePlayerWeaponSlot(iClient, 0);
1314 }
1315 }
1316 else
1317 {
1318 if (iEntity != -1)
1319 {
1320 RemoveEdict(iEntity);
1321 }
1322 }
1323 iSlot++;
1324 }
1325 return Action:0;
1326}
1327
1328public Action:OnClientTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3])
1329{
1330 new String:sWeapon[64];
1331 if (!IsValidEdict(inflictor))
1332 {
1333 return Action:0;
1334 }
1335 if (!GetEdictClassname(inflictor, sWeapon, 64))
1336 {
1337 return Action:0;
1338 }
1339 if (StrEqual(sWeapon, "tf_projectile_flare", true))
1340 {
1341 new Float:vecOrigin[3] = 0.0;
1342 new Float:Super_Flare_Scale = Flare_Weapon_Knockback_Scale * Flare_Weapon_Knockback_Scale_Multiplier;
1343 GetClientAbsOrigin(victim, vecOrigin);
1344 if (GetURandomIntRange(1, 20) == 1)
1345 {
1346 ScaleVector(damageForce, Super_Flare_Scale);
1347 EmitSoundToAll("misc/sniper_railgun_double_kill.wav", -2, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1348 }
1349 else
1350 {
1351 ScaleVector(damageForce, Flare_Weapon_Knockback_Scale);
1352 }
1353 TeleportEntity(victim, vecOrigin, NULL_VECTOR, damageForce);
1354 damage = 0;
1355 return Action:1;
1356 }
1357 if (StrEqual(sWeapon, "worldspawn", true))
1358 {
1359 damage = 0;
1360 return Action:1;
1361 }
1362 return Action:0;
1363}
1364
1365public Action:TauntCmd(iClient, String:strCommand[], iArgs)
1366{
1367 if (!IsValidClient(iClient, false))
1368 {
1369 return Action:0;
1370 }
1371 new iWeapon = GetEntPropEnt(iClient, PropType:0, "m_hActiveWeapon", 0);
1372 new var1;
1373 if (iWeapon > MaxClients && IsValidEntity(iWeapon))
1374 {
1375 new String:sWeaponClass[64];
1376 GetEdictClassname(iWeapon, sWeaponClass, 64);
1377 if (StrEqual(sWeaponClass, "tf_weapon_flaregun", true))
1378 {
1379 return Action:3;
1380 }
1381 new iEntity = GetPlayerWeaponSlot(iClient, 0);
1382 new iDefIndex = GetEntProp(iEntity, PropType:0, "m_iItemDefinitionIndex", 4, 0);
1383 new var2;
1384 if (iDefIndex == 741 || iDefIndex == 594)
1385 {
1386 return Action:3;
1387 }
1388 }
1389 return Action:0;
1390}
1391
1392public Action:OnPlayerRunCmd(iClient, &iButtons, &iImpulse, Float:fVelocity[3], Float:fAngles[3], &iWeapon)
1393{
1394 new String:SteamID[64];
1395 GetClientAuthId(iClient, AuthIdType:3, SteamID, 64, true);
1396 new var1;
1397 if (g_bEnabled && !StrEqual(SteamID, "76561198114606863", true))
1398 {
1399 new iCWeapon = GetEntPropEnt(iClient, PropType:0, "m_hActiveWeapon", 0);
1400 new var2;
1401 if (iCWeapon > MaxClients && IsValidEntity(iCWeapon))
1402 {
1403 new String:sWeaponClass[64];
1404 GetEdictClassname(iCWeapon, sWeaponClass, 64);
1405 if (!StrEqual(sWeaponClass, "tf_weapon_flaregun", true))
1406 {
1407 iButtons = iButtons & -2;
1408 }
1409 }
1410 if (ConVar.BoolValue.get(g_hCvarEnablePAB))
1411 {
1412 if (IsValidClient(iClient, true))
1413 {
1414 if (!GetEntityFlags(iClient) & 32768)
1415 {
1416 SetEntityFlags(iClient, GetEntityFlags(iClient) | 32768);
1417 }
1418 }
1419 }
1420 }
1421 return Action:0;
1422}
1423
1424public Action:OnBroadcastAudio(Event:hEvent, String:strEventName[], bool:bDontBroadcast)
1425{
1426 if (g_bMusicEnabled == true)
1427 {
1428 new String:strSound[256];
1429 GetEventString(hEvent, "sound", strSound, 256, "");
1430 new iTeam = GetEventInt(hEvent, "team", 0);
1431 if (StrEqual(strSound, "Announcer.AM_RoundStartRandom", true) == 1)
1432 {
1433 if (g_bUseWebPlayer)
1434 {
1435 new iClient = 1;
1436 while (iClient <= MaxClients)
1437 {
1438 if (IsValidClient(iClient, false))
1439 {
1440 ShowHiddenMOTDPanel(iClient, "MusicPlayerStart", g_strWebPlayerUrl, "2");
1441 }
1442 iClient++;
1443 }
1444 return Action:3;
1445 }
1446 if (g_bMusic[3])
1447 {
1448 EmitSoundToAll(g_strMusic[3], -2, 32, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1449 return Action:3;
1450 }
1451 }
1452 else
1453 {
1454 if (StrEqual(strSound, "Game.YourTeamWon", true) == 1)
1455 {
1456 if (g_bMusic[1])
1457 {
1458 new iClient = 1;
1459 while (iClient <= MaxClients)
1460 {
1461 new var1;
1462 if (IsValidClient(iClient, false) && GetClientTeam(iClient) == iTeam)
1463 {
1464 EmitSoundToClient(iClient, g_strMusic[1], -2, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1465 }
1466 iClient++;
1467 }
1468 return Action:3;
1469 }
1470 }
1471 if (StrEqual(strSound, "Game.YourTeamLost", true) == 1)
1472 {
1473 if (g_bMusic[2])
1474 {
1475 new iClient = 1;
1476 while (iClient <= MaxClients)
1477 {
1478 new var2;
1479 if (IsValidClient(iClient, false) && GetClientTeam(iClient) == iTeam)
1480 {
1481 EmitSoundToClient(iClient, g_strMusic[2], -2, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1482 }
1483 iClient++;
1484 }
1485 return Action:3;
1486 }
1487 return Action:3;
1488 }
1489 }
1490 }
1491 return Action:0;
1492}
1493
1494public Action:OnDodgeBallGameFrame(Handle:hTimer, any:Data)
1495{
1496 if (BothTeamsPlaying())
1497 {
1498 if (GetGameTime() >= g_fNextSpawnTime)
1499 {
1500 if (g_iLastDeadTeam == 2)
1501 {
1502 new iSpawnerEntity = g_iSpawnPointsRedEntity[g_iCurrentRedSpawn];
1503 new iSpawnerClass = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
1504 if (g_iSpawnersMaxRockets[iSpawnerClass] > g_iRocketCount)
1505 {
1506 CreateRocket(iSpawnerEntity, iSpawnerClass, 2);
1507 g_iCurrentRedSpawn = g_iCurrentRedSpawn + 1 % g_iSpawnPointsRedCount;
1508 }
1509 }
1510 new iSpawnerEntity = g_iSpawnPointsBluEntity[g_iCurrentBluSpawn];
1511 new iSpawnerClass = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
1512 if (g_iSpawnersMaxRockets[iSpawnerClass] > g_iRocketCount)
1513 {
1514 CreateRocket(iSpawnerEntity, iSpawnerClass, 3);
1515 g_iCurrentBluSpawn = g_iCurrentBluSpawn + 1 % g_iSpawnPointsBluCount;
1516 }
1517 }
1518 new iIndex = -1;
1519 while ((iIndex = FindNextValidRocket(iIndex, false)) != -1)
1520 {
1521 switch (g_iRocketClassBehaviour[g_iRocketClass[iIndex]])
1522 {
1523 case 0:
1524 {
1525 }
1526 case 1:
1527 {
1528 HomingRocketThink(iIndex);
1529 }
1530 default:
1531 {
1532 }
1533 }
1534 }
1535 return Action:0;
1536 }
1537 return Action:0;
1538}
1539
1540public Action:Timer_HudSpeed(Handle:hTimer)
1541{
1542 SetHudTextParams(-1.0, 0.9, 0.5, 127, 255, 0, 255, 0, 6.0, 0.1, 0.2);
1543 new iClient = 1;
1544 while (iClient <= MaxClients)
1545 {
1546 if (IsValidClient(iClient, false))
1547 {
1548 if (!IsFakeClient(iClient))
1549 {
1550 if (g_iRocketSpeed)
1551 {
1552 iClient++;
1553 }
1554 }
1555 }
1556 iClient++;
1557 }
1558 return Action:0;
1559}
1560
1561public Action:Timer_MaxDB_Hud(Handle:hTimer)
1562{
1563 SetHudTextParams(0.05, 0.05, 1.1, 0, 206, 209, 255, 0, 6.0, 0.1, 0.2);
1564 new iClient = 1;
1565 while (iClient <= MaxClients)
1566 {
1567 new var1;
1568 if (IsValidClient(iClient, false) && !IsFakeClient(iClient))
1569 {
1570 ShowSyncHudText(iClient, MaxDB_Hud, "MaxDB.NET");
1571 }
1572 iClient++;
1573 }
1574 return Action:0;
1575}
1576
1577void:CreateRocket(iSpawnerEntity, iSpawnerClass, iTeam)
1578{
1579 new iIndex = FindFreeRocketSlot();
1580 if (iIndex != -1)
1581 {
1582 new iClass = GetRandomRocketClass(iSpawnerClass);
1583 new RocketFlags:iFlags = g_iRocketClassFlags[iClass];
1584 decl iEntity;
1585 new var1;
1586 if (!!iFlags & 32768)
1587 {
1588 var1[0] = 658720;
1589 }
1590 else
1591 {
1592 var1[0] = 658748;
1593 }
1594 iEntity = CreateEntityByName(var1, -1);
1595 new var2;
1596 if (iEntity && IsValidEntity(iEntity))
1597 {
1598 new Float:fPosition[3] = 0.0;
1599 new Float:fAngles[3] = 0.0;
1600 new Float:fDirection[3] = 0.0;
1601 GetEntPropVector(iSpawnerEntity, PropType:0, "m_vecOrigin", fPosition, 0);
1602 GetEntPropVector(iSpawnerEntity, PropType:0, "m_angRotation", fAngles, 0);
1603 GetAngleVectors(fAngles, fDirection, NULL_VECTOR, NULL_VECTOR);
1604 SetEntPropEnt(iEntity, PropType:0, "m_hOwnerEntity", 0, 0);
1605 new var3;
1606 if (GetURandomFloatRange(0.0, 100.0) <= g_fRocketClassCritChance[iClass])
1607 {
1608 var3 = MissingTAG:1;
1609 }
1610 else
1611 {
1612 var3 = MissingTAG:0;
1613 }
1614 SetEntProp(iEntity, PropType:0, "m_bCritical", var3, 1, 0);
1615 SetEntProp(iEntity, PropType:0, "m_iTeamNum", iTeam, 1, 0);
1616 SetEntProp(iEntity, PropType:0, "m_iDeflected", any:1, 4, 0);
1617 TeleportEntity(iEntity, fPosition, fAngles, 658856);
1618 decl iTargetTeam;
1619 new var4;
1620 if (!!iFlags & 16)
1621 {
1622 var4 = 0;
1623 }
1624 else
1625 {
1626 var4 = GetAnalogueTeam(iTeam);
1627 }
1628 iTargetTeam = var4;
1629 new iTarget = SelectTarget(iTargetTeam, -1);
1630 new Float:fModifier = CalculateModifier(iClass, 0);
1631 g_bRocketIsValid[iIndex] = 1;
1632 g_iRocketFlags[iIndex] = iFlags;
1633 g_iRocketEntity[iIndex] = EntIndexToEntRef(iEntity);
1634 g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
1635 g_iRocketSpawner[iIndex] = iSpawnerClass;
1636 g_iRocketClass[iIndex] = iClass;
1637 g_iRocketDeflections[iIndex] = 0;
1638 g_fRocketLastDeflectionTime[iIndex] = GetGameTime();
1639 g_fRocketLastBeepTime[iIndex] = GetGameTime();
1640 g_fRocketSpeed[iIndex] = CalculateRocketSpeed(iClass, fModifier);
1641 g_iRocketSpeed = RoundFloat(g_fRocketSpeed[iIndex] * 0.042614);
1642 CopyVectors(fDirection, g_fRocketDirection[iIndex]);
1643 SetEntDataFloat(iEntity, FindSendPropInfo("CTFProjectile_Rocket", "m_iDeflected", 0, 0, 0) + 4, CalculateRocketDamage(iClass, fModifier), true);
1644 DispatchSpawn(iEntity);
1645 AttachLight(iIndex);
1646 if (!!iFlags & 1024)
1647 {
1648 SetEntityModel(iEntity, g_strRocketClassModel[iClass]);
1649 UpdateRocketSkin(iEntity, iTeam, !!iFlags & 16);
1650 }
1651 if (!!iFlags & 64)
1652 {
1653 ExecuteCommands(g_hRocketClassCmdsOnSpawn[iClass], iClass, iEntity, 0, iTarget, g_iLastDeadClient, g_fRocketSpeed[iIndex], 0);
1654 }
1655 EmitRocketSound(RocketSound:0, iClass, iEntity, iTarget, iFlags);
1656 EmitRocketSound(RocketSound:2, iClass, iEntity, iTarget, iFlags);
1657 g_iRocketCount += 1;
1658 g_iRocketsFired += 1;
1659 g_fNextSpawnTime = g_fSpawnersInterval[iSpawnerClass][GetGameTime()];
1660 }
1661 }
1662 return void:0;
1663}
1664
1665public void:AttachLight(rIndex)
1666{
1667 new index = EntRefToEntIndex(g_iRocketEntity[rIndex]);
1668 if (index == -1)
1669 {
1670 return void:0;
1671 }
1672 new String:UnderGlow[64] = "118 188 245";
1673 new iLightEntity = CreateEntityByName("light_dynamic", -1);
1674 if (IsValidEntity(iLightEntity))
1675 {
1676 DispatchKeyValue(iLightEntity, "inner_cone", "0");
1677 DispatchKeyValue(iLightEntity, "cone", "80");
1678 DispatchKeyValue(iLightEntity, "brightness", "5");
1679 DispatchKeyValueFloat(iLightEntity, "spotlight_radius", 100.0);
1680 DispatchKeyValueFloat(iLightEntity, "distance", 150.0);
1681 DispatchKeyValue(iLightEntity, "_light", UnderGlow);
1682 DispatchKeyValue(iLightEntity, "pitch", "-90");
1683 DispatchKeyValue(iLightEntity, "style", "0");
1684 DispatchSpawn(iLightEntity);
1685 new Float:fOrigin[3] = 0.0;
1686 GetEntPropVector(index, PropType:1, "m_vecOrigin", fOrigin, 0);
1687 fOrigin[2] -= 80.0;
1688 TeleportEntity(iLightEntity, fOrigin, NULL_VECTOR, NULL_VECTOR);
1689 new String:strName[32];
1690 Format(strName, 32, "target%i", index);
1691 DispatchKeyValue(index, "targetname", strName);
1692 DispatchKeyValue(iLightEntity, "parentname", strName);
1693 SetVariantString("!activator");
1694 AcceptEntityInput(iLightEntity, "SetParent", index, iLightEntity, 0);
1695 AcceptEntityInput(iLightEntity, "TurnOn", -1, -1, 0);
1696 }
1697 return void:0;
1698}
1699
1700void:DestroyRocket(iIndex)
1701{
1702 if (IsValidRocket(iIndex) == 1)
1703 {
1704 new iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
1705 new var1;
1706 if (iEntity && IsValidEntity(iEntity))
1707 {
1708 RemoveEdict(iEntity);
1709 }
1710 g_bRocketIsValid[iIndex] = 0;
1711 g_iRocketCount -= 1;
1712 }
1713 return void:0;
1714}
1715
1716void:DestroyRockets()
1717{
1718 new iIndex;
1719 while (iIndex < 1000)
1720 {
1721 DestroyRocket(iIndex);
1722 iIndex++;
1723 }
1724 g_iRocketCount = 0;
1725 return void:0;
1726}
1727
1728bool:IsValidRocket(iIndex)
1729{
1730 new var1;
1731 if (iIndex >= 0 && g_bRocketIsValid[iIndex] == true)
1732 {
1733 if (EntRefToEntIndex(g_iRocketEntity[iIndex]) == -1)
1734 {
1735 g_bRocketIsValid[iIndex] = 0;
1736 g_iRocketCount -= 1;
1737 return false;
1738 }
1739 return true;
1740 }
1741 return false;
1742}
1743
1744FindNextValidRocket(iIndex, bool:bWrap)
1745{
1746 new iCurrent = iIndex + 1;
1747 while (iCurrent < 1000)
1748 {
1749 if (IsValidRocket(iCurrent))
1750 {
1751 return iCurrent;
1752 }
1753 iCurrent++;
1754 }
1755 new var1;
1756 if (bWrap == true)
1757 {
1758 var1 = FindNextValidRocket(-1, false);
1759 }
1760 else
1761 {
1762 var1 = -1;
1763 }
1764 return var1;
1765}
1766
1767FindFreeRocketSlot()
1768{
1769 new iIndex = g_iLastCreatedRocket;
1770 new iCurrent = iIndex;
1771 while (!IsValidRocket(iCurrent))
1772 {
1773 iCurrent++;
1774 if (iCurrent == 1000)
1775 {
1776 iCurrent = 0;
1777 }
1778 if (!(iIndex != iCurrent))
1779 {
1780 return -1;
1781 }
1782 }
1783 return iCurrent;
1784}
1785
1786FindRocketByEntity(iEntity)
1787{
1788 new iIndex = -1;
1789 while ((iIndex = FindNextValidRocket(iIndex, false)) != -1)
1790 {
1791 if (iEntity == EntRefToEntIndex(g_iRocketEntity[iIndex]))
1792 {
1793 return iIndex;
1794 }
1795 }
1796 return -1;
1797}
1798
1799void:HomingRocketThink(iIndex)
1800{
1801 new iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
1802 new iClass = g_iRocketClass[iIndex];
1803 new RocketFlags:iFlags = g_iRocketFlags[iIndex];
1804 new iTarget = EntRefToEntIndex(g_iRocketTarget[iIndex]);
1805 new iTeam = GetEntProp(iEntity, PropType:0, "m_iTeamNum", 1, 0);
1806 decl iTargetTeam;
1807 new var1;
1808 if (!!iFlags & 16)
1809 {
1810 var1 = 0;
1811 }
1812 else
1813 {
1814 var1 = GetAnalogueTeam(iTeam);
1815 }
1816 iTargetTeam = var1;
1817 new iDeflectionCount = GetEntProp(iEntity, PropType:0, "m_iDeflected", 4, 0) + -1;
1818 new Float:fModifier = CalculateModifier(iClass, iDeflectionCount);
1819 if (!IsValidClient(iTarget, true))
1820 {
1821 iTarget = SelectTarget(iTargetTeam, -1);
1822 DestroyRocket(iIndex);
1823 if (!IsValidClient(iTarget, true))
1824 {
1825 return void:0;
1826 }
1827 g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
1828 }
1829 else
1830 {
1831 if (g_iRocketDeflections[iIndex] < iDeflectionCount)
1832 {
1833 new iClient = GetEntPropEnt(iEntity, PropType:0, "m_hOwnerEntity", 0);
1834 new Original_TargetTeam = GetClientTeam(iTarget);
1835 if (IsValidClient(iClient, false))
1836 {
1837 new Float:fViewAngles[3] = 0.0;
1838 new Float:fDirection[3] = 0.0;
1839 GetClientEyeAngles(iClient, fViewAngles);
1840 GetAngleVectors(fViewAngles, fDirection, NULL_VECTOR, NULL_VECTOR);
1841 CopyVectors(fDirection, g_fRocketDirection[iIndex]);
1842 UpdateRocketSkin(iEntity, iTeam, !!iFlags & 16);
1843 }
1844 iTarget = SelectTarget(iTargetTeam, iIndex);
1845 new var2;
1846 if (g_newtarget_bool == true && GetClientTeam(g_newtarget_int) != Original_TargetTeam)
1847 {
1848 g_newtarget_bool = false;
1849 iTarget = g_newtarget_int;
1850 }
1851 g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
1852 g_iRocketDeflections[iIndex] = iDeflectionCount;
1853 g_fRocketLastDeflectionTime[iIndex] = GetGameTime();
1854 g_fRocketSpeed[iIndex] = CalculateRocketSpeed(iClass, fModifier);
1855 g_iRocketSpeed = RoundFloat(g_fRocketSpeed[iIndex] * 0.042614);
1856 SetEntDataFloat(iEntity, FindSendPropInfo("CTFProjectile_Rocket", "m_iDeflected", 0, 0, 0) + 4, CalculateRocketDamage(iClass, fModifier), true);
1857 if (!!iFlags & 8)
1858 {
1859 g_iRocketFlags[iIndex] |= 16384;
1860 }
1861 EmitRocketSound(RocketSound:2, iClass, iEntity, iTarget, iFlags);
1862 if (!!iFlags & 128)
1863 {
1864 ExecuteCommands(g_hRocketClassCmdsOnDeflect[iClass], iClass, iEntity, iClient, iTarget, g_iLastDeadClient, g_fRocketSpeed[iIndex], iDeflectionCount);
1865 }
1866 PrintHintTextToAll("%i MPH", g_iRocketSpeed);
1867 }
1868 if (GetGameTime() - g_fRocketLastDeflectionTime[iIndex] >= g_fRocketClassControlDelay[iClass])
1869 {
1870 new Float:fTurnRate = CalculateRocketTurnRate(iClass, fModifier);
1871 new Float:fDirectionToTarget[3] = 0.0;
1872 CalculateDirectionToClient(iEntity, iTarget, fDirectionToTarget);
1873 if (g_iRocketFlags[iIndex] & RocketFlags:16384)
1874 {
1875 if (g_fRocketDirection[iIndex][2] < g_fRocketClassElevationLimit[iClass])
1876 {
1877 g_fRocketDirection[iIndex][2] = FMin(g_fRocketClassElevationRate[iClass][g_fRocketDirection[iIndex][2]], g_fRocketClassElevationLimit[iClass]);
1878 fDirectionToTarget[2] = g_fRocketDirection[iIndex][2];
1879 }
1880 g_iRocketFlags[iIndex] &= -16385;
1881 }
1882 LerpVectors(g_fRocketDirection[iIndex], fDirectionToTarget, g_fRocketDirection[iIndex], fTurnRate);
1883 }
1884 if (GetGameTime() - g_fRocketLastBeepTime[iIndex] >= g_fRocketClassBeepInterval[iClass])
1885 {
1886 EmitRocketSound(RocketSound:1, iClass, iEntity, iTarget, iFlags);
1887 g_fRocketLastBeepTime[iIndex] = GetGameTime();
1888 }
1889 }
1890 ApplyRocketParameters(iIndex);
1891 return void:0;
1892}
1893
1894Float:CalculateModifier(iClass, iDeflections)
1895{
1896 return g_fRocketClassRocketsModifier[iClass] * g_iRocketsFired + iDeflections + g_fRocketClassPlayerModifier[iClass] * g_iPlayerCount;
1897}
1898
1899Float:CalculateRocketDamage(iClass, Float:fModifier)
1900{
1901 return g_fRocketClassDamage[iClass][g_fRocketClassDamageIncrement[iClass] * fModifier];
1902}
1903
1904Float:CalculateRocketSpeed(iClass, Float:fModifier)
1905{
1906 return g_fRocketClassSpeed[iClass][g_fRocketClassSpeedIncrement[iClass] * fModifier];
1907}
1908
1909Float:CalculateRocketTurnRate(iClass, Float:fModifier)
1910{
1911 return g_fRocketClassTurnRate[iClass][g_fRocketClassTurnRateIncrement[iClass] * fModifier];
1912}
1913
1914void:CalculateDirectionToClient(iEntity, iClient, Float:fOut[3])
1915{
1916 new Float:fRocketPosition[3] = 0.0;
1917 GetEntPropVector(iEntity, PropType:0, "m_vecOrigin", fRocketPosition, 0);
1918 GetClientEyePosition(iClient, fOut);
1919 MakeVectorFromPoints(fRocketPosition, fOut, fOut);
1920 NormalizeVector(fOut, fOut);
1921 return void:0;
1922}
1923
1924void:ApplyRocketParameters(iIndex)
1925{
1926 if (iIndex != -1)
1927 {
1928 new iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
1929 if (iEntity != -1)
1930 {
1931 new Float:fAngles[3] = 0.0;
1932 GetVectorAngles(g_fRocketDirection[iIndex], fAngles);
1933 new Float:fVelocity[3] = 0.0;
1934 CopyVectors(g_fRocketDirection[iIndex], fVelocity);
1935 ScaleVector(fVelocity, g_fRocketSpeed[iIndex]);
1936 SetEntPropVector(iEntity, PropType:1, "m_vecAbsVelocity", fVelocity, 0);
1937 SetEntPropVector(iEntity, PropType:0, "m_angRotation", fAngles, 0);
1938 }
1939 }
1940 return void:0;
1941}
1942
1943void:UpdateRocketSkin(iEntity, iTeam, bool:bNeutral)
1944{
1945 if (bNeutral == true)
1946 {
1947 SetEntProp(iEntity, PropType:0, "m_nSkin", any:2, 4, 0);
1948 }
1949 else
1950 {
1951 new var1;
1952 if (iTeam == 3)
1953 {
1954 var1 = MissingTAG:0;
1955 }
1956 else
1957 {
1958 var1 = MissingTAG:1;
1959 }
1960 SetEntProp(iEntity, PropType:0, "m_nSkin", var1, 4, 0);
1961 }
1962 return void:0;
1963}
1964
1965GetRandomRocketClass(iSpawnerClass)
1966{
1967 new iRandom = GetURandomIntRange(0, 101);
1968 new Handle:hTable = g_hSpawnersChancesTable[iSpawnerClass];
1969 new iTableSize = GetArraySize(hTable);
1970 new iChancesLower;
1971 new iChancesUpper;
1972 new iEntry;
1973 while (iEntry < iTableSize)
1974 {
1975 iChancesLower = iChancesUpper + iChancesLower;
1976 iChancesUpper = GetArrayCell(hTable, iEntry, 0, false) + iChancesLower;
1977 new var1;
1978 if (iRandom >= iChancesLower && iRandom < iChancesUpper)
1979 {
1980 return iEntry;
1981 }
1982 iEntry++;
1983 }
1984 return 0;
1985}
1986
1987void:EmitRocketSound(RocketSound:iSound, iClass, iEntity, iTarget, RocketFlags:iFlags)
1988{
1989 switch (iSound)
1990 {
1991 case 0:
1992 {
1993 if (!!iFlags & 1)
1994 {
1995 if (!!iFlags & 2048)
1996 {
1997 EmitSoundToAll(g_strRocketClassSpawnSound[iClass], iEntity, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
1998 }
1999 EmitSoundToAll("weapons/sentry_rocket.wav", iEntity, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
2000 }
2001 }
2002 case 1:
2003 {
2004 if (!!iFlags & 2)
2005 {
2006 if (!!iFlags & 4096)
2007 {
2008 EmitSoundToAll(g_strRocketClassBeepSound[iClass], iEntity, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
2009 }
2010 EmitSoundToAll("weapons/sentry_scan.wav", iEntity, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
2011 }
2012 }
2013 case 2:
2014 {
2015 if (!!iFlags & 4)
2016 {
2017 if (!!iFlags & 8192)
2018 {
2019 EmitSoundToClient(iTarget, g_strRocketClassAlertSound[iClass], -2, 0, 75, 0, 1.0, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
2020 }
2021 EmitSoundToClient(iTarget, "weapons/sentry_spot.wav", -2, 0, 75, 0, 0.5, 100, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0);
2022 }
2023 }
2024 default:
2025 {
2026 }
2027 }
2028 return void:0;
2029}
2030
2031void:DestroyRocketClasses()
2032{
2033 new iIndex;
2034 while (iIndex < g_iRocketClassCount)
2035 {
2036 new Handle:hCmdOnSpawn = g_hRocketClassCmdsOnSpawn[iIndex];
2037 new Handle:hCmdOnKill = g_hRocketClassCmdsOnKill[iIndex];
2038 new Handle:hCmdOnExplode = g_hRocketClassCmdsOnExplode[iIndex];
2039 new Handle:hCmdOnDeflect = g_hRocketClassCmdsOnDeflect[iIndex];
2040 if (hCmdOnSpawn)
2041 {
2042 CloseHandle(hCmdOnSpawn);
2043 }
2044 if (hCmdOnKill)
2045 {
2046 CloseHandle(hCmdOnKill);
2047 }
2048 if (hCmdOnExplode)
2049 {
2050 CloseHandle(hCmdOnExplode);
2051 }
2052 if (hCmdOnDeflect)
2053 {
2054 CloseHandle(hCmdOnDeflect);
2055 }
2056 g_hRocketClassCmdsOnSpawn[iIndex] = 0;
2057 g_hRocketClassCmdsOnKill[iIndex] = 0;
2058 g_hRocketClassCmdsOnExplode[iIndex] = 0;
2059 g_hRocketClassCmdsOnDeflect[iIndex] = 0;
2060 iIndex++;
2061 }
2062 g_iRocketClassCount = 0;
2063 ClearTrie(g_hRocketClassTrie);
2064 return void:0;
2065}
2066
2067void:DestroySpawners()
2068{
2069 new iIndex;
2070 while (iIndex < g_iSpawnersCount)
2071 {
2072 CloseHandle(g_hSpawnersChancesTable[iIndex]);
2073 iIndex++;
2074 }
2075 g_iSpawnersCount = 0;
2076 g_iSpawnPointsRedCount = 0;
2077 g_iSpawnPointsBluCount = 0;
2078 g_iDefaultRedSpawner = -1;
2079 g_iDefaultBluSpawner = -1;
2080 ClearTrie(g_hSpawnersTrie);
2081 return void:0;
2082}
2083
2084void:PopulateSpawnPoints()
2085{
2086 g_iSpawnPointsRedCount = 0;
2087 g_iSpawnPointsBluCount = 0;
2088 new iEntity = -1;
2089 while ((iEntity = FindEntityByClassname(iEntity, "info_target")) != -1)
2090 {
2091 new String:strName[32];
2092 GetEntPropString(iEntity, PropType:1, "m_iName", strName, 32, 0);
2093 new var1;
2094 if (StrContains(strName, "rocket_spawn_red", true) == -1 && StrContains(strName, "tf_dodgeball_red", true) == -1)
2095 {
2096 new iIndex = FindSpawnerByName(strName);
2097 if (!IsValidRocket(iIndex))
2098 {
2099 iIndex = g_iDefaultRedSpawner;
2100 }
2101 g_iSpawnPointsRedClass[g_iSpawnPointsRedCount] = iIndex;
2102 g_iSpawnPointsRedEntity[g_iSpawnPointsRedCount] = iEntity;
2103 g_iSpawnPointsRedCount += 1;
2104 }
2105 new var2;
2106 if (StrContains(strName, "rocket_spawn_blue", true) == -1 && StrContains(strName, "tf_dodgeball_blu", true) == -1)
2107 {
2108 new iIndex = FindSpawnerByName(strName);
2109 if (!IsValidRocket(iIndex))
2110 {
2111 iIndex = g_iDefaultBluSpawner;
2112 }
2113 g_iSpawnPointsBluClass[g_iSpawnPointsBluCount] = iIndex;
2114 g_iSpawnPointsBluEntity[g_iSpawnPointsBluCount] = iEntity;
2115 g_iSpawnPointsBluCount += 1;
2116 }
2117 }
2118 if (!g_iSpawnPointsRedCount)
2119 {
2120 SetFailState("No RED spawn points found on this map.");
2121 }
2122 if (!g_iSpawnPointsBluCount)
2123 {
2124 SetFailState("No BLU spawn points found on this map.");
2125 }
2126 return void:0;
2127}
2128
2129FindSpawnerByName(String:strName[32])
2130{
2131 new iIndex = -1;
2132 GetTrieValue(g_hSpawnersTrie, strName, iIndex);
2133 return iIndex;
2134}
2135
2136void:RegisterCommands()
2137{
2138 RegServerCmd("tf_dodgeball_explosion", CmdExplosion, "", 0);
2139 RegServerCmd("tf_dodgeball_shockwave", CmdShockwave, "", 0);
2140 RegAdminCmd("dummy_dbpermissioncheck", CmdVoid, 2, "An empty object for permission checking", "", 0);
2141 RegAdminCmd("sm_votespeed", CmdStartSpeedVote, 0, "Vote for rocket speed", "", 0);
2142 RegAdminCmd("sm_votecount", CmdStartCountVote, 0, "Vote for rocket count", "", 0);
2143 RegAdminCmd("sm_topspeed", Cmd_TopSpeed, 0, "Top 10 rocket speed", "", 0);
2144 RegAdminCmd("sm_rocketcount", CmdRocketCount, 32, "", "", 0);
2145 RegAdminCmd("sm_rocketspeed", CmdRocketSpeed, 32, "", "", 0);
2146 RegAdminCmd("sm_forcevotespeed", CmdForceVoteSpeed, 32, "", "", 0);
2147 RegAdminCmd("sm_forcevotecount", CmdForceVoteCount, 32, "", "", 0);
2148 RegAdminCmd("sm_reloadtopspeed", Cmd_RebuildTopSpeed, 32, "", "", 0);
2149 RegAdminCmd("dummy_dbpermissioncheck_root", CmdVoid, 16384, "An empty object for permission checking", "", 0);
2150 RegAdminCmd("sm_redirectrocket", CmdRedirectRocket, 16384, "", "", 0);
2151 RegAdminCmd("sm_redirectrocketid", CmdRedirectRocketID, 16384, "", "", 0);
2152 RegAdminCmd("sm_dbsetflareammo", CmdSetFlareAmmo, 16384, "", "", 0);
2153 RegAdminCmd("sm_dbrehook", CmdRehookClientDamage, 16384, "", "", 0);
2154 RegAdminCmd("sm_dbsetknockbackscale", CmdSetKnockbackScale, 16384, "", "", 0);
2155 RegAdminCmd("sm_dbreparseconfig", CmdReparseConfig, 16384, "", "", 0);
2156 AddCommandListener(TauntCmd, "taunt");
2157 AddCommandListener(TauntCmd, "+taunt");
2158 return void:0;
2159}
2160
2161public Action:CmdReparseConfig(client, args)
2162{
2163 ParseConfigurations("general.cfg");
2164 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Reloaded main rocket config");
2165 return Action:3;
2166}
2167
2168public Action:CmdVoid(client, args)
2169{
2170 return Action:3;
2171}
2172
2173public Action:CmdRehookClientDamage(client, args)
2174{
2175 new i = 1;
2176 while (i <= MaxClients)
2177 {
2178 if (IsValidClient(i, false))
2179 {
2180 SDKHook(i, SDKHookType:2, OnClientTakeDamage);
2181 }
2182 i++;
2183 }
2184 return Action:3;
2185}
2186
2187public void:OnEntityCreated(entity, String:classname[])
2188{
2189 if (StrEqual(classname, "tf_projectile_rocket", true))
2190 {
2191 SDKHook(entity, SDKHookType:18, Should_Collide);
2192 return void:0;
2193 }
2194 if (StrEqual(classname, "tf_projectile_flare", true))
2195 {
2196 RequestFrame(RequestFrameCallback:205, entity);
2197 return void:0;
2198 }
2199 if (StrContains(classname, "tf_ammo_pack", true) != -1)
2200 {
2201 AcceptEntityInput(entity, "Kill", -1, -1, 0);
2202 return void:0;
2203 }
2204 return void:0;
2205}
2206
2207public bool:Should_Collide(entity, collisiongroup, contentsmask, bool:originalResult)
2208{
2209 return false;
2210}
2211
2212public void:Frame_SetModel(entity)
2213{
2214 if (IsValidEntity(entity))
2215 {
2216 new iOwner = GetEntPropEnt(entity, PropType:0, "m_hOwnerEntity", 0);
2217 if (IsValidClient(iOwner, false))
2218 {
2219 SetEntityModel(entity, "models/buildables/sentry_shield.mdl");
2220 }
2221 }
2222 return void:0;
2223}
2224
2225public Action:CmdSetKnockbackScale(client, args)
2226{
2227 if (args)
2228 {
2229 new String:buffer[64];
2230 GetCmdArg(1, buffer, 64);
2231 new Float:scale = StringToFloat(buffer);
2232 Flare_Weapon_Knockback_Scale = scale;
2233 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Knockback scale set to {aqua}%f", scale);
2234 return Action:3;
2235 }
2236 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Invalid Syntax");
2237 return Action:3;
2238}
2239
2240public Action:CmdSetFlareAmmo(client, args)
2241{
2242 if (0 < args)
2243 {
2244 new String:buffer[16];
2245 GetCmdArg(1, buffer, 16);
2246 new ammo = StringToInt(buffer, 10);
2247 SetAmmo(client, 1, ammo);
2248 }
2249 else
2250 {
2251 ReplyToCommand(client, "sm_dbsetflareammo <ammo>");
2252 }
2253 return Action:3;
2254}
2255
2256public Action:CmdRocketCount(client, args)
2257{
2258 if (args < 1)
2259 {
2260 PrintToConsole(client, "Usage: sm_rocketcount <count>");
2261 return Action:3;
2262 }
2263 new String:rc[32];
2264 GetCmdArg(1, rc, 32);
2265 new count = StringToInt(rc, 10);
2266 new iSpawnerClass_Red = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
2267 new iSpawnerClass_Blu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
2268 g_iSpawnersMaxRockets[iSpawnerClass_Red] = count;
2269 g_iSpawnersMaxRockets[iSpawnerClass_Blu] = count;
2270 PrintToConsole(client, "[MaxDB] Rocket count set to %d", count);
2271 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Rocket count set to {aqua}%d", count);
2272 return Action:3;
2273}
2274
2275public Action:CmdRedirectRocket(client, args)
2276{
2277 new buffer = GetClientAimTarget(client, true);
2278 if (buffer != -1)
2279 {
2280 g_newtarget_int = buffer;
2281 g_newtarget_bool = true;
2282 PrintToConsole(client, "[MaxDB] Rocket redirected to %N", g_newtarget_int);
2283 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Rocket redirected to {chartreuse}%N", g_newtarget_int);
2284 return Action:3;
2285 }
2286 return Action:3;
2287}
2288
2289public Action:CmdRedirectRocketID(client, args)
2290{
2291 if (args == 1)
2292 {
2293 new String:buffer[32];
2294 GetCmdArg(1, buffer, 32);
2295 new clientid = StringToInt(buffer, 10);
2296 if (IsValidClient(clientid, false))
2297 {
2298 g_newtarget_int = clientid;
2299 g_newtarget_bool = true;
2300 PrintToConsole(client, "[MaxDB] Rocket redirected to %N", g_newtarget_int);
2301 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Rocket redirected to {chartreuse}%N", g_newtarget_int);
2302 return Action:3;
2303 }
2304 PrintToConsole(client, "[MaxDB] Invalid Target");
2305 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Invalid Target");
2306 return Action:3;
2307 }
2308 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}sm_redirectrocketid <{aqua}id{grey}>", g_newtarget_int);
2309 return Action:3;
2310}
2311
2312public Action:CmdRocketSpeed(client, args)
2313{
2314 if (args < 1)
2315 {
2316 PrintToConsole(client, "Usage: sm_rocketspeed <increment>");
2317 return Action:3;
2318 }
2319 new String:rc[32];
2320 new Float:speed_f = 0.0;
2321 new Float:turn_rate = 0.0;
2322 new iIndex = -1;
2323 new iClass;
2324 new speed_i;
2325 GetCmdArg(1, rc, 32);
2326 new var1;
2327 if (StrEqual(rc, "reset", true) || StrEqual(rc, "0", true))
2328 {
2329 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Speed reset to {aqua}%.0f", g_defaultspeed * g_mph_convert);
2330 iIndex = 0;
2331 if (iIndex < 1000)
2332 {
2333 iClass = g_iRocketClass[iIndex];
2334 g_fRocketClassSpeed[iClass] = g_defaultspeed;
2335 g_fRocketClassTurnRate[iClass] = g_default_turn;
2336 return Action:3;
2337 }
2338 }
2339 else
2340 {
2341 speed_i = StringToInt(rc, 10);
2342 speed_f = speed_i / g_mph_convert;
2343 turn_rate = g_turnrate_convert * speed_i;
2344 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Base speed set to {aqua}%d", speed_i);
2345 iIndex = 0;
2346 if (iIndex < 1000)
2347 {
2348 iClass = g_iRocketClass[iIndex];
2349 g_fRocketClassSpeed[iClass] = speed_f;
2350 g_fRocketClassTurnRate[iClass] = turn_rate;
2351 return Action:3;
2352 }
2353 }
2354 return Action:3;
2355}
2356
2357public Handle_VoteMenu(Menu:menu, MenuAction:action, param1, param2)
2358{
2359 if (action == MenuAction:16)
2360 {
2361 CloseHandle(menu);
2362 menu = MissingTAG:0;
2363 }
2364 return 0;
2365}
2366
2367public void:Handle_RocketSpeedMenu(Menu:menu, num_votes, num_clients, client_info[][], num_items, item_info[][])
2368{
2369 new winner;
2370 new var1;
2371 if (num_items > 1 && item_info[1][1] == item_info[0][1])
2372 {
2373 winner = GetRandomInt(0, 1);
2374 }
2375 new String:speed[64];
2376 new speedc;
2377 new iIndex = -1;
2378 new iClass;
2379 new Float:turn_rate = 0.0;
2380 new Float:speed_f = 0.0;
2381 Menu.GetItem(menu, item_info[winner][0], speed, 64, 0, "", 0);
2382 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Vote ended for rocket {aqua}speed");
2383 ResetSpeedVotes();
2384 speedc = StringToInt(speed, 10);
2385 if (speedc)
2386 {
2387 speed_f = speedc / g_mph_convert;
2388 turn_rate = g_turnrate_convert * speedc;
2389 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Speed set to {aqua}%d", speedc);
2390 iIndex = 0;
2391 while (iIndex < 1000)
2392 {
2393 iClass = g_iRocketClass[iIndex];
2394 g_fRocketClassSpeed[iClass] = speed_f;
2395 g_fRocketClassTurnRate[iClass] = turn_rate;
2396 iIndex++;
2397 }
2398 }
2399 else
2400 {
2401 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Speed reset to {aqua}%.0f", g_defaultspeed * g_mph_convert);
2402 iIndex = 0;
2403 while (iIndex < 1000)
2404 {
2405 iClass = g_iRocketClass[iIndex];
2406 g_fRocketClassSpeed[iClass] = g_defaultspeed;
2407 g_fRocketClassTurnRate[iClass] = g_default_turn;
2408 iIndex++;
2409 }
2410 }
2411 return void:0;
2412}
2413
2414void:DoVoteRocketSpeed()
2415{
2416 if (IsVoteInProgress(Handle:0))
2417 {
2418 return void:0;
2419 }
2420 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Vote started for rocket {aqua}speed");
2421 new Menu:menu = Menu.Menu(Handle_VoteMenu, MenuAction:28);
2422 Menu.VoteResultCallback.set(menu, Handle_RocketSpeedMenu);
2423 Menu.SetTitle(menu, "Vote Rocket Speed");
2424 Menu.AddItem(menu, "0", "Normal", 0);
2425 Menu.AddItem(menu, "75", "Hard", 0);
2426 Menu.AddItem(menu, "90", "Brutal", 0);
2427 Menu.AddItem(menu, "100", "Hitler", 0);
2428 Menu.ExitButton.set(menu, false);
2429 Menu.DisplayVoteToAll(menu, 30, 0);
2430 return void:0;
2431}
2432
2433public void:Handle_RocketCountMenu(Menu:menu, num_votes, num_clients, client_info[][], num_items, item_info[][])
2434{
2435 new winner;
2436 new var1;
2437 if (num_items > 1 && item_info[1][1] == item_info[0][1])
2438 {
2439 winner = GetRandomInt(0, 1);
2440 }
2441 new String:count[64];
2442 new countc;
2443 Menu.GetItem(menu, item_info[winner][0], count, 64, 0, "", 0);
2444 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Vote ended for rocket {aqua}count");
2445 ResetCountVotes();
2446 countc = StringToInt(count, 10);
2447 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Rocket count set to {aqua}%d", countc);
2448 new iSpawnerClass_Red = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
2449 new iSpawnerClass_Blu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
2450 g_iSpawnersMaxRockets[iSpawnerClass_Red] = countc;
2451 g_iSpawnersMaxRockets[iSpawnerClass_Blu] = countc;
2452 return void:0;
2453}
2454
2455void:DoVoteRocketCount()
2456{
2457 if (IsVoteInProgress(Handle:0))
2458 {
2459 return void:0;
2460 }
2461 CPrintToChatAll("{lightseagreen}[MaxDB] {gray}Vote started for rocket {aqua}count");
2462 new Menu:menu = Menu.Menu(Handle_VoteMenu, MenuAction:28);
2463 Menu.VoteResultCallback.set(menu, Handle_RocketCountMenu);
2464 Menu.SetTitle(menu, "Vote Rocket Count");
2465 Menu.AddItem(menu, "1", "1", 0);
2466 Menu.AddItem(menu, "2", "2", 0);
2467 Menu.AddItem(menu, "3", "3", 0);
2468 Menu.AddItem(menu, "5", "5", 0);
2469 Menu.AddItem(menu, "10", "10", 0);
2470 Menu.ExitButton.set(menu, false);
2471 Menu.DisplayVoteToAll(menu, 30, 0);
2472 return void:0;
2473}
2474
2475public Action:CmdStartSpeedVote(client, args)
2476{
2477 AttemptVoteSpeed(client);
2478 return Action:3;
2479}
2480
2481public Action:CmdStartCountVote(client, args)
2482{
2483 AttemptVoteCount(client);
2484 return Action:3;
2485}
2486
2487void:AttemptVoteSpeed(client)
2488{
2489 if (g_SpeedVoted[client])
2490 {
2491 CPrintToChat(client, "{lightseagreen}[MaxDB] {grey}You already voted");
2492 return void:0;
2493 }
2494 if (g_VoteInProgress)
2495 {
2496 CPrintToChat(client, "{lightseagreen}[MaxDB] {grey}A vote is in progress");
2497 return void:0;
2498 }
2499 if (ConVar.IntValue.get(g_hCvarVoteSpeedEnabled) != 1)
2500 {
2501 CPrintToChat(client, "{lightseagreen}[MaxDB] {chartreuse}Speed {grey}Vote Is Disabled. Reason: %s", Fishy_DisableReason);
2502 return void:0;
2503 }
2504 new String:name[32];
2505 GetClientName(client, name, 32);
2506 g_SpeedVotes += 1;
2507 g_SpeedVoted[client] = 1;
2508 CPrintToChatAll("{lightseagreen}[MaxDB] {chartreuse}%s {grey}wish to change rocket {aqua}speed{grey}. ({aqua}%d {grey}votes, {aqua}%d {grey}required)", name, g_SpeedVotes, g_VotesNeeded);
2509 if (g_SpeedVotes >= g_VotesNeeded)
2510 {
2511 g_VoteInProgress = true;
2512 DoVoteRocketSpeed();
2513 }
2514 return void:0;
2515}
2516
2517void:AttemptVoteCount(client)
2518{
2519 if (g_CountVoted[client])
2520 {
2521 CPrintToChat(client, "{lightseagreen}[MaxDB] {grey}You already voted");
2522 return void:0;
2523 }
2524 if (g_VoteInProgress)
2525 {
2526 CPrintToChat(client, "{lightseagreen}[MaxDB] {grey}A vote is in progress");
2527 return void:0;
2528 }
2529 if (ConVar.IntValue.get(g_hCvarVoteCountEnabled) != 1)
2530 {
2531 CPrintToChat(client, "{lightseagreen}[MaxDB] {chartreuse}Count {grey}Vote Is Disabled. Reason: %s", Fishy_DisableReason);
2532 return void:0;
2533 }
2534 new String:name[32];
2535 GetClientName(client, name, 32);
2536 g_CountVotes += 1;
2537 g_CountVoted[client] = 1;
2538 CPrintToChatAll("{lightseagreen}[MaxDB] {chartreuse}%s {grey}wish to change rocket {aqua}count{grey}. ({aqua}%d {grey}votes, {aqua}%d {grey}required)", name, g_CountVotes, g_VotesNeeded);
2539 if (g_CountVotes >= g_VotesNeeded)
2540 {
2541 g_VoteInProgress = true;
2542 DoVoteRocketCount();
2543 }
2544 return void:0;
2545}
2546
2547void:ResetSpeedVotes()
2548{
2549 g_SpeedVotes = 0;
2550 new i = 1;
2551 while (i <= 65)
2552 {
2553 g_SpeedVoted[i] = 0;
2554 i++;
2555 }
2556 g_VoteInProgress = false;
2557 return void:0;
2558}
2559
2560void:ResetCountVotes()
2561{
2562 g_CountVotes = 0;
2563 new i = 1;
2564 while (i <= 65)
2565 {
2566 g_CountVoted[i] = 0;
2567 i++;
2568 }
2569 g_VoteInProgress = false;
2570 return void:0;
2571}
2572
2573public Action:CmdForceVoteSpeed(client, args)
2574{
2575 DoVoteRocketSpeed();
2576 return Action:3;
2577}
2578
2579public Action:CmdForceVoteCount(client, args)
2580{
2581 DoVoteRocketCount();
2582 return Action:3;
2583}
2584
2585public void:InitDB(&Handle:DbHNDL)
2586{
2587 new String:Error[256];
2588 DbHNDL = SQL_Connect("topspeed", true, Error, 255);
2589 if (!DbHNDL)
2590 {
2591 SetFailState(Error);
2592 }
2593 new String:Query[1000] = "CREATE TABLE IF NOT EXISTS `topspeed` (`steamid` VARCHAR(20) NOT NULL,`name` VARCHAR(100) NOT NULL,`mph` INT(10) NOT NULL,`achieved_at` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY(`steamid`),INDEX(`mph`));";
2594 SQL_LockDatabase(DbHNDL);
2595 SQL_FastQuery(DbHNDL, Query, -1);
2596 SQL_UnlockDatabase(DbHNDL);
2597 return void:0;
2598}
2599
2600public void:UpdatePlayerTopSpeed(client, mph)
2601{
2602 new String:steamid64[20];
2603 new String:name[32];
2604 new String:query[256];
2605 new String:escaped_name[100];
2606 GetClientAuthId(client, AuthIdType:3, steamid64, 20, true);
2607 GetClientName(client, name, 32);
2608 SQL_EscapeString(db, name, escaped_name, 100, 0);
2609 Format(query, 255, "INSERT INTO topspeed (`steamid`, `name`, `mph`) VALUES ('%s', '%s', '%i') ON DUPLICATE KEY UPDATE `name` = '%s', `mph` = GREATEST(%i, `mph`);", steamid64, escaped_name, mph, escaped_name, mph);
2610 Database.Query(db, SQLQueryCallback:259, query, any:0, DBPriority:1);
2611 return void:0;
2612}
2613
2614public void:SQL_OnUpdatePlayerTopSpeed(Database:odb, DBResultSet:results, String:error[], any:data)
2615{
2616 return void:0;
2617}
2618
2619Menu:BuildTopSpeed()
2620{
2621 new String:name[32];
2622 new mph;
2623 new row;
2624 new String:mphs[256];
2625 new String:buffer[256];
2626 new Menu:topspeed = Menu.Menu(Menu_Topspeed, MenuAction:28);
2627 new DBResultSet:query = SQL_Query(db, "SELECT `name`, `mph` FROM topspeed ORDER BY mph DESC LIMIT 10;", -1);
2628 if (query)
2629 {
2630 while (SQL_FetchRow(query))
2631 {
2632 SQL_FetchString(query, 0, name, 32, 0);
2633 mph = SQL_FetchInt(query, 1, 0);
2634 Format(buffer, 255, "%s - %i MPH", name, mph);
2635 IntToString(mph, mphs, 255);
2636 Menu.AddItem(topspeed, mphs, buffer, 0);
2637 if (row)
2638 {
2639 }
2640 else
2641 {
2642 SetConVarString(g_hCvarTopSpeedHolder, name, true, false);
2643 SetConVarInt(g_hCvarTopSpeedMPH, mph, true, false);
2644 row++;
2645 }
2646 }
2647 }
2648 CloseHandle(query);
2649 query = MissingTAG:0;
2650 Menu.SetTitle(topspeed, "Top 10 Rocket Speed");
2651 return topspeed;
2652}
2653
2654public Menu_Topspeed(Menu:menu, MenuAction:action, param1, param2)
2655{
2656 return 0;
2657}
2658
2659public Action:Cmd_TopSpeed(client, args)
2660{
2661 if (!TopRocketSpeed)
2662 {
2663 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Invalid Database Handle");
2664 }
2665 Menu.Display(TopRocketSpeed, client, 0);
2666 return Action:3;
2667}
2668
2669public Action:Cmd_RebuildTopSpeed(client, args)
2670{
2671 TopRocketSpeed = BuildTopSpeed();
2672 return Action:3;
2673}
2674
2675public Action:OnClientSayCommand(client, String:command[], String:sArgs[])
2676{
2677 new var1;
2678 if (strcmp(command, "say", true) && strcmp(command, "say_team", true))
2679 {
2680 if (!(strcmp(sArgs, "topspeed", true)))
2681 {
2682 if (TopRocketSpeed)
2683 {
2684 Menu.Display(TopRocketSpeed, client, 0);
2685 }
2686 CPrintToChat(client, "{lightseagreen}[MaxDB] {gray}Invalid Database Handle");
2687 }
2688 }
2689 return Action:0;
2690}
2691
2692public void:IntCmdExplosion(iClient)
2693{
2694 if (IsValidEntity(iClient))
2695 {
2696 new Float:fPosition[3] = 0.0;
2697 GetClientAbsOrigin(iClient, fPosition);
2698 switch (GetURandomIntRange(0, 4))
2699 {
2700 case 0:
2701 {
2702 PlayParticle(fPosition, 662836, "fireSmokeExplosion", 5.0, 9.0);
2703 }
2704 case 1:
2705 {
2706 PlayParticle(fPosition, 662868, "fireSmokeExplosion1", 5.0, 9.0);
2707 }
2708 case 2:
2709 {
2710 PlayParticle(fPosition, 662900, "fireSmokeExplosion2", 5.0, 9.0);
2711 }
2712 case 3:
2713 {
2714 PlayParticle(fPosition, 662932, "fireSmokeExplosion3", 5.0, 9.0);
2715 }
2716 case 4:
2717 {
2718 PlayParticle(fPosition, 662964, "fireSmokeExplosion4", 5.0, 9.0);
2719 }
2720 default:
2721 {
2722 }
2723 }
2724 PlayParticle(fPosition, 662996, "fireSmoke_collumnP", 5.0, 9.0);
2725 }
2726 return void:0;
2727}
2728
2729public Action:CmdExplosion(iArgs)
2730{
2731 if (iArgs == 1)
2732 {
2733 new String:strBuffer[8];
2734 new String:iClient;
2735 GetCmdArg(1, strBuffer, 8);
2736 iClient = StringToInt(strBuffer, 10);
2737 if (IsValidEntity(iClient))
2738 {
2739 new Float:fPosition[3] = 0.0;
2740 GetClientAbsOrigin(iClient, fPosition);
2741 switch (GetURandomIntRange(0, 4))
2742 {
2743 case 0:
2744 {
2745 PlayParticle(fPosition, 663028, "fireSmokeExplosion", 5.0, 9.0);
2746 }
2747 case 1:
2748 {
2749 PlayParticle(fPosition, 663060, "fireSmokeExplosion1", 5.0, 9.0);
2750 }
2751 case 2:
2752 {
2753 PlayParticle(fPosition, 663092, "fireSmokeExplosion2", 5.0, 9.0);
2754 }
2755 case 3:
2756 {
2757 PlayParticle(fPosition, 663124, "fireSmokeExplosion3", 5.0, 9.0);
2758 }
2759 case 4:
2760 {
2761 PlayParticle(fPosition, 663156, "fireSmokeExplosion4", 5.0, 9.0);
2762 }
2763 default:
2764 {
2765 }
2766 }
2767 PlayParticle(fPosition, 663188, "fireSmoke_collumnP", 5.0, 9.0);
2768 }
2769 }
2770 else
2771 {
2772 PrintToServer("Usage: tf_dodgeball_explosion <client index>");
2773 }
2774 return Action:3;
2775}
2776
2777public Action:CmdShockwave(iArgs)
2778{
2779 if (iArgs == 5)
2780 {
2781 new String:strBuffer[8];
2782 new iClient;
2783 new iTeam;
2784 new iDamage;
2785 new Float:fPosition[3] = 0.0;
2786 new Float:fPushStrength = 0.0;
2787 new Float:fRadius = 0.0;
2788 new Float:fFalloffRadius = 0.0;
2789 GetCmdArg(1, strBuffer, 8);
2790 iClient = StringToInt(strBuffer, 10);
2791 GetCmdArg(2, strBuffer, 8);
2792 iDamage = StringToInt(strBuffer, 10);
2793 GetCmdArg(3, strBuffer, 8);
2794 fPushStrength = StringToFloat(strBuffer);
2795 GetCmdArg(4, strBuffer, 8);
2796 fRadius = StringToFloat(strBuffer);
2797 GetCmdArg(5, strBuffer, 8);
2798 fFalloffRadius = StringToFloat(strBuffer);
2799 if (IsValidClient(iClient, false))
2800 {
2801 iTeam = GetClientTeam(iClient);
2802 GetClientAbsOrigin(iClient, fPosition);
2803 iClient = 1;
2804 while (iClient <= MaxClients)
2805 {
2806 new var1;
2807 if (IsValidClient(iClient, true) == 1 && iTeam == GetClientTeam(iClient))
2808 {
2809 new Float:fPlayerPosition[3] = 0.0;
2810 GetClientEyePosition(iClient, fPlayerPosition);
2811 new Float:fDistanceToShockwave = GetVectorDistance(fPosition, fPlayerPosition, false);
2812 if (fDistanceToShockwave < fRadius)
2813 {
2814 new Float:fImpulse[3] = 0.0;
2815 new Float:fFinalPush = 0.0;
2816 new iFinalDamage;
2817 fImpulse[0] = fPlayerPosition[0] - fPosition[0];
2818 fImpulse[1] = fPlayerPosition[1] - fPosition[1];
2819 fImpulse[2] = fPlayerPosition[2] - fPosition[2];
2820 NormalizeVector(fImpulse, fImpulse);
2821 if (fImpulse[2] < 0.4)
2822 {
2823 fImpulse[2] = 0.4;
2824 NormalizeVector(fImpulse, fImpulse);
2825 }
2826 if (fDistanceToShockwave < fFalloffRadius)
2827 {
2828 fFinalPush = fPushStrength;
2829 iFinalDamage = iDamage;
2830 }
2831 else
2832 {
2833 new Float:fImpact = 1.0 - fDistanceToShockwave - fFalloffRadius / fRadius - fFalloffRadius;
2834 fFinalPush = fImpact * fPushStrength;
2835 iFinalDamage = RoundToFloor(fImpact * iDamage);
2836 }
2837 ScaleVector(fImpulse, fFinalPush);
2838 SetEntPropVector(iClient, PropType:1, "m_vecAbsVelocity", fImpulse, 0);
2839 new Handle:hDamage = CreateDataPack();
2840 WritePackCell(hDamage, iClient);
2841 WritePackCell(hDamage, iFinalDamage);
2842 CreateTimer(0.1, ApplyDamage, hDamage, 2);
2843 }
2844 }
2845 iClient++;
2846 }
2847 }
2848 }
2849 else
2850 {
2851 PrintToServer("Usage: tf_dodgeball_shockwave <client index> <damage> <push strength> <radius> <falloff>");
2852 }
2853 return Action:3;
2854}
2855
2856void:ExecuteCommands(Handle:hDataPack, iClass, iRocket, iOwner, iTarget, iLastDead, Float:fSpeed, iNumDeflections)
2857{
2858 ResetPack(hDataPack, false);
2859 new iNumCommands = ReadPackCell(hDataPack);
2860 iNumCommands--;
2861 while (0 < iNumCommands)
2862 {
2863 new String:strCmd[256];
2864 new String:strBuffer[8];
2865 ReadPackString(hDataPack, strCmd, 256);
2866 ReplaceString(strCmd, 256, "@name", g_strRocketClassLongName[iClass], true);
2867 Format(strBuffer, 8, "%i", iRocket);
2868 ReplaceString(strCmd, 256, "@rocket", strBuffer, true);
2869 Format(strBuffer, 8, "%i", iOwner);
2870 ReplaceString(strCmd, 256, "@owner", strBuffer, true);
2871 Format(strBuffer, 8, "%i", iTarget);
2872 ReplaceString(strCmd, 256, "@target", strBuffer, true);
2873 Format(strBuffer, 8, "%i", iLastDead);
2874 ReplaceString(strCmd, 256, "@dead", strBuffer, true);
2875 Format(strBuffer, 8, "%f", fSpeed);
2876 ReplaceString(strCmd, 256, "@speed", strBuffer, true);
2877 Format(strBuffer, 8, "%i", iNumDeflections);
2878 ReplaceString(strCmd, 256, "@deflections", strBuffer, true);
2879 ServerCommand(strCmd);
2880 }
2881 return void:0;
2882}
2883
2884bool:ParseConfigurations(String:strConfigFile[])
2885{
2886 new String:strPath[256];
2887 new String:strFileName[256];
2888 Format(strFileName, 256, "configs/dodgeball/%s", strConfigFile);
2889 BuildPath(PathType:0, strPath, 256, strFileName);
2890 LogMessage("Executing configuration file %s", strPath);
2891 if (FileExists(strPath, true, "GAME"))
2892 {
2893 new Handle:kvConfig = CreateKeyValues("TF2_Dodgeball", "", "");
2894 if (!(FileToKeyValues(kvConfig, strPath)))
2895 {
2896 SetFailState("Error while parsing the configuration file.");
2897 }
2898 KvGotoFirstSubKey(kvConfig, true);
2899 do {
2900 new String:strSection[64];
2901 KvGetSectionName(kvConfig, strSection, 64);
2902 if (StrEqual(strSection, "general", true))
2903 {
2904 ParseGeneral(kvConfig);
2905 }
2906 else
2907 {
2908 if (StrEqual(strSection, "classes", true))
2909 {
2910 ParseClasses(kvConfig);
2911 }
2912 if (StrEqual(strSection, "spawners", true))
2913 {
2914 ParseSpawners(kvConfig);
2915 }
2916 }
2917 } while (KvGotoNextKey(kvConfig, true));
2918 CloseHandle(kvConfig);
2919 }
2920 return false;
2921}
2922
2923void:ParseGeneral(Handle:kvConfig)
2924{
2925 g_bMusicEnabled = KvGetNum(kvConfig, "music", 0);
2926 if (g_bMusicEnabled == true)
2927 {
2928 g_bUseWebPlayer = KvGetNum(kvConfig, "use web player", 0);
2929 KvGetString(kvConfig, "web player url", g_strWebPlayerUrl, 256, "");
2930 new var5 = g_strMusic;
2931 new var1;
2932 g_bMusic[0] = KvGetString(kvConfig, "round start", var5[0][var5], 256, "") && strlen(var6[0][var6]);
2933 new var2;
2934 g_bMusic[1] = KvGetString(kvConfig, "round end (win)", g_strMusic[1], 256, "") && strlen(g_strMusic[1]);
2935 new var3;
2936 g_bMusic[2] = KvGetString(kvConfig, "round end (lose)", g_strMusic[2], 256, "") && strlen(g_strMusic[2]);
2937 new var4;
2938 if (KvGetString(kvConfig, "gameplay", g_strMusic[3], 256, "") && strlen(g_strMusic[3]))
2939 {
2940 }
2941 }
2942 return void:0;
2943}
2944
2945void:ParseClasses(Handle:kvConfig)
2946{
2947 new String:strName[64];
2948 new String:strBuffer[256];
2949 KvGotoFirstSubKey(kvConfig, true);
2950 do {
2951 new iIndex = g_iRocketClassCount;
2952 new RocketFlags:iFlags;
2953 KvGetSectionName(kvConfig, strName, 64);
2954 strcopy(g_strRocketClassName[iIndex], 16, strName);
2955 KvGetString(kvConfig, "name", strBuffer, 256, "");
2956 strcopy(g_strRocketClassLongName[iIndex], 32, strBuffer);
2957 if (KvGetString(kvConfig, "model", strBuffer, 256, ""))
2958 {
2959 strcopy(g_strRocketClassModel[iIndex], 256, strBuffer);
2960 if (strlen(g_strRocketClassModel[iIndex]))
2961 {
2962 iFlags |= 1024;
2963 if (KvGetNum(kvConfig, "is animated", 0))
2964 {
2965 iFlags |= 32768;
2966 }
2967 }
2968 }
2969 KvGetString(kvConfig, "behaviour", strBuffer, 256, "homing");
2970 if (StrEqual(strBuffer, "homing", true))
2971 {
2972 g_iRocketClassBehaviour[iIndex] = 1;
2973 }
2974 else
2975 {
2976 g_iRocketClassBehaviour[iIndex] = 0;
2977 }
2978 if (KvGetNum(kvConfig, "play spawn sound", 0) == 1)
2979 {
2980 iFlags |= 1;
2981 new var1;
2982 if (KvGetString(kvConfig, "spawn sound", g_strRocketClassSpawnSound[iIndex], 256, "") && strlen(g_strRocketClassSpawnSound[iIndex]))
2983 {
2984 iFlags |= 2048;
2985 }
2986 }
2987 if (KvGetNum(kvConfig, "play beep sound", 0) == 1)
2988 {
2989 iFlags |= 2;
2990 g_fRocketClassBeepInterval[iIndex] = KvGetFloat(kvConfig, "beep interval", 0.5);
2991 new var2;
2992 if (KvGetString(kvConfig, "beep sound", g_strRocketClassBeepSound[iIndex], 256, "") && strlen(g_strRocketClassBeepSound[iIndex]))
2993 {
2994 iFlags |= 4096;
2995 }
2996 }
2997 if (KvGetNum(kvConfig, "play alert sound", 0) == 1)
2998 {
2999 iFlags |= 4;
3000 new var3;
3001 if (KvGetString(kvConfig, "alert sound", g_strRocketClassAlertSound[iIndex], 256, "") && strlen(g_strRocketClassAlertSound[iIndex]))
3002 {
3003 iFlags |= 8192;
3004 }
3005 }
3006 if (KvGetNum(kvConfig, "elevate on deflect", 1) == 1)
3007 {
3008 iFlags |= 8;
3009 }
3010 if (KvGetNum(kvConfig, "neutral rocket", 0) == 1)
3011 {
3012 iFlags |= 16;
3013 }
3014 g_fRocketClassDamage[iIndex] = KvGetFloat(kvConfig, "damage", 0.0);
3015 g_fRocketClassDamageIncrement[iIndex] = KvGetFloat(kvConfig, "damage increment", 0.0);
3016 g_fRocketClassCritChance[iIndex] = KvGetFloat(kvConfig, "critical chance", 0.0);
3017 g_fRocketClassSpeed[iIndex] = KvGetFloat(kvConfig, "speed", 0.0);
3018 g_fRocketClassSpeedIncrement[iIndex] = KvGetFloat(kvConfig, "speed increment", 0.0);
3019 if (!g_defaultspeed)
3020 {
3021 g_defaultspeed = KvGetFloat(kvConfig, "speed", 0.0);
3022 }
3023 g_fRocketClassTurnRate[iIndex] = KvGetFloat(kvConfig, "turn rate", 0.0);
3024 if (!g_default_turn)
3025 {
3026 g_default_turn = KvGetFloat(kvConfig, "turn rate", 0.0);
3027 }
3028 g_fRocketClassTurnRateIncrement[iIndex] = KvGetFloat(kvConfig, "turn rate increment", 0.0);
3029 g_fRocketClassElevationRate[iIndex] = KvGetFloat(kvConfig, "elevation rate", 0.0);
3030 g_fRocketClassElevationLimit[iIndex] = KvGetFloat(kvConfig, "elevation limit", 0.0);
3031 g_fRocketClassControlDelay[iIndex] = KvGetFloat(kvConfig, "control delay", 0.0);
3032 g_fRocketClassPlayerModifier[iIndex] = KvGetFloat(kvConfig, "no. players modifier", 0.0);
3033 g_fRocketClassRocketsModifier[iIndex] = KvGetFloat(kvConfig, "no. rockets modifier", 0.0);
3034 g_fRocketClassTargetWeight[iIndex] = KvGetFloat(kvConfig, "direction to target weight", 0.0);
3035 new Handle:hCmds;
3036 KvGetString(kvConfig, "on spawn", strBuffer, 256, "");
3037 if ((hCmds = ParseCommands(strBuffer)))
3038 {
3039 iFlags |= 64;
3040 g_hRocketClassCmdsOnSpawn[iIndex] = hCmds;
3041 }
3042 KvGetString(kvConfig, "on deflect", strBuffer, 256, "");
3043 if ((hCmds = ParseCommands(strBuffer)))
3044 {
3045 iFlags |= 128;
3046 g_hRocketClassCmdsOnDeflect[iIndex] = hCmds;
3047 }
3048 KvGetString(kvConfig, "on kill", strBuffer, 256, "");
3049 if ((hCmds = ParseCommands(strBuffer)))
3050 {
3051 iFlags |= 256;
3052 g_hRocketClassCmdsOnKill[iIndex] = hCmds;
3053 }
3054 KvGetString(kvConfig, "on explode", strBuffer, 256, "");
3055 if ((hCmds = ParseCommands(strBuffer)))
3056 {
3057 iFlags |= 512;
3058 g_hRocketClassCmdsOnExplode[iIndex] = hCmds;
3059 }
3060 SetTrieValue(g_hRocketClassTrie, strName, iIndex, true);
3061 g_iRocketClassFlags[iIndex] = iFlags;
3062 g_iRocketClassCount += 1;
3063 } while (KvGotoNextKey(kvConfig, true));
3064 KvGoBack(kvConfig);
3065 return void:0;
3066}
3067
3068void:ParseSpawners(Handle:kvConfig)
3069{
3070 new String:strBuffer[256];
3071 KvGotoFirstSubKey(kvConfig, true);
3072 do {
3073 new iIndex = g_iSpawnersCount;
3074 KvGetSectionName(kvConfig, strBuffer, 256);
3075 strcopy(g_strSpawnersName[iIndex], 32, strBuffer);
3076 g_iSpawnersMaxRockets[iIndex] = KvGetNum(kvConfig, "max rockets", 1);
3077 g_fSpawnersInterval[iIndex] = KvGetFloat(kvConfig, "interval", 1.0);
3078 g_hSpawnersChancesTable[iIndex] = CreateArray(1, 0);
3079 new iClassIndex;
3080 while (iClassIndex < g_iRocketClassCount)
3081 {
3082 Format(strBuffer, 256, "%s%%", g_strRocketClassName[iClassIndex]);
3083 PushArrayCell(g_hSpawnersChancesTable[iIndex], KvGetNum(kvConfig, strBuffer, 0));
3084 iClassIndex++;
3085 }
3086 SetTrieValue(g_hSpawnersTrie, g_strSpawnersName[iIndex], iIndex, true);
3087 g_iSpawnersCount += 1;
3088 } while (KvGotoNextKey(kvConfig, true));
3089 KvGoBack(kvConfig);
3090 GetTrieValue(g_hSpawnersTrie, "red", g_iDefaultRedSpawner);
3091 GetTrieValue(g_hSpawnersTrie, "blu", g_iDefaultBluSpawner);
3092 return void:0;
3093}
3094
3095Handle:ParseCommands(String:strLine[])
3096{
3097 TrimString(strLine);
3098 if (strlen(strLine))
3099 {
3100
3101/* ERROR! String index out of range: 664804 */
3102 function "ParseCommands" (number 117)
3103public Action:ApplyDamage(Handle:hTimer, any:hDataPack)
3104{
3105 ResetPack(hDataPack, false);
3106 new iClient = ReadPackCell(hDataPack);
3107 new iDamage = ReadPackCell(hDataPack);
3108 CloseHandle(hDataPack);
3109 SlapPlayer(iClient, iDamage, true);
3110 return Action:0;
3111}
3112
3113void:CopyVectors(Float:fFrom[3], Float:fTo[3])
3114{
3115 fTo[0] = fFrom[0];
3116 fTo[1] = fFrom[1];
3117 fTo[2] = fFrom[2];
3118 return void:0;
3119}
3120
3121void:LerpVectors(Float:fA[3], Float:fB[3], Float:fC[3], Float:t)
3122{
3123 if (t < 0.0)
3124 {
3125 t = 0.0;
3126 }
3127 if (t > 1.0)
3128 {
3129 t = 1.0;
3130 }
3131 fC[0] = fA[0] + fB[0] - fA[0] * t;
3132 fC[1] = fA[1] + fB[1] - fA[1] * t;
3133 fC[2] = fA[2] + fB[2] - fA[2] * t;
3134 return void:0;
3135}
3136
3137bool:IsValidClient(iClient, bool:bAlive)
3138{
3139 new var2;
3140 if (iClient >= 1 && iClient <= MaxClients && IsClientConnected(iClient) && IsClientInGame(iClient) && (bAlive && IsPlayerAlive(iClient)))
3141 {
3142 return true;
3143 }
3144 return false;
3145}
3146
3147bool:BothTeamsPlaying()
3148{
3149 new bool:bRedFound;
3150 new bool:bBluFound;
3151 new iClient = 1;
3152 while (iClient <= MaxClients)
3153 {
3154 if (IsValidClient(iClient, true))
3155 {
3156 new iTeam = GetClientTeam(iClient);
3157 if (iTeam == 2)
3158 {
3159 bRedFound = true;
3160 }
3161 if (iTeam == 3)
3162 {
3163 bBluFound = true;
3164 }
3165 }
3166 iClient++;
3167 }
3168 new var1;
3169 return bRedFound && bBluFound;
3170}
3171
3172CountAlivePlayers()
3173{
3174 new iCount;
3175 new iClient = 1;
3176 while (iClient <= MaxClients)
3177 {
3178 if (IsValidClient(iClient, true))
3179 {
3180 iCount++;
3181 }
3182 iClient++;
3183 }
3184 return iCount;
3185}
3186
3187SelectTarget(iTeam, iRocket)
3188{
3189 new iTarget = -1;
3190 new Float:fTargetWeight = 0.0;
3191 new Float:fRocketPosition[3] = 0.0;
3192 new Float:fRocketDirection[3] = 0.0;
3193 new Float:fWeight = 0.0;
3194 new bool:bUseRocket;
3195 if (iRocket != -1)
3196 {
3197 new iClass = g_iRocketClass[iRocket];
3198 new iEntity = EntRefToEntIndex(g_iRocketEntity[iRocket]);
3199 GetEntPropVector(iEntity, PropType:0, "m_vecOrigin", fRocketPosition, 0);
3200 CopyVectors(g_fRocketDirection[iRocket], fRocketDirection);
3201 fWeight = g_fRocketClassTargetWeight[iClass];
3202 bUseRocket = true;
3203 }
3204 new iClient = 1;
3205 while (iClient <= MaxClients)
3206 {
3207 if (IsValidClient(iClient, true))
3208 {
3209 new var1;
3210 if (!(iTeam && iTeam != GetClientTeam(iClient)))
3211 {
3212 new Float:fNewWeight = GetURandomFloatRange(0.0, 100.0);
3213 if (bUseRocket == true)
3214 {
3215 new Float:fClientPosition[3] = 0.0;
3216 GetClientEyePosition(iClient, fClientPosition);
3217 new Float:fDirectionToClient[3] = 0.0;
3218 MakeVectorFromPoints(fRocketPosition, fClientPosition, fDirectionToClient);
3219 fNewWeight += GetVectorDotProduct(fRocketDirection, fDirectionToClient) * fWeight;
3220 }
3221 new var2;
3222 if (iTarget == -1 || fNewWeight >= fTargetWeight)
3223 {
3224 iTarget = iClient;
3225 fTargetWeight = fNewWeight;
3226 }
3227 }
3228 }
3229 iClient++;
3230 }
3231 return iTarget;
3232}
3233
3234void:StopSoundToAll(iChannel, String:strSound[])
3235{
3236 new iClient = 1;
3237 while (iClient <= MaxClients)
3238 {
3239 if (IsValidClient(iClient, false))
3240 {
3241 StopSound(iClient, iChannel, strSound);
3242 }
3243 iClient++;
3244 }
3245 return void:0;
3246}
3247
3248void:PlayParticle(Float:fPosition[3], Float:fAngles[3], String:strParticleName[], Float:fEffectTime, Float:fLifeTime)
3249{
3250 new iEntity = CreateEntityByName("info_particle_system", -1);
3251 new var1;
3252 if (iEntity && IsValidEdict(iEntity))
3253 {
3254 TeleportEntity(iEntity, fPosition, fAngles, NULL_VECTOR);
3255 DispatchKeyValue(iEntity, "effect_name", strParticleName);
3256 ActivateEntity(iEntity);
3257 AcceptEntityInput(iEntity, "Start", -1, -1, 0);
3258 CreateTimer(fEffectTime, StopParticle, EntIndexToEntRef(iEntity), 0);
3259 CreateTimer(fLifeTime, KillParticle, EntIndexToEntRef(iEntity), 0);
3260 }
3261 else
3262 {
3263 LogError("ShowParticle: could not create info_particle_system");
3264 }
3265 return void:0;
3266}
3267
3268public Action:StopParticle(Handle:hTimer, any:iEntityRef)
3269{
3270 if (iEntityRef != any:-1)
3271 {
3272 new iEntity = EntRefToEntIndex(iEntityRef);
3273 new var1;
3274 if (iEntity && IsValidEntity(iEntity))
3275 {
3276 AcceptEntityInput(iEntity, "Stop", -1, -1, 0);
3277 }
3278 }
3279 return Action:0;
3280}
3281
3282public Action:KillParticle(Handle:hTimer, any:iEntityRef)
3283{
3284 if (iEntityRef != any:-1)
3285 {
3286 new iEntity = EntRefToEntIndex(iEntityRef);
3287 new var1;
3288 if (iEntity && IsValidEntity(iEntity))
3289 {
3290 RemoveEdict(iEntity);
3291 }
3292 }
3293 return Action:0;
3294}
3295
3296void:PrecacheParticle(String:strParticleName[])
3297{
3298 PlayParticle(664412, 664424, strParticleName, 0.1, 0.1);
3299 return void:0;
3300}
3301
3302GetAnalogueTeam(iTeam)
3303{
3304 if (iTeam == 2)
3305 {
3306 return 3;
3307 }
3308 return 2;
3309}
3310
3311void:ShowHiddenMOTDPanel(iClient, String:strTitle[], String:strMsg[], String:strType[])
3312{
3313 new Handle:hPanel = CreateKeyValues("data", "", "");
3314 KvSetString(hPanel, "title", strTitle);
3315 KvSetString(hPanel, "type", strType);
3316 KvSetString(hPanel, "msg", strMsg);
3317 ShowVGUIPanel(iClient, "info", hPanel, false);
3318 CloseHandle(hPanel);
3319 return void:0;
3320}
3321
3322void:PrecacheSoundEx(String:strFileName[], bool:bPreload, bool:bAddToDownloadTable)
3323{
3324 new String:strFinalPath[256];
3325 Format(strFinalPath, 256, "sound/%s", strFileName);
3326 PrecacheSound(strFileName, bPreload);
3327 if (bAddToDownloadTable == true)
3328 {
3329 AddFileToDownloadsTable(strFinalPath);
3330 }
3331 return void:0;
3332}
3333
3334void:PrecacheModelEx(String:strFileName[], bool:bPreload, bool:bAddToDownloadTable)
3335{
3336 PrecacheModel(strFileName, bPreload);
3337 if (bAddToDownloadTable)
3338 {
3339 new String:strDepFileName[256];
3340 Format(strDepFileName, 256, "%s.res", strFileName);
3341 if (FileExists(strDepFileName, false, "GAME"))
3342 {
3343 new Handle:hStream = OpenFile(strDepFileName, "r", false, "GAME");
3344 if (!hStream)
3345 {
3346 LogMessage("Error, can't read file containing model dependencies.");
3347 return void:0;
3348 }
3349 while (!IsEndOfFile(hStream))
3350 {
3351 new String:strBuffer[256];
3352 ReadFileLine(hStream, strBuffer, 256);
3353 CleanString(strBuffer);
3354 if (FileExists(strBuffer, true, "GAME"))
3355 {
3356 if (StrContains(strBuffer, ".vmt", false) != -1)
3357 {
3358 PrecacheDecal(strBuffer, true);
3359 }
3360 else
3361 {
3362 if (StrContains(strBuffer, ".mdl", false) != -1)
3363 {
3364 PrecacheModel(strBuffer, true);
3365 }
3366 if (StrContains(strBuffer, ".pcf", false) != -1)
3367 {
3368 PrecacheGeneric(strBuffer, true);
3369 }
3370 }
3371 AddFileToDownloadsTable(strBuffer);
3372 }
3373 }
3374 CloseHandle(hStream);
3375 }
3376 }
3377 return void:0;
3378}
3379
3380void:CleanString(String:strBuffer[])
3381{
3382 new Length = strlen(strBuffer);
3383 new iPos;
3384 while (iPos < Length)
3385 {
3386 switch (strBuffer[iPos])
3387 {
3388 case 9:
3389 {
3390 strBuffer[iPos] = MissingTAG:32;
3391 }
3392 case 10:
3393 {
3394 strBuffer[iPos] = MissingTAG:32;
3395 }
3396 case 13:
3397 {
3398 strBuffer[iPos] = MissingTAG:32;
3399 }
3400 default:
3401 {
3402 }
3403 }
3404 iPos++;
3405 }
3406 TrimString(strBuffer);
3407 return void:0;
3408}
3409
3410Float:FMin(Float:a, Float:b)
3411{
3412 new var1;
3413 if (a < b)
3414 {
3415 var1 = a;
3416 }
3417 else
3418 {
3419 var1 = b;
3420 }
3421 return var1;
3422}
3423
3424GetURandomIntRange(iMin, iMax)
3425{
3426 return GetURandomInt() % iMax - iMin + 1 + iMin;
3427}
3428
3429Float:GetURandomFloatRange(Float:fMin, Float:fMax)
3430{
3431 return fMin + GetURandomFloat() * fMax - fMin;
3432}
3433
3434void:SetAmmo(client, wepslot, newAmmo)
3435{
3436 new weapon = GetPlayerWeaponSlot(client, wepslot);
3437 if (IsValidEntity(weapon))
3438 {
3439 new iOffset = GetEntProp(weapon, PropType:0, "m_iPrimaryAmmoType", 1, 0) * 4;
3440 new iAmmoTable = FindSendPropInfo("CTFPlayer", "m_iAmmo", 0, 0, 0);
3441 SetEntData(client, iOffset + iAmmoTable, newAmmo, 4, true);
3442 }
3443 return void:0;
3444}
3445
3446void:SetAmmoAll(wepslot, newAmmo)
3447{
3448 new i = 1;
3449 while (i <= MaxClients)
3450 {
3451 if (IsValidClient(i, true))
3452 {
3453 new weapon = GetPlayerWeaponSlot(i, wepslot);
3454 if (IsValidEntity(weapon))
3455 {
3456 new iOffset = GetEntProp(weapon, PropType:0, "m_iPrimaryAmmoType", 1, 0) * 4;
3457 new iAmmoTable = FindSendPropInfo("CTFPlayer", "m_iAmmo", 0, 0, 0);
3458 SetEntData(i, iOffset + iAmmoTable, newAmmo, 4, true);
3459 }
3460 }
3461 i++;
3462 }
3463 return void:0;
3464}
3465
3466bool:ChangePlayerWeaponSlot(iClient, iSlot)
3467{
3468 new iWeapon = GetPlayerWeaponSlot(iClient, iSlot);
3469 if (iWeapon > MaxClients)
3470 {
3471 SetEntPropEnt(iClient, PropType:0, "m_hActiveWeapon", iWeapon, 0);
3472 return true;
3473 }
3474 return false;
3475}