Advertisement
HR_Shaft

Team Balance Plus for Sapp

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