Scripts:SquadlessKick
Introduction
In an effort to learn Python and create something useful, I wrote this script to kick squadless players. It's a step towards a smoothly running team.
The Algorithm
Originally, the script performed a check when players died. However, this caused problems with the autobalancing system because the way BF2 triggers events when switching teams. When a player switches teams, he is removed from a squad (if it applies), killed, and switched to the other side. The problem with checking at player death is the autobalance triggers it when switching a player to another team. Of course, he will definitely not be in a squad and be kicked.
A better way of performing the check is on player spawn. This ensures the intention of whether the player wants to work in a squad or not. Combined with Python's ability to use lists as queues, squadless players can be processed at a specified interval after they spawn squadless.
When the player spawns, we want to perform the check and add the player to the queue if he is squadless. Setting a timer will perform a second check at a specified period after the player spawns.
Player spawns Player is not in a squad or not commanding Player is added to a kick list Player is issued a warning to join a squad Set timer to kick player
When the kick timer is triggered, we want to double-check that the player is still squadless. It's like a second chance. What we do is get the first player in the list and perform the check on him. This would be at the specified time after the player has spawned.
Kick timer is triggered Retrieve first player in kick list Player is not in a squad or not commanding Player is kicked from server
We want to be fair and issue a general warning to all players every so often so they know to join a squad. If this timer is set to half the time of the kick timer, we can be sure that squadless players will see the warning at least once.
Message timer is triggered Display message to all players
In between games, we want to clean up the message timer and clear the kick list. Everybody starts fresh on a new round!
Game status changes Game status is Playing Set the message timer to trigger at set interval Game status is PreGame Destroy message timer Clear the kick list
Code
# Squadless Kick System # Module: squadless_kick_v2.py # Author: Sarc # Version: 0.3a # Description: Players not in a squad will be kicked from the server. # An automated message will issue general warnings at specified intervals. # Squadless player checks are done when the player spawns. # Installation: # Save this script, 'squadless_kick_v2.py', in your <bf2>/admin/standard_admin directory. # Add 'import squadless_kick_v2' and 'squadless_kick_v2.init()' to the file '<bf2>/admin/standard_admin/__init__.py'. import bf2 import host from bf2 import g_debug #debug flag sks_debug = False # for verbose server console messages #variable settings; intervals are in seconds kickInterval = 60 # time before a squadless player is kicked msgInterval = 30 # time between warning messages warningMsg = "ADMIN: |c1000Squadless players will be kicked!" # the warning message #timers msgTimer = None #queue lists kickList = [] # Initialize the kick system i.e. register game hooks. def init(): if g_debug: print "initializing squadless_kick script" host.registerHandler('PlayerSpawn', onPlayerSpawn) host.registerGameStatusHandler(onGameStatusChanged) # On spawn, checks if the player is in a squad or commanding. # Player is added to kick list if not in a squad or not commanding. def onPlayerSpawn(p, vehicle): global sks_debug global kickList, kickInterval if (p.getSquadId() == 0) and not p.isCommander(): # Add the player if not in kick list if kickList.count(p.index) == 0: kickList.append(p.index) # Set timer for kick bf2.Timer(onKickTimer, kickInterval, 1) if sks_debug: host.rcon_invoke("echo \"" + p.getName() + " was added to the kick list.\"") if sks_debug: host.rcon_invoke("echo \"Kick warning issued.\"") # Issue kick warning host.rcon_invoke("game.sayAll \"ADMIN: |c1000" + p.getName() + " will be kicked for not being in a squad\"") # Sends out warning messages def onMsgTimer(data): global sks_debug global warningMsg host.rcon_invoke("game.sayAll \"" + warningMsg + "\"") if sks_debug: host.rcon_invoke("echo \"Warning message issued.\"") # Processes the kick list queue. The next player in queue # is checked again and kicked if not in a squad or not commanding. def onKickTimer(data): global sks_debug global kickList if sks_debug: host.rcon_invoke("echo \"Kick timer triggered.\"") # Process the next player in queue. p = bf2.playerManager.getPlayerByIndex(kickList.pop(0)) # Player is still squadless, kick him. if (p.getSquadId() == 0) and not p.isCommander(): host.rcon_invoke("echo \"" + p.getName() + " was kicked for not being in a squad\"") host.rcon_invoke("admin.kickPlayer " + str(p.index)) # Handles clean up and initialization between rounds. def onGameStatusChanged(status): global kickList global msgInterval, msgTimer if status == bf2.GameStatus.Playing: host.rcon_invoke("echo \"Game Status: Playing\"") # Set the warning timer. msgTimer = bf2.Timer(onMsgTimer, msgInterval, 1) msgTimer.setRecurring(msgInterval) elif status == bf2.GameStatus.PreGame: host.rcon_invoke("echo \"Game Status: PreGame\"") # Destroy any timers msgTimer.destroy() msgTimer = None # Blank the list. kickList = [] elif status == bf2.GameStatus.EndGame: host.rcon_invoke("echo \"Game Status: EndGame\"")
History
0.1a
- Basic squadless kick functionality at death
- Warning message added
0.2a
- FIX: Players are not kicked when changing teams
- Warning message can be set at a user specified interval
- Kick list checks can be set at a user specified interval
0.3a
- FIX: Compatible with EA's autobalance script
- Checks are now done when a player spawns
- Message timer is destroyed when game ends and reinstantiated at game start
- Improved kick delay; now works by a queue for consistent kick delays
- Added debug flag for verbose server console messages