# autolimitteams.py
#
# Copyright (C) 2005 Guwashi <guwashi[AT]fooos[DOT]com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# Description:
#
#   Better autobalance script.
#
#
# Download:
#
#   http://d3.jpn.org/bf2/autolimitteams-1.1.0.zip
#
#
# Install:
#
#   - Copy autolimitteams.py to '{bf2}/Admin/standard_admin'
#     directory.
#
#   - Add the lines 'import autolimitteams' and 'autolimitteams.init()'
#     to the file '{bf2}/admin/standard_admin/__init__.py'.
#
#     ex.)
#       import autobalance
#       import tk_punish
#       import autolimitteams
#
#       autobalance.init()
#       tk_punish.init()
#       autolimitteams.init()
#
#   - Turn the default autobalance script off in server settings.
#
#
# Configuration:
#
#   - Is the autolimitteams enabled?
#
alt_enable = True
#
#   - What do you want to balance based on?
#     'player': number of players (default)
#     'ticket': number of tickets
#
alt_balanceMode = 'player'
#alt_balanceMode = 'ticket'
#
#   - Is team-balance enabled when player connected?
#
alt_enableOnPlayerConnect = True
#
#   - Is team-balance enabled when player changed teams?
#
alt_enableOnPlayerChangeTeams = True
#
#   - Is team-balance enabled when player died?
#
alt_enableOnPlayerDeath = True
#
#   - How many players(or tickets) do you allow to join an unequal team?
#     This is same as mp_limitteams in CS.
#
alt_limitTeams = 2
#
#   - Is the Commander protected from being switched?
#
alt_isProtectCommander = True
#
#   - Is the SquadLeader protected from being switched?
#
alt_isProtectSquadLeader = True
#
#   - Is the SquadMember protected from being switched?
#
alt_isProtectSquadMember = True
#
#   - Specify the team-ratio percent of each map.
#
alt_teamRatioPercentTable = {
    'kubra_dam'             : 100.0,
    'mashtuur_city'         : 100.0,
    'operation_clean_sweep' : 100.0,
    'zatar_wetlands'        : 100.0,
    'strike_at_karkand'     : 100.0,
    'sharqi_peninsula'      : 100.0,
    'gulf_of_oman'          : 100.0,
    'daqing_oilfields'      : 100.0,
    'dalian_plant'          : 100.0,
    'dragon_valley'         : 100.0,
    'fushe_pass'            : 100.0,
    'hingan_hills'          : 100.0,
    'songhua_stalemate'     : 100.0,
}
#
# etc.:
#
#   - The autolimitteams is licensed under the GPL. For details see
#     the COPYING file.
#
#
# Author:
#
#   Guwashi
#     - E-Mail
#       guwashi[AT]fooos[DOT]com
#     - Web
#       http://d3.jpn.org/
#     - Forums
#       not yet.
#
# ChangeLog:
#
#   - 1.1.0 2005/07/17
#     added alt_teamRatioPercentTable.
#   - 1.0.0 2005/07/16
#     first public release.


import sys
import string
import time
import bf2
import host
from bf2 import g_debug

AUTOLIMITTEAMS_VERSION = '1.1.0'

def init():
    global alt_enable
    if not alt_enable:
        return None
    printLog('initializing autolimitteams script')
    host.registerHandler('PlayerConnect', onPlayerConnect, 1)
    host.registerHandler('PlayerChangeTeams', onPlayerChangeTeams)
    host.registerHandler('PlayerDeath', onPlayerDeath)

def onPlayerConnect(player):
    global alt_enable, alt_enableOnPlayerConnect
    if bf2.serverSettings.getAutoBalanceTeam():
        return None
    if not alt_enable:
        return None
    if not alt_enableOnPlayerConnect:
        return None
    if player.isAlive():
        return None
    team1, team2 = getTeamStatus()
    recommendedTeam = getRecommendedTeam(team1, team2)
    if recommendedTeam:
        player.setTeam(recommendedTeam)

def onPlayerChangeTeams(player, humanHasSpawned):
    global alt_enable, alt_enableOnPlayerChangeTeams
    if bf2.serverSettings.getAutoBalanceTeam():
        return None
    if not alt_enable:
        return None
    if not alt_enableOnPlayerChangeTeams:
        return None
    team1, team2 = getTeamStatus()
    recommendedTeam = getRecommendedTeam(team1, team2)
    if recommendedTeam:
        player.setTeam(recommendedTeam)

def onPlayerDeath(player, soldier):
    global alt_enable, alt_enableOnPlayerDeath
    if bf2.serverSettings.getAutoBalanceTeam():
        return None
    if not alt_enable:
        return None
    if not alt_enableOnPlayerDeath:
        return None
    if player.getSuicide():
        player.setSuicide(0)
        return None
    team1, team2 = getTeamStatus()
    recommendedTeam = getRecommendedTeam(team1, team2)
    if recommendedTeam and (not isProtectMember(player)):
        player.setTeam(recommendedTeam)

def isProtectMember(player):
    '''Is this player protected from being switched?'''
    global alt_isProtectCommander, alt_isProtectSquadLeader, alt_isProtectSquadMember
    if alt_isProtectCommander and player.isCommander():
        return True
    if alt_isProtectSquadLeader and player.isSquadLeader():
        return True
    if alt_isProtectSquadMember and player.getSquadId():
        return True
    else:
        return False

def getRecommendedTeam(team1, team2):
    '''Get recommended team.'''
    global alt_limitTeams
    if abs(team1 - team2) <= alt_limitTeams:
        return 0
    elif team1 > team2:
        return 2
    else: # team1 <= team2
        return 1

def getTeamCount():
    '''Get team count.'''
    team1 = 0
    team2 = 0
    for player in bf2.playerManager.getPlayers():
        playersTeam = player.getTeam()
        if 1 == playersTeam:
            team1 += 1
        elif 2 == playersTeam:
            team2 += 1
        else:
            pass
    return team1, team2 * getTeamRatioPercent(bf2.serverSettings.getMapName()) / 100.0

def getTeamTicket():
    '''Get team tickets.'''
    return bf2.gameLogic.getTickets(1), bf2.gameLogic.getTickets(2)

def getTeamStatus():
    '''Get team status.'''
    global alt_balanceMode
    if 'ticket' == alt_balanceMode:
        return getTeamTicket()
    else: # 'player' == alt_balanceMode
        return getTeamCount()

def getTeamRatioPercent(mapName):
    '''Get team-ratio percent of each map.'''
    global alt_teamRatioPercentTable
    try:
        return alt_teamRatioPercentTable[string.lower(mapName)]
    except KeyError:
        return bf2.serverSettings.getTeamRatioPercent()

def printLog(message):
    '''Print log to stdout.'''
    if g_debug:
        print message
        sys.stdout.flush()