Plugin:mm squadless kick

From Tactical Wiki

Jump to: navigation, search

Contents

[edit] Introduction

The Squadless-Kick script was one of the first plugins requested at TacticalGamer. It helps ensure communication in-game, as only players in squads are truly part of the chain of command (and the in-game VOIP system).

[edit] Logic

This keys off of PlayerSpawn (a tip from Sarc which he implemented in his own squadless kick script).

On spawn, a check is run to see if the player is in a squad. If the answer is no (and the player is not the commander), two key things happen:

  • a "timeelapsed" attribute is added to the player's Player object
  • a Timer object is created

The timer is run every reminder_interval seconds, and each time, this reminder_interval is added to the player's "timeelapsed" attribute. If the time elapsed is less than kick_time, then the player is reminded how much time she has left to join a squad. If it's greater than or equal to kick_time, the player is given the boot (on a five second delay via the mm_utils module).

The values for kick_time and reminder_interval are set in the modmanager.con file. It is best if reminder_interval evenly divides into kick_time, but it is not mandatory.

[edit] Implementation

The code below should be saved to a file called "mm_squadless_kick.py", which should be saved in the Server\admin\modules\ folder. modmanager.con (in Server\mods\bf2\settings\) should have modmanager.loadModule "mm_squadless_kick" added to the Modules section, and values for the kick_time and reminder_interval should be set as shown in the code (with whichever values you choose, of course).

"tg_bf2_common.py" should also be put into the same modules directory as the squadless kick script itself.

[edit] Known Issues

Looking over the code, I see I need to add something that checks to see if a timer already exists before starting a new one when a player spawns.

[edit] Code

mm_squadless_kick.py (The main module)

# vim: ts=4 sw=4 noexpandtab
"""Squadless Kick System
Kicks a player from the server if they have not joined a squad in a specified interval.

===== Config =====
 # Sets time between spawning without a squad and being kicked
 mm_squadless_kick kick_time 90
 # Sets interval time to remind a player before being kicked
 mm_squadless_kick reminder_interval 15

===== History =====
 v2.2 - 30/08/2006  Created by Sean 'pokerface' Steeg.
 updated kicks and bans to tg_bf2_common (for pb kicks)

 v2.1 - 17/08/2005  Created by Sean 'pokerface' Steeg.
 updated to modmanager layout
 added reminder time

 v2.0:  Created by Sean 'pokerface' Steeg.  
 Changed to use a timer from player spawn instead of death.  Thanks, Sarc.
 
 v1.0:  Created by Sean 'pokerface' Steeg.  
 Buggy and ran off of player death.
"""

import bf2
import host
import tg_bf2_common
from tg_bf2_common import tg_debug
import mm_utils
import string

#import sys
#sys.stderr = tg_bf2_common.FileError()

__version__ = 2.2
__author__ = "Sean Steeg <sean at steegness dot com>"
__required_modules__ = {'modmanager': 1.0}
__supports_reload__ = True
__description__ = "TacticalGamer Squadless Kick v%s" % __version__

configDefaults = {'kick_time': 90,
                  'reminder_interval': 15}

class Squadless_Kicker(object):
    def __init__ (self, modManager):
        """Create a new instance."""
        self.mm = modManager
        self.__state = 0

    def checkSquadless(self, p):
        #Check that the player is squadless AND is not the comm
        if str(p.getSquadId()) == '0' and (not p.isCommander()):
            #increment the time for the player
            p.timeElapsed += self.reminderTime
            if p.timeElapsed < self.kickTime:
                if tg_debug: print 'Elapsed Time on %s: %d   KickTime: %d' %(p.getName(), p.timeElapsed, self.kickTime)
                #Still in the grace period.  Send a warning via global chat.
                kicknotice = "----------%s has %s seconds to join a squad or be kicked.----------" % (string.upper(p.getName()), str(self.kickTime - p.timeElapsed))
                mm_utils.msg_server(kicknotice)
            else:
                if tg_debug: print 'Squadless Time elapsed on player %s' % p.getName()
                #time's up.  begone, squadless person.
                kicknotice = "----------%s is being kicked (squadless)----------" % string.upper(p.getName())
                if tg_debug: print 'Kicknotice created for player %s' % p.getName()
                mm_utils.msg_server(kicknotice)
                if tg_debug: print 'Serverwide kicknotice sent for player %s' % p.getName()
                if tg_debug: print 'About to kick %s for being squadless' % p.getName()
                tg_bf2_common.pb_kick(p.getName(), "Joining a squad is a requirement on this server.")
                if tg_debug: print 'PB kick issued on %s' % p.getName()
                if tg_debug: print 'Destroying Timers'
                if self.squadlesstimer:
                    self.squadlesstimer.destroy()
                    self.squadlesstimer = None
                if self.remindtimer:
                    self.remindtimer.destroy()
                    self.remindtimer = None
        else:
            if self.squadlesstimer:
                self.squadlesstimer.destroy()
                self.squadlesstimer = None
            if self.remindtimer:
                self.remindtimer.destroy()
                self.remindtimer = None

#EVENTS
    def onPlayerSpawn(self, p, soldier):
        if self.__state != 1:
            return 0
        
        #on spawn, if a player is squadless, teamsay a warning (covered in checkSquadless for subsequent calls)
        p.timeElapsed = 0
        if (str(p.getSquadId()) == '0') and (not p.isCommander()):
            kicknotice = "----------%s has %s seconds to join a squad or be kicked.----------" % (string.upper(p.getName()), str(self.kickTime))
            mm_utils.msg_server(kicknotice)
            self.squadlesstimer = bf2.Timer(self.checkSquadless, self.reminderTime, 1, p)
            self.squadlesstimer.setRecurring(self.reminderTime)

#INIT / SHUTDOWN
    def init(self):
        if tg_debug: print 'initializing squadless_kick script'
        """Provides default initialization."""
        self.__config = self.mm.getModuleConfig(configDefaults)
        self.kickTime = self.__config['kick_time']
        self.reminderTime = self.__config['reminder_interval']
        self.squadlesstimer = None
        self.timeelapsed = 0

        if self.__state == 0:
            host.registerHandler('PlayerSpawn', self.onPlayerSpawn)

        self.__state = 1
        if tg_debug: print 'squadless kick successfully initialized.'
        
    def shutdown(self):
        """Shutdown and stop processing."""
        if self.squadlesstimer:
            self.squadlesstimer.destroy()
            self.squadlesstimer = None

        self.__state = 2

def mm_load(modManager):
    """Creates a Squadless Kick object."""
    return Squadless_Kicker(modManager)

tg_bf2_common.py (a set of helper functions defined across modules)

#tg_bf2_common.py
#sets of helper functions for bf2 scripts
#by pokerface <pokerface at tacticalgamer dot com>
#parts cribbed from BF2 Tech Wiki <http://bf2.fun-o-matic.org/index.php/Main_Page>
#version 2.0  30.08.2006

import host
import bf2
from bf2 import g_debug
import new, default

#A global debug variable.  Easier to find and change than the typical g_debug.
tg_debug = 0

#Should send a message to a single player, if properly supported
def sendPlayerMessage(playerId, message):
	host.sgl_sendTextMessage(playerId, 12, 1, message, 0)

#Echos a message to the server console.
def echo(message):
	host.rcon_invoke('echo "%s"' % str(message))

#Kick someone using PunkBuster (supports reasons).  Player MUST BE CONNECTED for this to work.
def pb_kick(playerName, reason="", length=0):
	if tg_debug: print 'PB Kick routine started -- pb_sv_kick "%s" %d %s' % (playerName, length, reason)
	host.rcon_invoke('pb_sv_kick "%s" %d %s' % (playerName, length, reason))

#Kick someone using RCON (no reasons given).  Will work on connecting players.
def rcon_kick(playerIndex):
	if tg_debug: print 'RCON Kick routine started on playerindex %d' % playerIndex
	host.rcon_invoke("admin.kickPlayer %d" % (playerIndex))

#Error redirect classes.  Set sys.stderr to either class.
#A class to write errors to the server console.
class EchoError:
	def write(self, s):
		echo(s)

#A class to write errors to a file.
class FileError:
	def __init__(self, filename=r'C:\bf2pyerrors.txt'):
		self.f = open(filename, 'w')
	def write(self, s):
		self.f.writeline(s)

[edit] Notes

In case this isn't patently obvious, ModManager is very much required for this to function as written. Thanks to Tempus, Apophis, and Wyzcrak for their support.


Return to BF2 Plugin Source Code.

Personal tools