Advertisement
HR_Shaft

Team Balance Plus v1.1 for SAPP

Jul 23rd, 2016
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.34 KB | None | 0 0
  1. -- Team Balance Plus v1.1  by H® Shaft  7/23/2016 -- corrected 2 logical errors which affected delays
  2. -- a variant version of 002's team balancer with new and re-witten functions, and modified
  3.  
  4. -- When teams have been unbalanced for 5 seconds, it will warn players that teams are unbalanced, then
  5. -- the next player to die on the bigger team will change teams, OR
  6. -- if no player switches or dies and the auto balance timer (editable time) expires, randomly selected members of bigger team will be switched, OR
  7. -- If players manually switch teams - via the lobby, they will not get a death, and will respawn instantly, OR
  8. -- If players volunteer to switch by typing "switch", they will not get a death, and will respawn instantly - AND keep their score, OR
  9. -- the next player on the bigger team who kills a smaller team member will change teams, OR
  10. -- the next player to suicide or betray will switch teams, but they keep their score, OR
  11.  
  12. -- when the following commands are used:
  13. -- type "switch" allow players to volunteer to switch teams (if they are on the bigger team) [any player]
  14. -- type "balance" to balance teams immediately [admin only]
  15. -- type "swap" to swap current admin with random player on opposite team [admin only]
  16. -- type "shuffle" to shuffle teams games (is not automatic) [admin only]
  17.  
  18. -- * re-wrote switch for betrayals and suicide (sometimes caused server exception), and added additional functions
  19. -- incorporated a portion of shuffler script written by 002
  20.  
  21. -- === NOTE === gametypes should have >> Team Play Options >> Auto Team Balance set to YES for best results - (but is not required)
  22.  
  23. -- Player switched message
  24. -- Variables: $PLAYER for the player, $TEAM for destination team
  25. PLAYER_SWITCHED = "$PLAYER switched to the $TEAM team!"
  26.  
  27. -- Number of seconds before teams will be auto-balanced if teams are still uneven after message a and b have been displayed
  28. AUTO_BAL_DELAY = 60
  29.  
  30. -- Number of seconds for the teams to be unbalanced to display message A then wait til AUTO_BAL_DELAY time expires, then show B.
  31. TEAMS_ARE_UNBALANCED_DELAY = 5
  32.  
  33. -- Teams are unbalanced message A - notification that teams are unbalanced
  34. -- Variables: $TEAM_SMALL = the name of the smaller team. $TEAM_BIG = the name of the bigger team.
  35. TEAMS_ARE_UNBALANCED_A = "Teams are Unbalanced: The next to die on $TEAM_BIG team will be switched to $TEAM_SMALL team."
  36.  
  37. -- Teams are unbalanced message B - notification when auto-balance will begin if teams are still unbalanced
  38. -- Variables: $TEAM_SMALL = the name of the smaller team. $TEAM_BIG = the name of the bigger team.
  39. TEAMS_ARE_UNBALANCED_B = "Random $TEAM_BIG team player selection begins in " .. TEAMS_ARE_UNBALANCED_DELAY .. " seconds."
  40.  
  41. -- End of configuration
  42. api_version = "1.8.0.0"
  43. delay = nil
  44. warning_a_shown = false
  45. warning_b_shown = false
  46. killed_by_nothing = {}
  47.  
  48.  
  49. function OnScriptLoad()
  50.     register_callback(cb['EVENT_TICK'],"OnTick")
  51.     register_callback(cb['EVENT_TEAM_SWITCH'],"OnTeamSwitch")
  52.     register_callback(cb['EVENT_DIE'],"OnPlayerDie")
  53.     register_callback(cb['EVENT_PRESPAWN'],"OnPlayerPreSpawn")
  54.     register_callback(cb['EVENT_CHAT'], "OnPlayerChat")
  55.     register_callback(cb['EVENT_GAME_START'],"OnNewGame")
  56.     register_callback(cb['EVENT_GAME_END'], "OnGameEnd")
  57.     if get_var(0, "$gt") ~= "n/a" then
  58.         game_started = true
  59.         team_play = getteamplay()
  60.         for i=1,16 do
  61.             if player_alive(i) then
  62.                 killed_by_nothing[i] = false
  63.             end
  64.         end    
  65.     end
  66. end
  67.  
  68. function OnScriptUnload()
  69.     killed_by_nothing = {}
  70.     switchplayertimer = nil
  71.     gametimer = nil
  72.     autobalancetimer = nil
  73.     manualbalancetimer = nil
  74.     balancenow = nil
  75. end
  76.  
  77. function OnNewGame()
  78.     gametimer = timer(5000, "GameTimer")
  79. end
  80.  
  81. function GameTimer()
  82.     game_started = true
  83.     team_play = getteamplay()
  84.     if team_play then
  85.         for i=1,16 do
  86.             if player_alive(i) then
  87.                 killed_by_nothing[i] = false
  88.             end
  89.         end
  90.     end
  91.     return false
  92. end
  93.  
  94. function AutoBalanceTimer()
  95.     if TeamsAreUneven() then
  96.         balancenow = timer(800, "BalanceNow")
  97.     end
  98.     return false
  99. end
  100.  
  101. function OnGameEnd()
  102.     game_started = false
  103.     gametimer = nil
  104.     team_play = getteamplay()
  105.     killed_by_nothing = {}
  106. end
  107.  
  108. function OnPlayerChat(PlayerIndex, Message)
  109.     local response = nil
  110.     if Message == nil then
  111.         return true
  112.     end
  113.     local Message = string.lower(Message)
  114.     if Message ~= nil then
  115.    
  116.         -- balance teams
  117.         if (Message == "balance") then
  118.             response = false
  119.             if team_play then
  120.                 if tonumber(get_var(PlayerIndex,"$lvl")) > 0 then
  121.                     if tonumber(get_var(0,"$pn")) >= 2 then
  122.                         manualbalancetimer = timer(500, "AutoBalanceTimer")
  123.                     else
  124.                         say(PlayerIndex, "**TEAM-BALANCE** You must have 2 or more players to balance the teams.")
  125.                     end
  126.                 else
  127.                     say(PlayerIndex, "**ADMIN ONLY** You are not an admin, thanks anyway.")
  128.                 end
  129.             else
  130.                 say(PlayerIndex, "**TEAM-BALANCE** This command is disabled during FFA games.")
  131.             end
  132.            
  133.         -- swap current admin with random player on opposite team  
  134.         elseif (Message == "swap") or (Message == "/swap") then
  135.             response = false
  136.             if team_play then
  137.                 if tonumber(get_var(PlayerIndex,"$lvl")) > 0 then
  138.                     local opp_team = get_var(PlayerIndex,"$oteam")
  139.                     local opp_team_count = nil
  140.                     local reds = tonumber(get_var(0,"$reds"))
  141.                     local blues = tonumber(get_var(0,"$blues"))
  142.                     if opp_team == "red" then
  143.                         opp_team_count = reds
  144.                     elseif opp_team == "blue" then
  145.                         opp_team_count = blues
  146.                     end
  147.                     if opp_team_count > 0 then
  148.                         execute_command("st rand" .. opp_team)
  149.                         switchplayertimer = timer(1500, "SwitchPlayer", PlayerIndex)
  150.                     else
  151.                         say(PlayerIndex, "**SWAP** No players to swap with on " .. opp_team .. " team.")
  152.                     end
  153.                 end
  154.             else
  155.                 say(PlayerIndex, "**SWAP** You can only use SWAP on team games.")
  156.             end
  157.            
  158.         elseif (Message == "shuffle") or (Message == "/shuffle") then
  159.             response = false
  160.             if team_play then
  161.                 if tonumber(get_var(0,"$pn")) >= 2 then
  162.                     say_all("... shuffling teams ...")
  163.                     ShuffleTeams()
  164.                 else   
  165.                     say(PlayerIndex, "**SHUFFLE** You can only use SHUFFLE with 2 or more players.")
  166.                 end    
  167.             else
  168.                 say(PlayerIndex, "**SHUFFLE** You can only use SHUFFLE on team games.")
  169.             end
  170.        
  171.         elseif (Message == "switch") or (Message == "/switch") then
  172.             response = false
  173.             if team_play then
  174.                 if TeamsAreUneven() then
  175.                     if warning_a_shown then
  176.                         local reds = tonumber(get_var(1,"$reds"))
  177.                         local blues = tonumber(get_var(1,"$blues"))
  178.                         local bigger_team = nil
  179.                         if (reds > blues + 1) then
  180.                             bigger_team = "red"
  181.                         elseif (blues > reds + 1) then
  182.                             bigger_team = "blue"
  183.                         end
  184.                         if (get_var(PlayerIndex,"$team") == bigger_team) then
  185.                             switchplayertimer = timer(50, "SwitchPlayer", PlayerIndex)
  186.                         else
  187.                             say(PlayerIndex, "**SWITCH** You are NOT on the bigger team, you cannot switch.")
  188.                         end
  189.                     else
  190.                         say(PlayerIndex, "**SWITCH** You cannot switch teams at this time, sorry.")
  191.                     end
  192.                 else
  193.                     say(PlayerIndex, "**SWITCH** You can only switch when teams are uneven.")
  194.                 end
  195.             else
  196.                 say(PlayerIndex, "**SWITCH** You can only switch during team games, when teams are uneven.")
  197.             end
  198.            
  199.         end
  200.        
  201.     end    
  202.     return response
  203. end
  204.  
  205. function SwitchPlayer(PlayerIndex)
  206.     if (player_present(PlayerIndex) == false) then return end
  207.     local opp_team = get_var(PlayerIndex,"$oteam")
  208.     execute_command("st me " ..opp_team, PlayerIndex)
  209.     say(PlayerIndex, "**TEAM-BALANCE** You were automatically team-switched!")
  210.     return false
  211. end
  212.  
  213. function BalanceNow()
  214.     local reds = tonumber(get_var(0,"$reds"))
  215.     local blues = tonumber(get_var(0,"$blues"))
  216.     local bigger_team = nil
  217.     while TeamsAreUneven() do
  218.         if (reds > blues + 1) then
  219.             bigger_team = "red"
  220.             teams_uneven = true
  221.             execute_command("st rand" .. bigger_team)
  222.         elseif (blues > reds + 1) then
  223.             bigger_team = "blue"
  224.             teams_uneven = true
  225.             execute_command("st rand" .. bigger_team)
  226.         end
  227.         if (reds == blues) or (reds == blues + 1) or (blues == reds + 1) then break end
  228.     end
  229.     teams_uneven = false
  230.     autobalancetimer = nil
  231.     manualbalancetimer = nil
  232.     return false   
  233. end
  234.  
  235. function TeamsAreUneven()
  236.     local red = tonumber(get_var(0,"$reds"))
  237.     local blue = tonumber(get_var(0,"$blues"))
  238.     if (red > blue + 1) or (blue > red + 1) then
  239.         return true
  240.     else
  241.         return false
  242.     end
  243. end
  244.  
  245. function getteamplay()
  246.     if get_var(0,"$ffa") == "0" then
  247.         return true
  248.     else
  249.         return false
  250.     end
  251. end
  252.  
  253. function OnTick()
  254.     if (team_play == true) then
  255.         local reds = tonumber(get_var(1,"$reds"))
  256.         local blues = tonumber(get_var(1,"$blues"))
  257.         local bigger_team = nil
  258.         local smaller_team = nil
  259.         if (reds > blues + 1) then
  260.             bigger_team = "red"
  261.             smaller_team = "blue"
  262.         elseif (blues > reds + 1) then
  263.             bigger_team = "blue"
  264.             smaller_team = "red"
  265.         else
  266.             delay = nil
  267.             warning_a_shown = false
  268.             warning_b_shown = false
  269.             return
  270.         end
  271.         if (delay == nil) then delay = os.clock() + TEAMS_ARE_UNBALANCED_DELAY end
  272.         if (os.clock() > delay and warning_a_shown == false) then
  273.             say_all(string.gsub(string.gsub(TEAMS_ARE_UNBALANCED_A,"$TEAM_BIG",string.upper(bigger_team)),"$TEAM_SMALL",smaller_team))
  274.             say_all(string.upper(bigger_team) .. " TEAM: Type \"SWITCH\" to voluntarily switch teams now AND keep your score.")
  275.             warning_a_shown = true
  276.             delay = os.clock() + AUTO_BAL_DELAY
  277.         elseif (os.clock() > delay and warning_b_shown == false) then
  278.             say_all(string.gsub(string.gsub(TEAMS_ARE_UNBALANCED_B,"$TEAM_BIG",string.upper(bigger_team)),"$TEAM_SMALL",smaller_team))
  279.             warning_b_shown = true
  280.             delay = os.clock() + TEAMS_ARE_UNBALANCED_DELAY
  281.         elseif (os.clock() > delay and warning_b_shown == true) then
  282.             autobalancetimer = timer(500, "AutoBalanceTimer")
  283.         end
  284.     end
  285. end
  286.  
  287. function OnTeamSwitch(PlayerIndex)
  288.     if (team_play == true) then
  289.         if (killed_by_nothing[PlayerIndex] == true) then
  290.             execute_command("deaths " .. PlayerIndex .. " -1")
  291.             write_dword(get_player(PlayerIndex) + 0x2C, 0)         
  292.             killed_by_nothing[PlayerIndex] = nil   
  293.         end        
  294.         say_all(string.gsub(string.gsub(PLAYER_SWITCHED,"$TEAM",get_var(PlayerIndex,"$team")),"$PLAYER",get_var(PlayerIndex,"$name")))
  295.     end
  296. end
  297.  
  298. function OnPlayerPreSpawn(PlayerIndex)
  299.     killed_by_nothing[PlayerIndex] = false
  300. end
  301.  
  302. function OnPlayerDie(PlayerIndex, KillerIndex)
  303.     if (team_play == true) then
  304.         if (tonumber(KillerIndex) == -1) and warning_a_shown then
  305.             killed_by_nothing[PlayerIndex] = true
  306.         end
  307.         -- determine if to proceed with balance checks
  308.         if (warning_b_shown == false) then return end
  309.         -- check team balances
  310.         local reds = tonumber(get_var(1,"$reds"))
  311.         local blues = tonumber(get_var(1,"$blues"))
  312.         local bigger_team = nil
  313.         local smaller_team = nil
  314.         -- if killer or victim is on the bigger team, switch them to smaller team
  315.         if (reds > blues + 1) then
  316.             bigger_team = "red"
  317.             smaller_team = "blue"
  318.             -- if killer is a player (not server, not fall damage, not killed by vehicle, not team change)
  319.             if (tonumber(KillerIndex) > 0) then
  320.                 -- betrayer on bigger team
  321.                 if get_var(PlayerIndex,"$team") == get_var(KillerIndex,"$team") then
  322.                     if (PlayerIndex ~= KillerIndex) then
  323.                         if (get_var(KillerIndex,"$team") == bigger_team) then
  324.                             if (player_present(KillerIndex) == true) then
  325.                                 switchplayertimer = timer(1500, "SwitchPlayer", KillerIndex)
  326.                             end
  327.                         end
  328.                     end    
  329.                 -- suicider on bigger team 
  330.                 elseif get_var(PlayerIndex,"$team") == get_var(KillerIndex,"$team") then
  331.                     if (PlayerIndex == KillerIndex) then
  332.                         if (get_var(KillerIndex,"$team") == bigger_team) then
  333.                             if (player_present(PlayerIndex) == true) then
  334.                                 switchplayertimer = timer(1500, "SwitchPlayer", PlayerIndex)
  335.                             end
  336.                         end
  337.                     end    
  338.                 -- smaller team kills a bigger team member, switch victim  
  339.                 elseif (get_var(KillerIndex,"$team") == smaller_team) and (get_var(PlayerIndex,"$team") == bigger_team) then
  340.                     if (player_present(PlayerIndex) == true) then
  341.                         switchplayertimer = timer(1500, "SwitchPlayer", PlayerIndex)
  342.                     end
  343.                 -- bigger team kills a smaller team member, switch killer      
  344.                 elseif (get_var(KillerIndex,"$team") == bigger_team) and (get_var(PlayerIndex,"$team") == smaller_team) then
  345.                     if (player_present(KillerIndex) == true) then
  346.                         switchplayertimer = timer(1500, "SwitchPlayer", KillerIndex)
  347.                     end                    
  348.                 end
  349.             end
  350.         elseif (blues > reds + 1) then
  351.             bigger_team = "blue"
  352.             smaller_team = "red"
  353.             -- if killer is a player (not server, not fall damage, not killed by vehicle, not team change)
  354.             if (tonumber(KillerIndex) > 0) then
  355.                 -- betrayer on bigger team
  356.                 if get_var(PlayerIndex,"$team") == get_var(KillerIndex,"$team") then
  357.                     if (PlayerIndex ~= KillerIndex) then
  358.                         if (get_var(KillerIndex,"$team") == bigger_team) then
  359.                             if (player_present(KillerIndex) == true) then
  360.                                 switchplayertimer = timer(1500, "SwitchPlayer", KillerIndex)
  361.                             end
  362.                         end
  363.                     end    
  364.                 -- suicider on bigger team 
  365.                 elseif get_var(PlayerIndex,"$team") == get_var(KillerIndex,"$team") then
  366.                     if (PlayerIndex == KillerIndex) then
  367.                         if (get_var(KillerIndex,"$team") == bigger_team) then
  368.                             if (player_present(PlayerIndex) == true) then
  369.                                 switchplayertimer = timer(1500, "SwitchPlayer", PlayerIndex)
  370.                             end
  371.                         end
  372.                     end    
  373.                 -- smaller team kills a bigger team member, switch victim  
  374.                 elseif (get_var(KillerIndex,"$team") == smaller_team) and (get_var(PlayerIndex,"$team") == bigger_team) then
  375.                     if (player_present(PlayerIndex) == true) then
  376.                         switchplayertimer = timer(1500, "SwitchPlayer", PlayerIndex)
  377.                     end
  378.                 -- bigger team kills a smaller team member, switch killer      
  379.                 elseif (get_var(KillerIndex,"$team") == bigger_team) and (get_var(PlayerIndex,"$team") == smaller_team) then
  380.                     if (player_present(KillerIndex) == true) then
  381.                         switchplayertimer = timer(1500, "SwitchPlayer", KillerIndex)
  382.                     end                    
  383.                 end
  384.             end
  385.         else
  386.             return
  387.         end
  388.     end
  389. end
  390.  
  391. function ShuffleTeams() -- written by 002
  392.     if(get_var(1,"$ffa") == "1") then return end
  393.     local players = {}
  394.     for i=1,16 do
  395.         if(player_present(i)) then
  396.             local player = get_player(i)
  397.             local old_value = read_word(player + 0xD4)
  398.             if(player_alive(i) == true) then
  399.                 write_word(player + 0xD4, 0xFFFF)
  400.                 kill(i)
  401.                 write_word(player + 0xD4, old_value)
  402.                 write_word(player + 0xAE, read_word(player + 0xAE) - 1)
  403.             end
  404.             players[table.getn(players) + 1] = i
  405.             write_dword(player + 0x2C, 0)
  406.             execute_command("st " .. i .. " red")
  407.         end
  408.     end
  409.     local players_count = table.getn(players)
  410.     while true do
  411.         local red = tonumber(get_var(1,"$reds"))
  412.         local blue = tonumber(get_var(1,"$blues"))
  413.         if (red > blue + 1) then
  414.             while true do
  415.                 local i = players[rand(1,players_count+1)]
  416.                 local player = get_player(i)
  417.                 if (read_word(player + 0x20) == 0) then
  418.                     execute_command("st " .. i .. " blue")
  419.                     break
  420.                 end
  421.             end
  422.         else
  423.             break
  424.         end
  425.     end
  426.     say_all("Teams have been shuffled.")
  427. end
  428.  
  429. function OnError(Message)
  430.     print(debug.traceback())
  431. end
  432.  
  433. -- Created by H® Shaft (Holy Phuckeroo! - this was a lot of work!)
  434. -- Visit http://halorace.org
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement