Advertisement
Guest User

PUG

a guest
Sep 10th, 2012
4,125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 66.08 KB | None | 0 0
  1. #include <sourcemod>
  2. #include <cstrike>
  3. #include <sdktools>
  4. #include <sdktools_functions>
  5.  
  6. #if defined MAXPLAYERS
  7. #undef MAXPLAYERS
  8. #define MAXPLAYERS 64
  9. #endif
  10.  
  11. new Handle:hTVEnabled;
  12. new Handle:RestartTimers = INVALID_HANDLE;
  13. new Handle:hMaxPlayers;
  14. #define MAX_PLAYERS_DEFAULT "10"
  15. new OffsetAccount; // MONEY OFFSET
  16. new bool:bPubChatMuted[MAXPLAYERS+1]=false;
  17. new bool:bTeamChatMuted[MAXPLAYERS+1]=false;
  18. new bool:bMuted[MAXPLAYERS+1][MAXPLAYERS+1];
  19. new Float:fLastMessage[MAXPLAYERS+1];
  20. new bool:bAuthed[MAXPLAYERS+1];
  21. new Handle:hBotQuota = INVALID_HANDLE;
  22. new PlCount = 0;
  23.  
  24. // Current match stuff
  25. enum MatchState
  26. {
  27. MS_Pre_Setup = 0,
  28. MS_Setup,
  29. MS_Before_First_Half, // This is only used if the map changes.
  30. MS_Live_First_Half,
  31. MS_Before_Second_Half, // Always used.
  32. MS_Live_Second_Half,
  33. MS_Before_Overtime_First_Half,
  34. MS_Live_Overtime_First_Half,
  35. MS_Before_Overtime_Second_Half,
  36. MS_Live_Overtime_Second_Half,
  37. MS_Post_Match,
  38. };
  39.  
  40. new MatchState:gMatchState = MS_Pre_Setup;
  41. new TeamAScore; // Team A goes CT first.
  42. new TeamBScore; // Team B goes T first.
  43. // Keep in mind team A and B are always randomized / captains.
  44. // In the case of captains, it is still random which captains will be on which team, A or B.
  45. new CurrentRound = 0;
  46. new String:MatchMap[32] = ""; // Map name.
  47. enum RuleType
  48. {
  49. Rules_PUG = 0,
  50. Rules_CGS,
  51. };
  52. new RuleType:Ruleset = Rules_PUG;
  53. #define ROUNDS_HALF_PUG 15
  54. #define ROUNDS_HALF_CGS 11
  55. #define ROUNDS_OVERTIME_HALF_PUG 5
  56. #define ROUNDS_OVERTIME_HALF_CGS 1
  57. #define MAX_ROUNDS 50 // We won't exceed 50 rounds for now.
  58. new Handle:hMatchDamage[MAX_ROUNDS]; // Vector of all the damage.
  59. new Handle:hMatchKills[MAX_ROUNDS]; // Vector of all the kills.
  60. new bool:CaptainMode = false;
  61. new bool:BunnyHopMode = false;
  62. #define MAX_MAPS 50 // For now.
  63. new String:MapNames[MAX_MAPS][32]; // Loaded OnPluginStart()
  64. #define TEAM_A 0
  65. #define TEAM_B 1
  66. #define TEAM_COUNT 2
  67. #define TEAM_CAPTAIN 0
  68. new String:TeamPlayers[TEAM_COUNT][5][24]; // Steam ID's. Cached before map change.
  69. new bool:RoundCounterOn = false;
  70.  
  71. //Clients
  72. new bool:bReady[MAXPLAYERS+1];
  73. new String:clientUsername[MAXPLAYERS+1][24];
  74. new readyUpTime[MAXPLAYERS+1];
  75. new notReadyTime[MAXPLAYERS+1];
  76. new bool:FirstSpawn[MAXPLAYERS+1] = true;
  77. new bool:AutoDmg[MAXPLAYERS+1] = false;
  78. new bool:bDisconnecting[MAXPLAYERS+1] = true;
  79.  
  80. OnAllReady()
  81. {
  82. /*
  83. enum MatchState
  84. {
  85. MS_Pre_Setup = 0,
  86. MS_Setup_Up,
  87. MS_Before_First_Half, // This is only used if the map changes.
  88. MS_Live_First_Half,
  89. MS_Before_Second_Half, // Always used.
  90. MS_Live_Second_Half,
  91. MS_Before_Overtime_First_Half,
  92. MS_Live_Overtime_First_Half,
  93. MS_Before_Overtime_Second_Half,
  94. MS_Live_Overtime_Second_Half,
  95. MS_Post_Match,
  96. };
  97. */
  98. if(gMatchState == MS_Pre_Setup)
  99. {
  100. StartMatchSetup();
  101. }
  102. else if(gMatchState == MS_Before_First_Half)
  103. {
  104. StartFirstHalf();
  105. }
  106. else if(gMatchState == MS_Before_Second_Half)
  107. {
  108. StartSecondHalf();
  109. }
  110. else if(gMatchState == MS_Before_Overtime_First_Half)
  111. {
  112. StartOTFirstHalf();
  113. }
  114. else if(gMatchState == MS_Before_Overtime_Second_Half)
  115. {
  116. StartOTSecondHalf();
  117. }
  118. }
  119.  
  120. PartialNameClient(const String:matchText[])
  121. {
  122. new Client = 0;
  123. for(new x=1;x<=MAXPLAYERS;x++)
  124. {
  125. if(ValidClient(x) && !IsSourceTV(x))
  126. {
  127. new String:clName[32];
  128. GetClientName(x, clName, 32);
  129. if(StrContains(clName, matchText, false)>=0)
  130. {
  131. if(Client!=0)
  132. {
  133. return -1; // -1 == multiple
  134. }
  135. else
  136. {
  137. Client = x;
  138. }
  139. }
  140. }
  141. }
  142. return Client;
  143. }
  144.  
  145. CSLTeam(client)
  146. {
  147. if(!ValidClient(client) || IsSourceTV(client))
  148. {
  149. return -1;
  150. }
  151. new String:steamID[24];
  152. GetClientAuthString(client, steamID, 24);
  153. return CSLTeamOfSteam(steamID);
  154. }
  155.  
  156. CSLTeamOfSteam(const String:steamID[])
  157. {
  158. for(new x=0;x<5;x++)
  159. {
  160. if(StrEqual(steamID, TeamPlayers[TEAM_A][x]))
  161. {
  162. return TEAM_A;
  163. }
  164. }
  165. for(new x=0;x<5;x++)
  166. {
  167. if(StrEqual(steamID, TeamPlayers[TEAM_B][x]))
  168. {
  169. return TEAM_B;
  170. }
  171. }
  172. return -1;
  173. }
  174.  
  175. bool:AllowBots()
  176. {
  177. return false; // Temp.
  178. }
  179.  
  180. ClientDefaults(client)
  181. {
  182. fLastMessage[client] = 0.0;
  183. AutoDmg[client] = false;
  184. FirstSpawn[client] = true;
  185. if(ValidClient(client)) {
  186. GetClientName(client, clientUsername[client], 24);
  187. }
  188. bAuthed[client] = false;
  189. bReady[client] = false;
  190. readyUpTime[client] = 0;
  191. notReadyTime[client] = 0;
  192. bDisconnecting[client] = true;
  193. bPubChatMuted[client] = false;
  194. bTeamChatMuted[client] = false;
  195. for(new x=0;x<=MAXPLAYERS;x++)
  196. {
  197. bMuted[client][x] = false;
  198. }
  199. }
  200.  
  201. Kick(client, String:format[], any:...)
  202. {
  203. if(!ValidClient(client))
  204. {
  205. return;
  206. }
  207. new String:reason[256];
  208. VFormat(reason, sizeof(reason), format, 3);
  209. if(StrEqual(reason,""))
  210. {
  211. KickClient(client);
  212. }
  213. else
  214. {
  215. KickClient(client,"%s",reason);
  216. }
  217. PrintToServer("KICK (%d): %s",client,reason);
  218. }
  219.  
  220. bool:ReadyUpState()
  221. {
  222. if(gMatchState==MS_Pre_Setup || gMatchState==MS_Before_First_Half || gMatchState==MS_Before_Second_Half
  223. || gMatchState==MS_Before_Overtime_First_Half || gMatchState==MS_Before_Overtime_Second_Half)
  224. {
  225. return true;
  226. }
  227. return false;
  228. }
  229.  
  230. ChangeCvar(const String:cvarName[], const String:newValue[])
  231. {
  232. new Handle:hVar = FindConVar(cvarName);
  233. new oldFlags = GetConVarFlags(hVar);
  234. new newFlags = oldFlags;
  235. newFlags &= ~FCVAR_NOTIFY;
  236. SetConVarFlags(hVar, newFlags);
  237. SetConVarString(hVar, newValue);
  238. SetConVarFlags(hVar, oldFlags);
  239. }
  240.  
  241. EnterReadyUpState()
  242. {
  243. // Just a hack for freeze time.
  244. ChangeCvar("mp_freezetime", "3");
  245. ChangeCvar("mp_buytime", "999");
  246. ChangeCvar("mp_forcecamera", "0");
  247. for(new x=0;x<=MAXPLAYERS;x++)
  248. {
  249. notReadyTime[x] = GetTime();
  250. bReady[x] = false;
  251. }
  252. }
  253.  
  254. public Action:WarmUpSpawner(Handle:timer)
  255. {
  256. if(ReadyUpState())
  257. {
  258. if(GetClientCount() != 10)
  259. {
  260. PrintToChatAll("[PUG] %d/10 Players are connected.", GetClientCount());
  261. }
  262. else
  263. {
  264. PrintToChatAll("[PUG] All player have connected.");
  265. }
  266. PrintToChatAll("Players not ready:");
  267. for(new x=1;x<=MAXPLAYERS;x++)
  268. {
  269. if(!bReady[x])
  270. {
  271. new String:plName[32];
  272. GetClientName(x, plName, 32);
  273. PrintToChatAll("%s ", plName);
  274. }
  275. else
  276. {
  277. PrintToChatAll("(Waiting for more players...)");
  278. }
  279. PrintToChatAll("---------------------------------------");
  280. PrintToChatAll("Type /ready in chat when you are ready.");
  281. }
  282. DeleteBomb();
  283. for(new x=1;x<=MAXPLAYERS;x++)
  284. {
  285. if(ValidClient(x) && !IsSourceTV(x) && GetClientTeam(x)>=CS_TEAM_T && !IsPlayerAlive(x))
  286. {
  287. // Is it warm up?
  288. if(ReadyUpState())
  289. {
  290. CS_RespawnPlayer(x);
  291. }
  292. }
  293. }
  294. }
  295. }
  296.  
  297. new seconds=60;
  298. new minute=9;
  299.  
  300. public Action:OneSecCheck(Handle:timer)
  301. {
  302. seconds--;
  303. for(new x=1;x<=MAXPLAYERS;x++)
  304. {
  305. if(ValidClient(x) && !IsFakeClient(x))
  306. {
  307. if(ReadyUpState())
  308. {
  309. new Handle:hBuffer = StartMessageOne("KeyHintText", x);
  310. new String:tmptext[256];
  311. if(seconds==-1)
  312. {
  313. minute--;
  314. seconds=59;
  315. }
  316. if(minute==-1)
  317. {
  318. seconds=-2;
  319. }
  320. Format(tmptext, 256, "TIME: 0s");
  321. if(minute==9)
  322. {
  323. Format(tmptext, 256, "TIME: 9m %is", seconds);
  324. }
  325. if(minute==8)
  326. {
  327. Format(tmptext, 256, "TIME: 8m %is", seconds);
  328. }
  329. if(minute==7)
  330. {
  331. Format(tmptext, 256, "TIME: 7m %is", seconds);
  332. }
  333. if(minute==6)
  334. {
  335. Format(tmptext, 256, "TIME: 6m %is", seconds);
  336. }
  337. if(minute==5)
  338. {
  339. Format(tmptext, 256, "TIME: 5m %is", seconds);
  340. }
  341. if(minute==4)
  342. {
  343. Format(tmptext, 256, "TIME: 4m %is", seconds);
  344. }
  345. if(minute==3)
  346. {
  347. Format(tmptext, 256, "TIME: 3m %is", seconds);
  348. }
  349. if(minute==2)
  350. {
  351. Format(tmptext, 256, "TIME: 2m %is", seconds);
  352. }
  353. if(minute==1)
  354. {
  355. Format(tmptext, 256, "TIME: 1m %is", seconds);
  356. }
  357. if(seconds != -2 && minute == 0)
  358. {
  359. Format(tmptext, 256, "TIME: %is", seconds);
  360. }
  361. BfWriteByte(hBuffer, 1);
  362. BfWriteString(hBuffer, tmptext);
  363. EndMessage();
  364. }
  365. }
  366. }
  367. return Plugin_Continue;
  368. }
  369.  
  370. // This function checks if a STEAMID is valid.
  371. // AS VALVE UPDATES THEIR STANDARDS CHANGE THIS
  372. bool:BadSteamId(const String:steamID[])
  373. {
  374. if(!AllowBots() && StrEqual(steamID,"BOT"))
  375. return true;
  376.  
  377. return false; // It's good.
  378. }
  379.  
  380. bool:ValidClient(client,bool:check_alive=false)
  381. {
  382. if(client>0 && client<=MaxClients && IsClientConnected(client) && IsClientInGame(client))
  383. {
  384. if(check_alive && !IsPlayerAlive(client))
  385. {
  386. return false;
  387. }
  388. return true;
  389. }
  390. return false;
  391. }
  392.  
  393. public Action:MapDelayed(Handle:timer)
  394. {
  395. ChangeMatchState(MS_Before_First_Half);
  396. new String:curmap[32];
  397. GetCurrentMap(curmap, 32);
  398. if(!StrEqual(curmap, MatchMap))
  399. {
  400. ForceChangeLevel(MatchMap, "Setting up match");
  401. }
  402. }
  403.  
  404. TeamSize(teamCSL)
  405. {
  406. new i = 0;
  407. for(new x=0;x<5;x++)
  408. {
  409. if(!StrEqual(TeamPlayers[teamCSL][x],""))
  410. {
  411. i++;
  412. }
  413. }
  414. return i;
  415. }
  416.  
  417. TeamSizeActive(teamCSL)
  418. {
  419. new i = 0;
  420. for(new x=0;x<5;x++)
  421. {
  422. if(!StrEqual(TeamPlayers[teamCSL][x],""))
  423. {
  424. new cAtX = ClientOfSteamId(TeamPlayers[teamCSL][x]);
  425. if(ValidClient(cAtX))
  426. {
  427. i++;
  428. }
  429. }
  430. }
  431. return i;
  432. }
  433.  
  434. AddSteamToTeam(const String:steamID[], teamNum)
  435. {
  436. // If the team is full, look for a disconnect. They are going to be replaced and will probably be penelized.
  437. new TeamCount = TeamSize(teamNum);
  438. if(TeamCount<5)
  439. {
  440. for(new x=0;x<5;x++)
  441. {
  442. if(StrEqual(TeamPlayers[teamNum][x],""))
  443. {
  444. Format(TeamPlayers[teamNum][x], 24, "%s", steamID);
  445. return;
  446. }
  447. }
  448. }
  449. else
  450. {
  451. // Sorry, whoever left is bound to cry if they were trying to come back :(
  452. for(new x=0;x<5;x++)
  453. {
  454. new ClientAt = ClientOfSteamId(TeamPlayers[teamNum][x]);
  455. if(!ValidClient(ClientAt))
  456. {
  457. Format(TeamPlayers[teamNum][x], 24, "%s", steamID);
  458. return;
  459. }
  460. }
  461. }
  462. }
  463.  
  464. StartFirstHalf()
  465. {
  466. // Record.
  467. // Map.
  468. ServerCommand("tv_record %d_%s\n", GetTime(), MatchMap);
  469. if(!CaptainMode)
  470. {
  471. // Go through each person (random order), if they aren't on a team assign them to the team lacking players, or random.
  472. new bool:ClientIterated[MAXPLAYERS+1] = false;
  473. for(new i=1;i<=MAXPLAYERS;i++)
  474. {
  475. new RandClient = GetRandomInt(1,MAXPLAYERS);
  476. while(ClientIterated[RandClient])
  477. {
  478. RandClient = GetRandomInt(1,MAXPLAYERS);
  479. }
  480. ClientIterated[RandClient] = true;
  481. if(!ValidClient(RandClient) || IsSourceTV(RandClient))
  482. {
  483. continue;
  484. }
  485. new String:steamID[24];
  486. GetClientAuthString(RandClient, steamID, 24);
  487. if(CSLTeam(RandClient)!=-1)
  488. {
  489. continue; // Already on a team, on a group likely.
  490. }
  491. // Now put them on a team.
  492. new TeamACount = TeamSizeActive(TEAM_A);
  493. new TeamBCount = TeamSizeActive(TEAM_B);
  494. if(TeamACount < TeamBCount)
  495. {
  496. AddSteamToTeam(steamID, TEAM_A);
  497. }
  498. else if(TeamBCount < TeamACount)
  499. {
  500. AddSteamToTeam(steamID, TEAM_B);
  501. }
  502. else
  503. {
  504. new RandTeam = GetRandomInt(TEAM_A, TEAM_B);
  505. AddSteamToTeam(steamID, RandTeam);
  506. }
  507. }
  508. }
  509. /*
  510. else
  511. {
  512. Later
  513. }
  514. */
  515. // Clear scores just incase.
  516. TeamAScore = 0;
  517. TeamBScore = 0;
  518. // Team A goes T first
  519. for(new x=1;x<=MAXPLAYERS;x++)
  520. {
  521. if(ValidClient(x) && !IsSourceTV(x))
  522. {
  523. new Team = CSLTeam(x);
  524. if(Team==TEAM_A)
  525. {
  526. CS_SwitchTeam(x, CS_TEAM_T);
  527. }
  528. else if(Team==TEAM_B)
  529. {
  530. CS_SwitchTeam(x, CS_TEAM_CT);
  531. }
  532. else
  533. {
  534. Kick(x, "Sorry, you aren't supposed to be here");
  535. }
  536. }
  537. }
  538.  
  539. ChangeMatchState(MS_Live_First_Half);
  540.  
  541. PrintToChatAll("[PUG] Starting the first half...");
  542. EnforceMatchCvars();
  543. ServerCommand("mp_restartgame 1\n");
  544. RestartTimers = CreateTimer(2.0, RestartSecondTime);
  545. }
  546.  
  547. public Action:RestartSecondTime(Handle:timer)
  548. {
  549. ServerCommand("mp_restartgame 5\n");
  550. RestartTimers = CreateTimer(6.0, RestartThirdTime)
  551. }
  552.  
  553. public Action:RestartThirdTime(Handle:timer)
  554. {
  555. ServerCommand("mp_restartgame 5\n");
  556. PrintToChatAll("[PUG] Next round is live.");
  557. RestartTimers = CreateTimer(4.5, LiveMessageTimer);
  558. }
  559.  
  560. public Action:LiveMessageTimer(Handle:timer)
  561. {
  562. RestartTimers = INVALID_HANDLE;
  563. PrintCenterTextAll("MATCH IS LIVE!");
  564. RoundCounterOn = true;
  565. PrintToChatAll("[PUG] Match is live!");
  566. }
  567.  
  568. bool:TeamsSetup()
  569. {
  570. if(gMatchState>=MS_Live_First_Half && gMatchState<MS_Post_Match)
  571. {
  572. return true;
  573. }
  574. return false;
  575. }
  576.  
  577. EnforceMatchCvars(bool:ot = false)
  578. {
  579. ChangeCvar("mp_freezetime", "8");
  580. ChangeCvar("mp_forcecamera", "1");
  581. ChangeCvar("mp_buytime", "15");
  582. if(BunnyHopMode)
  583. {
  584. ChangeCvar("sv_enablebunnyhopping", "1");
  585. }
  586. else
  587. {
  588. ChangeCvar("sv_enablebunnyhopping", "0");
  589. }
  590. if(Ruleset==Rules_PUG)
  591. {
  592. ChangeCvar("mp_roundtime", "1.75");
  593. }
  594. else if(Ruleset==Rules_CGS)
  595. {
  596. ChangeCvar("mp_roundtime", "1.50");
  597. }
  598. if(ot)
  599. {
  600. if(Ruleset==Rules_PUG)
  601. {
  602. ChangeCvar("mp_startmoney", "8000");
  603. }
  604. else if(Ruleset==Rules_CGS)
  605. {
  606. ChangeCvar("mp_startmoney", "16000");
  607. }
  608. }
  609. else
  610. {
  611. if(Ruleset==Rules_PUG)
  612. {
  613. ChangeCvar("mp_startmoney", "800");
  614. }
  615. else if(Ruleset==Rules_CGS)
  616. {
  617. ChangeCvar("mp_startmoney", "8000");
  618. }
  619. }
  620. }
  621.  
  622. StartSecondHalf()
  623. {
  624. ChangeMatchState(MS_Live_Second_Half);
  625. EnforceMatchCvars();
  626. PrintToChatAll("[PUG] Starting the second half...");
  627. ServerCommand("mp_restartgame 1\n");
  628. RestartTimers = CreateTimer(2.0, RestartSecondTime);
  629. }
  630.  
  631. StartOTFirstHalf()
  632. {
  633. ChangeMatchState(MS_Live_Overtime_First_Half);
  634.  
  635. PrintToChatAll("[PUG] Starting the first half of overtime...");
  636. EnforceMatchCvars(true);
  637. ServerCommand("mp_restartgame 1\n");
  638. RestartTimers = CreateTimer(2.0, RestartSecondTime);
  639. }
  640.  
  641. StartOTSecondHalf()
  642. {
  643. ChangeMatchState(MS_Live_Overtime_Second_Half);
  644.  
  645. PrintToChatAll("[PUG] Starting the second half of overtime...");
  646. EnforceMatchCvars(true);
  647. ServerCommand("mp_restartgame 1\n");
  648. RestartTimers = CreateTimer(2.0, RestartSecondTime);
  649. }
  650.  
  651. // BUG: Votes dont continue if failed.
  652. TryStartMatch()
  653. {
  654. // Are we on the correct map?
  655. new String:curmap[32];
  656. GetCurrentMap(curmap, 32);
  657. if(!StrEqual(curmap, MatchMap))
  658. {
  659. PrintToChatAll("[PUG] Map is changing in 5 seconds, brace yourselves.");
  660. CreateTimer(5.0, MapDelayed);
  661. }
  662. else
  663. {
  664. StartFirstHalf();
  665. }
  666. }
  667.  
  668. RulesCSL()
  669. {
  670. PrintToChatAll("[PUG] Ruleset will be: PUG");
  671. Ruleset = Rules_PUG;
  672. TeamVote();
  673. }
  674.  
  675. SetMatchMap(const String:mapname[])
  676. {
  677. PrintToChatAll("[PUG] Map will be: %s", mapname);
  678. Format(MatchMap, 32, mapname);
  679. TryStartMatch();
  680. }
  681.  
  682. public Handle_MapVote(Handle:menu, MenuAction:action, param1, param2)
  683. {
  684. if (action == MenuAction_End)
  685. {
  686. CloseHandle(menu);
  687. } else if (action == MenuAction_VoteEnd) {
  688. new String:map[32];
  689. GetMenuItem(menu, param1, map, sizeof(map));
  690. if(StrEqual(map,"Random"))
  691. {
  692. SetMatchMap(MapNames[GetRandomInt(0, GetMapCount()-1)]);
  693. }
  694. else
  695. {
  696. SetMatchMap(map);
  697. }
  698. }
  699. else if(action==MenuAction_VoteCancel)
  700. {
  701. // Choose a random map.
  702. SetMatchMap(MapNames[GetRandomInt(0, GetMapCount()-1)]);
  703. }
  704. }
  705.  
  706. StartMapVote()
  707. {
  708. // Choose a rule set.
  709. if (IsVoteInProgress())
  710. {
  711. CancelVote();
  712. }
  713.  
  714. new Handle:menu = CreateMenu(Handle_MapVote);
  715. SetMenuTitle(menu, "Vote for the map");
  716. // Random order.
  717. new bool:bShowed[MAX_MAPS];
  718. for(new x=0;x<GetMapCount();x++)
  719. {
  720. new Rand = GetRandomInt(0, GetMapCount()-1);
  721. while(bShowed[Rand])
  722. {
  723. Rand = GetRandomInt(0, GetMapCount()-1);
  724. }
  725. bShowed[Rand] = true;
  726. AddMenuItem(menu, MapNames[Rand], MapNames[Rand]);
  727. }
  728. SetMenuExitButton(menu, false);
  729. VoteMenuToAll(menu, 15);
  730. }
  731.  
  732. BHopOn()
  733. {
  734. PrintToChatAll("[PUG] Bunnyhopping will be enabled.");
  735. BunnyHopMode = true;
  736. StartMapVote();
  737. }
  738.  
  739. BHopOff()
  740. {
  741. PrintToChatAll("[PUG] Bunnyhopping will be disabled.");
  742. BunnyHopMode = false;
  743. StartMapVote();
  744. }
  745.  
  746. public Handle_BHopVote(Handle:menu, MenuAction:action, param1, param2)
  747. {
  748. if (action == MenuAction_End)
  749. {
  750. CloseHandle(menu);
  751. } else if (action == MenuAction_VoteEnd) {
  752. // 0 = Off
  753. // 1 = On
  754. if(param1 == 0)
  755. {
  756. BHopOff();
  757. }
  758. else
  759. {
  760. BHopOn();
  761. }
  762. }
  763. else if(action==MenuAction_VoteCancel)
  764. {
  765. BHopOff();
  766. }
  767. }
  768.  
  769. BHopVote()
  770. {
  771. if(IsVoteInProgress())
  772. {
  773. CancelVote();
  774. }
  775.  
  776. new Handle:menu = CreateMenu(Handle_BHopVote);
  777. SetMenuTitle(menu, "Vote for bunny hopping");
  778. AddMenuItem(menu, "off", "Off");
  779. AddMenuItem(menu, "on", "On");
  780. SetMenuExitButton(menu, false);
  781. VoteMenuToAll(menu, 15);
  782. }
  783.  
  784. TeamsRandom()
  785. {
  786. CaptainMode = false;
  787. BHopVote();
  788. }
  789.  
  790. /*public Handle_TeamVote(Handle:menu, MenuAction:action, param1, param2)
  791. {
  792. if (action == MenuAction_End)
  793. {
  794. CloseHandle(menu);
  795. } else if (action == MenuAction_VoteEnd) {
  796. // 0 = Random
  797. // 1 = Captains
  798. if(param1 == 0)
  799. {
  800. TeamsRandom();
  801. }
  802. else
  803. {
  804. TeamsCaptains();
  805. }
  806. }
  807. }*/
  808.  
  809. TeamVote()
  810. {
  811. // For now random teams.
  812. TeamsRandom();
  813. /*// Choose a team set.
  814. if (IsVoteInProgress())
  815. {
  816. CancelVote();
  817. }
  818.  
  819. new Handle:menu = CreateMenu(Handle_TeamVote);
  820. SetMenuTitle(menu, "Vote for team sorting");
  821. AddMenuItem(menu, "rand", "Random");
  822. AddMenuItem(menu, "capt", "Captains");
  823. SetMenuExitButton(menu, false);
  824. VoteMenuToAll(menu, 15);*/
  825. }
  826.  
  827. RulesCGS()
  828. {
  829. PrintToChatAll("[PUG] Ruleset will be: CGS");
  830. Ruleset = Rules_CGS;
  831. TeamVote();
  832. }
  833.  
  834. public Handle_RulesVote(Handle:menu, MenuAction:action, param1, param2)
  835. {
  836. if (action == MenuAction_End)
  837. {
  838. CloseHandle(menu);
  839. } else if (action == MenuAction_VoteEnd) {
  840. // 0 = CSL
  841. // 1 = Pug
  842. if(param1 == 0)
  843. {
  844. RulesCSL();
  845. }
  846. else
  847. {
  848. RulesCGS();
  849. }
  850. }
  851. else if(action==MenuAction_VoteCancel)
  852. {
  853. RulesCSL();
  854. }
  855. }
  856.  
  857. StartRulesVote()
  858. {
  859. // Choose a rule set.
  860. if (IsVoteInProgress())
  861. {
  862. CancelVote();
  863. }
  864.  
  865. new Handle:menu = CreateMenu(Handle_RulesVote);
  866. SetMenuTitle(menu, "Vote for rule set");
  867. AddMenuItem(menu, "csl", "CSL (15 Round Halves, $800)");
  868. AddMenuItem(menu, "cgs", "CGS (9 Round Halves, $8000)");
  869. SetMenuExitButton(menu, false);
  870. VoteMenuToAll(menu, 15);
  871. }
  872.  
  873. ChangeMatchState(MatchState:newState)
  874. {
  875. gMatchState = newState;
  876.  
  877. if(ReadyUpState())
  878. {
  879. EnterReadyUpState();
  880. }
  881. }
  882.  
  883. StartMatchSetup()
  884. {
  885. // Vote for rule set.
  886. PrintToChatAll("[PUG] Starting match setup and votes.");
  887. ChangeMatchState(MS_Setup);
  888. StartRulesVote();
  889. }
  890.  
  891. public Action:SayTeamHook(client,args)
  892. {
  893. return SayHook(client, args, true);
  894. }
  895.  
  896. public Action:SayPubHook(client,args)
  897. {
  898. return SayHook(client, args, false);
  899. }
  900.  
  901. ReadyUp(client) {
  902. new String:plName[32];
  903. GetClientName(client, plName, 32);
  904. bReady[client] = true;
  905. readyUpTime[client] = GetTime();
  906. PrintToChatAll("[PUG] %s is now ready.", plName);
  907. // If this is the last ready up.
  908. new bool:bStillMore = false;
  909. new PlCount = 0;
  910. for(new a=1;a<=MAXPLAYERS;a++)
  911. {
  912. if(ValidClient(a) && !IsSourceTV(a))
  913. {
  914. PlCount++;
  915. if(!bReady[a])
  916. {
  917. bStillMore = true;
  918. }
  919. }
  920. }
  921. if(!bStillMore)
  922. {
  923. if(PlCount == GetConVarInt(hMaxPlayers))
  924. {
  925. OnAllReady();
  926. }
  927. }
  928. }
  929.  
  930. public Action:SayHook(client,args,bool:team)
  931. {
  932. if(!client)
  933. return Plugin_Continue; // Don't block the server ever.
  934.  
  935. decl String:ChatText[256];
  936. GetCmdArgString(ChatText,256);
  937. StripQuotes(ChatText);
  938. new String:Words[100][256];
  939. new WordCount = ExplodeString(ChatText, " ", Words, 100, 256);
  940. new bool:bHookMessage = false;
  941. new bool:bCommand = true;
  942.  
  943. if(StrEqual(Words[0],"/ready", false))
  944. {
  945. if(!ReadyUpState())
  946. {
  947. PrintToChat(client, "[PUG] You don't need to ready up right now.");
  948. bHookMessage = true;
  949. }
  950. else
  951. {
  952. if(bReady[client])
  953. {
  954. PrintToChat(client,"[PUG] You are already ready.");
  955. bHookMessage = true;
  956. }
  957. else
  958. {
  959. ReadyUp(client);
  960. }
  961. }
  962. }
  963. else if(StrEqual(Words[0], "/mute", false))
  964. {
  965. bHookMessage = true;
  966. new String:fullSecond[256];
  967. Format(fullSecond, 256, "%s", Words[1]);
  968. for(new x=2;x<WordCount;x++)
  969. {
  970. Format(fullSecond, 256, "%s %s", fullSecond, Words[x]);
  971. }
  972. if(StrEqual(fullSecond,""))
  973. {
  974. PrintToChat(client, "[PUG] Syntax: /mute <part of name>");
  975. }
  976. else
  977. {
  978. new cl = PartialNameClient(fullSecond);
  979. if(cl==-1)
  980. {
  981. PrintToChat(client, "[PUG] Be more specific, multiple matches.");
  982. }
  983. else if(cl==0)
  984. {
  985. PrintToChat(client, "[PUG] No matches for \"%s\".", fullSecond);
  986. }
  987. else
  988. {
  989. if(client==cl)
  990. {
  991. PrintToChat(client, "[PUG] You can't mute yourself.");
  992. }
  993. else if(IsPlayerMuted(client, cl))
  994. {
  995. PrintToChat(client, "[PUG] Player already muted.");
  996. }
  997. else
  998. {
  999. PrintToChat(client, "[PUG] Player muted.");
  1000. bMuted[client][cl] = true;
  1001. }
  1002. }
  1003. }
  1004. }
  1005. else if(StrEqual(Words[0], "/unmute", false))
  1006. {
  1007. bHookMessage = true;
  1008. new String:fullSecond[256];
  1009. Format(fullSecond, 256, "%s", Words[1]);
  1010. for(new x=2;x<WordCount;x++)
  1011. {
  1012. Format(fullSecond, 256, "%s %s", fullSecond, Words[x]);
  1013. }
  1014. if(StrEqual(fullSecond,""))
  1015. {
  1016. PrintToChat(client, "[PUG] Syntax: /unmute <part of name>");
  1017. }
  1018. else
  1019. {
  1020. new cl = PartialNameClient(fullSecond);
  1021. if(cl==-1)
  1022. {
  1023. PrintToChat(client, "[PUG] Be more specific, multiple matches.");
  1024. }
  1025. else if(cl==0)
  1026. {
  1027. PrintToChat(client, "[PUG] No matches for \"%s\".", fullSecond);
  1028. }
  1029. else
  1030. {
  1031. if(client==cl)
  1032. {
  1033. PrintToChat(client, "[PUG] You can't mute yourself.");
  1034. }
  1035. else if(!IsPlayerMuted(client, cl))
  1036. {
  1037. PrintToChat(client, "[PUG] Player isn't muted.");
  1038. }
  1039. else
  1040. {
  1041. PrintToChat(client, "[PUG] Player unmuted.");
  1042. bMuted[client][cl] = false;
  1043. }
  1044. }
  1045. }
  1046. }
  1047. else if(StrEqual(Words[0], "/chat", false))
  1048. {
  1049. bHookMessage = true;
  1050. if(IsPubChatMuted(client))
  1051. {
  1052. bPubChatMuted[client] = false;
  1053. PrintToChat(client, "[PUG] Public chat unmuted");
  1054. }
  1055. else
  1056. {
  1057. bPubChatMuted[client] = true;
  1058. PrintToChat(client, "[PUG] Public chat muted.");
  1059. }
  1060. }
  1061. else if(StrEqual(Words[0], "/teamchat", false))
  1062. {
  1063. bHookMessage = true;
  1064. if(IsTeamChatMuted(client))
  1065. {
  1066. bTeamChatMuted[client] = false;
  1067. PrintToChat(client, "[PUG] Team chat unmuted.");
  1068. }
  1069. else
  1070. {
  1071. bTeamChatMuted[client] = true;
  1072. PrintToChat(client, "[PUG] Team chat muted.");
  1073. }
  1074. }
  1075. else if(StrEqual(Words[0], "/unready", false))
  1076. {
  1077. if(!bReady[client])
  1078. {
  1079. PrintToChat(client, "[PUG] You already are unready.");
  1080. bHookMessage = true;
  1081. }
  1082. else
  1083. {
  1084. new curTime = GetTime();
  1085. if(readyUpTime[client] + 3 > curTime)
  1086. {
  1087. PrintToChat(client, "[PUG] You must wait 3 seconds between ready commands.");
  1088. bHookMessage = true;
  1089. }
  1090. else
  1091. {
  1092. bReady[client] = false;
  1093. new String:plName[32];
  1094. GetClientName(client, plName, 32);
  1095. PrintToChatAll("[PUG] %s is no longer ready.", plName);
  1096. notReadyTime[client] = GetTime();
  1097. }
  1098. }
  1099. }
  1100. else if(StrEqual(Words[0], "/autodmg",false))
  1101. {
  1102. if(AutoDmg[client])
  1103. {
  1104. AutoDmg[client] = false;
  1105. PrintToChat(client, "[PUG] Auto /dmg has been toggled off.");
  1106. }
  1107. else
  1108. {
  1109. AutoDmg[client] = true;
  1110. PrintToChat(client, "[PUG] Auto /dmg has been toggled on.");
  1111. }
  1112. }
  1113. else if(StrEqual(Words[0], "/dmg", false))
  1114. {
  1115. if(!MatchLive())
  1116. {
  1117. PrintToChat(client, "[PUG] You can't use this now.");
  1118. bHookMessage = true;
  1119. }
  1120. else
  1121. {
  1122. if(IsPlayerAlive(client))
  1123. {
  1124. PrintToChat(client, "[PUG] You must be dead to use this.");
  1125. bHookMessage = true;
  1126. }
  1127. else
  1128. {
  1129. PrintDmgReport(client);
  1130. }
  1131. }
  1132. }
  1133. else if(StrEqual(Words[0], "/help", false))
  1134. {
  1135. PrintToChat(client, "[PUG] Commands: /ready, /help, /dmg, /autodmg");
  1136. bHookMessage = true;
  1137. }
  1138. else
  1139. {
  1140. bCommand = false;
  1141. }
  1142. new bool:bCanChat = (fLastMessage[client] + 0.5 <= GetEngineTime());
  1143. if(!bCommand && !bHookMessage && team && IsTeamChatMuted(client))
  1144. {
  1145. PrintToChat(client, "[PUG] You can't team chat until you re-enable it with /teamchat.");
  1146. return Plugin_Handled;
  1147. }
  1148. if(!bCommand && !bHookMessage && !team && IsPubChatMuted(client))
  1149. {
  1150. PrintToChat(client, "[PUG] You can't public chat until you re-enable it with /chat.");
  1151. return Plugin_Handled;
  1152. }
  1153. if(!bHookMessage && bCanChat)
  1154. {
  1155. fLastMessage[client] = GetEngineTime();
  1156. ChatMsg(client, team, ChatText);
  1157. }
  1158. return Plugin_Handled;
  1159. }
  1160.  
  1161. public Action:RespawnCheck(Handle:timer, any:userid)
  1162. {
  1163. new client = GetClientOfUserId(userid);
  1164. if(ReadyUpState() && ValidClient(client) && !IsSourceTV(client) && !IsPlayerAlive(client))
  1165. {
  1166. CS_RespawnPlayer(client);
  1167. }
  1168. }
  1169.  
  1170. LogKillLocalStats(const String:steamAttacker[], const String:steamVictim[], const String:weapon[], bool:headshot)
  1171. {
  1172. if(!MatchLive())
  1173. {
  1174. return;
  1175. }
  1176. if(CurrentRound<1)
  1177. {
  1178. return;
  1179. }
  1180. // Create a new array.
  1181. new Handle:newArray = CreateArray(24);
  1182. PushArrayString(newArray, steamAttacker);
  1183. PushArrayString(newArray, steamVictim);
  1184. PushArrayString(newArray, weapon);
  1185. PushArrayCell(newArray, headshot);
  1186. }
  1187.  
  1188. LogKill(attacker, victim, const String:weapon[], bool:headshot)
  1189. {
  1190. if(MatchLive())
  1191. {
  1192. new String:steamAttacker[24];
  1193. new String:steamVictim[24];
  1194. GetClientAuthString(attacker, steamAttacker, 24);
  1195. GetClientAuthString(victim, steamVictim, 24);
  1196. LogKillLocalStats(steamAttacker, steamVictim, weapon, headshot);
  1197. }
  1198. }
  1199.  
  1200. public Action:DeathCallback(Handle:event, const String:name[], bool:dontBroadcast)
  1201. {
  1202. new userid = GetEventInt(event, "userid");
  1203. CreateTimer(2.0, RespawnCheck, userid);
  1204. new client = GetClientOfUserId(userid);
  1205. new attacker_userid = GetEventInt(event, "attacker");
  1206. new attacker = GetClientOfUserId(attacker_userid);
  1207. new String:weapon[64];
  1208. GetEventString(event, "weapon", weapon, 64);
  1209. new bool:Headshot = (GetEventInt(event, "headshot")==0)?false:true;
  1210. if(ValidClient(client))
  1211. {
  1212. if(attacker==client || attacker==0)
  1213. {
  1214. LogKill(client, client, weapon, false);
  1215. }
  1216. else if(ValidClient(attacker))
  1217. {
  1218. LogKill(attacker, client, weapon, Headshot);
  1219. }
  1220. }
  1221.  
  1222. if(MatchLive() && AutoDmg[client])
  1223. {
  1224. PrintDmgReport(client);
  1225. }
  1226.  
  1227. return Plugin_Continue;
  1228. }
  1229.  
  1230. public Action:RoundStartCallback(Handle:event, const String:name[], bool:dontBroadcast)
  1231. {
  1232. if(RoundCounterOn == true)
  1233. {
  1234. CurrentRound++;
  1235. // Create an array here.
  1236. hMatchDamage[CurrentRound] = CreateArray();
  1237. hMatchKills[CurrentRound] = CreateArray();
  1238. // Who is winning?
  1239. if(TeamAScore>TeamBScore)
  1240. {
  1241. // Is team A ct or t?
  1242. if(CSTeamToCSL(CS_TEAM_CT) == TEAM_A)
  1243. {
  1244. // They are CT's.
  1245. PrintToChatAll("[PUG] Round %d. CT's winning %d - %d", CurrentRound, TeamAScore, TeamBScore);
  1246. }
  1247. else
  1248. {
  1249. PrintToChatAll("[PUG] Round %d. T's winning %d - %d", CurrentRound, TeamAScore, TeamBScore);
  1250. }
  1251. }
  1252. else if(TeamBScore>TeamAScore)
  1253. {
  1254. if(CSTeamToCSL(CS_TEAM_CT) == TEAM_B)
  1255. {
  1256. // They are CT's.
  1257. PrintToChatAll("[PUG] Round %d. CT's winning %d - %d", CurrentRound, TeamBScore, TeamAScore);
  1258. }
  1259. else
  1260. {
  1261. PrintToChatAll("[PUG] Round %d. T's winning %d - %d", CurrentRound, TeamBScore, TeamAScore);
  1262. }
  1263. }
  1264. else
  1265. {
  1266. PrintToChatAll("[PUG] Round %d. Tie game, %d - %d", CurrentRound, TeamAScore, TeamBScore);
  1267. }
  1268. }
  1269. return Plugin_Continue;
  1270. }
  1271.  
  1272. public Action:RoundEndCallback(Handle:event, const String:name[], bool:dontBroadcast)
  1273. {
  1274. //new reason = GetEventInt(event, "reason");
  1275. new winner = GetEventInt(event, "winner");
  1276. if(RoundCounterOn == true)
  1277. {
  1278. if(winner==CS_TEAM_T)
  1279. {
  1280. new CSLT = CSTeamToCSL(CS_TEAM_T);
  1281. if(CSLT == TEAM_A)
  1282. {
  1283. TeamAScore++;
  1284. }
  1285. else
  1286. {
  1287. TeamBScore++;
  1288. }
  1289. }
  1290. else if(winner==CS_TEAM_CT)
  1291. {
  1292. new CSLCT = CSTeamToCSL(CS_TEAM_CT);
  1293. if(CSLCT == TEAM_A)
  1294. {
  1295. TeamAScore++;
  1296. }
  1297. else
  1298. {
  1299. TeamBScore++;
  1300. }
  1301. }
  1302.  
  1303. // Is this CSL or CGS rules?
  1304. // Check score first, if there is a winner call WinLegit or whatever.
  1305. // Are we in overtime?
  1306. // Check for a winner, then check for transitioning stuff. If there is a winner, no need to go to Half, etc...
  1307. if(gMatchState >= MS_Before_Overtime_First_Half && gMatchState!=MS_Post_Match)
  1308. {
  1309. // If CSL, overtime start score is 15-15
  1310. // Otherwise, 9 - 9
  1311. if(Ruleset==Rules_PUG)
  1312. {
  1313. if(TeamAScore >= 21)
  1314. {
  1315. MatchWinOT(TEAM_A);
  1316. return Plugin_Continue;
  1317. }
  1318. else if(TeamBScore >= 21)
  1319. {
  1320. MatchWinOT(TEAM_B);
  1321. return Plugin_Continue;
  1322. }
  1323. else if(TeamAScore == 20 && TeamBScore == 20)
  1324. {
  1325. // Tie.
  1326. MatchTieOT();
  1327. return Plugin_Continue;
  1328. }
  1329. }
  1330. else if(Ruleset==Rules_CGS)
  1331. {
  1332. if(TeamAScore >= 13)
  1333. {
  1334. MatchWinOT(TEAM_A);
  1335. return Plugin_Continue;
  1336. }
  1337. else if(TeamBScore >= 13)
  1338. {
  1339. MatchWinOT(TEAM_B);
  1340. return Plugin_Continue;
  1341. }
  1342. else if(TeamAScore == 12 && TeamBScore == 12)
  1343. {
  1344. // Tie.
  1345. MatchTieOT();
  1346. return Plugin_Continue;
  1347. }
  1348. }
  1349. }
  1350. else
  1351. {
  1352. if(Ruleset==Rules_PUG)
  1353. {
  1354. // Check of score >=16.
  1355. if(TeamAScore>=16)
  1356. {
  1357. MatchWin(TEAM_A);
  1358. }
  1359. else if(TeamBScore>=16)
  1360. {
  1361. MatchWin(TEAM_B);
  1362. }
  1363. }
  1364. else if(Ruleset==Rules_CGS)
  1365. {
  1366. // Check of score >=10.
  1367. if(TeamAScore>=10)
  1368. {
  1369. MatchWin(TEAM_A);
  1370. }
  1371. else if(TeamBScore>=10)
  1372. {
  1373. MatchWin(TEAM_B);
  1374. }
  1375. }
  1376. }
  1377.  
  1378. // Now do our checks for transitions.
  1379. if(Ruleset==Rules_PUG)
  1380. {
  1381. if(CurrentRound==15)
  1382. {
  1383. // Go to second half.
  1384. TransSecondHalfWarmup();
  1385. return Plugin_Continue;
  1386. }
  1387. else if(CurrentRound==30)
  1388. {
  1389. // Previous checks allow for no use of ==15, ==15
  1390. TransOTFirstHalfWarmup();
  1391. return Plugin_Continue;
  1392. }
  1393. else if(CurrentRound==35)
  1394. {
  1395. TransOTSecondHalfWarmup();
  1396. return Plugin_Continue;
  1397. }
  1398. }
  1399. else if(Ruleset==Rules_CGS)
  1400. {
  1401. if(CurrentRound==9)
  1402. {
  1403. // Go to second half.
  1404. TransSecondHalfWarmup();
  1405. return Plugin_Continue;
  1406. }
  1407. else if(CurrentRound==18)
  1408. {
  1409. // Previous checks allow for no use of ==15, ==15
  1410. TransOTFirstHalfWarmup();
  1411. return Plugin_Continue;
  1412. }
  1413. else if(CurrentRound==21)
  1414. {
  1415. TransOTSecondHalfWarmup();
  1416. return Plugin_Continue;
  1417. }
  1418. }
  1419. }
  1420. return Plugin_Continue;
  1421. }
  1422.  
  1423. MoveAfterTrans()
  1424. {
  1425. for(new x=1;x<=MAXPLAYERS;x++)
  1426. {
  1427. if(ValidClient(x) && !IsSourceTV(x))
  1428. {
  1429. new cslTeam = CSLTeam(x);
  1430. if(cslTeam!=TEAM_A && cslTeam!=TEAM_B)
  1431. {
  1432. continue; // Should we kick him? Probably not. This shouldn't happen.
  1433. }
  1434. else
  1435. {
  1436. new csTeam = CSLToCSTeam(cslTeam);
  1437. new curTeam = GetClientTeam(x);
  1438. if(curTeam!=csTeam)
  1439. {
  1440. CS_SwitchTeam(x, csTeam);
  1441. }
  1442. }
  1443. }
  1444. }
  1445. }
  1446.  
  1447. TransSecondHalfWarmup()
  1448. {
  1449. // All stop the round counter.
  1450. RoundCounterOn = false;
  1451. // Change state.
  1452. ChangeMatchState(MS_Before_Second_Half);
  1453. // Move them.
  1454. MoveAfterTrans();
  1455. }
  1456.  
  1457. TransOTFirstHalfWarmup()
  1458. {
  1459. RoundCounterOn = false;
  1460. ChangeMatchState(MS_Before_Overtime_First_Half);
  1461. MoveAfterTrans();
  1462. }
  1463.  
  1464. TransOTSecondHalfWarmup()
  1465. {
  1466. RoundCounterOn = false;
  1467. ChangeMatchState(MS_Before_Overtime_Second_Half);
  1468. MoveAfterTrans();
  1469. }
  1470.  
  1471. public Action:ReduceToOneHundred(Handle:timer, any:userid)
  1472. {
  1473. new client = GetClientOfUserId(userid);
  1474. if(ValidClient(client) && ReadyUpState() && IsPlayerAlive(client))
  1475. {
  1476. if(GetClientHealth(client)>100)
  1477. {
  1478. SetEntityHealth(client, 100);
  1479. }
  1480. }
  1481. }
  1482.  
  1483. public Action:SpawnCallback(Handle:event, const String:name[], bool:dontBroadcast)
  1484. {
  1485. new userid = GetEventInt(event, "userid");
  1486. new client = GetClientOfUserId(userid);
  1487. if(!ValidClient(client) || IsSourceTV(client))
  1488. {
  1489. return Plugin_Continue;
  1490. }
  1491. if(ReadyUpState())
  1492. {
  1493. if(FirstSpawn[client])
  1494. {
  1495. FirstSpawn[client] = false;
  1496. PrintToChat(client, "[PUG] Welcome! Please /ready up and type /help if you need help.");
  1497. }
  1498. else if(!bReady[client])
  1499. {
  1500. PrintToChat(client, "[PUG] Type /ready in chat when you are ready.");
  1501. }
  1502. if(GetMoney(client)!=16000)
  1503. {
  1504. SetMoney(client, 16000);
  1505. }
  1506.  
  1507. if(!bReady[client] && IsFakeClient(client)) {
  1508. ReadyUp(client);
  1509. }
  1510.  
  1511. // Spawn protection.
  1512. SetEntityHealth(client, 500);
  1513. CreateTimer(2.0, ReduceToOneHundred, userid);
  1514. }
  1515. else
  1516. {
  1517. if(FirstSpawn[client])
  1518. {
  1519. PrintToChat(client, "[PUG] Welcome! Match is LIVE, type /help for help.");
  1520. FirstSpawn[client] = false;
  1521. }
  1522. }
  1523. return Plugin_Continue;
  1524. }
  1525.  
  1526. PrintDmgReport(client)
  1527. {
  1528. // Get current round.
  1529. new OurTeam = GetClientTeam(client);
  1530. for(new x=1;x<=MAXPLAYERS;x++)
  1531. {
  1532. if(ValidClient(x) && !IsSourceTV(x) && GetClientTeam(x)!=OurTeam)
  1533. {
  1534. new Handle:dmgRound = hMatchDamage[CurrentRound];
  1535. new dmgSize = GetArraySize(dmgRound);
  1536. new dmgTo = 0;
  1537. new dmgHits = 0;
  1538. new String:clName[24];
  1539. GetClientName(x, clName, 24);
  1540. for(new y=0;y<dmgSize;y++)
  1541. {
  1542. new String:Att[24];
  1543. new String:Vic[24];
  1544. new Handle:singleDmg = GetArrayCell(dmgRound, y);
  1545. GetArrayString(singleDmg, 0, Att, 24);
  1546. GetArrayString(singleDmg, 1, Vic, 24);
  1547. new dM = GetArrayCell(singleDmg, 2);
  1548. new IndAtt = ClientOfSteamId(Att);
  1549. new IndVic = ClientOfSteamId(Vic);
  1550. if(ValidClient(IndAtt) && ValidClient(IndVic) && IndAtt==client && IndVic==x)
  1551. {
  1552. dmgTo+=dM;
  1553. dmgHits++;
  1554. }
  1555. }
  1556. PrintToChat(client, "[PUG] %s - Damage Given: %d (%d hits)", clName, dmgTo, dmgHits);
  1557. }
  1558. }
  1559.  
  1560. }
  1561.  
  1562. LogDmg(Attacker, Victim, Dmg)
  1563. {
  1564. if(!MatchLive())
  1565. {
  1566. return;
  1567. }
  1568. if(CurrentRound<1)
  1569. {
  1570. return;
  1571. }
  1572. new String:AttackerSteam[24];
  1573. new String:VictimSteam[24];
  1574. GetClientAuthString(Attacker, AttackerSteam, 24);
  1575. GetClientAuthString(Victim, VictimSteam, 24);
  1576. // Create a new array.
  1577. new Handle:newArray = CreateArray(24);
  1578. PushArrayString(newArray, AttackerSteam);
  1579. PushArrayString(newArray, VictimSteam);
  1580. PushArrayCell(newArray, Dmg);
  1581. PushArrayCell(hMatchDamage[CurrentRound], newArray);
  1582. }
  1583.  
  1584. public Action:HurtCallback(Handle:event, const String:name[], bool:dontBroadcast)
  1585. {
  1586. // userid, attacker, dmg_health
  1587. new VictimUserid = GetEventInt(event, "userid");
  1588. new AttackerUserid = GetEventInt(event, "attacker");
  1589. new VictimIndex = GetClientOfUserId(VictimUserid);
  1590. new AttackerIndex = GetClientOfUserId(AttackerUserid);
  1591. new Dmg = GetEventInt(event, "dmg_health");
  1592. if(VictimIndex>0 && AttackerIndex>0 && ValidClient(VictimIndex) && ValidClient(AttackerIndex) && AttackerIndex!=VictimIndex)
  1593. {
  1594. LogDmg(AttackerIndex, VictimIndex, Dmg);
  1595. }
  1596. return Plugin_Continue;
  1597. }
  1598.  
  1599. SetMoney(client, money)
  1600. {
  1601. if(ValidClient(client) && !IsSourceTV(client))
  1602. {
  1603. SetEntData(client, OffsetAccount, money);
  1604. }
  1605. }
  1606.  
  1607. GetMoney(client)
  1608. {
  1609. if(ValidClient(client) && !IsSourceTV(client))
  1610. {
  1611. return GetEntData(client, OffsetAccount);
  1612. }
  1613. return 0;
  1614. }
  1615.  
  1616. #define CS_TEAM_T 2
  1617. #define CS_TEAM_CT 3
  1618. #define CS_TEAM_SPEC 1
  1619. #define CS_TEAM_AUTO 0
  1620.  
  1621. public Action:HookSpectate(client, const String:command[], argc)
  1622. {
  1623. PrintCenterText(client, "CSL: You can't join spectator.");
  1624. return Plugin_Handled;
  1625. }
  1626.  
  1627. OurAutojoin(client)
  1628. {
  1629. // Which team are we supposed to be on?
  1630. // Have the teams been setup yet?
  1631. if(TeamsSetup())
  1632. {
  1633. new MyTeam = CSLTeam(client);
  1634. if(MyTeam!=-1)
  1635. {
  1636. // Join the team we are on.
  1637. if(GetClientTeam(client)!=CSLToCSTeam(MyTeam))
  1638. {
  1639. CS_SwitchTeam(client, CSLToCSTeam(MyTeam));
  1640. }
  1641. }
  1642. else
  1643. {
  1644. // Find a team for us.
  1645. // What team has less active players?
  1646. new String:steamID[24];
  1647. GetClientAuthString(client, steamID, 24);
  1648. new APTeamA = TeamSizeActive(TEAM_A);
  1649. new APTeamB = TeamSizeActive(TEAM_B);
  1650. if(APTeamA<APTeamB)
  1651. {
  1652. // Team A
  1653. AddSteamToTeam(steamID, TEAM_A);
  1654. }
  1655. else if(APTeamB<APTeamA)
  1656. {
  1657. // Team B
  1658. AddSteamToTeam(steamID, TEAM_B);
  1659. }
  1660. else
  1661. {
  1662. // Random
  1663. new RandTeam = GetRandomInt(TEAM_A, TEAM_B);
  1664. AddSteamToTeam(steamID, RandTeam);
  1665. }
  1666. MyTeam = CSLTeam(client);
  1667. if(MyTeam!=-1)
  1668. {
  1669. // Join the team we are on.
  1670. if(GetClientTeam(client)!=CSLToCSTeam(MyTeam))
  1671. {
  1672. CS_SwitchTeam(client, CSLToCSTeam(MyTeam));
  1673. }
  1674. }
  1675. }
  1676. }
  1677. }
  1678.  
  1679. TryGoT(client)
  1680. {
  1681. if(TeamsSetup())
  1682. {
  1683. new MyTeam = CSLTeam(client);
  1684. if(MyTeam!=-1)
  1685. {
  1686. // Join the team we are on.
  1687. if(CSLToCSTeam(MyTeam)!=CS_TEAM_T)
  1688. {
  1689. PrintCenterText(client, "[PUG] You are on Team %s, they are currently Counter-Terrorist.", ((MyTeam==TEAM_A)?"A":"B"));
  1690. }
  1691. if(GetClientTeam(client)!=CSLToCSTeam(MyTeam))
  1692. {
  1693. CS_SwitchTeam(client, CSLToCSTeam(MyTeam));
  1694. }
  1695. }
  1696. else
  1697. {
  1698. // They clearly want to be a Terrorist, which team is T?
  1699. new TCSL = CSTeamToCSL(CS_TEAM_T);
  1700. new CTCSL = CSTeamToCSL(CS_TEAM_CT);
  1701. new ATCount = TeamSizeActive(TCSL);
  1702. new ACTCount = TeamSizeActive(CTCSL);
  1703. new String:steamID[24];
  1704. GetClientAuthString(client, steamID, 24);
  1705. if(ATCount <= ACTCount)
  1706. {
  1707. // Let them, and add them to the team.
  1708. AddSteamToTeam(steamID, TCSL);
  1709. if(GetClientTeam(client)!=CS_TEAM_T)
  1710. {
  1711. CS_SwitchTeam(client, CS_TEAM_T);
  1712. }
  1713. }
  1714. else
  1715. {
  1716. // They gotta go CT, add em and tell em the bad news :(
  1717. PrintCenterText(client, "CSL: Sorry, you have been forced to Team %s, the Counter-Terrorists.", ((CTCSL==TEAM_A)?"A":"B"));
  1718. AddSteamToTeam(steamID, CTCSL);
  1719. if(GetClientTeam(client)!=CS_TEAM_CT)
  1720. {
  1721. CS_SwitchTeam(client, CS_TEAM_CT);
  1722. }
  1723. }
  1724. }
  1725. }
  1726. }
  1727.  
  1728. CSLToCSTeam(cslTeam)
  1729. {
  1730. /*
  1731. MS_Before_First_Half, // This is only used if the map changes.
  1732. MS_Live_First_Half,
  1733. MS_Before_Second_Half, // Always used. Team A is CT B is T
  1734. MS_Live_Second_Half, // Team A is CT team B is T
  1735. MS_Before_Overtime_First_Half, // Team A is T, Team B is CT
  1736. MS_Live_Overtime_First_Half, // Team A is T, Team B is CT
  1737. MS_Before_Overtime_Second_Half, // Team A is CT, Team B is T
  1738. MS_Live_Overtime_Second_Half, // Team A is CT, Team B is T
  1739. */
  1740. // This might need an edit when captains come along?
  1741. if(gMatchState==MS_Live_First_Half)
  1742. {
  1743. if(cslTeam==TEAM_A)
  1744. {
  1745. return CS_TEAM_T;
  1746. }
  1747. else
  1748. {
  1749. return CS_TEAM_CT;
  1750. }
  1751. }
  1752. else if(gMatchState==MS_Before_Second_Half || gMatchState==MS_Live_Second_Half)
  1753. {
  1754. if(cslTeam==TEAM_A)
  1755. {
  1756. return CS_TEAM_CT;
  1757. }
  1758. else
  1759. {
  1760. return CS_TEAM_T;
  1761. }
  1762. }
  1763. else if(gMatchState==MS_Before_Overtime_First_Half || gMatchState==MS_Live_Overtime_First_Half)
  1764. {
  1765. if(cslTeam==TEAM_A)
  1766. {
  1767. return CS_TEAM_T;
  1768. }
  1769. else
  1770. {
  1771. return CS_TEAM_CT;
  1772. }
  1773. }
  1774. else if(gMatchState==MS_Before_Overtime_Second_Half || gMatchState==MS_Live_Overtime_Second_Half)
  1775. {
  1776. if(cslTeam==TEAM_A)
  1777. {
  1778. return CS_TEAM_CT;
  1779. }
  1780. else
  1781. {
  1782. return CS_TEAM_T;
  1783. }
  1784. }
  1785. else
  1786. {
  1787. return -1;
  1788. }
  1789. }
  1790.  
  1791. CSTeamToCSL(csTeam)
  1792. {
  1793. if(CSLToCSTeam(TEAM_A) == csTeam)
  1794. {
  1795. return TEAM_A;
  1796. }
  1797. else
  1798. {
  1799. return TEAM_B;
  1800. }
  1801. }
  1802.  
  1803. TryGoCT(client)
  1804. {
  1805. if(TeamsSetup())
  1806. {
  1807. new MyTeam = CSLTeam(client);
  1808. if(MyTeam!=-1)
  1809. {
  1810. // Join the team we are on.
  1811. if(CSLToCSTeam(MyTeam)!=CS_TEAM_CT)
  1812. {
  1813. PrintCenterText(client, "[PUG] You are on Team %s, they are currently Terrorist.", ((MyTeam==TEAM_A)?"A":"B"));
  1814. }
  1815. if(GetClientTeam(client)!=CSLToCSTeam(MyTeam))
  1816. {
  1817. CS_SwitchTeam(client, CSLToCSTeam(MyTeam));
  1818. }
  1819. }
  1820. else
  1821. {
  1822. // They clearly want to be a Counter-Terrorist, which team is CT?
  1823. new TCSL = CSTeamToCSL(CS_TEAM_T);
  1824. new CTCSL = CSTeamToCSL(CS_TEAM_CT);
  1825. new ATCount = TeamSizeActive(TCSL);
  1826. new ACTCount = TeamSizeActive(CTCSL);
  1827. new String:steamID[24];
  1828. GetClientAuthString(client, steamID, 24);
  1829. if(ACTCount <= ATCount)
  1830. {
  1831. // Let them, and add them to the team.
  1832. AddSteamToTeam(steamID, CTCSL);
  1833. if(GetClientTeam(client)!=CS_TEAM_CT)
  1834. {
  1835. CS_SwitchTeam(client, CS_TEAM_CT);
  1836. }
  1837. }
  1838. else
  1839. {
  1840. // They gotta go CT, add em and tell em the bad news :(
  1841. PrintCenterText(client, "CSL: Sorry, you have been forced to Team %s, the Terrorists.", ((TCSL==TEAM_A)?"A":"B"));
  1842. AddSteamToTeam(steamID, TCSL);
  1843. if(GetClientTeam(client)!=CS_TEAM_T)
  1844. {
  1845. CS_SwitchTeam(client, CS_TEAM_T);
  1846. }
  1847. }
  1848. }
  1849. }
  1850. }
  1851.  
  1852. public Action:HookJoinTeam(client, const String:command[], argc)
  1853. {
  1854. // Destined team
  1855. new String:firstParam[16];
  1856. GetCmdArg(1, firstParam, 16);
  1857. StripQuotes(firstParam);
  1858. new firstParamNumber = StringToInt(firstParam);
  1859. if(!ValidClient(client) || IsFakeClient(client) || IsSourceTV(client))
  1860. {
  1861. return Plugin_Continue;
  1862. }
  1863.  
  1864. if(firstParamNumber == CS_TEAM_SPEC)
  1865. {
  1866. // No.
  1867. PrintCenterText(client, "CSL: You can't join spectator.");
  1868. return Plugin_Handled;
  1869. }
  1870. else if(firstParamNumber == CS_TEAM_T)
  1871. {
  1872. if(TeamsSetup())
  1873. TryGoT(client);
  1874. else
  1875. return Plugin_Continue;
  1876. }
  1877. else if(firstParamNumber == CS_TEAM_CT)
  1878. {
  1879. if(TeamsSetup())
  1880. TryGoCT(client);
  1881. else
  1882. return Plugin_Continue;
  1883. }
  1884. else // Autojoin, our own version.
  1885. {
  1886. if(TeamsSetup())
  1887. OurAutojoin(client);
  1888. else
  1889. return Plugin_Continue;
  1890. }
  1891. return Plugin_Handled;
  1892. }
  1893.  
  1894. public Action:HookBuy(client, const String:command[], argc)
  1895. {
  1896. // Destined team
  1897. new String:firstParam[16];
  1898. GetCmdArg(1, firstParam, 16);
  1899. StripQuotes(firstParam);
  1900. if(ReadyUpState())
  1901. {
  1902. if(StrEqual(firstParam,"flashbang") || StrEqual(firstParam,"hegrenade") || StrEqual(firstParam,"smokegrenade"))
  1903. {
  1904. PrintCenterText(client, "CSL: No grenades during warm up.");
  1905. return Plugin_Handled;
  1906. }
  1907. }
  1908. return Plugin_Continue;
  1909. }
  1910.  
  1911. ClearMatch()
  1912. {
  1913. ServerCommand("tv_stoprecord\n"); // Leet, MIRITE?!
  1914. if(RestartTimers!=INVALID_HANDLE)
  1915. {
  1916. CloseHandle(RestartTimers);
  1917. }
  1918. RoundCounterOn = false;
  1919. ChangeMatchState(MS_Pre_Setup);
  1920. TeamAScore = 0;
  1921. TeamBScore = 0;
  1922. CurrentRound = 0;
  1923. Format(MatchMap, 32, "");
  1924. for(new x=0;x<MAX_ROUNDS;x++)
  1925. {
  1926. if(hMatchDamage[x]!=INVALID_HANDLE)
  1927. {
  1928. // How big is the array?
  1929. new s = GetArraySize(hMatchDamage[x]);
  1930. for(new y=0;y<s;y++)
  1931. {
  1932. new Handle:aAt = GetArrayCell(hMatchDamage[x], y);
  1933. CloseHandle(aAt);
  1934. }
  1935. CloseHandle(hMatchDamage[x]);
  1936. hMatchDamage[x] = INVALID_HANDLE;
  1937. }
  1938. if(hMatchKills[x]!=INVALID_HANDLE)
  1939. {
  1940. new s = GetArraySize(hMatchKills[x]);
  1941. for(new y=0;y<s;y++)
  1942. {
  1943. new Handle:aAt = GetArrayCell(hMatchKills[x], y);
  1944. CloseHandle(aAt);
  1945. }
  1946. CloseHandle(hMatchKills[x]);
  1947. hMatchKills[x] = INVALID_HANDLE;
  1948. }
  1949. }
  1950. Ruleset = Rules_PUG;
  1951. CaptainMode = false;
  1952. BunnyHopMode = false;
  1953. for(new x=0;x<TEAM_COUNT;x++)
  1954. {
  1955. Format(TeamPlayers[x][0], 24, "");
  1956. Format(TeamPlayers[x][1], 24, "");
  1957. Format(TeamPlayers[x][2], 24, "");
  1958. Format(TeamPlayers[x][3], 24, "");
  1959. Format(TeamPlayers[x][4], 24, "");
  1960. }
  1961. }
  1962.  
  1963. GetMapCount()
  1964. {
  1965. new mapCount = 0;
  1966. for(new x=0;x<MAX_MAPS;x++)
  1967. {
  1968. if(!StrEqual(MapNames[x],""))
  1969. {
  1970. mapCount++;
  1971. }
  1972. }
  1973. return mapCount;
  1974. }
  1975.  
  1976. AddToOurMaps(const String:mapName[])
  1977. {
  1978. for(new x=0;x<MAX_MAPS;x++)
  1979. {
  1980. if(StrEqual(MapNames[x],""))
  1981. {
  1982. Format(MapNames[x], 32, mapName);
  1983. break;
  1984. }
  1985. }
  1986. }
  1987.  
  1988. LoadMapsDir()
  1989. {
  1990. // Build path and look for .bsp files.
  1991. new String:mapsDir[1024];
  1992. BuildPath(Path_SM, mapsDir, 1024, "../../maps/");
  1993. new String:path[1024];
  1994. new Handle:dir = OpenDirectory(mapsDir);
  1995. new FileType:type;
  1996. while(ReadDirEntry(dir, path, sizeof(path), type))
  1997. {
  1998. if(type == FileType_File && StrContains(path, ".bsp") != -1)
  1999. {
  2000. // How many dots in the path?
  2001. new len = strlen(path);
  2002. new periods = 0;
  2003. for(new x=0;x<len;x++)
  2004. {
  2005. if(path[x]=='.')
  2006. {
  2007. periods++;
  2008. }
  2009. }
  2010. if(periods==1)
  2011. {
  2012. ReplaceString(path, 1024, ".bsp", "", false);
  2013. AddToOurMaps(path);
  2014. }
  2015. }
  2016. }
  2017. CloseHandle(dir);
  2018. }
  2019.  
  2020. GoPostgame(winning_team, bool:forfeit = false)
  2021. {
  2022. RoundCounterOn = false;
  2023. // Send stats?
  2024. ChangeMatchState(MS_Post_Match);
  2025.  
  2026. // TODO
  2027. new bool:tie=(winning_team==-1)?true:false;
  2028. if(tie)
  2029. {
  2030. forfeit = false; // Just incase?
  2031. }
  2032.  
  2033. // Show everyone their stats page.
  2034.  
  2035. ClearMatch();
  2036. }
  2037.  
  2038. MatchWinForfeit(winning_team)
  2039. {
  2040. PrintToChatAll("[PUG] %s wins due to forfeit", (winning_team==TEAM_A)?"Team A":"Team B");
  2041. GoPostgame(winning_team, true);
  2042. }
  2043.  
  2044. MatchWin(winning_team)
  2045. {
  2046. // Was the winning_team T or CT?
  2047. new WinningScore = (winning_team==TEAM_A)?TeamAScore:TeamBScore;
  2048. new LosingScore = (winning_team==TEAM_A)?TeamBScore:TeamAScore;
  2049. PrintToChatAll("[PUG] Match is over, %s wins the match %d - %d",(winning_team==TEAM_A)?"Team A":"Team B", WinningScore, LosingScore);
  2050.  
  2051. GoPostgame(winning_team);
  2052. }
  2053.  
  2054. MatchWinOT(winning_team)
  2055. {
  2056. // Was the winning_team T or CT?
  2057. new WinningScore = (winning_team==TEAM_A)?TeamAScore:TeamBScore;
  2058. new LosingScore = (winning_team==TEAM_A)?TeamBScore:TeamAScore;
  2059. PrintToChatAll("[PUG] Overtime is over, %s wins the match %d - %d",(winning_team==TEAM_A)?"Team A":"Team B", WinningScore, LosingScore);
  2060.  
  2061. GoPostgame(winning_team);
  2062. }
  2063.  
  2064. MatchTieOT()
  2065. {
  2066. PrintToChatAll("[PUG] Match ends in a tie, %d - %d", TeamAScore, TeamBScore);
  2067. GoPostgame(-1);
  2068. }
  2069.  
  2070. DeleteBomb()
  2071. {
  2072. for (new i = 1; i <= MaxClients; i++)
  2073. {
  2074. if (IsClientInGame(i) && IsPlayerAlive(i))
  2075. {
  2076. new iWeapon = GetPlayerWeaponSlot(i, 4);
  2077.  
  2078. if (iWeapon != -1 && IsValidEdict(iWeapon))
  2079. {
  2080. decl String:szClassName[64];
  2081. GetEdictClassname(iWeapon, szClassName, sizeof(szClassName));
  2082.  
  2083. if (StrEqual(szClassName, "weapon_c4"))
  2084. {
  2085. RemovePlayerItem(i, iWeapon);
  2086. RemoveEdict(iWeapon);
  2087. }
  2088. }
  2089. }
  2090. }
  2091.  
  2092. }
  2093.  
  2094. bool:IsPubChatMuted(client)
  2095. {
  2096. return bPubChatMuted[client];
  2097. }
  2098.  
  2099. bool:IsTeamChatMuted(client)
  2100. {
  2101. return bTeamChatMuted[client];
  2102. }
  2103.  
  2104. bool:IsPlayerMuted(client, player)
  2105. {
  2106. return bMuted[client][player];
  2107. }
  2108.  
  2109. TryTranslatePlace(const String:input[], String:output[], maxlen)
  2110. {
  2111. new bool:bOtherCheck = false;
  2112. if(StrEqual(input, "CTSpawn"))
  2113. {
  2114. Format(output, maxlen, "CT Spawn");
  2115. }
  2116. else if(StrEqual(input, "TSpawn"))
  2117. {
  2118. Format(output, maxlen, "T Spawn")
  2119. }
  2120. else
  2121. {
  2122. bOtherCheck = true;
  2123. }
  2124. if(!bOtherCheck)
  2125. {
  2126. return;
  2127. }
  2128. new len=strlen(input);
  2129. // Clear the output.
  2130. Format(output, maxlen, "");
  2131. new bool:bPrevHadSpace = true;
  2132. new bool:bPrevWasIndi = true;
  2133. for(new x=0;x<len;x++)
  2134. {
  2135. if(input[x]==' ')
  2136. {
  2137. bPrevWasIndi = false;
  2138. if(bPrevHadSpace)
  2139. {
  2140. bPrevHadSpace = false;
  2141. }
  2142. else
  2143. {
  2144. Format(output, maxlen, "%s ", output);
  2145. bPrevHadSpace = true;
  2146. }
  2147. }
  2148. else if( (input[x]>='A' && input[x]<='Z') || (input[x]>='1' && input[x]<='9'))
  2149. {
  2150. if(bPrevWasIndi)
  2151. {
  2152. Format(output, maxlen, "%s%c", output, input[x]);
  2153. bPrevHadSpace = false;
  2154. }
  2155. else
  2156. {
  2157. if(bPrevHadSpace)
  2158. {
  2159. Format(output, maxlen, "%s%c", output, input[x]);
  2160. bPrevHadSpace = false;
  2161. }
  2162. else
  2163. {
  2164. Format(output, maxlen, "%s %c", output, input[x]);
  2165. bPrevHadSpace = true;
  2166. }
  2167. }
  2168. bPrevWasIndi = true;
  2169. }
  2170. else
  2171. {
  2172. bPrevWasIndi = false;
  2173. if(bPrevHadSpace)
  2174. {
  2175. bPrevHadSpace = false;
  2176. }
  2177. Format(output, maxlen, "%s%c", output, input[x]);
  2178. }
  2179. }
  2180. }
  2181.  
  2182. ChatMsg(client, bool:team, const String:chatMsg[])
  2183. {
  2184. if(!ValidClient(client))
  2185. {
  2186. return;
  2187. }
  2188. new cTeam = GetClientTeam(client);
  2189. if(cTeam<CS_TEAM_T || cTeam>CS_TEAM_CT)
  2190. {
  2191. return;
  2192. }
  2193. new String:cTeamName[32];
  2194. if(cTeam == CS_TEAM_T)
  2195. {
  2196. Format(cTeamName, 32, "Terrorist");
  2197. }
  2198. else
  2199. {
  2200. Format(cTeamName, 32, "Counter-Terrorist");
  2201. }
  2202. new bool:bAlive = IsPlayerAlive(client);
  2203. new String:fullChat[250];
  2204. new String:sPlaceName[64];
  2205. new String:sNewPlaceName[64];
  2206. new String:plName[64];
  2207. GetClientName(client, plName, 64);
  2208. GetEntPropString(client, Prop_Data, "m_szLastPlaceName", sPlaceName, 64);
  2209. TryTranslatePlace(sPlaceName, sNewPlaceName, 64);
  2210. if(bAlive)
  2211. {
  2212. if(team)
  2213. {
  2214. if(StrEqual(sNewPlaceName, ""))
  2215. {
  2216. Format(fullChat, 250, "\x01(%s) \x03%s\x01 : %s", cTeamName, plName, chatMsg);
  2217. }
  2218. else
  2219. {
  2220. Format(fullChat, 250, "\x01(%s) \x03%s\x01 @ \x04%s\x01 : %s", cTeamName, plName, sNewPlaceName, chatMsg);
  2221. }
  2222. }
  2223. else
  2224. {
  2225. Format(fullChat, 250, "\x03%s\x01 : %s", plName, chatMsg);
  2226. }
  2227. }
  2228. else
  2229. {
  2230. if(team)
  2231. {
  2232. Format(fullChat, 250, "\x01*DEAD*(%s) \x03%s\x01 : %s", cTeamName, plName, chatMsg);
  2233. }
  2234. else
  2235. {
  2236. Format(fullChat, 250, "\x01*DEAD* \x03%s\x01 : %s", plName, chatMsg);
  2237. }
  2238. }
  2239.  
  2240. // Console friendly.
  2241. // But first clean it up a bit ;]
  2242. new String:fullChatClean[250];
  2243. Format(fullChatClean, 250, "%s", fullChat);
  2244. ReplaceString(fullChatClean, 250, "\x01", "");
  2245. ReplaceString(fullChatClean, 250, "\x02", "");
  2246. ReplaceString(fullChatClean, 250, "\x03", "");
  2247. ReplaceString(fullChatClean, 250, "\x04", "");
  2248. PrintToServer("%s", fullChatClean);
  2249.  
  2250. for(new x=1;x<=MAXPLAYERS;x++)
  2251. {
  2252. if(!ValidClient(x) || IsFakeClient(x))
  2253. {
  2254. continue;
  2255. }
  2256. new bool:bForMe = true;
  2257. if(team && GetClientTeam(x) != cTeam)
  2258. {
  2259. bForMe = false;
  2260. }
  2261. if(!bAlive)
  2262. {
  2263. if(IsPlayerAlive(x))
  2264. {
  2265. bForMe = false;
  2266. }
  2267. }
  2268. if(IsPlayerMuted(x, client))
  2269. {
  2270. bForMe = false;
  2271. }
  2272. if(team && IsTeamChatMuted(x))
  2273. {
  2274. bForMe = false;
  2275. }
  2276. if(!team && IsPubChatMuted(x))
  2277. {
  2278. bForMe = false;
  2279. }
  2280. if(bForMe)
  2281. {
  2282. new Handle:hBuffer = StartMessageOne("SayText2", x);
  2283. BfWriteByte(hBuffer, client);
  2284. BfWriteByte(hBuffer, true);
  2285. BfWriteString(hBuffer, fullChat);
  2286. EndMessage();
  2287. }
  2288. }
  2289. }
  2290.  
  2291. public OnPluginStart()
  2292. {
  2293. ServerCommand("exec server_pug.cfg\n");
  2294. OffsetAccount = FindSendPropOffs("CCSPlayer", "m_iAccount");
  2295. hMaxPlayers = CreateConVar("sv_maxplayers", MAX_PLAYERS_DEFAULT, "Match size.", FCVAR_PLUGIN|FCVAR_REPLICATED|FCVAR_SPONLY|FCVAR_NOTIFY);
  2296. CreateConVar("sm_pug_version", "0.1", "PUG Plugin Version",FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
  2297. hTVEnabled = FindConVar("tv_enable");
  2298. hBotQuota = FindConVar("bot_quota");
  2299. SetConVarInt(hBotQuota, 0);
  2300.  
  2301. //SetConVarInt(hTVEnabled, 1);
  2302. ClearMatch();
  2303. new Handle:hTagsCvar = FindConVar("sv_tags");
  2304. new oldFlags = GetConVarFlags(hTagsCvar);
  2305. new newFlags = oldFlags;
  2306. newFlags &= ~FCVAR_NOTIFY;
  2307. SetConVarFlags(hTagsCvar, newFlags);
  2308. //new Handle:hTVName = FindConVar("tv_name");
  2309. //SetConVarString(hTVName, "CSL SourceTV");
  2310. //new Handle:hTVTrans = FindConVar("tv_transmitall");
  2311. CreateTimer(4.0, WarmUpSpawner, _, TIMER_REPEAT);
  2312. //SetConVarInt(hTVTrans, 1);
  2313. LoadMapsDir();
  2314. HookEvent("player_spawn",SpawnCallback);
  2315. HookEvent("player_death",DeathCallback);
  2316. HookEvent("player_hurt",HurtCallback);
  2317. HookEvent("round_start",RoundStartCallback);
  2318. HookEvent("round_end",RoundEndCallback);
  2319. AddCommandListener(HookJoinTeam, "jointeam");
  2320. AddCommandListener(HookSpectate, "spectate");
  2321. AddCommandListener(HookBuy, "buy");
  2322. for(new x=0;x<MAXPLAYERS+1;x++) //[0-64]
  2323. {
  2324. ClientDefaults(x);
  2325. }
  2326. // Hooks
  2327. RegConsoleCmd("say",SayPubHook);
  2328. RegConsoleCmd("say_team",SayTeamHook);
  2329. CreateTimer(1.0, OneSecCheck, _, TIMER_REPEAT);
  2330. }
  2331.  
  2332. enum ConnAction
  2333. {
  2334. ConnAction_Connect_NonMember = 0,
  2335. ConnAction_Connect_Member,
  2336. ConnAction_Disconnect,
  2337. };
  2338.  
  2339. bool:MatchLive()
  2340. {
  2341. if(gMatchState == MS_Live_First_Half || gMatchState == MS_Live_Second_Half || gMatchState == MS_Live_Overtime_First_Half || gMatchState == MS_Live_Overtime_Second_Half)
  2342. {
  2343. return true;
  2344. }
  2345. return false;
  2346. }
  2347.  
  2348. public T_NoCallback(Handle:owner,Handle:hndl,const String:error[],any:data)
  2349. {
  2350. // pst... it's quiet... too quiet? maybe log errors?
  2351. }
  2352.  
  2353. public StatsCallback(Handle:owner,Handle:hndl,const String:error[],any:data)
  2354. {
  2355. new client=GetClientOfUserId(data);
  2356. if(!ValidClient(client))
  2357. {
  2358. return;
  2359. }
  2360. if(hndl!=INVALID_HANDLE)
  2361. {
  2362. SQL_Rewind(hndl);
  2363. if(!SQL_FetchRow(hndl))
  2364. {
  2365. PrintToChat(client, "[PUG] Sorry, username doesn't exist.");
  2366. }
  2367. else
  2368. {
  2369. new steamid;
  2370. SQL_FieldNameToNum(hndl, "steamid", steamid);
  2371. new String:steam[24];
  2372. SQL_FetchString(hndl, steamid, steam, 24);
  2373. new String:fullURL[192];
  2374. Format(fullURL, 192, "http://thecsleague.com/stats.php?steam=%s", steam);
  2375. ShowMOTDPanel(client, "Stats", fullURL, MOTDPANEL_TYPE_URL);
  2376. }
  2377. }
  2378. }
  2379.  
  2380. StartAuth(client)
  2381. {
  2382. if(!ValidClient(client) || IsSourceTV(client))
  2383. {
  2384. return;
  2385. }
  2386. if(!AllowBots() && IsFakeClient(client))
  2387. {
  2388. Kick(client,"No bots!"); // No bots stupid.
  2389. return;
  2390. }
  2391. notReadyTime[client] = GetTime();
  2392. // Make sure they are a customer.
  2393. decl String:steamID[24];
  2394. GetClientAuthString(client, steamID, 24);
  2395. if(BadSteamId(steamID))
  2396. {
  2397. Kick(client,"Your STEAMID isn't valid.");
  2398. return;
  2399. }
  2400.  
  2401. notReadyTime[client] = GetTime();
  2402. // Is the match already live? If it is put this person on a team etc...
  2403. // TODO: This will need to be changed once we have a captain mode.
  2404. if(TeamsSetup())
  2405. {
  2406. OurAutojoin(client);
  2407. }
  2408. }
  2409.  
  2410. bool:IsSourceTV(client)
  2411. {
  2412. if(!ValidClient(client))
  2413. return false;
  2414. decl String:plName[64];
  2415. GetClientName(client, plName, 64);
  2416. if(IsFakeClient(client) && ( StrEqual(plName,"SourceTV") || StrEqual(plName,"CSL SourceTV") ))
  2417. {
  2418. return true;
  2419. }
  2420. return false;
  2421. }
  2422.  
  2423. public OnClientPutInServer(client)
  2424. {
  2425. ClientDefaults(client);
  2426. if(IsSourceTV(client))
  2427. return; // Don't auth the SourceTV dude! :P
  2428. new cCount = GetClientCount();
  2429. if(GetConVarInt(hTVEnabled)==1)
  2430. cCount -= 1;
  2431. if(cCount>GetConVarInt(hMaxPlayers))
  2432. {
  2433. Kick(client, "Sorry, this match is full");
  2434. return;
  2435. }
  2436. StartAuth(client);
  2437. }
  2438.  
  2439. ClientOfSteamId(const String:steamID[])
  2440. {
  2441. for(new x=1;x<=MAXPLAYERS;x++)
  2442. {
  2443. if(ValidClient(x) && !IsSourceTV(x))
  2444. {
  2445. new String:mySteam[24];
  2446. GetClientAuthString(x, mySteam, 24);
  2447. if(StrEqual(steamID, mySteam))
  2448. {
  2449. return x;
  2450. }
  2451. }
  2452. }
  2453. return 0;
  2454. }
  2455.  
  2456. TeamOfSteamId(const String:steamID[])
  2457. {
  2458. // Return of -1 indicates none yet.
  2459. for(new x=0;x<TEAM_COUNT;x++)
  2460. {
  2461. for(new y=0;y<5;y++)
  2462. {
  2463. if(StrEqual(steamID, TeamPlayers[x][y]))
  2464. {
  2465. return x;
  2466. }
  2467. }
  2468. }
  2469. return -1;
  2470. }
  2471.  
  2472. public OnClientDisconnect(client)
  2473. {
  2474. bDisconnecting[client] = true;
  2475.  
  2476. new bool:specialCase = false;
  2477.  
  2478. if(IsFakeClient(client) && !IsSourceTV(client)) {
  2479. specialCase = true;
  2480. }
  2481.  
  2482. if(IsSourceTV(client))
  2483. return;
  2484.  
  2485. if(MatchLive())
  2486. {
  2487. new String:steamID[24];
  2488. GetClientAuthString(client, steamID, 24);
  2489. new TeamAB = TeamOfSteamId(steamID);
  2490. if(TeamAB==-1)
  2491. {
  2492. return; // They we're on a team yet.
  2493. }
  2494. // Is anyone else on their team still there? If not, the match has been forfeited.
  2495. new bool:AnyOnline = false;
  2496. for(new x=0;x<5;x++)
  2497. {
  2498. new cOfSteam = ClientOfSteamId(TeamPlayers[TeamAB][x]);
  2499. if(ValidClient(cOfSteam) && client!=cOfSteam)
  2500. {
  2501. AnyOnline = true;
  2502. }
  2503. }
  2504. if(!AnyOnline && !specialCase)
  2505. {
  2506. MatchWinForfeit( (TeamAB==TEAM_A) ? TEAM_B : TEAM_A );
  2507. }
  2508. }
  2509. /*else
  2510. {
  2511. // TODO: If we are picking teams?
  2512. }*/
  2513. }
  2514.  
  2515. public OnMapStart()
  2516. {
  2517. ServerCommand("mp_do_warmup_period 0");
  2518. ServerCommand("mp_maxrounds 0");
  2519. ServerCommand("bot_quota 0");
  2520. ServerCommand("bot_kick");
  2521. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement