Scripts:SquadlessKick

From BF2 Technical Information Wiki
Revision as of 15:31, 22 June 2018 by Pireax (talk | contribs) (Created page with "__TOC__ == 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 te...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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