Thomas

Founder
  • Content count

    301
  • Joined

  • Last visited

Posts posted by Thomas


  1. Sad to see you go iMtroll, you had a good run. I am lucky to have worked with you, thank you for saving Raid when it was going to be shut down. To the new managers, I wish you good luck, as the position is not an easy one. If you ever need me, always feel free to PM me.

     

    Thank you for your dedication and service to Raid.

     

    -Thomas

    6

  2. BigBrotherBot is able to manage the rotation of the maps by setting dvars. This plugin manages the frequency of the map by setting map_rotation by player count: rotationmanager.py

    #
    # Plugin for BigBrotherBot(B3) (www.bigbrotherbot.net)
    # Copyright (C) 2005 www.xlr8or.com
    # 
    # This program 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 of the License, or
    # (at your option) any later version.
    #
    # This program 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 program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    #
    # Changelog:
    # 1.0.0 - 1.1.0: Added MapDelay and smart/random creation of rotations
    # 1.0.0 - 1.1.1: Added fallbackrotation and some errorchecking
    # 1.1.1 - 1.1.2: Added some more debugging.
    # 1.1.2 - 1.1.3: Introduced copy.deepcopy()
    # 1.1.3 - 1.1.4: Added CoD1/CoD2 restartcompatibility
    #                Fixed a bug where B3 was unresponsive while in restart-countdown
    # 1.1.4 - 1.1.5: Few Bugfixes.
    # 1.1.5 - 1.1.6: Stripped space at end of rotation.
    # 1.1.6 - 1.2.0: Added hysteresis, added some comments, added caching of roundstartrotation
    # 1.2.0 - 1.2.1: Fixed a bug where the cached rotation would remain 'None'
    # 1.2.1 - 1.2.2: Added another safety .strip() when storing _roundstart_mapRotationCurrent
    # 1.2.2 - 1.2.3: Introduced version 11 for UO; generate rotations with all gametypes
    # 1.2.3 - 1.2.4: Added check for limitation of the maximum stringlength (capped at 980)
    # 1.3.0        : Added support for CoD4
    # 1.3.1        : fixed a bug where on slower boxes the rotation wasn't stored on time
    # 1.3.2        : only add maps that have not been added in the last 4 passes, no more double maps
    # 1.3.3        : ...
    # 1.3.4        : bugfix in maphistory
    # 1.3.5        : Added gametypehistory, changed maphistory: both are now configurable for each
    #                rotation size individually - Just a baka
    # 1.3.6        : Added cod7 support, beautified code - Just a baka
    # 1.3.7        : Reworked adjustrotation, fixed bugs that were causing unnecessary
    #                setrotation() calls - Just a baka
    # 1.3.8        : Implemented proper cod6 support, optimized first saveroundstartrotation - Just a baka
    # 1.3.9        : Added map, maps and nextmap commands for ranked cod7 - 82ndab-Bravo17
    # 1.3.9a       : Added Names translation for COD7 maps - 82ndab-Bravo17
    # 1.3.9b       : Added DLC2 Maps
    # 1.3.9c       : Added DLC3 Maps
    # 1.4.0        : Correct hysteresis logic and add second hysteresis value, now have one for snall-medium and one for medium-high
    
    __version__ = '1.4.0'
    __author__  = 'xlr8or, Just a baka, 82ndab-Bravo17'
    
    import copy
    import threading
    import time
    import random
    import b3
    import b3.events
    import string
    
    #--------------------------------------------------------------------------------------------------
    class RotationmanagerPlugin(b3.plugin.Plugin):
        _rotation_small = {}
        _rotation_medium = {}
        _rotation_large = {}
        _currentrotation = 0
        _immediate = 0
        _switchcount1 = 0
        _switchcount2 = 0
        _hysteresis1 = 0
        _hysteresis2 = 0
        _playercount = -1
        _oldplayercount = None
        _mapDelay = 0
        _version = 0
        _restartCmd = ''
        _countDown = 0
        _donotadjustnow = False
        _randomizerotation = 0
        _roundstart_mapRotation = None
        _roundstart_mapRotationCurrent = ''
        _roundstart_currentrotation = 0
        _fallbackrotation = ''
        _needfallbackrotation = False
        _initialrecount = False
        _rotation_size = 1                    # 1 - small, 2 - medium, 3 - large
        _recentmaps = []                      # The Maphistory
        _recentgts = []                       # The Gametype history
        _hmm = [0,0,0]                        # HowManyMaps to keep as a maphistory
        _hmgt = [0,0,0]                       # HowManyGameTypes to keep as a gametype history
        _cod7MapRotation = []
        _cod7MapRotationFixed = []
        _nextmap7 = []
        _outofrotation = False
    
        _cod7Maps = ['mp_array','mp_cairo','mp_cosmodrome','mp_cracked','mp_crisis','mp_duga','mp_firingrange','mp_hanoi',
                     'mp_havoc','mp_nuked','mp_mountain','mp_radiation','mp_russianbase','mp_villa','mp_berlinwall2',
                     'mp_kowloon','mp_stadium','mp_discovery','mp_gridlock','mp_hotel','mp_outskirts','mp_zoo','mp_area51','mp_drivein','mp_silo','mp_golfcourse']
        _cod7Mapeasynames = ['Array','Havanna','Launch','Cracked','Crisis','Grid','Firing Range','Hanoi',
                             'Jungle','Nuketown','Summit','Radiation','WMD','Villa','Berlin Wall',
                             'Kowloon','Stadium','Discovery','Gridlock','Hotel','Outskirts','Zoo','Hanger 18','Drive-in','Silo','Hazard']
        _cod7Mapeasynameslower = ['array','havanna','launch','cracked','crisis','grid','firing range','hanoi',
                                  'jungle','nuketown','summit','radiation','wmd','villa','berlin wall',
                                  'kowloon','stadium','discovery','gridlock','hotel','outskirts','zoo','hanger 18','drive-in','silo','hazard']
        _cod7Playlists = {18: {
                                0: {'tdm':1, 'dm':2, 'ctf':3, 'sd':4, 'koth':5, 'dom':6, 'sab':7, 'dem':8},         # softcore
                                1: {'tdm':9, 'dm':10, 'ctf':11, 'sd':12, 'koth':13, 'dom':14, 'sab':15, 'dem':16},  # hardcore
                                2: {'tdm':17, 'dm':18, 'ctf':19, 'sd':20, 'koth':21, 'dom':22, 'sab':23, 'dem':24}, # barebones
                              },
                          12: {
                                0: {'tdm':32, 'dm':33, 'ctf':34, 'sd':35, 'koth':36, 'dom':37, 'sab':38, 'dem':39}, # softcore
                                1: {'tdm':41, 'dm':42, 'ctf':43, 'sd':44, 'koth':45, 'dom':46, 'sab':47, 'dem':48}, # hardcore
                                2: {'tdm':50, 'dm':51, 'ctf':52, 'sd':53, 'koth':54, 'dom':55, 'sab':56},           # barebones (yes, no dem)
                              }
                         }
        _slot_num = 18
        _game_mode = 0
        _cod7Gametypes = ['tdm', 'dm', 'ctf', 'sd', 'hq', 'koth', 'dom', 'sab', 'dem']
    
    
        def onStartup(self):
            """\
            Initialize plugin settings
            """
            
    
            # get the admin plugin so we can register commands
            self._adminPlugin = self.console.getPlugin('admin')
            if not self._adminPlugin:
                # something is wrong, can't start without admin plugin
                self.error('Could not find admin plugin')
                return False
    
            # register our commands
            if 'commands' in self.config.sections() and self._version == 7:
                for cmd in self.config.options('commands'):
                    level = self.config.get('commands', cmd)
                    sp = cmd.split('-')
                    alias = None
                    if len(sp) == 2:
                        cmd, alias = sp
    
                    func = self.getCmd(cmd)
                    if func:
                        self._adminPlugin.registerCommand(self, cmd, level, func, alias)
            # Register our events
            self.verbose('Registering events')
            self.registerEvent(b3.events.EVT_CLIENT_CONNECT)
            self.registerEvent(b3.events.EVT_CLIENT_DISCONNECT)
            self.registerEvent(b3.events.EVT_GAME_EXIT)
    
            # don't adjust the rotation just yet
            self._donotadjustnow = True
            
            if self._version != 7:
                self._needfallbackrotation = True
                self._initialrecount = True
                # we'll store the initial rotation
                self.retrievefallback()
    
            # wait half a minute after pluginstart to do an initial playercount
            t1 = threading.Timer(30, self.recountplayers)
            t1.start()
    
            self.debug('Started')
    
    
        def onLoadConfig(self):
            # load our settings
            self.verbose('Loading config')
            self._switchcount1 = self.config.getint('settings', 'switchcount1')
            self._switchcount2 = self.config.getint('settings', 'switchcount2')
            self._hysteresis1 = self.config.getint('settings', 'hysteresis1')
            self._hysteresis2 = self.config.getint('settings', 'hysteresis2')
            self._immediate = self.config.getboolean('settings', 'immediate')
            self._mapDelay = self.config.getint('settings', 'mapdelay')
            self._version = self.config.getint('settings', 'version')
            self._randomizerotation = self.config.getboolean('settings', 'randomizerotation')
    
            self._hmm[0] = abs(self.config.getint('histories', 'maphistory_small'))
            self._hmm[1] = abs(self.config.getint('histories', 'maphistory_medium'))
            self._hmm[2] = abs(self.config.getint('histories', 'maphistory_large'))
            self.debug('MapHistory is set to: %s' % self._hmm)
    
            self._hmgt[0] = abs(self.config.getint('histories', 'gthistory_small'))
            self._hmgt[1] = abs(self.config.getint('histories', 'gthistory_medium'))
            self._hmgt[2] = abs(self.config.getint('histories', 'gthistory_large'))
            self.debug('GTHistory is set to: %s' % self._hmgt)
    
            if self._version == 7:
                self._slot_num = self.config.getint('cod7', 'slot_num')
                if self._slot_num not in (12, 18):
                    self.error ('Incorrect number of slots (%d), assuming you meant 18.' % self._slot_num)
                    self._slot_num = 18
    
                self._game_mode = self.config.getint('cod7', 'game_mode')
                if self._game_mode not in (0, 1, 2):
                    self.error ('Incorrect game mode (%d), assuming you meant softcore.' % self._game_mode)
                    self._game_mode = 0
            
            for gametype in self.config.options('rotation_small'):
                maps = self.config.get('rotation_small', gametype)
                maps = maps.split(' ')
                self._rotation_small[gametype] = maps
                self.debug('Small %s: %s' %(gametype, maps))
    
            for gametype in self.config.options('rotation_medium'):
                maps = self.config.get('rotation_medium', gametype)
                maps = maps.split(' ')
                self._rotation_medium[gametype] = maps
                self.debug('Medium %s: %s' % (gametype, maps))
    
            for gametype in self.config.options('rotation_large'):
                maps = self.config.get('rotation_large', gametype)
                maps = maps.split(' ')
                self._rotation_large[gametype] = maps
                self.debug('Large %s: %s' % (gametype, maps))
    
            if self._version in (1, 11):            # 1: CoD1 or 11: CoD UO
                self._restartCmd = 'map_restart'
            elif self._version in (2, 4, 5, 6):     # CoD2, CoD4, CoD5 or CoD6
                self._restartCmd = 'fast_restart'
            else:
                self._mapDelay = 0
    
        def getCmd(self, cmd):
            cmd = 'cmd_%s' % cmd
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                return func
        
            return None
    
        def onEvent(self, event):
            """\
            Handle intercepted events
            """
            if event.type == b3.events.EVT_CLIENT_CONNECT:
                self._playercount += 1
                self.debug('PlayerCount +1: %s' % self._playercount)
                # we're going up, pass a positive 1 to the adjustmentfunction
                self.adjustrotation(+1)
            elif event.type == b3.events.EVT_CLIENT_DISCONNECT:
                self._playercount -= 1
                self.debug('PlayerCount -1: %s' % self._playercount)        
                # we're going down, pass a negative 1 to the adjustmentfunction
                self.adjustrotation(-1)
            elif event.type == b3.events.EVT_GAME_EXIT:
                self._donotadjustnow = True
                # wait 2 mins and cache the current rotation cvars
                if self._version != 7:
                    t3 = threading.Timer(120, self.saveroundstartrotation)
                    t3.start()
                # wait 3 mins and do a recount
                t4 = threading.Timer(180, self.recountplayers)
                t4.start()
                # should we fast_restart?
                if self._mapDelay != 0 and self._version != 7:
                    t5 = threading.Thread(target=self.fastrestart)
                    t5.start()
                # cod7 map change support
                if self._version == 7:
                    # wait 2 minutes and set the next map
                    self.debug ('Map change detected, Will push the new map to the server after 2 minutes.')
                    self.cod7getnextmap()
                    t6 = threading.Timer(120, self.cod7maprotate)
                    t6.start()
    
    
        def adjustrotation(self, delta):
            if self._donotadjustnow:
                return None
    
            new_rotation = 0 # size: from 1 (small) to 3 (large)
    
            if delta == +1:
                if self._rotation_size == 3 or self._playercount > (self._switchcount2 + self._hysteresis2):
                    new_rotation = 3
                elif self._rotation_size == 2 or self._playercount > (self._switchcount1 + self._hysteresis1):
                    new_rotation = 2
                else:
                    new_rotation = 1
    
            elif delta == -1:
                if self._rotation_size == 1 or self._playercount < (self._switchcount1 - self._hysteresis1):
                    new_rotation = 1
                elif self._rotation_size == 2 or self._playercount < (self._switchcount2 - self._hysteresis2):
                    new_rotation = 2
                else:
                    new_rotation = 3
    
            elif delta == 0:
                if self._playercount < self._switchcount1:
                    new_rotation = 1
                elif self._playercount < self._switchcount2:
                    new_rotation = 2
                else:
                    new_rotation = 3
    
            if new_rotation != 0 and (new_rotation != self._rotation_size or\
                                     (self._version == 7 and len(self._cod7MapRotation) == 0) or\
                                      self._initialrecount):
                self.setrotation (new_rotation)
            elif new_rotation == 0:
                self.debug ('Invalid delta has been passed to adjustrotation, aborting.')
            else:
                self.debug ('Rotation size has not changed, will not update rotation.')
    
            return None
    
    
        def setrotation(self, newrotation):
            if newrotation == self._currentrotation and self._version != 7:
                return None
    
            # restore the rotation if the new one is the same as the one at round/map start
            if newrotation == self._roundstart_currentrotation and self._roundstart_mapRotation is not None and self._version != 7:
                self.debug('Restoring Cached Roundstart Rotations')
                if self._version != 6:
                    if self._roundstart_mapRotation != '':
                        self.console.setCvar('sv_mapRotation', self._roundstart_mapRotation)
                    if self._roundstart_mapRotationCurrent != '':
                        self.console.setCvar('sv_mapRotationCurrent', self._roundstart_mapRotationCurrent)
                else:
                    if self._roundstart_mapRotation != '':
                        self.console.write('sv_mapRotation %s' % self._roundstart_mapRotation)
                    if self._roundstart_mapRotationCurrent != '':
                        self.console.write('sv_mapRotationCurrent %s' % self._roundstart_mapRotationCurrent)
    
                self._currentrotation = newrotation
                return None
    
            if newrotation == 1:
                rotname = "small"
                rotation = self._rotation_small
            elif newrotation == 2:
                rotname = "medium"
                rotation = self._rotation_medium
            elif newrotation == 3:
                rotname = "large"
                rotation = self._rotation_large
            else:
                self.error('Error: Invalid newrotation passed to setrotation.')
                return None
    
            self._rotation_size = newrotation
    
            self.debug('Adjusting to %s mapRotation' % rotname)
            self._rotation = self.generaterotation(rotation)
    
            if self._version != 7:
                if self._version != 6:
                    self.console.setCvar('sv_mapRotation', self._rotation)
                else:
                    self.console.write('sv_mapRotation %s' % self._rotation)
    
                if self._immediate and self._version != 6:
                    self.console.setCvar('sv_mapRotationCurrent', '')
                elif self._immediate:
                    self.console.write('reset sv_mapRotationCurrent')
                self._currentrotation = newrotation
    
                if self._initialrecount:
                    self.saveroundstartrotation(self._rotation)
            else:
                self.cod7getnextmap()
                self.cod7maprotate()
    
    
        def generaterotation(self, rotation):
            #self.debug('Generate from: %s @ size: %s' % (rotation, self._rotation_size))
            rotation_size = self._rotation_size - 1  # We'll be using it as an index for _hmgt
            r = ''
            self._cod7MapRotation = []
    
            if self._randomizerotation:
                self.debug('Creating randomized rotation...')
                rot = copy.deepcopy(rotation)
                count = 0
                lastgametype = ''
                for gametype,maplist in rot.items():
                    count += len(maplist)
                self.debug('MapCount: %s' % count)
                while count > 0:
                    c = random.randint(1,count)
                    #self.debug('Random: %s' % c)
                    for gametype,maplist in rot.items():
                        if c > len(maplist):
                            #self.debug('Length this maplist: %s' % (len(maplist)))
                            c -= len(maplist)
                        else:
                            # Check if this mode was recently added
                            if gametype in self._recentgts:
                                self.debug('Gametype %s skipped, already added in the last %s items' % (gametype, self._hmgt[rotation_size]) )
                                continue    # skip to the next map in queue
                            # Check if this map was recently added
                            elif maplist[c-1] in self._recentmaps:
                                self.debug('Map %s skipped, already added in the last %s items' % (maplist[c-1], self._hmm[rotation_size]) )
                                continue    # skip to the next map in queue
                            # cod7 - check if this gametype exists for the chosen game mode and a number of slots
                            elif self._version == 7 and gametype not in self._cod7Playlists[self._slot_num][self._game_mode]:
                                self.warning('Gametype %s cannot be played in current playlist (game_mode=%d, slot_num=%d)' % (gametype, self._slot_num, self._game_mode))
                                continue    # skip to the next map in queue
    
                            if self._version != 7:
                                addition = ''
    
                            if gametype != lastgametype or self._version in (4, 6, 11): #UO, CoD4 and CoD6 need every gametype pre map
                                addition = 'gametype ' + gametype + ' '
    
                            addingmap = maplist.pop(c-1)
                            
                            if self._version != 7:
                                addition = addition + 'map ' + addingmap + ' '
    
                            if self._version != 7 and (len(r) + len(addition)) > 960:
                                self.debug('Maximum sv_rotation stringlength reached... Aborting adding maps to rotation!')
                                count = 0 # Make sure we break out of the while loop
                                break     # Break out of the for loop
    
                            if self._version != 7:
                                r += addition
                            else:
                                self._cod7MapRotation.append ([gametype,addingmap])
    
                            #self.debug('Building: %s' % r)
                            rot[gametype] = maplist
                            lastgametype = gametype
    
                            if self._hmm[rotation_size] != 0:
                                self._recentmaps.append(addingmap)
                                self._recentmaps = self._recentmaps[-self._hmm[rotation_size]:] # Slice the last _hmm nr. of maps
                            if self._hmgt[rotation_size] != 0:
                                self._recentgts.append(gametype)
                                self._recentgts = self._recentgts[-self._hmgt[rotation_size]:] # Slice the last _hmgt nr. of gametypes
                            break
                    count -= 1
    
            else:
                self.debug('Creating non-randomized rotation...')
                stringmax = 0
                # UO, CoD6 and CoD4 needs every gametype pre map
                if self._version in (4, 6, 11):
                    for gametype,maplist in rotation.items():
                        for map in maplist:
                            addition = 'gametype ' + gametype + ' ' + 'map ' + map + ' '
                            if (len(r) + len(addition)) > 980:
                                self.debug('Maximum sv_rotation stringlength reached... Aborting adding maps to rotation!')
                                stringmax = 1 # Make sure we break out of the first for loop
                                break         # Break out of the nested for loop
                            r += addition
                        if stringmax == 1:
                            break # Break out of the first for loop
    
                elif self._version == 7:
                    addition = []
                    for gametype,maplist in rotation.items():
                        for map in maplist:
                            addition = [gametype, map]
                            self._cod7MapRotation.append (addition)
                    self._cod7MapRotationFixed = self._cod7MapRotation
    
                else:
                    for gametype,maplist in rotation.items():
                        r2 = r # Backup r
                        r = r + 'gametype ' + gametype + ' '
                        for map in maplist:
                            r = r + 'map ' + map + ' '
                            if len(r) > 980 and self._version != 7:
                                self.debug('Maximum sv_rotation stringlength reached... Aborting adding maps to rotation!')
                                r = r2 # Restore r and break out
                                stringmax = 1
                                break
                            r2 = r # Backup r
                        if stringmax == 1:
                            break # Break out completely
    
            if self._version != 7:
                self.debug('NewRotation: %s' % r)
            else:
                self.debug('NewBlackOpsRotation: %s' % self._cod7MapRotation)
            if self._version != 7 and r.strip() == '':
                r = self._fallbackrotation
                self.error('Error: Generation failed! Reverting to original rotation!')
            # Strip excessive spaces from the new rotation
            r = r.strip()
            return r
    
    
        def recountplayers(self):
            if self._version != 7:
                # do we still need the original rotation
                if self._needfallbackrotation:
                    self.retrievefallback()
                # if we still didnt get it we'll wait for the next round/map
                if self._needfallbackrotation:
                    self.error('Error: Still not able to retrieve initial rotation!')
                    return None
    
            # reset, recount and set a rotation
            self._oldplayercount = self._playercount
            self._playercount = 0
            self._donotadjustnow = False
    
            self._playercount = len (self.console.clients.getList())
    
            self.debug('PlayerCount recount players: %s' % self._playercount)
    
            if self._oldplayercount == -1:
                self.adjustrotation(0)
            elif self._playercount > self._oldplayercount:
                self.adjustrotation(+1)
            elif self._playercount < self._oldplayercount:
                self.adjustrotation(-1)
            else:
                pass
    
    
        def retrievefallback(self):
            self._fallbackrotation = self.console.getCvar('sv_mapRotation').getString()
            time.sleep(0.5) # Give us plenty time to store the rotation
            if self._fallbackrotation is not None:
                self.debug('Fallbackrotation: %s' % self._fallbackrotation)
                # this is the only place where _needfallbackrotation is set to False!
                self._needfallbackrotation = False
            else:
                self.error('Could not save original rotation... Waiting for next pass')
    
    
        def saveroundstartrotation(self, rotation=''):
            if self._initialrecount and self._version != 7:
                self.debug('Saving the first generated rotation as the cached roundstart rotation')
                self._roundstart_mapRotation = rotation
                self._roundstart_mapRotationCurrent = ''
                self._initialrecount = False
    
            elif self._version != 7:
                self.debug('Getting current Rotation')
                self._roundstart_mapRotation = self.console.getCvar('sv_mapRotation')
                if self._roundstart_mapRotation is not None and self._roundstart_mapRotation != '':
                    self._roundstart_mapRotation = self._roundstart_mapRotation.getString()
                    self.debug('Cached Rotation: %s' % self._roundstart_mapRotation)
                else:
                    self._roundstart_mapRotation = None
    
                self._roundstart_mapRotationCurrent = self.console.getCvar('sv_mapRotationCurrent')
                if self._roundstart_mapRotationCurrent is not None and self._roundstart_mapRotationCurrent != '':
                    self._roundstart_mapRotationCurrent = self._roundstart_mapRotationCurrent.getString()
                    # Removing extra spaces just in case...
                    self._roundstart_mapRotationCurrent = self._roundstart_mapRotationCurrent.strip()
                    self.debug('Cached RotationCurrent: %s' % self._roundstart_mapRotationCurrent)
                else:
                    self._roundstart_mapRotationCurrent = ''
    
                self._roundstart_currentrotation = self._currentrotation
            else:
                pass
    
        def cod7getnextmap(self):
            if len(self._cod7MapRotation) == 0:
                self._donotadjustnow = False
                self.debug ('Nothing to rotate, re-adjusting rotation...')
                self.adjustrotation(0)
    
            # Get the next [gametype,map] and remove it from _cod7MapRotation
            if not self._outofrotation:
                self._nextrotationmap = self._cod7MapRotation.pop(0)
            self._nextmap7 = self._nextrotationmap
            self._outofrotation = False
    
        def cod7maprotate(self):
            self.debug('COD7MAPROTATE: next map will be %s at %s' % (self._nextmap7[0], self._nextmap7[1]))
    
            # Set the playlist thus changing the gametype
            self.console.write('setadmindvar playlist %s' % self._cod7Playlists[self._slot_num][self._game_mode][self._nextmap7[0]])
    
            # Build a map exclusion rule then apply it. Will exclude every map except the next one.
            exclusion = copy.copy (self._cod7Maps)
            exclusion.remove (self._nextmap7[1])
            self.console.write ('setadmindvar playlist_excludeMap "%s"' % ' '.join(exclusion))
    
            # Keep playlist_excludeGametypeMap empty, I'm in charge here!
            # If next map is in this dvar, server will keep not changing maps until it recieves something that's not restricted
            self.console.write ('setadmindvar playlist_excludeGametypeMap ""')
    
    
        def fastrestart(self):
            self._countDown = int(self._mapDelay)/10
            while self._countDown > 0:
                self.console.say('^1*** MATCH STARTING IN ^7%s^1 SECONDS ***' % (self._countDown*10) )
                self._countDown -= 1
                time.sleep(10)
    
            self.console.say('^7*** ^1MATCH ^7*** ^1STARTING ^7***')
            time.sleep(3)
            self.console.write(self._restartCmd)
    
        def cmd_maps(self, data, client=None, cmd=None):
            """\
            - list the server's map rotation for cod7, optionally limit the number in the list
            """
    
            if not self._adminPlugin.aquireCmdLock(cmd, client, 60, True):
                client.message('^7Do not spam commands')
                return
    
            m = self._adminPlugin.parseUserCmd(data)
            if m:
                try:
                    limitno = int(m[0])
                except:
                    limitno = 1000
                
            else:
                limitno = 1000
    
            if self._randomizerotation:
                rotation = self._cod7MapRotation[0:limitno]
            else:
                if limitno == 1000:
                    rotation = self._cod7MapRotationFixed
                else:
                    rotation = self._cod7MapRotation[0:limitno]
    
            maplist = ''
            
            for maps in rotation:
                mapeasyname = self.getcod7mapeasyname(maps[1])
                maplist = maplist + mapeasyname + '^7-^3' + maps[0] + '  ^2'
                
            if len(maplist) > 0:
                cmd.sayLoudOrPM(client, '^7Map Rotation: ^2%s' % maplist)
            else:
                client.message('^7Error: could not get map list')
        
        def cmd_nextmap(self, data, client=None, cmd=None):
            """\
            - list the next map in rotation for cod7
            """
            if not self._adminPlugin.aquireCmdLock(cmd, client, 60, True):
                client.message('^7Do not spam commands')
                return
    
            map = self._nextmap7
    
            if map:
                mapeasyname =  self.getcod7mapeasyname(map[1])
                if map[0] == 'koth':
                    gt = 'hq'
                else:
                    gt = map[0]
                    
                cmd.sayLoudOrPM(client, '^7Next Map: ^2%s with ^3%s^2 gametype' % (mapeasyname, gt))
            else:
                client.message('^7Error: could not get map name')
                
        def cmd_map(self, data, client=None, cmd=None):
            """\
            - switch what the next map and gametype is for cod7
            """
            #m = self._adminPlugin.parseUserCmd(data)
            m = data.split(' ')
            self.debug(m)
            gt = m[-1]
            map = string.join(m[0:-1])
            
            self.debug('Result is map %s gametype %s' % (map, gt))
            map = map.lower()
            if (map not in self._cod7Maps) and (map not in self._cod7Mapeasynameslower):
                client.message('^7You must supply a map and valid gametype to change to.')
                return
            
            if map in self._cod7Mapeasynameslower:
                maphardname = self.getcod7maphardname(map)
             
            if not gt or gt not in self._cod7Gametypes or gt not in self._cod7Playlists[self._slot_num][self._game_mode]:
                client.message('^7You must supply a valid gametype to change to.')
                return
            # Set the playlist thus changing the gametype
            if gt == 'hq':
                gt = 'koth'
                
    
            self._outofrotation = True
            self._nextmap7 = [gt, maphardname]
            if gt == 'koth':
                gt = 'hq'
            client.message('^7Next map changed to ^2%s with ^3%s^2 gametype' % (map, gt))
            self.cod7maprotate()
    
    
        def aquireCmdLock(self, cmd, client, delay, all=True):
            if client.maxLevel >= 20:
                return True
            elif cmd.time + delay <= self.console.time():
                return True
            else:
                return False    
        
        def getcod7mapeasyname(self, map):
            if map in self._cod7Maps:
                ix = self._cod7Maps.index(map)
                self.debug(map)
                return self._cod7Mapeasynames[ix]
            else:
                return 'Error'
                
        def getcod7maphardname(self, map):
            map = map.lower()
            if map in self._cod7Mapeasynameslower:
                ix = self._cod7Mapeasynameslower.index(map)
                return self._cod7Maps[ix]
            else:
                return 'Error'
                
    
    if __name__ == '__main__':
        print ('\nThis is version '+__version__+' by '+__author__+' for BigBrotherBot.\n')
    
    
    0

  3. Not sure what you're trying to accomplish, but good luck with it.

     

    Couple of comments based on what I've seen so far:

     

    Following code may be a bit messy since I'm a nub:

    The way you've declared your class is wrong, and b3 will throw an error
    
    class PartychatPlugin(b3.plugin.Plugin):
      _adminPlugin = None
    This code is unnecessary, as you can just declare these as global variables in the beginning of the class.
    
    return int(self.value)
    
    
    _command = partykick
    _commandexec = adm kick:&&1
    
    
    return:
    _command
    _commandexec
    import
    I'd remove all but the following based on what I've seen so far:
    
    import b3, re
    import b3.events
    import time
    
    Add this to your first line of the code, otherwise none of your commands will work
    
    def startup(self):
        """\
        Initialize plugin settings
        """
    
        # get the admin plugin so we can register commands
        self._adminPlugin = self.console.getPlugin('admin')
        if not self._adminPlugin:
          # something is wrong, can't start without admin plugin
          self.error('Could not find admin plugin')
          return False
          
    
        # register our commands
        if 'commands' in self.config.sections():
          for cmd in self.config.options('commands'):
            level = self.config.get('commands', cmd)
            sp = cmd.split('-')
            alias = None
            if len(sp) == 2:
              cmd, alias = sp
    
            func = self.getCmd(cmd)
            if func:
              self._adminPlugin.registerCommand(self, cmd, level, func, alias)
    
        self.debug('Started')
    
    Add this as your second function, as you can add commands by defining a function
    
    def getCmd(self, cmd):
        cmd = 'cmd_%s' % cmd
        if hasattr(self, cmd):
          func = getattr(self, cmd)
          return func
    
        return None
    
    Add this as well, this allows for interception of events called via gamelog
    
    def onEvent(self, event):
        """\
        Handle intercepted events
        """
    
    This is an example of my code from previous project: 
    
    if event.type == b3.events.EVT_GAME_MAP_PREV:
                            self.Prevmap = event.data
                            self.Prevmapscore = self.console.getCvar('dr_info_%s' % (event.data))
                            self.stripscoredata(self.Prevmapscore)
                            self.verbose("[MapSave]: Saving Scores For %s" % (str(self.Prevmap)))
                            self.verbose("[MapSave]: Score for %s is '%s'" % (str(self.Prevmap),str(self.Prevmapscore)))
                            if self.Prevmapscore != None:
                                    con = mdb.connect(self.Hostname,self.Username,self.Password,self.Database)
                                    cur = con.cursor()
                                    cur.execute("SELECT * FROM mapsave WHERE mapname = '%s'" % (str(self.Prevmap)));
                                    if (cur.rowcount == 0):
                                            try:
                                                    cur.execute("INSERT INTO mapsave (mapname,score) VALUES ('%s','%s')" % (str(self.Prevmap),str(self.Prevmapscore)))
                                                    time.sleep(10)
                                                    self.console.say("[MapSave]: Successfully inserted new scores!")
                                            except:
                                                    self.error('[MapSave]: Error Inserting New Scores For %s' % (str(self.Prevmap)))
                                                    time.sleep(10)
                                                    self.console.say("[MapSave] Encountered an error inserting new scores!")
                                    else:
                                            try:
                                                    cur.execute("UPDATE mapsave SET score = '%s' WHERE mapname = '%s'" % (str(self.Prevmap),str(self.Prevmapscore)))
                                                    time.sleep(10)
                                                    self.console.say("[MapSave]: Successfully updated scores!")
                                            except:
                                                    self.error('[MapSave]: Error Updating New Scores For %s' % (str(self.Prevmap)))
                                                    time.sleep(10)
                                                    self.console.say("[MapSave]: Encountered an error updating scores!")
                            else:
                                    time.sleep(10)
                                    self.console.say("[MapSave]: There was no previous map to save or an error has occurred!")
                    elif event.type == b3.events.b3.events.EVT_GAME_MAP_CURR:
                            self.Currmap = event.data
                            con = mdb.connect(self.Hostname,self.Username,self.Password,self.Database)
                            cur = con.cursor()
                            cur.execute("SELECT * FROM mapsave WHERE mapname = '%s'" % (str(self.Currmap)));
                            if (cur.rowcount == 0):
                                    self.console.say("[MapSave]: No Scores For This Map. Can You Beat The Scores?")
                                    self.verbose("[MapSave]: Map %s Has No Scores" % (str(self.Currmap)))
                            else:
                                    try:
                                            row = cur.fetchone()
                                            cmapname = str((row[1]))
                                            ckillval = str((row[2]))
                                            ckillguid = str((row[3]))
                                            ckillplayer = str((row[4]))
                                            cdeathsval = str((row[5]))
                                            cdeathsguid = str((row[6]))
                                            cdeathsplayer = str((row[7]))
                                            cheadshotsval = str((row[8]))
                                            cheadshotsguid = str((row[9]))
                                            cheadshotsplayer = str((row[10]))
                                            cscoreval = str((row[11]))
                                            cscoreguid = str((row[12]))
                                            cscoreplayer = str((row[13]))
                                            cknifesval = str((row[14]))
                                            cknifesguid = str((row[15]))
                                            cknifesplayer = str((row[16]))
                                            ctimeval = str((row[17]))
                                            ctimeguid = str((row[18]))
                                            ctimeplayer = str((row[19]))
                                            ctotal = ';kills,%s,%s,%s;deaths,%s,%s,%s;headshots,%s,%s,%s;score,%s,%s,%s;knifes,%s,%s,%s;time,%s,%s,%s' % ((killval),(killguid),(killplayer),(deathsval),(deathsguid),(deathsplayer),(headshotsval),(headshotsguid),(headshotsplayer),(scoreval),(scoreguid),(scoreplayer)(knifesval),(knifesguid),(knifesplayer),(timeval),(timeguid),(timeplayer))
                                            self.console.write("set dr_info_%s %s" % (str(self.cmapname),str(self.ctotal)))
                                            self.verbose("[MapSave]: Map %s Has Has Scores, Getting Default Scores Ready For Map End" % (cmapname))
                                            time.sleep(10)
                                            self.console.say("[MapSave]: Type !mapscore To View The Scores. Can You Beat The Scores?")
                                    except:
                                            self.error("[MapSave]: Something Unexpected Has Happened! Mapname:%s Scores:%s" % ((self.cmapname),(ctotal)))
    
    
    Add commands using the following:
    
    def cmd_site(self, data, client, cmd=None):
        """\
        !site - What is our website
           """
        cmd.sayLoudOrPM(client, 'Our website is www.raid-gaming.net')
        return True
    
    

    Good luck finishing the plugin!

    0

  4. Hello Raid Community!

    We recently had a day of downtime, and we'd like to explain ourselves. Yesterday, 8/23/14 upon rebooting our server, a file was corrupt and the server could not be started. After checking with OVH, our only option was to reformat the entire hard disk. So today, we've been fixing everything and pulling files out of our asses. Huge thanks to every one who helped, especially @NNJ for the backups. Next time we will be better prepared and backup everything on a separate server.

    In the next day, we will be rolling out the Deathrun, CodJumper, and Combined Ops server.

    Sorry for the delays, please let us know if you have any questions, comments, or complaints.


     

    Status:

    Teamspeak - UP

    Forums/Website - UP

    Fun server - UP

    Fun server B3 - UP

    Deathrun server - UP

    Deathrun B3 - UP

    CodJumper server - UP

    CodJumper B3 - DOWN

    Combined Ops server - UP

    Combined Ops B3 - UP

    Redirect - UP

    XLRSTATS - UP

    Echelon - UP (took a bit of work)

    0