Advertisement
Guest User

l4d2_team_unscrambler.sp

a guest
Jan 15th, 2014
772
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 8.85 KB | None | 0 0
  1. #pragma semicolon 1
  2.  
  3. #define TEAM_SPECTATE 1
  4. #define TEAM_SURVIVORS 2
  5. #define TEAM_INFECTED 3
  6.  
  7. #define TEAM_A 0
  8. #define TEAM_B 1
  9.  
  10. #include <sourcemod>
  11. #include <sdktools>
  12.  
  13. // This plugin is rewrite of "L4D2 Score/Team Manager" by AtomicStryker (https://forums.alliedmods.net/showthread.php?p=1029519)
  14.  
  15. public Plugin:myinfo =
  16. {
  17.     name = "L4D2 Team Unscrambler",
  18.     author = "Quattros",
  19.     description = "Ignore team balancing and swap players to their teams.",
  20.     version = "0.3",
  21.     url = ""
  22. };
  23.  
  24. static Handle:g_hCVarSurvivorLimit = INVALID_HANDLE;
  25. static Handle:g_hCVarInfectedLimit = INVALID_HANDLE;
  26.  
  27. static Handle:g_hDesiredTeamPlacement = INVALID_HANDLE;
  28.  
  29. static g_iSurvivorLimit;
  30. static g_iInfectedLimit;
  31.  
  32. static g_iTeamPlacementTry[256];
  33. static g_iTeamPlacementAttempts[256];
  34.  
  35. static bool:g_bPendingTryTeamPlacement;
  36. static bool:g_bRoundSwitch;
  37.  
  38. public OnPluginStart()
  39. {
  40.     g_hCVarSurvivorLimit = FindConVar("survivor_limit");
  41.     g_hCVarInfectedLimit = FindConVar("z_max_player_zombies");
  42.  
  43.     g_iSurvivorLimit = GetConVarInt(g_hCVarSurvivorLimit);
  44.     g_iInfectedLimit = GetConVarInt(g_hCVarInfectedLimit);
  45.  
  46.     HookConVarChange(g_hCVarSurvivorLimit, CVarChangeSurvivorLimit);
  47.     HookConVarChange(g_hCVarInfectedLimit, CVarChangeInfectedLimit);
  48.  
  49.     g_hDesiredTeamPlacement = CreateTrie();
  50.  
  51.     HookEvent("round_start", EventRoundStart, EventHookMode_PostNoCopy);
  52.     HookEvent("round_end", EventRoundEnd, EventHookMode_PostNoCopy);
  53.     HookEvent("player_disconnect", EventPlayerDisconnect, EventHookMode_Post);
  54.     HookEvent("player_team", EventPlayerTeam, EventHookMode_Post);
  55. }
  56.  
  57. public OnPluginEnd()
  58. {
  59.     CloseHandle(g_hDesiredTeamPlacement);
  60. }
  61.  
  62. public CVarChangeSurvivorLimit(Handle:hCVar, const String:sOldValue[], const String:sNewValue[])
  63. {
  64.     g_iSurvivorLimit = StringToInt(sNewValue);
  65. }
  66.  
  67. public CVarChangeInfectedLimit(Handle:hCVar, const String:sOldValue[], const String:sNewValue[])
  68. {
  69.     g_iInfectedLimit = StringToInt(sNewValue);
  70. }
  71.  
  72. public EventRoundStart(Handle:hEvent, const String:sName[], bool:bDontBroadcast)
  73. {
  74.     g_bRoundSwitch = false;
  75. }
  76.  
  77. public EventRoundEnd(Handle:hEvent, const String:sName[], bool:bDontBroadcast)
  78. {
  79.     if (!g_bRoundSwitch && InSecondHalfOfRound())
  80.     {
  81.         CreateTimer(10.0, TimerCalculateTeamPlacement, _, TIMER_FLAG_NO_MAPCHANGE);
  82.     }
  83.  
  84.     g_bRoundSwitch = true;
  85. }
  86.  
  87. public EventPlayerDisconnect(Handle:hEvent, const String:sName[], bool:bDontBroadcast)
  88. {
  89.     if (!g_bRoundSwitch && !IsClientHuman(GetClientOfUserId(GetEventInt(hEvent, "userid"))))
  90.     {
  91.         TryTeamPlacementDelayed();
  92.     }
  93. }
  94.  
  95. public EventPlayerTeam(Handle:hEvent, const String:sName[], bool:bDontBroadcast)
  96. {
  97.     if (g_bRoundSwitch)
  98.     {
  99.         return;
  100.     }
  101.  
  102.     new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  103.  
  104.     if (iClient < 1 || iClient > MaxClients || IsFakeClient(iClient))
  105.     {
  106.         return;
  107.     }
  108.  
  109.     new iTeam;
  110.  
  111.     decl String:sAuthID[32];
  112.     GetClientAuthString(iClient, sAuthID, sizeof(sAuthID));
  113.  
  114.     if (GetTrieValue(g_hDesiredTeamPlacement, sAuthID, iTeam))
  115.     {
  116.         g_iTeamPlacementTry[iClient] = iTeam;
  117.  
  118.         RemoveFromTrie(g_hDesiredTeamPlacement, sAuthID);
  119.     }
  120.  
  121.     TryTeamPlacementDelayed();
  122. }
  123.  
  124. public Action:TimerCalculateTeamPlacement(Handle:hTimer)
  125. {
  126.     new iTeamScores[2];
  127.  
  128.     iTeamScores[TEAM_A] = GetVsCampaignScores(TEAM_A);
  129.     iTeamScores[TEAM_B] = GetVsCampaignScores(TEAM_B);
  130.  
  131.     new bool:bTeamsFlipped = AreTeamsFlipped();
  132.     new bool:bRevertTeams;
  133.  
  134.     if ((bTeamsFlipped && iTeamScores[TEAM_A] > iTeamScores[TEAM_B])
  135.     || (!bTeamsFlipped && iTeamScores[TEAM_A] < iTeamScores[TEAM_B]))
  136.     {
  137.         bRevertTeams = true;
  138.     }
  139.  
  140.     ClearTeamPlacement();
  141.  
  142.     new iDesiredTeam;
  143.     decl String:sAuthID[32];
  144.  
  145.     for (new i = 1; i <= MaxClients; i++)
  146.     {
  147.         if (IsClientInGame(i) && !IsFakeClient(i))
  148.         {
  149.             GetClientAuthString(i, sAuthID, sizeof(sAuthID));
  150.  
  151.             iDesiredTeam = GetClientTeamForNextMap(bRevertTeams, GetClientTeam(i));
  152.  
  153.             SetTrieValue(g_hDesiredTeamPlacement, sAuthID, iDesiredTeam);
  154.         }
  155.     }
  156. }
  157.  
  158. static GetClientTeamForNextMap(bool:bRevertTeams, iTeam)
  159. {
  160.     if (!bRevertTeams)
  161.     {
  162.         return iTeam;
  163.     }
  164.  
  165.     switch (iTeam)
  166.     {
  167.         case TEAM_SURVIVORS:
  168.         {
  169.             return TEAM_INFECTED;
  170.         }
  171.  
  172.         case TEAM_INFECTED:
  173.         {
  174.             return TEAM_SURVIVORS;
  175.         }
  176.     }
  177.  
  178.     return TEAM_SPECTATE;
  179. }
  180.  
  181. static TryTeamPlacementDelayed()
  182. {
  183.     if (!g_bPendingTryTeamPlacement)
  184.     {
  185.         CreateTimer(0.1, TimerTryTeamPlacement);
  186.  
  187.         g_bPendingTryTeamPlacement = true;
  188.     }
  189. }
  190.  
  191. public Action:TimerTryTeamPlacement(Handle:hTimer)
  192. {
  193.     TryTeamPlacement();
  194.  
  195.     g_bPendingTryTeamPlacement = false;
  196. }
  197.  
  198. static TryTeamPlacement()
  199. {
  200.     new iFreeSlots[4];
  201.  
  202.     iFreeSlots[TEAM_SPECTATE] = GetTeamMaxHumans(TEAM_SPECTATE);
  203.     iFreeSlots[TEAM_SURVIVORS] = GetTeamMaxHumans(TEAM_SURVIVORS);
  204.     iFreeSlots[TEAM_INFECTED] = GetTeamMaxHumans(TEAM_INFECTED);
  205.  
  206.     iFreeSlots[TEAM_SURVIVORS] -= GetTeamHumanCount(TEAM_SURVIVORS);
  207.     iFreeSlots[TEAM_INFECTED] -= GetTeamHumanCount(TEAM_INFECTED);
  208.  
  209.     for (new i = 1; i <= MaxClients; i++)
  210.     {
  211.         if (IsClientInGame(i) && !IsFakeClient(i))
  212.         {
  213.             new iTeam = g_iTeamPlacementTry[i];
  214.  
  215.             if (!iTeam)
  216.             {
  217.                 continue;
  218.             }
  219.  
  220.             new iOldTeam = GetClientTeam(i);
  221.  
  222.             if (iTeam == iOldTeam)
  223.             {
  224.                 g_iTeamPlacementTry[i] = 0;
  225.                 g_iTeamPlacementAttempts[i] = 0;
  226.             }
  227.             else if (iFreeSlots[iTeam] > 0)
  228.             {
  229.                 ChangePlayerTeamDelayed(i, iTeam);
  230.  
  231.                 iFreeSlots[iTeam]--;
  232.                 iFreeSlots[iOldTeam]++;
  233.             }
  234.             else
  235.             {
  236.                 if (g_iTeamPlacementAttempts[i] > 0)
  237.                 {
  238.                     if (GetClientTeam(i) != TEAM_SPECTATE)
  239.                     {
  240.                         g_iTeamPlacementTry[i] = 0;
  241.  
  242.                         g_iTeamPlacementAttempts[i] = 0;
  243.                     }
  244.                 }
  245.                 else
  246.                 {
  247.                     iFreeSlots[TEAM_SPECTATE]--;
  248.                     iFreeSlots[iOldTeam]++;
  249.  
  250.                     ChangePlayerTeamDelayed(i, TEAM_SPECTATE);
  251.  
  252.                     g_iTeamPlacementAttempts[i]++;
  253.                 }
  254.             }
  255.         }
  256.         else
  257.         {
  258.             if (!IsClientConnected(i) || IsFakeClient(i))
  259.             {
  260.                 g_iTeamPlacementTry[i] = 0;
  261.                 g_iTeamPlacementAttempts[i] = 0;
  262.             }
  263.         }
  264.     }
  265. }
  266.  
  267. static ChangePlayerTeamDelayed(iClient, iTeam)
  268. {
  269.     new Handle:hPack;
  270.  
  271.     CreateDataTimer(0.1, TimerChangePlayerTeam, hPack);
  272.  
  273.     WritePackCell(hPack, iClient);
  274.     WritePackCell(hPack, iTeam);
  275. }
  276.  
  277. public Action:TimerChangePlayerTeam(Handle:hTimer, Handle:hPack)
  278. {
  279.     ResetPack(hPack);
  280.  
  281.     new iClient = ReadPackCell(hPack);
  282.     new iTeam = ReadPackCell(hPack);
  283.  
  284.     if (IsClientHuman(iClient))
  285.     {
  286.         ChangePlayerTeam(iClient, iTeam);
  287.     }
  288. }
  289.  
  290. static bool:ChangePlayerTeam(iClient, iTeam)
  291. {
  292.     if (GetClientTeam(iClient) == iTeam)
  293.     {
  294.         return true;
  295.     }
  296.  
  297.     if (iTeam == TEAM_SPECTATE)
  298.     {
  299.         ChangeClientTeam(iClient, iTeam);
  300.  
  301.         return true;
  302.     }
  303.  
  304.     if (GetTeamHumanCount(iTeam) == GetTeamMaxHumans(iTeam))
  305.     {
  306.         return false;
  307.     }
  308.  
  309.     if (iTeam == TEAM_INFECTED)
  310.     {
  311.         ChangeClientTeam(iClient, iTeam);
  312.  
  313.         return true;
  314.     }
  315.  
  316.     new iBot = FindSurvivorBot();
  317.     new iFlags;
  318.  
  319.     if (iBot == -1)
  320.     {
  321.         ChangeClientTeam(iClient, _:iTeam);
  322.         iFlags = GetCommandFlags("respawn");
  323.         SetCommandFlags("respawn", iFlags & ~FCVAR_CHEAT);
  324.         FakeClientCommand(iClient, "respawn");
  325.         SetCommandFlags("respawn", iFlags);
  326.     }
  327.     else
  328.     {
  329.         iFlags = GetCommandFlags("sb_takecontrol");
  330.         SetCommandFlags("sb_takecontrol", iFlags & ~FCVAR_CHEAT);
  331.         FakeClientCommand(iClient, "sb_takecontrol");
  332.         SetCommandFlags("sb_takecontrol", iFlags);
  333.     }
  334.  
  335.     return true;
  336. }
  337.  
  338. static ClearTeamPlacement()
  339. {
  340.     for (new i = 1; i <= MaxClients; i++)
  341.     {
  342.         g_iTeamPlacementTry[i] = 0;
  343.         g_iTeamPlacementAttempts[i] = 0;
  344.     }
  345.  
  346.     ClearTrie(g_hDesiredTeamPlacement);
  347. }
  348.  
  349. stock bool:IsClientHuman(iClient)
  350. {
  351.     return bool:(iClient > 0 && iClient <= MaxClients && IsClientInGame(iClient) && !IsFakeClient(iClient));
  352. }
  353.  
  354. stock bool:InSecondHalfOfRound()
  355. {
  356.     return bool:GameRules_GetProp("m_bInSecondHalfOfRound");
  357. }
  358.  
  359. stock bool:AreTeamsFlipped()
  360. {
  361.     return bool:GameRules_GetProp("m_bAreTeamsFlipped");
  362. }
  363.  
  364. stock GetVsCampaignScores(iTeamNumber)
  365. {
  366.     return GameRules_GetProp("m_iCampaignScore", _, iTeamNumber);
  367. }
  368.  
  369. stock GetOppositeClientTeam(iClient)
  370. {
  371.     return OppositeCurrentTeam(GetClientTeam(iClient));
  372. }
  373.  
  374. stock OppositeCurrentTeam(iTeam)
  375. {
  376.     if (iTeam == TEAM_SPECTATE)
  377.     {
  378.         return TEAM_SPECTATE;
  379.     }
  380.     else if (iTeam == TEAM_SURVIVORS)
  381.     {
  382.         return TEAM_INFECTED;
  383.     }
  384.     else if (iTeam == TEAM_INFECTED)
  385.     {
  386.         return TEAM_SURVIVORS;
  387.     }
  388.  
  389.     return -1;
  390. }
  391.  
  392. stock GetTeamHumanCount(iTeam)
  393. {
  394.     new iHumans = 0;
  395.  
  396.     for (new i = 1; i <= MaxClients; i++)
  397.     {
  398.         if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) == iTeam)
  399.         {
  400.             iHumans++;
  401.         }
  402.     }
  403.  
  404.     return iHumans;
  405. }
  406.  
  407. stock GetTeamMaxHumans(iTeam)
  408. {
  409.     if (iTeam == TEAM_SURVIVORS)
  410.     {
  411.         return g_iSurvivorLimit;
  412.     }
  413.     else if (iTeam == TEAM_INFECTED)
  414.     {
  415.         return g_iInfectedLimit;
  416.     }
  417.     else if (iTeam == TEAM_SPECTATE)
  418.     {
  419.         return MaxClients;
  420.     }
  421.  
  422.     return -1;
  423. }
  424.  
  425. stock FindSurvivorBot()
  426. {
  427.     new iBot;
  428.  
  429.     for (iBot = 1; iBot <= MaxClients && (!IsClientInGame(iBot) || !IsFakeClient(iBot) || (GetClientTeam(iBot) != TEAM_SURVIVORS)); iBot++) { }
  430.  
  431.     return (iBot == MaxClients + 1) ? -1 : iBot;
  432. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement