
                       ==== AutoTeamBalance README ====



# Installation:

    Drop the AutoTeamBalance.u file and the AutoTeamBalance.int file in your UT
    server's System folder.  Optionally edit and drop AutoTeamBalance.ini also.

    Then do one of the following:

      * Add the following line to your server's UnrealTournament.ini, under the
        [Engine.GameEngine] section:

          ServerActors=AutoTeamBalance.AutoTeamBalance

      OR

      * Tell your server to use AutoTeamBalance as a mutator (for example,
        using WebAdmin, or on the startup command).

    Don't worry, if you manged to do both of the above, AutoTeamBalance should
    detect that it is running twice, and recover gracefully.

    [ Do not add it as a ServerPackage; there is no need, and it will only
    cause "Version mismatch" errors for your players if you upgrade to a newer
    version. ]

    You may also wish to increase your server's NetWait to 10 or 20 seconds.
    (This value can be found in the [Botpack.DeathMatchPlus] section.)
    Initial teambalance is more effective if all the players are on the server
    when the game starts.  Players who join after game-start (e.g. because they
    were downloading the map) cannot be balanced so well.

    You should also ensure your server waits at least 10 seconds after the end
    of each game, before switching map, otherwise AutoTeamBalance will not
    have time to update the stats.  This *might* be the RestartWait variable.

    I think, if your server has any bots, you should ensure that bBalanceTeams
    is set in your UnrealTournament.ini.  Since AutoTeamBalance does not affect
    the team placement of bots when they join, or when a player switches teams,
    this method should be enabled.  (AutoTeamBalance *will* change bots to
    different teams during *mid-game* balancing, if bBalanceBots is set.)



# What does it do?

AutoTeamBalance keeps a record of the skills of players on your server, and
uses the information to balance the teams at the beginning of each game. In
theory this should make games closer and fairer, or at the very least, better
than just randomly picked teams.

It actually performs team balancing with three different algorithms:

    1) At the beginning of the game (or when forced by a semi-admin), all
       players are balanced in a 1-2-2-2... pickup style
       [ForceFullTeamsRebalance].

    2) When a new player joins mid-game, he is assigned to the smaller team,
       or if both teams are the same size, the weaker team [ModifyLogin].

    3) When a player or admin requests [MidGameTeamBalance], either the
       1-player-switch or 2-player-switch rebalance algorithm will be called,
       depending on whether one team has more players or not.  This will
       attempt to make the strengths of the two teams as close as possible.

Usually one or two "!teams" rebalances should be sufficient to even the teams
if players have left the server mid-game.  But in unbalance emergencies,
semi-admins may also force a ForceFullTeamsRebalance mid-game, as in event 1,
but in this case players holding flags may get switched too!

AutoTeamBalance updates player stats shortly after the end of the game.
Players who leave before or immediately after the game ends will not have their
stats updated.  The default settings record the average of of each player's
score-and-frags, normalised relative to the other players on the server.
Since unknown players start with a score of 50, this will be the average
player strength.



# Commands available to players:

    Say "!teams" or "teams" to request MidGameTeamBalance.
    (Can be disabled by setting bLetPlayersRebalance to False in the config.)

    Say "!red" or "!blue" to get auto-switched to that team.

    Say "!spec" or "!play" to switch between spectator and player.

    Say "!vote" to bring up MapVote (BDB and derivatives).
    Say "!stats" to bring up SmartCTFStats.

    Type "mutate strengths" in the console, to see the strengths of current
    players on the server.



The Administrator and semi-admins can type the following commands in the
console.  (You may wish to change the admin password in the config file, so
that semi-admins need not know the full server admin pass.  You can also empty
the password entirely, so that any player who knows the commands can be a
semi-admin, without having to type the password every time, but this may be
subject to abuse.)

    mutate help

        Displays a quick reminder of all these commands.

    mutate teams [password]

        Will switch one player to the other team, or will swap two players.
        The same as saying "teams" when bLetPlayersRebalance is set in the
        config.  Refuses to balance again for MinSecondsBeforeRebalance.

    mutate forceteams [password]

        The same as the teambalance which occurs at the beginning of the game.
        May switch a lot of players, including players holding the flag!

    mutate tored <player_name> [password]

        Moves the player to the Red team.  Here, and below, <player_name> need
        only be a part of the player's nick.

    mutate toblue <player_name> [password]

        Moves the player to the Blue team.

    mutate switch <player_name> <other_player_name> [password]

        Swaps the two players (easier and neater than using tored then toblue).

    mutate warn <player_name> <warning_message> [password]

        Flashes the warning message on the player's screen, and shakes his/her
        view.  (You may like to try it on yourself first.)

    mutate kick <player_name> [<reason_message>] [password]

        Flashes the (optional) message on the player's screen, then kicks
        him/her from the server.

    mutate kickban <player_name> [<reason_message>] [password]

        Flashes the (optional) message on the player's screen, then kicks and
        bans him/her from the server.



The following commands are only available to the Server Admin when he is logged
in:

    mutate saveconfig

        Updates the stats and saves everthing to the config file.  Note: if the
        game ends after this then the this time period passed will be counted
        again!

    mutate grantadmin <player_name>

        You can let a trusted player fiddle with your server, without having to
        give him the admin pass.

    mutate get <package> <var_name>

        Will display the gameengine's current value of the config variable.

    mutate set <package> <var_name> <new_value>

        Will change, and then display, the gameengine's current value of the
        config variable.  This is just a little friendlier than admin set,
        because you get feedback on your change.

    mutate getprop <var_name>
    mutate setprop <var_name> <new_value>
    mutate console <command>

        Experimental commands; use at your own risk



The default config should be fine for most servers.  But you may wish to tweak
one or two values to your needs.  For example, bWarnMidGameUnbalance is
disabled by default because you might find it too annoying - you may want to
try enabling it.  Here's an explanation of all the config variables:

  bBroadcastStuff=True                      - Whether or not to broadcast information to players at game start, game end, and when rebalancing mid-game.
  bBroadcastCookies=False                   - When enabled, at the end of the game, every player's strength change will be broadcast, represented as earning or losing cookies.  For debugging, or for fun.
  bFlashCookies=False                       - When enabled, each player will see his number of cookies at the start of the game, and how many he gained or lost at the end of the game.  For debugging, or for fun.
  bDebugLogging=False                       - Enable this only if you need to debug AutoTeamBalance.
  bEnablePlayerCommands=True                - *NEW* Allows players to use !red !blue !spec !play !vote !stats (you might want to disable this if, for example, you are already using ASC to do this.)
  bForceEvenTeams=False                     - Automatically switches a player when one team has 2 players more than the other team.
  bLetPlayersRebalance=True                 - Allows players to fix teams mid-game by typing "teams" or "!teams".
  MinRequestsForRebalance=1                 - *NEW* Will not rebalance until this many players request it (unless teams differ by 2 or more players).  If you set this to 2 or more, you may wish to reduce MinSecondsBeforeRebalance to 1 (but do not set it to 0!).
  bFlashRebalanceRequest=True               - *NEW* Whether the "!teams" request is flashed to all players, or just shown in chat area.
  bShowProposedSwitch=False                 - *NEW* On "!teams" request, or mid-game inbalance warning, shows the proposed player(s) that could be switched, otherwise just shows the request.
  bWarnMidGameUnbalance=False               - Warns players if teams become uneven mid-game.
  bFlashOnWarning=True                      - The warning will flash across the HUD, instead of appearing in the chat area
  bShakeOnWarning=False                     - The warning will shake the screens of players on the stronger team
  bBuzzOnWarning=False                      - The warning will make the sound of buzzing flies for players on the stronger team
  bAllowSemiAdminKick=True                  - You can prevent semi-admins from kicking players by switching this off.
  bAllowSemiAdminForceTravel=True           - You can prevent semi-admins from forcing a server move by switching this off.
  bBalanceBots=False                        - Whether or not to balance bots as if they were humans (recommended off, since it might create 2v0 if bots are as strong as humans).
  bRankBots=False                           - Whether or not to record strengths for the bots (just for curiosity really).
  MinSecondsBeforeRebalance=20              - Prevents players from spamming "!teams"; should be at least 1, to avoid a bug with multiple calls to MutatorTeamMessage().
  SemiAdminPass=defaults_to_admin_pass      - Set this if you want semi-admins to use a different pass from the server admin pass.
  bAutoBalanceTeamsForCTF=True
  bAutoBalanceTeamsForTDM=True              - You can select which game-modes will be balanced, and which will not.
  bAutoBalanceTeamsForAS=True
  bAutoBalanceTeamsForOtherTeamGames=True
  bUpdatePlayerStatsForCTF=True             - BUG TODO:  Argh!  Won't this update scores from BT games too?!
  bUpdatePlayerStatsForTDM=True             - If you are normalising scores, then updating stats for TDM should be ok.  But if you are not normalising scores, then the different bonuses in CTF will make stats from the different gametypes incompatible.  (Basically TDMers will get lower strengths because they never get the bonus points from caps/covers/etc.)  So in this case you are recommended only to build stats for your server's most popular gametype.  Actually, now that we are using ScoringMethod 3, stats can be safely updated for all gametypes.
  bUpdatePlayerStatsForAS=True              - Now that the default scoring method is method 3, the huge AS bonuses are not a problem when updating player strengths.
  bUpdatePlayerStatsForOtherTeamGames=True  - This will record stats from JailBreak and Siege games, for example.
  bUpdatePlayerStatsForNonTeamGames=True    - DM scores are a good indication of a player's strength, even though it's not a team-game
  bLogExtraStats=False                      - records some extra player stats to the logfile at game-end, in case you are interested
  MaxHoursWhenCopyingOldRecord=2.0          - when a player changes nick or IP, his hours_played with the new nick or ip will be reduced to this, just in case it was a false-match, to minimise inaccurate stats for the new player
  HoursBeforeRecyclingStrength=4.0          - once a player has played for this long, his older scores start to fade away in favour of his more recent scores (to follow the strengths of players who get better or worse over time)
  MinHumansForStats=4                       - It's probably not healthy to update stats for 1v1 games, scores can be a little extreme
  ScoringMethod=2                           - How do we update the player's stats?  0=score, 1=frags, 2=average_frags_and_score, 3=0-100_ordered_ranking.  For CTF/TDM I recommend methods 0 or 2.  For Assault I recommend methods 2 or 3.
  bNormaliseScores=True                     - Normalises scores so that the average score for every game is 50, or whatever specified.  This is useful if scores from different games can be very different.  E.g. small spammy games get higher scores than large 2v2 games, and CTF has bonuses which you don't get in TDM.  You should only disable normalisation if your server has similar scores at the end of every game.
  bRelativeNormalisation=True               - During normalisation, the target average will be the average strength of the current players in the game.  So if you played against strong players, the strength you gain/lose will reflect this.  If False, will normalise around NormalisedStrength instead (old method).
  bScalePlayerScoreToFullTime=True          - Should be kept True to ensure that scores are comparable when some players have joined the game late.  Players strength records are still only updated relative to the time they spent playing.
  NormalisedStrength=50                     - This need not be changed.  When using bNormaliseScores, it will simply affect the size of the numbers recorded in the database.
  UnknownStrength=50                        - New players are assumed to have strength 50 (Should be the same as NormalisedStrength, or if bNormaliseScores=False, it should be the average endgame-score-per-20-minute-game of new players on your server.  Only used for a new players during their first game; forgotten immediately afterwards.  Once your server has established stats for regular players, you may wish to reduce this value for the "newbie" players who join, although it will also apply to regulars who have changed their nick and their IP address.
  BotStrength=10                            - Maybe 20 or 30 is better, if you disable normalisation, or your bots are strong.
  FlagStrength=10                           - Affects the strength of each team, according to how many caps they have made.  If it's 3:0, the leading team will appear to have an extra 3*FlagStrength = 30 points of strength.  This is used for balancing teams mid-game.  Now auto-adjusts for non-CTF gametypes.  20 is a reasonably strong setting, 0 of course has no effect.
  StrengthThreshold=100                     - If bWarnMidGameUnbalance=True and team strength difference is greater than this, then all players are warned of team inbalance.  (Some threshold was needed, otherwise any player which switched to the smaller team would just make it look unbalanced the other way, causing never-ending team-unbalance warning!  In theory this might still happen with players of highly different strengths, in which case increase the threshold, or disable bWarnMidGameUnbalance)
  WinningTeamBonus=0                        - Maybe you scored low, but played good teamplay, so your team won, and you deserve higher strength for that.  Recommended values: 0/5/10.
  bClanWar=False                            - For clan wars; on player login or game start, moves players to the appropriate team by their clan tag.
  clanTag=XOL                               - Clan tag of red team (all other players are sent to blue).
  bUseOnlyInGameScoresForRebalance=False    - Mid-game balancing usually looks up player records to see their strengths.  If you feel this causes lag on the server when a new player joins or during mid-game rebalancing, or you only want to balance using current game scores anyway (ignoring player records), then set this to True.
  bLogFakenickers=False                     - Write to log any players who had a previous record with a different nick or IP.
  bBroadcastFakenickers=False               - Broadcast to game any players who had a previous record with a different nick or IP.
  bSeparateStatsByGamemode=False            - *NEW* Builds separate stats in the database for different gametypes.  Only use this if your server has a *few* different gametypes, and they require significantly different skills.  The number of records in your database will be multiplied by the number of different modes your server has.
  bSeparateStatsByMutators=False            - *NEW* Builds separate stats in the database, according to which mutators are running (by adding a short mutator signature to each player's nick).  Could differentiate between instagib and normal weapons games, or games with/without the translocator.  Not recommended if you change mutators regularly, or have very many game modes with different mutators.
  MaxPlayerData=4096                        - *NEW* To avoid bugs related to the database being too large.  Do not set above the static limit 4096.  Reduce this value if you are getting problems.  (Records in the database beyond MaxPlayerData will be lost.)



# Known bugs:

  Well it hasn't been tested on BT games.  If the average score ends up below
  0, and score normalisation is enabled, then probably the players who died
  most will be given the highest strengths!  I recommend setting
  bNormaliseScores=False on BT servers.

  The mid-game teambalance warning can sometimes be a bit over-sensitive, e.g.
  in 2v1 situations.  If this happens too much, disable bWarnMidGameUnbalance,
  or increase the StrengthThreshold.

  I never got around to recording a player's last_time_played, which might be
  interesting info for admins, and also useful for recycling old player records
  when the database becomes full.



# Feedback:

  Please direct your feedback to the UnrealAdmin thread:
  http://www.unrealadmin.org/forums/showthread.php?t=23777

  If I get run over by a bus, I hope other coders can meet your requests for
  improvements there.



# Thanks to:

  XOL's Sourcerer, for the original mod which worked great on XOL, the
  initial code that got me started on UnrealScript, and feedback on earliest
  versions.
  iDeFiX, for holding my hand through my initial coding.
  Rork and _tAiger for testing.
  The author of TeamBallancer, because I lifted a tiny bit of his code.
  Adrian and Matt for some useful info in the Adwvaad thread.
  Debian GNU/Linux package maintainers, otherwise dammit I wouldn't have an OS
  to code on!
  And last but not least, my mum, for unleashing me upon you all.



Good luck and have fun, F0X|nogginBasher aka (-:SMo:-)c00ki3Mnstr.

