def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('var'): if (name == "banmatch"): self.BANMATCH = int(value) if (name == "sflimit"): self.SFLIMIT = int(value) if (name == "levellimit"): self.LEVELLIMIT = int(value) if (name == "matchlimit"): self.MATCHLIMIT = int(value) for (name, value) in ini.items('ipban'): self.ipban.append(name) admins = os.path.join(os.path.dirname(config),'admin.ini') ini.read(admins) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) print self.adminlist pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('paths'): if (name == "base"): self.base = value if (name == "sent"): self.sent = value
def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level': value}) pass
def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('balancer'): if (name == "threshold"): self.THRESHOLD = int(value) if (name == "jointhreshold"): self.JOINTHRESHOLD = int(value) pass
def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) #for (name, value) in config.items('balancer'): # if (name == "level"): # self._level = int(value) # if (name == "sf"): # self._sf = int(value) pass
def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level': value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass
def onPluginLoad(self, config): self.config = self.CONFIG_DEFAULT.copy() self.ms = MasterServer() print(self.config) ini = ConfigParser.ConfigParser() ini.read(config) for name in self.config.keys(): try: self.config[name] = ini.get('limit', name) except: raise print(self.config) pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) pass
class limit(ConsolePlugin): CONFIG_DEFAULT = { 'reason': "This server has restrictions on", 'level_min': 10, 'level_max': 100, 'sf_min': 50, 'sf_max': 500, 'forcespec': False, } def onPluginLoad(self, config): self.config = self.CONFIG_DEFAULT.copy() self.ms = MasterServer() print(self.config) ini = ConfigParser.ConfigParser() ini.read(config) for name in self.config.keys(): try: self.config[name] = ini.get('limit', name) except: raise print(self.config) pass def onAccountId(self, *args, **kwargs): config = self.config reason = config['reason'] clnum = int(args[0]) id = int(args[1]) stats = self.ms.getStatistics("%d" % (id)).get('all_stats').get(id) lv = int(stats['level']) sf = int(stats['sf']) act = False if (lv < config['level_min']) or (lv > config['level_max']): act = True reason += ". Level %d - %d only" % (config['level_min'], config['level_max']) if (sf < config['sf_min']) or (sf > config['sf_max']): act = True reason += ". SF %d - %d only" % (config['sf_min'], config['sf_max']) if not act: return if not config['forcespec']: kwargs['Broadcast'].put("kick %d \"%s\"" % (clnum, reason)) else: kwargs['Broadcast'].put("SendMessage %d \"%s\"" % (clnum, reason)) kwargs['Broadcast'].put("SetTeam #GetIndexFromClientNum(%d)# 0" % (clnum)) kwargs['Broadcast'].broadcast() return
def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('modders'): self.leaderlist.append({'name': name, 'level' : value}) pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append(name) #Don't know how to get boolean values for things in a specific section of .ini for (name, value) in ini.items('var'): if (name == "changesvrname") and (value == "true"): self.SVRNAME = True if (name == "changesvrdesc") and (value == "true"): self.SVRDESC = True if (name == "svrname"): self.svrname = value if (name == "changesvrname"): self.svrdesc = value if (name == "double") and (value == "true"): self.DOUBLEELIM = True
def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer() if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('balancer'): if (name == "threshold"): self.THRESHOLD = int(value) if (name == "jointhreshold"): self.JOINTHRESHOLD = int(value) pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass
def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) #for (name, value) in config.items('mapvote'): # if (name == "level"): # self._level = int(value) # if (name == "sf"): # self._sf = int(value) for (name, value) in ini.items('maps'): self.maplist.append({'name': name, 'status': value}) for (name, value) in ini.items('var'): if (name == "votepercent"): self.VOTEPERCENT = value if (name == "minplayers"): self.MINPLAYERS = value print self.MINPLAYERS, self.VOTEPERCENT pass
def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass
def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('maps'): self.maplist.append({'name' : name, 'status' : value}) for (name, value) in ini.items('var'): if (name == "votepercent"): self.VOTEPERCENT = value if (name == "minplayers"): self.MINPLAYERS = value print self.MINPLAYERS, self.VOTEPERCENT pass
def onPluginLoad(self, config): print("In Plugin Load") self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('queue'): print("In ini Loop: " + str(name) + " / " + str(value)) if (name == "ismodserver"): print("In: if (name == isModServer):") queue.isModServer = value if (name == "ismodservercurrentmod"): print("In: if (name == isModServerCurrentMod)") queue.isModServerCurrentMod = value print("Setting: " + "Set " + str(queue.isModServerGameVar) + " " + str(queue.isModServer)) print("isModServerCurrentMod: " + queue.isModServerCurrentMod)
def handle(self, **kwargs): Log().info("@[{}]".format(self.__class__.__name__)) scenario = kwargs["scenario"] if not is_open("localhost", 5000): # Master server is not running, will do start. Log().info("Master Server starting... ") master_server = MasterServer() master_server.set_scenario(scenario) master_server.start() else: Log().info("Master Server already started.") super(StartMaster, self).handle(**kwargs)
def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer () if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid
class admin(ConsolePlugin): VERSION = "1.3.6" playerlist = [] adminlist = [] banlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client': None, 'firsttime': 0, 'lasttime': 0, 'repeat': 0} def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level': value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level': value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath( os.path.dirname(os.path.realpath(__file__)) + "/../s2wrapper.ini") print config ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem" ) kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem" ) def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'commander' : False}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics(client['acctid']).get('all_stats').get( client['acctid']) level = int(stats['level']) sf = int(stats['sf']) client['sf'] = sf client['level'] = level client['active'] = True #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli, None), kwargs=kwargs) statthread.start() if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Send the chat message: ^rhelp ^cto see what commands you can perform."\ % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>."\ % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) #ADDED: more than 5 message in 1 second = kick tm = time.time() last = self.LASTMESSAGE['lasttime'] first = self.LASTMESSAGE['firsttime'] if (self.LASTMESSAGE['client'] == name): self.LASTMESSAGE['lasttime'] = tm #commanders are immune if not client['commander']: self.LASTMESSAGE['repeat'] += 1 print 'repeat' else: self.LASTMESSAGE['client'] = name self.LASTMESSAGE['firsttime'] = tm self.LASTMESSAGE['repeat'] = 0 if self.LASTMESSAGE['repeat'] > 4: if ((last - first) < 1): reason = "Spamming chat results in automatic kicking." kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (clinum, reason)) self.LASTMESSAGE['client'] = None self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 else: self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['client'] = None self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast( "SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return #Pass to superCommand if the player is a superuser if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast( "SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum, None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists" \ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast( "SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.onBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.getBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.reportBalance, args=(), kwargs=kwargs) balancethread.start() self.logCommand(client['name'], message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmi kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address till the end of the game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) def getBalance(self, *args, **kwargs): clinum = args[0] for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) def reportBalance(self, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) def superCommand(self, message, **kwargs): #This allows superuser to issue any console command supercommand = re.match("sudo (.*)", message, flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath( os.path.dirname(os.path.realpath(__file__)) + "/../.git") command = ["git", "--git-dir", gitpath, "pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onShuffle(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1, 2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -= 1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even self.onBalance(clinum, **kwargs) def onBalance(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #Get Information about the teams teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) startstack = self.evaluateBalance(teamone, teamtwo) #Send message to admin that called the shuffle/balance kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yPrior to balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s" \ % (args[0], teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = self.evaluateBalance(teamone, teamtwo, player1, player2, True) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast(\ "echo unproductive balance") return #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1" \ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #kwargs['Broadcast'].broadcast(\ # "SendMessage %s ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ # % (clinum, teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf / sizeteam med = median(teamsf) teaminfo = { 'size': sizeteam, 'avg': avgteam, 'total': combteamsf, 'median': med } return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total'] / (teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median'] / (teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights': 700, 'Ammo Pack': 500, 'Ammo Satchel': 200, 'Chainmail': 300, 'Gust of Wind': 450, 'Magic Amplifier': 700, 'Brain of Maliken': 750, 'Heart of Maliken': 950, 'Lungs of Maliken': 800, 'Mana Crystal': 500, 'Mana Stone': 200, 'Platemail': 650, 'Power Absorption': 350, 'Shield of Wisdom': 650, 'Stone Hide': 650, 'Tough Skin': 300, 'Trinket of Restoration': 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value'] / 2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0
class beginners(ConsolePlugin): VERSION = "1.0.0" ms = None TIME = 0 GAMESTARTED = 0 STARTSTAMP = 0 CHAT_INTERVAL = 10 CHAT_STAMP = 0 PHASE = 0 MATCHES = 0 playerlist = [] adminlist = [] ipban = [] BANMATCH = 20 SFLIMIT = 110 LEVELLIMIT = 10 MATCHLIMIT = 4 def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('var'): if (name == "banmatch"): self.BANMATCH = int(value) if (name == "sflimit"): self.SFLIMIT = int(value) if (name == "levellimit"): self.LEVELLIMIT = int(value) if (name == "matchlimit"): self.MATCHLIMIT = int(value) for (name, value) in ini.items('ipban'): self.ipban.append(name) admins = os.path.join(os.path.dirname(config),'admin.ini') ini.read(admins) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) print self.adminlist pass def onStartServer(self, *args, **kwargs): self.VERSION = "0.0.6" self.TIME = 0 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.CHAT_INTERVAL = 10 self.CHAT_STAMP = 0 self.PHASE = 0 self.MATCHES = 0 self.playerlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): print 'already have entry with that clientnum!' return for each in self.ipban: if each == ip: kwargs['Broadcast'].broadcast("kick %s You are banned from this server" % (cli)) self.playerlist.append ({'clinum' : id, 'acctid' : 0, 'level' : 0, 'sf' : 0, 'name' : 'X', 'active' : 0, 'banned' : False, 'ip' : ip, 'banstamp' : 0, 'kills' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = 0 def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): doKick = False reason1 = "This is a beginners server. Please go play on a normal server." reason2 = "You (or someone at your IP address) have been temporarily prohibited from this server." reason3 = "Please go play on normal server." cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) wins = int(stats['wins']) losses = int(stats['losses']) dcs = int(stats['d_conns']) exp = int(stats['exp']) time = int(stats['secs']) if sf == 0 and time > 0: time = time/60 sf = int(exp/time) total = wins + losses + dcs client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = 1 if client['banned']: reason = reason3 doKick = True for each in self.playerlist: if each['banned'] and (each['ip'] == client['ip']): reason = reason2 doKick = True if (sf > self.SFLIMIT) and (total > self.MATCHLIMIT): reason = reason1 doKick = True client ['banned'] = True client ['banstamp'] = self.MATCHES if (level > self.LEVELLIMIT): reason = reason1 doKick = True for each in self.adminlist: if each['name'].lower() == client['name'].lower(): doKick = False client['banned'] = False if doKick: kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) print client def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) if (team > 0): client['active'] = 1 if (team == 0): client['active'] = 0 def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.onGameEnd() if (phase == 5): self.onGameStart(*args, **kwargs) def onGameEnd(self, *args, **kwargs): self.MATCHES += 1 #all players are unbanned after 15 matches for each in self.playerlist: each['kills'] = 0 each['active'] = 0 duration = self.MATCHES - int(each['banstamp']) if duration > self.BANMATCH: each['banned'] = False self.GAMESTARTED = 0 def onGameStart (self, *args, **kwargs): self.STARTSTAMP = args[1] self.GAMESTARTED = 1 for each in self.playerlist: each['kills'] = 0 def onServerStatus(self, *args, **kwargs): CURRENTSTAMP = int(args[1]) self.TIME = int(CURRENTSTAMP) - int(self.STARTSTAMP) if self.PHASE == 5: if (self.TIME > (10 * 60 * 1000)): self.smurfCheck (**kwargs) def onGetLevels(self, *args, **kwargs): clinum = args[0] level = int(args[1]) client = self.getPlayerByClientNum(clinum) def onGetLevels(self, *args, **kwargs): clinum = args[0] level = int(args[1]) client = self.getPlayerByClientNum(clinum) doKick = False reason = "This is either a smurf account or you are too good for this server. You should play on another server." if level > 6: doKick = True client ['banned'] = True client ['banstamp'] = self.MATCHES if doKick: kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) def onHasKilled(self, *args, **kwargs): killed = self.getPlayerByName(args[0]) killer = self.getPlayerByName(args[1]) killer['kills'] += 1 print killer print killed def smurfCheck(self, **kwargs): totalkills = 0 activeplayers = 0 avgkills = 0 reason = "Congratulations! You have done a great job and have graduated from this server." for each in self.playerlist: if each['active'] == 1: activeplayers += 1 totalkills += int(each['kills']) avgkills = int(totalkills/activeplayers) kwargs['Broadcast'].broadcast("echo BEGINNERS: Average kills: %s" % (avgkills)) for players in self.playerlist: if players['active'] == 1: over = 'No' if (players['kills'] > (avgkills * 3)) and (players['kills'] > 20): over = 'Yes' cli = players['clinum'] #players['banned'] = True #players['banstamp'] = self.MATCHES #kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) kwargs['Broadcast'].broadcast("echo BEGINNERS: Player: %s, Kills: %s, Over?: %s" % (players['name'], players['kills'], over)) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) if (args[0] == "SQUAD") and (message == 'report bans'): for bans in self.playerlist: if bans['banned']: kwargs['Broadcast'].broadcast("SendMessage %s Banned: %s, IP: %s" % (client['clinum'], bans['name'], bans['ip']))
class mapvote(ConsolePlugin): VERSION = "0.0.1" ms = None PHASE = 0 playerlist = [] maplist = [] votelist = {'votes': 0, 'playervotes': []} TOTALPLAYERS = 0 VOTEPERCENT = 40 MINPLAYERS = 0 NEWMAP = None MAPVOTE = True def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) #for (name, value) in config.items('mapvote'): # if (name == "level"): # self._level = int(value) # if (name == "sf"): # self._sf = int(value) for (name, value) in ini.items('maps'): self.maplist.append({'name': name, 'status': value}) for (name, value) in ini.items('var'): if (name == "votepercent"): self.VOTEPERCENT = value if (name == "minplayers"): self.MINPLAYERS = value print self.MINPLAYERS, self.VOTEPERCENT pass def onStartServer(self, *args, **kwargs): print 'serverstarted' def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] self.playerlist.append({ 'clinum': id, 'acctid': 0, 'name': 'X', 'active': 0 }) def onSetName(self, *args, **kwargs): mapnames = [] for each in self.maplist: mapnames.append(each['name']) mapnames = ', '.join(mapnames) mapmessage = "^cThis server is currently equipped with the ability to vote for a map change. Before a game has started you can send the message to ^rALL ^cchat: ^ynextmap mapname" mapmessage2 = "^cThis will register your vote for that map." mapmessage3 = ("^cCurrent valid maps are: ^y%s" % (mapnames)) cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage2)) kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage3)) def onAccountId(self, *args, **kwargs): self.TOTALPLAYERS += 1 cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['active'] = 1 def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) for each in self.playerlist: if cli == each['clinum']: each['active'] = 0 #if a player has voted and disconnects, remove their vote for each in self.votelist['playervotes']: if each['player'] == client['name']: self.votelist['playervotes'].remove(each) self.votelist['votes'] -= 1 self.TOTALPLAYERS -= 1 def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.onGameEnd(**kwargs) if (phase == 6): self.clearMapVotes(*args, **kwargs) if (phase == 5): self.clearMapVotes(*args, **kwargs) def onNewGame(self, *args, **kwargs): if (self.PICKING == 1): print 'team picking has begun, do not clear team player lists' kwargs['Broadcast'].broadcast( "echo team picking has begun, do not clear team player lists!") self.PICKING = 0 return def voteCheck(self, *args, **kwargs): tie = False totalplayers = self.TOTALPLAYERS totalvotes = self.votelist['votes'] minplayers = int(self.MINPLAYERS) threshold = int(self.VOTEPERCENT) votepercent = int(totalvotes / totalplayers) * 100 #At least this many players must be present to even trigger a map selection if totalplayers < minplayers: print totalplayers print 'minplayer abort' return #This percentage of the total number of players must vote to trigger a map selection if votepercent < threshold: print votepercent print 'percent abort' return #determine which map has the most votes d = {} for votes in self.votelist['playervotes']: maps = votes['mapvote'] d.setdefault(maps, 0) d[maps] += 1 items = [(v, k) for k, v in d.items()] items.sort() items.reverse() size = len(items) if size > 1: if items[0][0] == items[1][0]: print 'we have a tie' tie = True if tie: kwargs['Broadcast'].broadcast( "Serverchat ^cThere is a tie between ^r%s ^cand ^r%s. ^cIf you would like to change your vote you may do so." % (items[0][1], items[1][1])) return #We have a map winner newmap = items[0][1] self.ChangeMap(newmap, **kwargs) def ChangeMap(self, newmap, **kwargs): status = 'official' for each in self.maplist: if each['name'] == newmap: status = each['status'] if status == 'unofficial': kwargs['Broadcast'].broadcast( "set svr_sendStats false; set svr_official false ") kwargs['Broadcast'].broadcast("changeworld %s" % (newmap)) self.clearMapVotes(*args, **kwargs) def onMessage(self, *args, **kwargs): voted = False votemap = None #ignore anything that isn't sent to ALL chat if args[0] != "ALL": return #if the game has started, or we are in end phase, ignore if self.PHASE == 5 or self.PHASE == 7: return name = args[1] message = args[2] client = self.getPlayerByName(name) mapvote = re.match("nextmap (\S+)", message, flags=re.IGNORECASE) formap = mapvote.group(1) if not mapvote: return if mapvote: voted = self.CheckVoted(client) for maps in self.maplist: if formap == maps['name']: votemap = formap if votemap == None: #Map name is invalid, tell them they got it wrong kwargs['Broadcast'].broadcast( "SendMessage %s ^cMap name not recognized." % (client['clinum'])) return #player has already voted, just change their map selection if voted: for each in self.votelist['playervotes']: if each['player'] == client['name']: each['mapvote'] = votemap kwargs['Broadcast'].broadcast( "SendMessage %s ^cYou have switched your vote to ^r%s." % (client['clinum'], votemap)) self.reportVotes(**kwargs) self.voteCheck(**kwargs) return #player has not yet voted, add to the total number of votes and add their selection to the list self.votelist['votes'] += 1 self.votelist['playervotes'].append({ 'player': client['name'], 'mapvote': votemap }) kwargs['Broadcast'].broadcast( "SendMessage %s ^cYou have voted for ^r%s." % (client['clinum'], votemap)) self.reportVotes(**kwargs) #check to see if all the voting critera have been met self.voteCheck(**kwargs) def CheckVoted(self, client, **kwargs): for each in self.votelist['playervotes']: if each['player'] == client['name']: return True def clearMapVotes(self, *args, **kwargs): self.votelist = {'votes': 0, 'playervotes': []} self.TOTALPLAYERS = 0 def reportVotes(self, *args, **kwargs): d = {} for votes in self.votelist['playervotes']: maps = votes['mapvote'] d.setdefault(maps, 0) d[maps] += 1 items = [(v, k) for k, v in d.items()] items.sort() items.reverse() for each in items: kwargs['Broadcast'].broadcast("Serverchat ^cVotes for ^r%s: ^c%s" % (each[1], each[0])) def onGameEnd(self, *args, **kwargs): kwargs['Broadcast'].broadcast( "set svr_sendStats true; set svr_official true")
class sandbox(ConsolePlugin): VERSION = "0.2.5" playerlist = [] leaderlist = [] modlist = [] PHASE = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('modders'): self.leaderlist.append({'name': name, 'level' : value}) pass def reload_config(self): self.leaderlist = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('modders'): self.leaderlist.append({'name': name, 'level' : value}) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'sandbox': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.modlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'level' : 0,\ 'leader' : False,}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername kwargs['Broadcast'].broadcast("SendMessage %s ^yThis server is running the Sandbox plugin by GGGGGGGG. Version : %s. Mods currently active: ^r%" % (cli, self.VERSION, self.modlist)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) client = self.getPlayerByClientNum(cli) client['level'] = level client['active'] = True if self.isLeader(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as a modder. You can now use the sandbox. Send the chat message: ^rsb help ^cto see what commands you can perform."\ % (cli)) client['leader'] = True def isLeader(self, client, **kwargs): leader = False for each in self.leaderlist: if client['name'].lower() == each['name']: leader = True return leader def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) leader = self.isLeader(client, **kwargs) if not leader: return startgame = re.match("sb startgame", message, flags=re.IGNORECASE) giveteamgold = re.match("sb giveteamgold (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayergold = re.match("sb givegold (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayersoul = re.match("sb givesoul (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayerexperience = re.match("sb giveexp (\S+) (\S+)", message, flags=re.IGNORECASE) giveplayerammo = re.match("sb giveammo (\S+)", message, flags=re.IGNORECASE) resetattributes = re.match("sb resetattributes (\S+)", message, flags=re.IGNORECASE) resetexp = re.match("sb resetexp (\S+)", message, flags=re.IGNORECASE) refillhealth = re.match("sb refillhealth (\S+)", message, flags=re.IGNORECASE) refillmana = re.match("sb refillmana (\S+)", message, flags=re.IGNORECASE) refillstamina = re.match("sb refillstamina (\S+)", message, flags=re.IGNORECASE) kick = re.match("sb kick (\S+)", message, flags=re.IGNORECASE) slap = re.match("sb slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("sb changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("sb help", message, flags=re.IGNORECASE) playerhelp = re.match("sb player help", message, flags=re.IGNORECASE) teamchange = re.match("sb allowteamchange", message, flags=re.IGNORECASE) teamdifference = re.match("sb teamdiff", message, flags=re.IGNORECASE) changepassword = re.match("sb password (\S+)", message, flags=re.IGNORECASE) setteam = re.match("sb setteam (\S+) (\S+)", message, flags=re.IGNORECASE) sbsudo = re.match("sb sudo (.*)", message, flags=re.IGNORECASE) modhelp = re.match("sb mod help", message, flags=re.IGNORECASE) movespeed = re.match("sb mod speed (\S+)", message, flags=re.IGNORECASE) gravity = re.match("sb mod gravity (\S+)", message, flags=re.IGNORECASE) buildspeed = re.match("sb mod buildspeed (\S+)", message, flags=re.IGNORECASE) jump = re.match("sb mod jump (\S+)", message, flags=re.IGNORECASE) modenable = re.match("mm enable (\S+)", message, flags=re.IGNORECASE) modactive = re.match("mm get active", message, flags=re.IGNORECASE) modindirectory = re.match("mm get list", message, flags=re.IGNORECASE) modreset = re.match("mm reset", message, flags=re.IGNORECASE) mmhelp = re.match("mm help", message, flags=re.IGNORECASE) mmcreate = re.match("mm create (\S+)", message, flags=re.IGNORECASE) mmdelete = re.match("mm delete (\S+)", message, flags=re.IGNORECASE) mmmodify = re.match("mm modify (\S+) (\S+) (.*)", message, flags=re.IGNORECASE) mmview = re.match("mm view (\S+)", message, flags=re.IGNORECASE) mmwrite = re.match("mm write (\S+) (.*)") if startgame: kwargs['Broadcast'].broadcast("startgame") if sbsudo: kwargs['Broadcast'].broadcast("%s" % (sbsudo.group(1))) if giveteamgold: kwargs['Broadcast'].broadcast("giveteamgold %s %s" % (giveteamgold.group(1), giveteamgold.group(2))) if giveplayergold: playergold = self.getPlayerByName(giveplayergold.group(1)) kwargs['Broadcast'].broadcast("givegold %s %s" % (playergold['clinum'], giveplayergold.group(2))) if giveplayerammo: playerammo = self.getPlayerByName(giveplayerammo.group(1)) kwargs['Broadcast'].broadcast("giveammo %s" % (playerammo['clinum'])) if giveplayersoul: playersoul = self.getPlayerByName(giveplayersoul.group(1)) kwargs['Broadcast'].broadcast("givesoul %s %s" % (playersoul['clinum'], giveplayersoul.group(2))) if giveplayerexperience: playerexperience = self.getPlayerByName(giveplayerexperience.group(1)) kwargs['Broadcast'].broadcast("giveexp %s %s" % (playerexperience['clinum'], giveplayerexperience.group(2))) if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast("Kick %s \"%s\""% (kickclient['clinum'], reason)) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: kwargs['Broadcast'].broadcast("changeworld %s" % (changeworld.group(1))) if movespeed: kwargs['Broadcast'].broadcast("set p_speed %s" % (movespeed.group(1))) if jump: kwargs['Broadcast'].broadcast("set p_jump %s" % (jump.group(1))) if gravity: kwargs['Broadcast'].broadcast("set p_gravity %s" % (gravity.group(1))) if buildspeed: kwargs['Broadcast'].broadcast(\ "set Player_Conjurer_BuildingRepairRate %s;\ set Player_Engineer_BuildingRepairRate %s;"\ % (buildspeed.group(1), buildspeed.group(1))) if teamchange: kwargs['Broadcast'].broadcast("set g_allowteamchange true") if teamdifference: kwargs['Broadcast'].broadcast("set sv_maxTeamDifference 20") if changepassword: kwargs['Broadcast'].broadcast("set svr_connectpass %s" % (changepassword.group(1))) if setteam: #swap a player to a different team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) if resetattributes: resetattributesplayer = self.getPlayerByName(resetattributes.group(1)) kwargs['Broadcast'].broadcast("ResetAttributes #GetIndexFromClientNum(%s)#" % (resetattributesplayer['clinum'])) if resetexp: resetexpplayer = self.getPlayerByName(resetexp.group(1)) kwargs['Broadcast'].broadcast("ResetExp %s" % (resetexpplayer['clinum'])) if refillhealth: refillhealthplayer = self.getPlayerByName(refillhealth.group(1)) kwargs['Broadcast'].broadcast("RefillHealth #GetIndexFromClientNum(%s)#" % (refillhealthplayer['clinum'])) if refillmana: refillmanaplayer = self.getPlayerByName(refillmana.group(1)) kwargs['Broadcast'].broadcast("RefillMana #GetIndexFromClientNum(%s)#" % (refillmanaplayer['clinum'])) if refillstamina: refillstaminaplayer = self.getPlayerByName(refillstamina.group(1)) kwargs['Broadcast'].broadcast("RefillStamina #GetIndexFromClientNum(%s)#" % (refillstaminaplayer['clinum'])) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod help ^w for more info about the sb mod commands."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb player help ^w for more info about command's that affect players."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb startgame ^w will start the game"\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveteamgold team amount^w. will give gold to a team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb sudo args ^wdo whatever commands you want."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb allowteamchange ^wwill allow switching team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb teamdiff ^wwill allow everyone to join in the same team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb changepassword ^wwill change the server's password."\ % (client['clinum'])) if modhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb buildspeed amount ^wwill change the build speed."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod gravity amount ^wwill change the gravity."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod jump amount ^wwill change the jump height."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb mod speed amount ^wwill change the movement speed of the server."\ % (client['clinum'])) if playerhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb setteam playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb givegold player amount ^wwill give gold to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb givesoul player amount ^wwill give souls to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveexp player amount ^wwill give experience to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb resetexp player ^wwill reset exp of a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb resetattributes ^wwill reset all attributes of a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillhealth ^wwill refill a player health."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillmana ^wwill refill a player mana."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb refillstamina ^wwill refill a player stamina."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb giveammo player ^wwill give ammo to a player."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb kick ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rsb slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) if mmhelp: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm enable modname ^wwill enable a mod."\ % (client['clinum'])) #modenable kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm get active ^wwill show all active mods."\ % (client['clinum'])) #modactive kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm get list ^wwill show all the possible mods."\ % (client['clinum'])) #modindirectory kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm reset ^wwill reset everything to its default settings."\ % (client['clinum'])) #modreset kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm create name ^wwill create a new mod with the specified name."\ % (client['clinum'])) #mmcreate kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm delete name^wwill delete a mod with the specified name."\ % (client['clinum'])) #mmdelete kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm modify name linenumber arg^wwill edit a mod by replacing a line with its arg."\ % (client['clinum'])) #mmmodify kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm view name ^wwill view what a mod contain with the specified name."\ % (client['clinum'])) #mmview kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rmm write name arg ^wwill write a line in a mod file."\ % (client['clinum'])) #mmwrite if modenable: #Enable a specific mod modName = "./mods/" + modenable.group(1) if os.path.isfile(modName): #Check if it exists with open(modName, 'r') as modfile: for line in modfile: kwargs['Broadcast'].broadcast("%s" % (line)) self.modlist.append(modenable.group(1)) kwargs['Broadcast'].broadcast("SendMessage -1 %s has been enabled." % (modenable.group(1))) else: kwargs['Broadcast'].broadcast("SendMessage -1 %s does not exist." % (modenable.group(1))) if modactive: #Shows the active mods currently on the server kwargs['Broadcast'].broadcast("SendMessage %s mods currently active on this server:" % (client['clinum'])) if len(self.modlist) == 0: kwargs['Broadcast'].broadcast("SendMessage %s None" % (client['clinum'])) else: for element in self.modlist: kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], element)) if modreset: #Reset all the mods to its original state self.modlist = [] with open("./mods/original", 'r') as original: for line in original: kwargs['Broadcast'].broadcast("%s" % (line)) kwargs['Broadcast'].broadcast("SendMessage -1 All mods have been reseted.") if modindirectory: #Used to check what mods are in the directory modindir = os.listdir("./mods/") for each in modindir: kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], each)) if mmcreate: #Used to create a mod modName = mmcreate.group(1) with open(modName, 'w') as newmodfile: newmodfile.write("//%s", newmodfile) kwargs['Broadcast'].broadcast("SendMessage %s %s has been created succesfully" % (client['clinum'], newmodfile)) if mmview: #Used to view a mod with open("./mods/" + mmview.group(1), 'r') as modFile: for line in modFile: numberLine = 0 kwargs['Broadcast'].broadcast("SendMessage %s %s %s" % (client['clinum'], numberLine, line)) numberLine += 1 if mmdelete: #Used to delete a mod os.remove("./mods/" + mmdelete.group(1)) kwargs['Broadcast'].broadcast("SendMessage %s %s has been deleted with success" % (client['clinum'], mmdelete.group(1))) if mmwrite: #Used to write a line in a mod with open("./mods/" + mmwrite.group(1), 'a+') as modFile: modFile.write(mmwrite.group(2)) kwargs['Broadcast'].broadcast("SendMessage %s %s has been added to %s successfully" % (client['clinum'], mmwrite.group(2), mmwrite.group(1))) if mmmodify: #modify a specific line with open("./mods/" + mmmodify.group(1), 'r') as modFile: data = modFile.readlines() data[mmmodify.group(2)] = mmmodifiy.group(3) with open("./mods" + mmmodify.group(1), 'w') as modFile: modFile.writelines(data) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] self.modlist = [] with open("./mods/original", 'r') as original: for line in original: kwargs['Broadcast'].broadcast("%s" % (line)) for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch leader list and reload at the start of each game try: response = urllib2.urlopen('http://cedeqien.com/modders.ini') leaderlist = response.read() leaderfile = os.path.join(os.path.dirname(self.CONFIG),'modders.ini') with open(leaderfile, 'w') as f: f.write(leaderlist) #reload the config file self.onPluginLoad(leaderfile) except: return def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum']))
class balancer(ConsolePlugin): VERSION = "1.0.8" ms = None TIME = 0 THRESHOLD = 6 JOINTHRESHOLD = 8 DIFFERENCE = -1 GAMESTARTED = 0 STARTSTAMP = 0 DENY = 0 OPTION = 0 PICKING = 0 CHAT_INTERVAL = 10 CHAT_STAMP = 0 PHASE = 0 TOTAL1 = 0 TOTAL2 = 0 STAMPS = 0 reason = "Your Skill Factor is 0. Please play some matches on official beginner servers to get some stats before you join this server." playerlist = [] itemlist = [] balancereport = [] teamOne = {'size': 0, 'avgBF': -1, 'combinedBF': 0, 'players': []} teamTwo = {'size': 0, 'avgBF': -1, 'combinedBF': 0, 'players': []} game = {'size': 0, 'avgBF': -1} switchlist = [] followlist = [] def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('balancer'): if (name == "threshold"): self.THRESHOLD = int(value) if (name == "jointhreshold"): self.JOINTHRESHOLD = int(value) pass def onStartServer(self, *args, **kwargs): self.TIME = 0 self.THRESHOLD = 6 self.DIFFERENCE = -1 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.PICKING = 0 self.CHAT_INTERVAL = 10 self.CHAT_STAMP = 0 self.PHASE = 0 self.TOTAL1 = 0 self.TOTAL2 = 0 self.STAMPS = 0 self.playerlist = [] self.itemlist = [] self.balancereport = [] self.teamOne = {'size': 0, 'avgBF': -1, 'combinedBF': 0, 'players': []} self.teamTwo = {'size': 0, 'avgBF': -1, 'combinedBF': 0, 'players': []} self.game = {'size': 0, 'avgBF': -1} self.switchlist = [] self.followlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onRefresh(self, *args, **kwargs): del self.teamOne['players'][:] del self.teamTwo['players'][:] self.teamOne['size'] = 0 self.teamTwo['size'] = 0 for client in self.playerlist: if (client['active'] == 1): kwargs['Broadcast'].broadcast( "set _idx #GetIndexFromClientNum(%s)#; set _team #GetTeam(|#_idx|#)#; echo CLIENT %s is on TEAM #_team#" % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) if (team > 0): client = self.getPlayerByClientNum(clinum) teamlists = self.GetTeamLists(client, team) fromteam = teamlists['fromteam'] self.addTeamMember(client, fromteam, team, **kwargs) return def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): #added 10/12. If a player DCs and reconnects, they are auto-joined to their old team #but there is no team join message. This automatically adds them back to the balancer team list. print 'already have entry with that clientnum!' team = int(client['team']) if (team > 0): teamlists = self.GetTeamLists(client, team) toteam = teamlists['toteam'] fromteam = teamlists['fromteam'] self.addTeamMember(client, fromteam, team, **kwargs) client['active'] = 1 return return self.playerlist.append({ 'clinum': id, 'acctid': 0, 'level': 0, 'sf': 0, 'bf': 0, 'lf': 0, 'name': 'X', 'team': 0, 'moved': 0, 'index': 0, 'exp': 2, 'value': 150, 'prevent': 0, 'active': 0, 'gamelevel': 1 }) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onAccountId(self, *args, **kwargs): doKick = False cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) if sf == 0 and exp > 500: time = time / 60 sf = int(exp / time) client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['level'] = level client['sf'] = sf client['lf'] = lf client['exp'] = exp client['active'] = 1 if sf == 0: doKick = True if doKick: kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, self.reason)) self.retrieveLevels(cli, **kwargs) def checkForSpectator(self, cli): player = self.getPlayerByClientNum(cli) if (player['team'] > 0): return cli else: return -1 def getTeamMember(self, item, cli, fromteam): indice = -1 for player in fromteam['players']: indice += 1 if (player['clinum'] == cli): return indice def getPlayerIndex(self, cli): indice = -1 for player in self.playlist: indice += 1 if (player['clinum'] == cli): return indice def removeTeamMember(self, client, fromteam, team, **kwargs): print 'Removing player....' client['team'] = team cli = client['clinum'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) fromteam['combinedBF'] -= fromteam['players'][PLAYER_INDICE]['bf'] del fromteam['players'][PLAYER_INDICE] self.getGameInfo(**kwargs) def addTeamMember(self, client, toteam, team, **kwargs): print 'Adding player....' cli = client['clinum'] client['active'] = 1 NAME = client['name'] level = client['level'] SF = client['sf'] #BF = SF + level + (client ['gamelevel'] * 4) BF = SF + (client['gamelevel'] * 4) LF = client['lf'] + 10 moved = client['moved'] client['team'] = team client['bf'] = BF toteam['players'].append({ 'clinum': cli, 'name': NAME, 'sf': SF, 'lf': LF, 'level': level, 'moved': moved, 'bf': BF }) self.getGameInfo(**kwargs) def GetTeamLists(self, client, team): currentteam = client['team'] L = {'toteam': '0', 'fromteam': '0'} if (int(currentteam) == 1): L['fromteam'] = self.teamOne L['toteam'] = self.teamTwo return L if (int(currentteam) == 2): L['fromteam'] = self.teamTwo L['toteam'] = self.teamOne return L if (int(team) == 1): L['toteam'] = self.teamOne if (int(team) == 2): L['toteam'] = self.teamTwo return L #don't think I need this but I am leaving it in del L[0] def onTeamChange(self, *args, **kwargs): spec = -1 team = int(args[1]) cli = args[0] self.retrieveLevels(cli, **kwargs) client = self.getPlayerByClientNum(cli) currentteam = client['team'] prevented = int(client['prevent']) teamlists = self.GetTeamLists(client, team) toteam = teamlists['toteam'] fromteam = teamlists['fromteam'] if (self.DENY == 1): self.DIFFERENCE = abs(self.evaluateBalance()) diff = self.DIFFERENCE #check to see if the player is on a team and going to spectator. spec = -1 unless the player is already on a team if (int(team) == 0): spec = self.checkForSpectator(cli) #need to have this to avoid having players added multiple times as I have seen happen if (spec == -1) and (int(currentteam) == int(team)): return #if the player is switching teams, add them to the new team and remove from the old if (spec == -1) and (int(currentteam) > 0): self.addTeamMember(client, toteam, team, **kwargs) self.removeTeamMember(client, fromteam, team, **kwargs) #if the player hasn't joined a team yet, go ahead and add them to the team elif (spec == -1): self.addTeamMember(client, toteam, team, **kwargs) self.getGameInfo(**kwargs) #Players are prevented from joining in the deny phase if they will cause greater than a 10% stack #this applies to both even and uneven games. The player is forced back to team 0. if (self.DENY == 1): self.DIFFERENCE = abs(self.evaluateBalance()) if (self.DIFFERENCE > self.JOINTHRESHOLD) and (self.DIFFERENCE > diff): action = 'PREVENT' self.retrieveIndex(client, action, **kwargs) return #There may be an issue if the player is forced back to team 0 that they can't join a team #even if conditions are met. This just forcibly puts the player on the team they are are trying to join #provided the above critera is not true. if (prevented == 1): action = 'ALLOW' self.retrieveIndex(client, action, **kwargs) #if the player is going to spec, just remove them from the team if (spec > -1): self.removeTeamMember(client, fromteam, team, **kwargs) self.OPTION = 0 def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) team = client['team'] if (int(team) > 0): teamlist = self.GetTeamLists(client, team) fromteam = teamlist['fromteam'] self.removeTeamMember(client, fromteam, team, **kwargs) #self.sendGameInfo(**kwargs) client['active'] = 0 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) team = client['team'] cli = client['clinum'] teamlist = self.GetTeamLists(client, team) fromteam = teamlist['fromteam'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) fromteam['players'][PLAYER_INDICE]['bf'] = client['sf'] + ( client['gamelevel'] * 4) #fromteam['players'][PLAYER_INDICE]['bf'] = int(client['sf'] + client['level'] + (client['gamelevel']*4)) fromteam['players'][PLAYER_INDICE]['moved'] = 0 client['moved'] = 0 def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) team = client['team'] teamlist = self.GetTeamLists(client, team) fromteam = teamlist['fromteam'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) #fromteam['players'][PLAYER_INDICE]['bf'] = client ['lf'] fromteam['players'][PLAYER_INDICE]['bf'] = fromteam['players'][ PLAYER_INDICE]['lf'] fromteam['players'][PLAYER_INDICE]['moved'] = 1 #set moved to 1 to prevent the player from being auto-swapped as commander client['moved'] = 1 def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.onGameEnd(**kwargs) if (phase == 5): self.onGameStart(*args, **kwargs) self.PICKING = 0 if (phase == 3): self.PICKING = 1 if (phase == 6): self.onNewGame(*args, **kwargs) def onGameEnd(self, *args, **kwargs): avg1 = int(self.TOTAL1 / self.STAMPS) avg2 = int(self.TOTAL2 / self.STAMPS) print avg1, avg2, self.STAMPS kwargs['Broadcast'].broadcast( "Serverchat ^cHow stacked was this game from start to finish? Humans had an average combined BF of ^r%s^c, Beasts had an average combined BF of ^r%s ^cfrom a total of ^y%s ^ctime points." % (avg1, avg2, self.STAMPS)) #clear out the team dictionary info and globals when the map is reloaded del self.teamOne['players'][:] del self.teamTwo['players'][:] for player in self.playerlist: player['active'] = 0 player['team'] = 0 player['gamelevel'] = 1 player['bf'] = int(player['sf'] + player['level']) player['value'] = 150 self.teamOne['size'] = 0 self.teamOne['avgBF'] = -1 self.teamOne['combinedBF'] = 0 self.teamTwo['size'] = 0 self.teamTwo['avgBF'] = -1 self.teamTwo['combinedBF'] = 0 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.DIFFERENCE = -1 self.PICKING = 0 self.balancereport = [] #self.playerlist = [] self.TOTAL1 = 0 self.TOTAL2 = 0 self.STAMPS = 0 def onNewGame(self, *args, **kwargs): if (self.PICKING == 1): print 'team picking has begun, do not clear team player lists' kwargs['Broadcast'].broadcast( "echo team picking has begun, do not clear team player lists!") self.PICKING = 0 return #clear out the team dictionary info and globals when the map is reloaded del self.teamOne['players'][:] del self.teamTwo['players'][:] for player in self.playerlist: player['active'] = 0 player['team'] = 0 player['gamelevel'] = 1 player['bf'] = int(player['sf'] + player['level']) player['value'] = 150 self.teamOne['size'] = 0 self.teamOne['avgBF'] = -1 self.teamOne['combinedBF'] = 0 self.teamTwo['size'] = 0 self.teamTwo['avgBF'] = -1 self.teamTwo['combinedBF'] = 0 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.DIFFERENCE = -1 self.RegisterScripts(**kwargs) def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem" ) kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem" ) #this makes sure we get an update every thirty seconds. kwargs['Broadcast'].broadcast("set sv_statusNotifyTime 30000") def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights': 700, 'Ammo Pack': 500, 'Ammo Satchel': 200, 'Chainmail': 300, 'Gust of Wind': 450, 'Magic Amplifier': 700, 'Brain of Maliken': 750, 'Heart of Maliken': 950, 'Lungs of Maliken': 800, 'Mana Crystal': 500, 'Mana Stone': 200, 'Platemail': 650, 'Power Absorption': 350, 'Shield of Wisdom': 650, 'Stone Hide': 650, 'Tough Skin': 300, 'Trinket of Restoration': 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def retrieveIndex(self, mover, action, **kwargs): #Use this for any manipulations when you need to get the current player index from the server. This is used for MOVE, PREVENT, ALLOW cli = mover['clinum'] client = self.getPlayerByClientNum(cli) kwargs['Broadcast'].broadcast( "set _value #GetIndexFromClientNum(%s)#; echo Sv: Client %s index is #_value#. ACTION: %s" % (cli, cli, action)) def onRetrieveIndex(self, *args, **kwargs): #get stuff from parser clinum = args[0] index = args[1] action = args[2] if (action == 'MOVE'): self.move(clinum, index, **kwargs) if (action == 'PREVENT'): self.prevent(clinum, index, **kwargs) if (action == 'ALLOW'): self.allow(clinum, index, **kwargs) if (action == 'LEVEL'): self.level(clinum, index, **kwargs) def runBalancer(self, **kwargs): #determines if it is even or uneven balancer #3-23-11 - If there are fewer than 8 players, don't bother with balancer if (self.teamOne['size'] + self.teamTwo['size']) < 8: return diff = self.teamOne['size'] - self.teamTwo['size'] print diff if (diff == 0): self.EvenTeamBalancer(**kwargs) #uneven balancer if there is a difference between 1-3. if it more than that, it would be best to restart, but that has not been implemented elif (abs(diff) > 0 and abs(diff) < 4): self.UnEvenTeamBalancer(**kwargs) else: return def onGameStart(self, *args, **kwargs): self.ItemList() self.STARTSTAMP = args[1] self.GAMESTARTED = 1 kwargs['Broadcast'].broadcast("echo GAMESTARTED") self.sendGameInfo(**kwargs) kwargs['Broadcast'].broadcast( "ServerChat ^cIf necessary, the teams will be auto-balanced at 1, 3, and 6 minutes of game time." ) kwargs['Broadcast'].broadcast( "ServerChat ^cAfter 6 minutes, joining will be limited to players that do not generate imbalance." ) kwargs['Broadcast'].broadcast( "ServerChat ^cAt 5 minute increments starting at minute 10, the server will check for imbalance and notify players that they will be switched in one minute unless they reject the move." ) kwargs['Broadcast'].broadcast( "ServerChat ^cSelected players may send the message 'reject' to ^bALL ^cchat to prevent the change." ) self.RegisterScripts(**kwargs) self.startFollow(**kwargs) def onServerStatus(self, *args, **kwargs): CURRENTSTAMP = int(args[1]) self.TIME = int(CURRENTSTAMP) - int(self.STARTSTAMP) #self.getTeamLevels(**kwargs) kwargs['Broadcast'].broadcast( "set _team1num #GetNumClients(1)#; set _team2num #GetNumClients(2)#; echo SERVER-SIDE client count, Team 1 #_team1num#, Team 2 #_team2num#" ) if (self.GAMESTARTED == 1): self.TOTAL1 += self.teamOne['combinedBF'] self.TOTAL2 += self.teamTwo['combinedBF'] self.STAMPS += 1 def evaluateBalance(self, BF1=0.0, BF2=0.0, moving=False, **kwargs): large = self.getLargeTeam() small = self.getSmallTeam() largebf = float(large['combinedBF']) smallbf = float(small['combinedBF']) totalbf = largebf + smallbf largeshare = (largebf - BF1 + BF2) / totalbf smallshare = (smallbf + BF1 - BF2) / totalbf largesize = float(large['size']) smallsize = float(small['size']) totalsize = largesize + smallsize if moving: largesize = float(large['size']) - 1.0 smallsize = float(small['size']) + 1.0 sizediff = largesize / totalsize largepercent = largeshare #largepercent = largeshare + sizediff return (largepercent - 0.5) * 100 #return (largepercent - 1) * 100 def getClosestPersonToTarget(self, team, **kwargs): lowest = -1 pick = None for player1 in team['players']: if (player1['moved'] == 1): continue ltarget = abs(self.evaluateBalance(float(player1['bf']), 0.0, True)) print ltarget if (lowest < 0): lowest = ltarget # wouldn't work if the first player was the one to pick, so had to do this here pick = player1 continue if (lowest < ltarget): continue lowest = ltarget pick = player1 print pick if (pick == None): kwargs['Broadcast'].broadcast( "echo BALANCER: UNEVEN balancer was not happy for some reason I can't figure out" ) return kwargs['Broadcast'].broadcast( "echo BALANCER: UNEVEN balancer selections: Client %s with bf %s for a starting BF stacking of %s to %s" % (pick['clinum'], pick['bf'], self.DIFFERENCE, lowest)) #if the selected option doesn't actually improve anything, terminate if (lowest > self.DIFFERENCE): kwargs['Broadcast'].broadcast( "echo BALANCER: unproductive UNEVEN balance") return if (self.OPTION == 0): #get the player index and move them action = 'MOVE' self.retrieveIndex(pick, action, **kwargs) return if (self.OPTION == 1): self.switchlist.append({ 'name': pick['name'], 'clinum': pick['clinum'], 'accept': 0 }) print self.switchlist self.giveOption(**kwargs) def getClosestTwoToTarget(self, team1, team2, **kwargs): lowest = -1 pick1 = None pick2 = None for player1 in team1['players']: if (player1['moved'] == 1): continue for player2 in team2['players']: if (player2['moved'] == 1): continue ltarget = abs( self.evaluateBalance(float(player1['bf']), float(player2['bf']))) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 print pick1, pick2 kwargs['Broadcast'].broadcast( "echo Balancer selections: Clients %s, %s with BF %s, %s." % (pick1['clinum'], pick2['clinum'], pick1['bf'], pick2['bf'])) if (lowest >= self.DIFFERENCE): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast("echo unproductive EVEN balance") return if (self.OPTION == 0): action = 'MOVE' self.retrieveIndex(pick1, action, **kwargs) self.retrieveIndex(pick2, action, **kwargs) return if (self.OPTION == 1): self.switchlist.append({ 'name': pick1['name'], 'clinum': pick1['clinum'], 'accept': 0 }) self.switchlist.append({ 'name': pick2['name'], 'clinum': pick2['clinum'], 'accept': 0 }) print self.switchlist self.giveOption(**kwargs) def giveOption(self, **kwargs): index = -1 playermessage = "^cYou have been selected to change teams to promote balance. You have one minute to REJECT this change by sending the message 'reject' to ^bALL ^cchat." for player in self.switchlist: index += 1 kwargs['Broadcast'].broadcast("SendMessage %s %s" % (player['clinum'], playermessage)) if (index == 0): kwargs['Broadcast'].broadcast( "Serverchat ^cTeams are currently unbalanced. ^r%s ^chas been selected to improve balance. They will automatically switch teams in one minute unless they reject the move by sending the message 'reject' to ^bALL ^cchat, or another player joins." % (self.switchlist[0]['name'])) else: kwargs['Broadcast'].broadcast( "Serverchat ^cTeams are currently unbalanced. ^r%s ^cand ^r%s ^chave been selected to improve balance. They will automatically switch teams in one minute unless one of them rejects the move by sending the message 'reject' to ^bALL ^cchat, or another player joins." % (self.switchlist[0]['name'], self.switchlist[1]['name'])) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) if (args[0] == "SQUAD") and (message == 'report balance'): self.getGameInfo() kwargs['Broadcast'].broadcast( "SendMessage %s Balance Report: ^yTeam 1 combined: ^g%s (%s players, %s BF average), ^yTeam 2 combined: ^g%s (%s players, %s BF average). ^yStack percentage: ^r%s. ^yCurrent Phase: ^c%s. ^yCurrent time stamp: ^c%s. ^yBalancer active = ^r%s" % (client['clinum'], self.teamOne['combinedBF'], self.teamOne['size'], self.teamOne['avgBF'], self.teamTwo['combinedBF'], self.teamTwo['size'], self.teamTwo['avgBF'], round(self.evaluateBalance(), 1), self.PHASE, self.TIME, self.GAMESTARTED)) for moves in self.balancereport: kwargs['Broadcast'].broadcast( "SendMessage %s BALANCER: Balanced move for: %s at time %s" % (client['clinum'], moves['name'], moves['time'])) if (args[0] == "SQUAD") and (message == 'report team one'): for player in self.teamOne['players']: kwargs['Broadcast'].broadcast( "SendMessage %s Team One Report: Player: ^c%s ^rBF: ^y%s" % (client['clinum'], player['name'], player['bf'])) if (args[0] == "SQUAD") and (message == 'report team two'): for player in self.teamTwo['players']: kwargs['Broadcast'].broadcast( "SendMessage %s Team Two Report: Player: ^c%s ^rBF: ^y%s" % (client['clinum'], player['name'], player['bf'])) if (args[0] == "SQUAD") and (message == 'report playerlist'): for active in self.playerlist: if (active['active'] == 1): kwargs['Broadcast'].broadcast( "SendMessage %s Active Player List: Player: ^c%s ^rSF: ^y%s" % (client['clinum'], active['name'], active['sf'])) if (args[0] == "SQUAD") and (message == 'report version'): kwargs['Broadcast'].broadcast( "SendMessage %s Balancer version: ^y%s" % (client['clinum'], self.VERSION)) if args[0] != "ALL": return if re.match(".*tell\s+(?:me\s+)?(?:the\s+)?(?:SFs?|balance)(?:\W.*)?$", message, flags=re.IGNORECASE): tm = time.time() if (tm - self.CHAT_STAMP) < self.CHAT_INTERVAL: return self.CHAT_STAMP = tm return self.sendGameInfo(**kwargs) if (self.OPTION == 1) and (message == 'reject'): for player in self.switchlist: if (player['name'] == name): kwargs['Broadcast'].broadcast( "ServerChat ^r%s ^chas rejected a move to promote balance between the teams." % (name)) del self.switchlist[:] def optionCheck(self, **kwargs): if (self.OPTION == 1): for player in self.switchlist: action = 'MOVE' self.retrieveIndex(player, action, **kwargs) del self.switchlist[:] def move(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) client['moved'] = 1 name = client['name'] #only have to move players that are already on a team, and since they can only go to the other team we can use this if (int(client['team']) == 1): newteam = 2 else: newteam = 1 kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, newteam)) kwargs['Broadcast'].broadcast( "Serverchat ^r%s ^chas switched teams to promote balance." % (name)) kwargs['Broadcast'].broadcast("ResetAttributes %s" % (index)) self.balancereport.append({'time': self.TIME, 'client': name}) self.moveNotify(clinum, **kwargs) def prevent(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) client['prevent'] = 1 newteam = 0 kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, newteam)) self.preventNotify(clinum, **kwargs) def allow(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) team = client['team'] kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, team)) client['prevent'] = 0 def level(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) team = client['team'] kwargs['Broadcast'].broadcast( "set _plevel #GetLevel(%s)#; set team%s_level [team%s_level + _plevel]" % (index, team, team)) def moveNotify(self, clinum, **kwargs): #this lets the player know the have been moved and compensates them for their purchased items. There is current no way to know #how much gold a player holds, though I think gold may actually transfer. Not 100% sure. client = self.getPlayerByClientNum(clinum) value = client['value'] kwargs['Broadcast'].broadcast( "SendMessage %s ^cYou have automatically switched teams to promote balance." % (clinum)) kwargs['Broadcast'].broadcast( "SendMessage %s ^cYou have been compensated ^g%s ^cgold for your non-consumable items and your attributes have been reset." % (clinum, value)) kwargs['Broadcast'].broadcast("GiveGold %s %s" % (clinum, value)) client['value'] = 0 def preventNotify(self, clinum, **kwargs): kwargs['Broadcast'].broadcast( "SendMessage %s ^cYou cannot join that team as it will create imbalance. Please wait for another player to join or leave." % (clinum)) def getSmallTeam(self): #writing these all out explicitly because I was having trouble with them if (self.teamOne['size'] < self.teamTwo['size']): return self.teamOne if (self.teamTwo['size'] < self.teamOne['size']): return self.teamTwo if (self.teamTwo['size'] == self.teamOne['size']): return self.teamTwo def getLargeTeam(self): #writing these all out explicitly because I was having trouble with them if (self.teamOne['size'] > self.teamTwo['size']): return self.teamOne if (self.teamTwo['size'] > self.teamOne['size']): return self.teamTwo if (self.teamTwo['size'] == self.teamOne['size']): return self.teamOne def getHighTeam(self): if (self.teamOne['avgBF'] > self.teamTwo['avgBF']): return self.teamOne return self.teamTwo def getLowTeam(self): if (self.teamOne['avgBF'] > self.teamTwo['avgBF']): return self.teamTwo return self.teamOne def getTeamOne(self): return self.teamOne def getTeamTwo(self): return self.teamTwo def getTeamAvg(self, team): #this updates the info for a team team['combinedBF'] = 0 team['size'] = 0 for clients in team['players']: team['combinedBF'] += clients['bf'] team['size'] += 1 if (team['size'] > 0): team['avgBF'] = (team['combinedBF'] / team['size']) else: team['avgBF'] = 0 def getGameInfo(self, **kwargs): self.getTeamAvg(self.teamOne) self.getTeamAvg(self.teamTwo) self.game['size'] = (self.teamOne['size'] + self.teamTwo['size']) self.game['avgBF'] = ((self.teamOne['avgBF'] + self.teamTwo['avgBF']) / 2) def sendGameInfo(self, **kwargs): self.getGameInfo(**kwargs) if (self.GAMESTARTED == 1): self.DIFFERENCE = abs(self.evaluateBalance()) if self.GAMESTARTED == 1: kwargs['Broadcast'].broadcast( "ServerChat ^cCurrent balance: ^yTeam 1 Avg. BF: ^g%s (%s players), ^yTeam 2 Avg. BF: ^g%s (%s players). Stack percentage: ^r%s" % (self.teamOne['avgBF'], self.teamOne['size'], self.teamTwo['avgBF'], self.teamTwo['size'], round(self.DIFFERENCE, 1))) def EvenTeamBalancer(self, **kwargs): self.getGameInfo(**kwargs) #added these to prevent any moves if there is an error in BF calculation that has sprung up on occasion for clients in self.teamOne['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return for clients in self.teamTwo['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return self.DIFFERENCE = abs(self.evaluateBalance()) print(self.DIFFERENCE) if (self.DIFFERENCE > self.THRESHOLD): self.getClosestTwoToTarget(self.getLargeTeam(), self.getSmallTeam(), **kwargs) else: kwargs['Broadcast'].broadcast( "Serverchat ^cEven team balancer initiated but current balance percentage of ^y%s ^cdoes not meet the threshold of ^y%s" % (round(self.DIFFERENCE, 1), self.THRESHOLD)) def UnEvenTeamBalancer(self, **kwargs): self.getGameInfo(**kwargs) #added these to prevent any moves if there is an error in BF calculation that has sprung up on occasion for clients in self.teamOne['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return for clients in self.teamTwo['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return overcheck = self.evaluateBalance() self.DIFFERENCE = abs(self.evaluateBalance()) #In this scenario, the larger team has a much lower BF, so do a player swap instead of a single move. if (overcheck < 0) and (self.DIFFERENCE > self.THRESHOLD): self.getClosestTwoToTarget(self.getLargeTeam(), self.getSmallTeam(), **kwargs) kwargs['Broadcast'].broadcast( "echo BALANCER: ^cUneven team balancer with swap initiated") return #In this scenario, the larger team has greater BF, so do a single mvoe. if (overcheck > 0) and (self.DIFFERENCE > self.THRESHOLD): self.getClosestPersonToTarget(self.getLargeTeam(), **kwargs) else: print 'threshold not met' kwargs['Broadcast'].broadcast( "Serverchat ^cUneven team balancer initiated, but current balance percentage of ^y%s ^cdoes not meet the threshold of ^y%s" % (round(self.DIFFERENCE, 1), self.THRESHOLD)) def onTeamCheck(self, *args, **kwargs): if (self.TIME % (60 * 1000)) == 0: self.sendGameInfo(**kwargs) if (self.teamOne['size'] == int(args[0])) and (self.teamTwo['size'] == int(args[1])): kwargs['Broadcast'].broadcast( "echo BALANCER: Team 1 count is correct") kwargs['Broadcast'].broadcast( "echo BALANCER: Team 2 count is correct") if (self.PHASE == 5): self.GAMESTARTED = 1 if (self.TIME == (1 * 60 * 1000)): self.runBalancer(**kwargs) elif (self.TIME == (3 * 60 * 1000)): self.runBalancer(**kwargs) elif (self.TIME == (6 * 60 * 1000)): self.runBalancer(**kwargs) if (self.TIME >= (6 * 60 * 1000)): self.DENY = 1 self.optionCheck(**kwargs) self.OPTION = 1 if (self.TIME % (5 * 60 * 1000)) == 0: self.runBalancer(**kwargs) return else: #kwargs['Broadcast'].broadcast("Serverchat ^cBalancer is currently off until player counts can be verified.") kwargs['Broadcast'].broadcast("ListClients") kwargs['Broadcast'].broadcast("echo refresh") #this initiates turns balancer off and tries to refresh the teams to get the proper count self.GAMESTARTED = 0 self.DENY = 0 def retrieveLevels(self, cli, **kwargs): kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; set _plevel #GetLevel(|#_index|#)#;echo CLIENT %s is LEVEL #_plevel#; set _plevel 1" % (cli, cli)) def getTeamLevels(self, **kwargs): if (self.GAMESTARTED == 1): for player1 in self.teamOne['players']: self.retrieveLevels(player1['clinum'], **kwargs) for player2 in self.teamTwo['players']: self.retrieveLevels(player2['clinum'], **kwargs) def onGetLevels(self, *args, **kwargs): clinum = args[0] level = int(args[1]) client = self.getPlayerByClientNum(clinum) client['gamelevel'] = level client['bf'] = client['sf'] + client['level'] + (4 * level) if (client['team'] == 1): for player in self.teamOne['players']: if client['clinum'] == player['clinum']: player['bf'] = client['bf'] if (client['team'] == 2): for player in self.teamTwo['players']: if client['clinum'] == player['clinum']: player['bf'] = client['bf'] def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] print 'making client active' client = self.getPlayerByName(name) client['active'] = 1 def onMapReset(self, *args, **kwargs): if (self.PHASE == 5): kwargs['Broadcast'].broadcast("prevphase") self.GAMESTARTED = 0 else: return def startFollow(self, **kwargs): for followings in self.followlist: kwargs['Broadcast'].broadcast( "set _follower #GetIndexFromClientNum(%s)#; set _followed #GetIndexFromClientNum(%s)#; set _x #GetPosX(|#_followed|#)#; set _y #GetPosY(|#_followed|#)#; set _z #GetPosZ(|#_followed|#)#; SetPosition #_follower# [_x + 200] [_y + 200] [_z + 200]" % (followings['follower'], followings['followed']))
class training(ConsolePlugin): ms = None playerlist = [] unallowedlist = [] def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) #for (name, value) in config.items('balancer'): # if (name == "level"): # self._level = int(value) # if (name == "sf"): # self._sf = int(value) pass def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) print ('Current phase: %d' % (phase)) if (phase == 5): self.onGameStart(*args, **kwargs) def onGameStart(self, *args, **kwargs): self.RegisterScripts(**kwargs) self.unallowedunits(**kwargs) def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].put("RegisterGlobalScript -1 \"echo changing team....;MakeOfficer #GetScriptParam(clientid)#; ChangeUnit #GetScriptParam(index)# Player_Savage true false false false false false false; ForceSpawn #GetScriptParam(changedindex)#;echo\" changeteam") kwargs['Broadcast'].put("set sv_squadsize 1") kwargs['Broadcast'].put("set _team 0") kwargs['Broadcast'].put("RegisterGlobalScript -1 \"CreateVar int _player_#GetScriptParam(clientid)#_duel -1;Set _maxteams #GetMaxTeams()#;Set _curclients #GetNumClients()#;if [_maxteams <= _curclients + 1] SetMaxTeams [_maxteams + 1];Set _maxteams #GetMaxTeams()#;Set _team [_team + 1];echo #_team#;Set _player_joining 1;SetTeam #GetScriptParam(index)# #_team#;MakeOfficer #GetScriptParam(clientid)#;ChangeUnit #GetScriptParam(index)# Player_Savage true false false false false false false;ForceSpawn #GetScriptParam(changedindex)#;Set _playerteam #GetTeam(|#GetScriptParam(changedindex)|#)#;Set _loop 1;Set _max #GetMaxTeams()#;ExecScript ally1;Set _player_joining 0;GiveExperience #GetScriptParam(index)# 1073741824;ResetAttributes #GetScriptParam(index)#;Set _message \\\"This is a duel arena that allows players to join the same team. By joining the same team you can use VOIP to communicate and help newer players. This also allows players to have team duels!\\\";Set _image /ui/commander/attack_down.tga;Set _header Welcome to the duel arena!;ClientExecScript #GetScriptParam(clientid)# Welcome header #_header# content #_message# texture #_image#;ClientExecScript #GetScriptParam(clientid)# SetupMusic; echo\" playerjoin") kwargs['Broadcast'].put("RegisterGlobalScript -1 \"if [_loop != _playerteam] AddAlliedTeam #_playerteam# #_loop#';if [_loop != _playerteam] AddAlliedTeam #_loop# #_playerteam#;Set _loop [_loop + 1];if [_loop < _max] ExecScript ally2; echo\" ally1") kwargs['Broadcast'].put("RegisterGlobalScript -1 \"if [_loop != _playerteam] AddAlliedTeam #_playerteam# #_loop#';if [_loop != _playerteam] AddAlliedTeam #_loop# #_playerteam#;Set _loop [_loop + 1];if [_loop < _max] ExecScript ally1; echo\" ally2") kwargs['Broadcast'].broadcast() def onServerStatus(self, *args, **kwargs): kwargs['Broadcast'].put("SendMessage -1 \"^cThis server allows training of players. Send the message: ^ytrain <playername> ^cto ^bALL^c chat to begin training. This will allow you to use in-game VOIP to communicate. End training by sending the message: ^yend training\"") kwargs['Broadcast'].broadcast() def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'] == name): return client def onConnect(self, *args, **kwargs): id = args[0] self.playerlist.append({ 'clinum' : id, 'acctid' : 0, 'level' : 0, 'sf' : 0, 'lf' : 0, 'name' : 'X', 'team' : 0, 'oldteam' : 0, 'trainee' : -1, 'unit' : 'Player_Savage' }) def onDisconnect(self, *args, **kwargs): cli = args[0] index = self.getPlayerIndex(cli) #index = self.playerlist.index(clinum[cli]) print index del self.playerlist[index] print self.playerlist def getPlayerIndex (self, cli): indice = -1 for player in self.playerlist: indice += 1 if (player['clinum'] == cli): return indice def onSetName(self, *args, **kwargs): print args cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onUnitChange(self, *args, **kwargs): cli = args[0] unit = args[1] client = self.getPlayerByClientNum(cli) if unit in self.unallowedlist: kwargs['Broadcast'].broadcast("set _value #GetIndexFromClientNum(%s)#; ChangeUnit #_value# %s true false false false false false false; SendMessage %s ^cYou can't select that unit. Sorry!" % (cli, client['unit'], cli)) return client['unit'] = unit def unallowedunits(self, *args, **kwargs): self.unallowedlist = [ 'Player_Malphas', 'Player_Maliken', 'Player_Behemoth', 'Player_Steambuchet', 'Player_BatteringRam', 'Player_Devourer', 'Player_Tempest' ] def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team print self.playerlist def onMessage(self, *args, **kwargs): # process only ALL chat messages if args[0] != "ALL": return name = args[1] (func, arg) = args[2].split(None, 1) # only single person training is supported right now arg = arg.split(None, 1) if func == "train" and arg: self.trainingStart(name, arg, **kwargs) elif func == "end" and arg == "training": return self.trainingEnd(name, **kwargs) def trainingStart(self, name, trainee, **kwargs): trainer = self.getPlayerByName(name) if (int(trainer['trainee']) > -1): kwargs['Broadcast'].broadcast("SendMessage %s You are currently in a training session. End that session first." % (trainer['clinum'])) return if (player['name'].lower() == trainee.lower()): toteam = player['team'] trainer['oldteam'] = trainer['team'] trainer['team'] = toteam trainer['trainee'] = player['clinum'] kwargs['Broadcast'].broadcast("set _value #GetIndexFromClientNum(%s)#; set X #GetPosX(|#_value|#)#; set Y #GetPosY(|#_value|#)#; set Z #GetPosZ(|#_value|#)#; echo CLIENT %s POSITION #X# #Y# #Z#" % (trainer['clinum'], trainer['clinum'])) client = self.getPlayerByClientNum(trainer['clinum']) kwargs['Broadcast'].broadcast("set _value #GetIndexFromClientNum(%s)#; SetTeam #_value# %s; SendMessage %s You are now in a training session with %s; ChangeUnit #GetIndexFromClientNum(%s)# %s; SetPosition #_value# #X# #Y# #Z#" % (client['clinum'], toteam, client['clinum'], trainee, client['clinum'], client['unit'])) def trainingEnd(self, name, **kwargs): trainer = self.getPlayerByName(name) if (int(trainer['trainee']) == -1): return kwargs['Broadcast'].broadcast("set _value #GetIndexFromClientNum(%s)#; SetTeam #_value# %s; SendMessage %s ^cYou have ended your training session.; SendMessage %s ^r%s ^chas ended their training session with you." % (trainer['clinum'], trainer['oldteam'], trainer['clinum'], trainer['trainee'], trainer['name'])) trainer['team'] = trainer['oldteam'] trainer['trainee'] = -1
class pug(ConsolePlugin): VERSION = "1.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False HUMANPICK = False playerlist = [] startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} teamlist = []; TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) #kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";") if self.PICKING: resetall(**kwargs) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";") if self.PICKING: resetall(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername client ['play'] = True kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time/60 #sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = True client ['clan'] = clan client ['newteam'] = 0 kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) if self.PICKING: kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" % (cli)) def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team if self.PICKING: for each in self.teamlist: if (each['player'] == cli) and (team != each['team']): #don't let them switch kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['player'],each['team'])) return #kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['player'])) def onGameStart (self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True self.PICKING = False if phase == 6: self.PICKING = False self.teamlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"") if phase == 7: for each in self.playerlist: each['newteam'] = 0 self.PICKING = False self.STARTED = False resetall(**kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast("SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' #kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] #info = self.startinfo #Captain initiated if event == 'Captain': #If they are already captain, do nothing if caller == self.startinfo['b_captain'] or caller == self.startinfo['h_captain']: return #Beasts, set captain if value == 'beasts': self.startinfo['b_captain'] = caller kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; set Pet_BeastWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['h_captain']: self.startinfo['h_first'] = True #Humans, set captain if value == 'humans': self.startinfo['h_captain'] = caller kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; set Pet_HumanWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['b_captain']: self.startinfo['b_first'] = True #Check if picking is initiated, if so determine who gets the next picking if self.PICKING: self.setpicking(**kwargs) return #Start picking process through the normal mechanism if self.startinfo['h_captain'] and self.startinfo['b_captain']: self.beginpicking(**kwargs) #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) #switch everything to ingame_picking function if the game is already started if self.PHASE == 5: #pickthread = threading.Thread(target=self.ingame_picking, args=(caller, client, player, None), kwargs=kwargs) #pickthread.start() #self.ingame_picking(caller, client, player, **kwargs) print 'Will go to ingame picking' if caller == self.startinfo['h_captain']: #check players status if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 self.teamlist.append({"player" : player["clinum"], "team" : 1}); kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) self.HUMANPICK = False if caller == self.startinfo['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 2 client['newteam'] = 2 self.teamlist.append({"player" : player["clinum"], "team" : 2}); kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'],self.startinfo['h_captain'] )) self.HUMANPICK = True if self.PICKING: self.setpicking(**kwargs) #Ready if event == 'Ready': if self.STARTED: return if caller == self.startinfo['h_captain']: if self.startinfo['h_ready']: return self.startinfo['h_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == self.startinfo['b_captain']: if self.startinfo['b_ready']: return self.startinfo['b_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if self.startinfo['h_ready'] and self.startinfo['b_ready']: kwargs['Broadcast'].broadcast("set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) if event == 'Resign': #if pick has begun and a captain resigns, just reset the whole damn thing if self.PICKING: self.resetall(**kwargs); if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";") if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";") #self.setpicking(**kwargs) def resetall(self, **kwargs): self.PICKING = False self.teamlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"") for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0; SendMessage -1 ^yTeams are reset after captain resignation." % (each['clinum'])) def RegisterStart(self, **kwargs): self.PICKING = True def beginpicking(self, **kwargs): #move everyone to spec for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) self.teamlist = []; #start by making the teams unjoinable kwargs['Broadcast'].broadcast("set sv_setupTimeCommander 600000000; set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";") kwargs['Broadcast'].broadcast("ClientExecScript -1 clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"") #move captains to the appropriate team and have them switch back to lobby for each in self.playerlist: if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['h_captain'])) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['b_captain'])) self.teamlist.append({"player" : self.startinfo['h_captain'], "team" : 1}); self.teamlist.append({"player" : self.startinfo['b_captain'], "team" : 2}); #Set variables to get the first captain to start picking if self.startinfo['h_first']: self.HUMANPICK = True self.setpicking(**kwargs) else: self.HUMANPICK = False self.setpicking(**kwargs) kwargs['Broadcast'].broadcast("echo STARTTOURNEY") def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast("NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) def onServerStatus(self, *args, **kwargs): if self.STARTED != 1: return pickthread = threading.Thread(target=self.ingame_picking, args=(), kwargs=kwargs) pickthread.start() def ingame_picking(self, *args, **kwargs): self.listClients(self, **kwargs) teamone = [] teamtwo = [] time.sleep(1) #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #figure out who gets the pick team1 = len(teamone) team2 = len(teamtwo) if team1 > team2: self.HUMANPICK = False self.setpicking(**kwargs) if team2 > team1: self.HUMANPICK = True self.setpicking(**kwargs) if team1 == team2: return def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def setpicking(self, **kwargs): if self.HUMANPICK: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'],self.startinfo['h_captain'] )) else: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain']))
class tournament(ConsolePlugin): VERSION = "1.0.2" STARTED = 0 MINIMUM = 2 RECRUIT = False ORGANIZER = -1 DUELROUND = 0 TOURNEYROUND = 0 MISSING = -1 DOUBLEELIM = False CANCEL = False CURRENT = 1 lastwinner = -1 lastloser = -1 playerlist = [] tourneylist = {'totalplayers' : 0, 'players' : []} tourneystats = {'entries' : 0, 'avgSF' : 0, 'winner' : {}, 'runnerup' : {}} seededlist = [] activeduel = [] statueangle = [] statuelist = [] unitlist = [] adminlist = [] blockerlist = [] OFFICIAL = False STATUE = 1 SVRDESC = False svr_desc = "^yTourney - Last Winner: ^r" SVRNAME = False svr_name = "^yTourney - Last Winner: ^r" def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append(name) #Don't know how to get boolean values for things in a specific section of .ini for (name, value) in ini.items('var'): if (name == "changesvrname") and (value == "true"): self.SVRNAME = True if (name == "changesvrdesc") and (value == "true"): self.SVRDESC = True if (name == "svrname"): self.svrname = value if (name == "changesvrname"): self.svrdesc = value if (name == "double") and (value == "true"): self.DOUBLEELIM = True def onStartServer(self, *args, **kwargs): print 'SERVER RESTARTED' self.statuelist = [] self.STARTED = 0 self.MINIMUM = 2 self.RECRUIT = False self.ORGANIZER = -1 self.DUELROUND = 0 self.TOURNEYROUND = 0 self.MISSING = -1 self.playerlist = [] self.tourneylist = {'totalplayers' : 0, 'players' : []} self.seededlist = [] self.winnerlist = [] self.loserlist = [] self.activeduel = [] self.unitlist = [] self.counts = 4 self.counter = 0 f = open('winners.txt', 'r') self.statuelist = f.readlines() f.close() self.statueangle = ["0.0000 0.0000 161.7999", "0.0000 0.0000 107.5998", "0.0000 0.0000 53.1997", "0.0000 0.0000 -22.6002", "0.0000 0.0000 -63.0003", "0.0000 0.0000 -109.2003"] self.blockerlist = [{'angles' : '0.0000 0.0000 -3.4000', 'name' : 'blocker1', 'position' : '7751.7021 8648.5215 -215.2963', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 38.6000', 'name' : 'blocker2', 'position' : '7112.2378 8417.8262 -148.7921', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 74.8001', 'name' : 'blocker3', 'position' : '6739.8462 8053.7290 -33.6641', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 105.200', 'name' : 'blocker4', 'position' : '6751.2056 7424.2529 20.8391', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 142.000', 'name' : 'blocker5', 'position' : '7105.5361 6935.4971 -244.8373', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 176.800', 'name' : 'blocker6', 'position' : '7682.2261 6741.1899 -246.9767', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 210.400', 'name' : 'blocker7', 'position' : '8237.4541 6833.5957 -14.6271', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 249.200', 'name' : 'blocker8', 'position' : '8587.6348 7221.5093 -58.0270 -215.2963', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 277.800', 'name' : 'blocker9', 'position' : '8664.1816 7800.2666 -182.6546', 'scale' : '33.4070'}, {'angles' : '0.0000 0.0000 304.200', 'name' : 'blocker10', 'position' : '8420.5273 8446.7617 -6.7577', 'scale' : '33.4070'}] self.spawnStatues(**kwargs) self.doBlockers('on',**kwargs) def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id, 'acctid' : 0, 'level' : 0, 'sf' : 0, 'name' : 'X', 'index' : 0, 'active' : 0, 'register' : 0, 'loses' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = 0 for each in self.activeduel: if each['clinum'] == cli: self.fightersPresent(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = 1 if (self.STARTED == 1) and (cli == self.MISSING): kwargs['Broadcast'].broadcast("set _MISSING -1") #self.nextDuelRound(**kwargs) kwargs['Broadcast'].broadcast("SendMessage %s ^cDuel Tournament made by ^yOld55 ^cand ^yPidgeoni" % (cli)) if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast("SendMessage %s ^cYou are registered as an administrator for this tournament server. Send the chat message: ^rhelp ^cto see what commands you can perform." % (cli)) def getPlayerIndex (self, cli): indice = -1 for player in self.playlist: indice += 1 if (player['clinum'] == cli): return indice def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #default unit list self.unitlist = ['Player_Savage', \ 'Player_ShapeShifter', \ 'Player_Predator', \ 'Player_Hunter', \ 'Player_Marksman'] kwargs['Broadcast'].broadcast("set _green #GetIndexFromName(green_spawn)#; \ set _red #GetIndexFromName(red_spawn)#; \ set _exit1 #GetIndexFromName(exit1)#; \ set _exit2 #GetIndexFromName(exit2)#; \ set _p1x #GetPosX(|#_green|#)#; \ set _p1y #GetPosY(|#_green|#)#; \ set _p1z #GetPosZ(|#_green|#)#; \ set _p2x #GetPosX(|#_red|#)#; \ set _p2y #GetPosY(|#_red|#)#; \ set _p2z #GetPosZ(|#_red|#)#; \ set _e1x #GetPosX(|#_exit1|#)#; \ set _e1y #GetPosY(|#_exit1|#)#; \ set e1z #GetPosZ(|#_exit1|#)#; \ set _e2x #GetPosX(|#_exit2|#)#; \ set _e2y #GetPosY(|#_exit2|#)#; \ set _e2z #GetPosZ(|#_exit2|#)#; \ set _MISSING -1") def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each: admin = True return admin def adminCommands (self, message, client, **kwargs): start = re.match("start", message, flags=re.IGNORECASE) official = re.match("toggle official", message, flags=re.IGNORECASE) redo = re.match("redo", message, flags=re.IGNORECASE) next = re.match("next", message, flags=re.IGNORECASE) elim = re.match("double", message, flags=re.IGNORECASE) fail = re.match("remove (\S+)", message, flags=re.IGNORECASE) kick = re.match("kick (\S+)", message, flags=re.IGNORECASE) help = re.match("help", message, flags=re.IGNORECASE) blocker = re.match("blocker (\S+)", message, flags=re.IGNORECASE) cancel = re.match("cancel", message, flags=re.IGNORECASE) #lets admin register people, even if not official tournament register = re.match("register (\S+)", message, flags=re.IGNORECASE) if start: self.start (client, **kwargs) if official: self.toggleOfficial (client, **kwargs) if redo: self.redoDuel (**kwargs) if next: self.endDuel (**kwargs) if register: client = self.getPlayerByName(register.group(1)) self.register (client, **kwargs) if fail: killer = -1 killed = -1 client = self.getPlayerByName(fail.group(1)) for each in self.activeduel: if each['clinum'] == client['clinum']: killed = each['clinum'] each['loses'] = 3 continue if each['clinum'] != client['clinum']: killer = each['clinum'] if killer > -1 and killed > -1: self.onDeath(killer, killed, **kwargs) kwargs['Broadcast'].broadcast("SendMessage %s ^yAn administrator has removed you from the tournament" % (killed)) if kick: reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (kickclient['clinum'], reason)) if blocker: self.doBlockers(blocker.group(1), **kwargs) if elim: if self.STARTED == 1: kwargs['Broadcast'].broadcast("SendMessage %s A tournament has already started" % (client['clinum'])) return self.toggleDouble (client, **kwargs) if cancel: self.CANCEL = True self.endTourney(**kwargs) kwargs['Broadcast'].broadcast(\ "Serverchat The tournament has been ended by an administrator") if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. The following are commands and a short description of what they do." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s As an admin you must ALWAYS register yourself by sending the message: ^rregister yourname" % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rtoggle official ^wsets the tournament between official and unofficial status.\ Admins MUST register people for official tournaments. Only admins can start tournaments in official mode." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rregister playername ^wwill register a player for the tournament. Must be used in official mode but also works in unofficial." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rblocker on/off ^wwill turn range blockers on/off around the arena." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rredo ^wwill force the players fighting in the arena to redo the last match. ONLY use after players have respawned as the next unit." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rremove playername ^wwill force a player to lose the match. Currently only works \ when the player is on the server. If they have disconnected, it is best to just let them timeout." % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rcancel ^wwill cancel the current tournament." % (client['clinum'])) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) admin = self.isAdmin(client, **kwargs) #pass to admincommands if admin: self.adminCommands(message, client, **kwargs) #only admins are allowed to start/add/redo/etc. if the tournament is official if self.OFFICIAL: return roundunit = re.match("Round (\S+) Unit (\S+)", message, flags=re.IGNORECASE) register = re.match("register", message, flags=re.IGNORECASE) if register: self.register (client, **kwargs) if roundunit: if client['clinum'] != self.ORGANIZER: return duelround = int(roundunit.group(1)) unit = (roundunit.group(2)) print duelround, unit self.unitlist[duelround-1] = ("Player_%s" % (unit)) def doBlockers (self, toggle, **kwargs): if toggle == 'on': for each in self.blockerlist: kwargs['Broadcast'].broadcast(\ "SpawnEntity Prop_Scenery model \"/world/props/tools/blocker_range.mdf\" position \"%s\" name \"%s\" angles \"%s\" scale \"%s\"" \ % (each['position'], each['name'], each['angles'], each['scale'])) if toggle == "off": for each in self.blockerlist: kwargs['Broadcast'].broadcast("RemoveEntity #GetIndexFromName(%s)#" % (each['name'])) return def toggleOfficial (self, client, **kwargs): if self.OFFICIAL: self.OFFICIAL = False else: self.OFFICIAL = True kwargs['Broadcast'].broadcast("SendMessage %s ^rOfficial Status: %s" % (client['clinum'], self.OFFICIAL)) def toggleDouble (self, client, **kwargs): if self.DOUBLEELIM: self.OFFICIAL = False else: self.DOUBLEELIM = True kwargs['Broadcast'].broadcast("SendMessage %s ^rDouble Elimination Status: %s" % (client['clinum'], self.DOUBLEELIM)) def redoDuel (self, **kwargs): self.DUELROUND -= 1 for each in self.activeduel: if (each['clinum'] == self.lastloser): each['loses'] -= 1 if (each['clinum'] == self.lastwinner): each['wins'] -= 1 kwargs['Broadcast'].broadcast("ExecScript GlobalSet var R%sS%s val %s" % (each['bracket'], each['column'], each['wins'])) kwargs['Broadcast'].broadcast("ExecScript GlobalSync") kwargs['Broadcast'].broadcast("set _DUELER1 -1; set _DUELER2 -1") self.nextDuelRound(**kwargs) def start (self, client, **kwargs): admin = self.isAdmin(client, **kwargs) if self.RECRUIT or self.STARTED == 1: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rA tournament has already been started. You must wait till the current tournament ends to start a new one." % (client['clinum'])) return activeplayers = 0 for player in self.playerlist: if player['active'] == 1: activeplayers += 1 if (activeplayers < self.MINIMUM): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rA minimum of two active players is required to call a tournament" % (client['clinum'])) return self.RegisterScripts(**kwargs) self.RECRUIT = True kwargs['Broadcast'].broadcast(\ "ServerChat ^r%s ^chas started a tournament! To join the tournament, send the message 'register' to ALL, SQUAD, or TEAM chat.; \ ExecScript starttourney; \ ExecScript GlobalSet var TSB val %s; \ ExecScript GlobalShowDuel" \ % (client['name'], client['name'])) self.ORGANIZER = client['clinum'] kwargs['Broadcast'].broadcast("ClientExecScript %s ClientShowOptions" % (self.ORGANIZER)) def register (self, client, **kwargs): kwargs['Broadcast'].broadcast("TakeItem #GetIndexFromClientNum(%s)# 10" % (client ['clinum'])) if self.RECRUIT and client['register'] == 0: self.tourneylist ['players'].append ({'clinum' : client['clinum'], 'acctid' : client['acctid'], 'name' : client['name'], 'sf' : client['sf'], 'level' : client['level'], 'totalwins' : 0, 'totalloses' : 0, 'seed' : 0, 'advance' : 2, 'bye' : 0, 'bracket' : 0}) client['register'] = 1 self.tourneylist ['totalplayers'] += 1 kwargs['Broadcast'].broadcast(\ "Serverchat ^r%s ^chas registered for the tournament." % (client ['name'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yYou have successfully registered for the tournament." % (client ['clinum'])) else: return def RegisterStart(self, **kwargs): self.RECRUIT = False self.STARTED = 1 self.seedPlayers(**kwargs) def getTourneyinfo(self, **kwargs): entries = self.seededlist['totalplayers'] self.tourneystats['entries'] = entries totalsf = 0 for each in self.seededlist['players']: totalsf += each['sf'] self.tourneystats['avgSF'] = int(totalsf/entries) def seedPlayers(self, **kwargs): self.TOURNEYROUND = 1 kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var TR val 1") kwargs['Broadcast'].broadcast(\ "ClientExecScript %s ClientHideOptions" % (self.ORGANIZER)) if (self.tourneylist ['totalplayers'] < 4): self.tourneylist = {'totalplayers' : 0, 'players' : []} self.seededlist = [] self.STARTED = 0 self.ORGANIZER = -1 self.RECRUIT = False for each in self.playerlist: each['register'] = 0 kwargs['Broadcast'].broadcast(\ "ClientExecScript -1 ClientClear") kwargs['Broadcast'].broadcast(\ "Serverchat The tournament must have 4 people to start. Aborting.") return self.seededlist = sorted(self.tourneylist ['players'], key=itemgetter('sf', 'level', 'clinum'), reverse=True) seed = 0 #Gets information about tournament for scoring purposes #self.getTourneyinfo() for player in self.seededlist: seed += 1 player['seed'] += seed totalplayers = self.tourneylist['totalplayers'] start = 0 end = totalplayers - 1 #round 1 seeding/bracket placement if (self.tourneylist['totalplayers'] % (2)) == 0: total_brackets = (totalplayers / 2) bracket = 1 while (start < total_brackets): self.seededlist[start]['bracket'] = bracket self.seededlist[end]['bracket'] = bracket kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sNA val %s;\ ExecScript GlobalSet var R%sFA val %s;\ ExecScript GlobalSet var R%sNB val %s;\ ExecScript GlobalSet var R%sFB val %s;"\ % (bracket, self.seededlist[start]['name'],bracket,self.seededlist[start]['sf'],bracket,self.seededlist[end]['name'],bracket,self.seededlist[end]['sf'])) start += 1 end -= 1 bracket += 1 if (self.tourneylist['totalplayers'] % (2)) != 0: totalplayers = totalplayers+1 total_brackets = (totalplayers / 2) bracket = 1 self.seededlist[start]['bye'] = 1 self.seededlist[start]['bracket'] = bracket self.seededlist[start]['advance'] = 1 self.winnerlist.append(self.seededlist[start]) print self.winnerlist kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sSA val 3;\ ExecScript GlobalSet var R%sNA val %s;\ ExecScript GlobalSet var R%sFA val %s;\ ExecScript GlobalSet var R%sNB val BYE"\ % (bracket,bracket,self.seededlist[start]['name'],bracket,self.seededlist[start]['sf'],bracket)) start += 1 bracket += 1 while (start < total_brackets): self.seededlist[start]['bracket'] = bracket self.seededlist[end]['bracket'] = bracket kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sNA val %s;\ ExecScript GlobalSet var R%sFA val %s; \ ExecScript GlobalSet var R%sNB val %s; \ ExecScript GlobalSet var R%sFB val %s;"\ % (bracket,self.seededlist[start]['name'],bracket,self.seededlist[start]['sf'],bracket,self.seededlist[end]['name'],bracket,self.seededlist[end]['sf'])) bracket += 1 start += 1 end -= 1 self.checkRound(**kwargs) def checkRound(self, **kwargs): #figure out who has yet to fight print 'at checkRound' bl = [] for brackets in self.seededlist: bl.append(brackets['bracket']) print bl for item in set(bl): if (bl.count(item) > 1): print item self.nextDuel(item, **kwargs) return self.nextRound(**kwargs) print 'round over' self.TOURNEYROUND += 1 def nextDuel(self, bracket, **kwargs): print bracket kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var CR val %s;\ ExecScript GlobalSync"\ % (bracket)) for each in self.seededlist: if each['bracket'] == bracket: #added to kill each of the duelers before the start so they get out of their current duels kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ KillEntity #_index#"\ % (each['clinum'])) self.activeduel.append(each) for each in self.activeduel: each['loses'] = 0 each['wins'] = 0 self.activeduel[0]['column'] = "A" self.activeduel[1]['column'] = "B" self.getNextDuel(**kwargs) def getNextDuel(self, *args, **kwargs): self.nextDuelRound(**kwargs) def nextDuelRound(self, **kwargs): if self.fightersPresent(**kwargs): kwargs['Broadcast'].broadcast("set _DUEL 0") self.getUnit(**kwargs) kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ GiveItem #_index# 9 Spell_CommanderHeal;\ StartEffectOnObject #_index# \"shared/effects/green_aura.effect\";\ ResetAttributes #_index#;\ SetPosition #_index# #_p1x# #_p1y# #_p1z#;\ ChangeUnit #_index# #_UNIT# true false false false false false false;\ ClientExecScript %s holdmove"\ % (self.activeduel[0]['clinum'],self.activeduel[0]['clinum'])) kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ GiveItem #_index# 9 Spell_CommanderHeal;\ StartEffectOnObject #_index# \"shared/effects/red_aura.effect\"; \ ResetAttributes #_index#; \ SetPosition #_index# #_p2x# #_p2y# #_p2z#;\ ChangeUnit #_index# #_UNIT# true false false false false false false;\ ClientExecScript %s holdmove"\ % (self.activeduel[1]['clinum'],self.activeduel[1]['clinum'])) kwargs['Broadcast'].broadcast(\ "ExecScript setdueler dueler1 %s dueler2 %s"\ % (self.activeduel[0]['clinum'], self.activeduel[1]['clinum'])) kwargs['Broadcast'].broadcast(\ "Execscript duelcountdown") else: print 'player missing' def waitForPlayer(self, *args, **kwargs): action = args[0] if (action == 'Timeout'): for each in self.activeduel: if each['clinum'] == self.MISSING: each['loses'] = 3 missing = each['clinum'] self.MISSING = -1 else: remaining = each['clinum'] self.onDeath(remaining, missing,**kwargs) if (action == 'Connected'): #if (self.DUELROUND > 0): #self.DUELROUND -= 1 self.MISSING = -1 kwargs['Broadcast'].broadcast("set _DUELER1 -1; set _DUELER2 -1") self.nextDuelRound(**kwargs) def getUnit(self, **kwargs): unit = self.unitlist[self.DUELROUND] kwargs['Broadcast'].broadcast("set _UNIT %s" % (unit)) def fightersPresent(self, **kwargs): if self.MISSING > -1: return False for each in self.activeduel: clinum = each['clinum'] for players in self.playerlist: if (players['clinum'] == clinum) and (players['active'] == 0): self.MISSING = players['clinum'] name = players['name'] kwargs['Broadcast'].broadcast(\ "ServerChat ^cThe next duel is between ^r%s ^cand ^r%s^c, but ^r%s ^chas disconnected. They have 1 minute to reconnect or they will lose the round.;\ set _MISSING %s;\ ExecScript missingfighter"\ % (self.activeduel[0]['name'],self.activeduel[1]['name'], name, self.MISSING)) return False return True def onDeath(self, *args, **kwargs): print 'got Death' #this will be called from a specific filter killer = args[0] killed = args[1] wasduel = 0 print args if self.STARTED != 1 or self.MISSING > -1: return for each in self.activeduel: if (each['clinum'] == killed): wasduel += 1 clikilled = each if (each['clinum'] == killer): wasduel += 1 clikill = each if wasduel == 2: self.DUELROUND += 1 self.lastloser = clikilled['clinum'] clikilled['loses'] += 1 kwargs['Broadcast'].broadcast(\ "set _idx #GetIndexFromClientNum(%s)#;\ TakeItem #_idx# 9;\ set _DUELER1 -1;\ set _DUELER2 -1"\ % (clikilled['clinum'])) self.lastwinner = clikill['clinum'] clikill['wins'] += 1 kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sS%s val %s;\ ExecScript GlobalSync"\ % (clikill['bracket'], clikill['column'], clikill['wins'])) for each in self.activeduel: if each['loses'] > 2: self.checkendDuel(**kwargs) kwargs['Broadcast'].broadcast("ExecScript GlobalSync") return kwargs['Broadcast'].broadcast("ExecScript nextduelround") def checkendDuel(self, **kwargs): kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ StopEffectOnObject #_index# \"shared/effects/green_aura.effect\";\ SetPosition #_index# #_e1x# #_e1y# #_e1z#;\ ChangeUnit #_index# Player_Savage true false false false false false false"\ % (self.activeduel[0]['clinum'])) kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ StopEffectOnObject #_index# \"shared/effects/red_aura.effect\";\ SetPosition #_index# #_e2x# #_e2y# #_e2z#;\ ChangeUnit #_index# Player_Savage true false false false false false false"\ % (self.activeduel[1]['clinum'])) if not self.OFFICIAL: self.endDuel(**kwargs) return if self.OFFICIAL: kwargs['Broadcast'].broadcast(\ "SendMessage %s This duel is over. Please send message 'next' to chat for the next duel, or 'redo' if there was an error."\ % (self.ORGANIZER)) def endDuel(self, **kwargs): for each in self.activeduel: if each['loses'] > 2: loser = each['name'] clinum = each['clinum'] each['totalloses'] += 1 self.loserlist.append(each) self.tourneystats['runnerup'] = { 'name' : each['name'], 'acctid' : each['acctid'] } self.removePlayer(each['clinum']) if each['loses'] < 3: winner = each['name'] self.tourneystats['winner'] = { 'name' : each['name'], 'acctid' : each['acctid'] } each['totalwins'] += 1 if each['totalloses'] == 0: self.winnerlist.append(each) if each['totalloses'] == 1: self.loserlist.append(each) kwargs['Broadcast'].broadcast(\ "ServerChat ^y%s ^chas defeated ^y%s ^cand moves on to the next round"\ % (winner, loser)) self.activeduel = [] self.DUELROUND = 0 self.checkRound(**kwargs) def swapList(self, winners, losers, **kwargs): #gets if we are currently in winners or losers bracket, 1 = winner 2 = losers #special condition, all remaining players are in losers bracket if winners == 0: print 'condition: no winners' self.CURRENT = 2 self.seededlist = list(self.loserlist) del self.loserlist[:] return #special condition, all are in winners bracket if losers == 0: print 'condition: no losers' self.CURRENT = 1 self.seededlist = list(self.winnerlist) del self.winnerlist[:] return #special condition, split brackets if losers == 1 and winners == 1: print 'condition: split lists' self.seededlist = [self.winnerlist[0], self.loserlist[0]] del self.loserlist[:] del self.winnerlist[:] return if self.CURRENT == 1: if losers > 1: print 'condition: start loser bracket' self.CURRENT = 2 self.seededlist = list(self.loserlist) self.loserlist = [] return elif losers < 2: self.CURRENT = 1 self.seededlist = list(self.winnerlist) self.winnerlist = [] return if self.CURRENT == 2: if winners > 1: print 'condition: start winner bracket' self.CURRENT = 1 self.seededlist = list(self.winnerlist) self.winnerlist = [] return elif winners < 2: self.CURRENT = 2 self.seededlist = list(self.loserlist) self.loserlist = [] return print self.seededlist def nextRound(self, **kwargs): kwargs['Broadcast'].broadcast("ExecScript GlobalClear; ClientExecScript -1 releasemove") print 'made it to nextRound' remaining = 0 self.TOURNEYROUND += 1 kwargs['Broadcast'].broadcast("ExecScript GlobalSet var TR val %s" % (self.TOURNEYROUND)) if self.DOUBLEELIM: winners = self.getRemaining(self.winnerlist, **kwargs) losers = self.getRemaining(self.loserlist, **kwargs) remaining = winners + losers if remaining == 1: self.endTourney(**kwargs) return print winners, losers self.swapList(winners, losers) remaining = self.getRemaining(self.seededlist, **kwargs) kwargs['Broadcast'].broadcast("echo Remaining players: %s" % (remaining)) if (remaining == 1): self.endTourney(**kwargs) return if (remaining % (2)) != 0: self.getBye(**kwargs) self.seededlist = sorted(self.seededlist, key=itemgetter('advance', 'bracket')) #re-seed the list if we are switching to the loser bracket if self.CURRENT == 2: self.seededlist = sorted(self.seededlist, key=itemgetter('advance', 'seed', 'bracket')) #now to do the re-bracketing start = 0 end = remaining - 1 doround = True bracket = 0 if (self.seededlist[start]['advance'] == 1): bracket = 1 byer = self.seededlist[start] byer['bracket'] = bracket if byer['totalloses'] == 1: self.loserlist.append(self.seededlist[start]) if byer['totalloses'] == 0: self.winnerlist.append(self.seededlist[start]) kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sSA val 3;\ ExecScript GlobalSet var R%sNA val %s;\ ExecScript GlobalSet var R%sFA val %s;\ ExecScript GlobalSet var R%sNB val BYE"\ % (bracket,bracket,self.seededlist[start]['name'],bracket,self.seededlist[start]['sf'],bracket)) self.seededlist[start]['column'] = 'A' start += 1 while doround: bracket += 1 self.seededlist[start]['bracket'] = bracket self.seededlist[end]['bracket'] = bracket kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var R%sNA val %s;\ ExecScript GlobalSet var R%sFA val %s;\ ExecScript GlobalSet var R%sNB val %s;\ ExecScript GlobalSet var R%sFB val %s;"\ % (bracket,self.seededlist[start]['name'],bracket,self.seededlist[start]['sf'],bracket,self.seededlist[end]['name'],bracket,self.seededlist[end]['sf'])) self.seededlist[start]['column'] = "A" self.seededlist[end]['column'] = "B" if (end - start) == 1: doround = False start += 1 end -= 1 print self.seededlist self.checkRound(**kwargs) def getRemaining(self, getlist, **kwargs): remaining = 0 for each in getlist: each['advance'] = 2 remaining += 1 return remaining def endTourney(self, **kwargs): if not self.CANCEL: winner = self.seededlist[0] name = winner['name'] clinum = winner['clinum'] wins = winner['totalwins'] kwargs['Broadcast'].broadcast(\ "ServerChat ^cThis tournament is over! The winner is %s with a total of %s wins."\ % (name, wins)) kwargs['Broadcast'].broadcast(\ "set _winnerind #GetIndexFromClientNum(%s);\ ClientExecScript %s ClientHideOptions"\ % (clinum, self.ORGANIZER)) if self.SVRDESC: kwargs['Broadcast'].broadcast(\ "set svr_desc \"%s\"%s" % (self.svr_desc, name)) if self.SVRNAME: kwargs['Broadcast'].broadcast(\ "set svr_name \"%s\"%s"\ % (self.svr_name, name)) #Adds a statue kwargs['Broadcast'].broadcast(\ "RemoveEntity #GetIndexFromName(player_%s)#;\ SpawnEntityAtEntity statue_%s Prop_Dynamic name player_%s maxhealth 999999999 model \"/world/props/arena/stone_legionnaire.mdf\" angles \"%s\" team 0 seed 0 scale 1.7627 propname %s"\ % (self.STATUE,self.STATUE,self.STATUE,self.statueangle[self.STATUE-1],name)) self.STATUE += 1 if self.STATUE > 6: self.STATUE = 1 #add name to statue list self.statuelist.append(name) #Truncate statuelist to 6 winners size = len(self.statuelist) if size > 5: del self.statuelist[0] #writes file, winners.txt f = open('winners.txt', 'w') for each in self.statuelist: f.write("%s" % (each)) f.close() self.tourneylist = {'totalplayers' : 0, 'players' : []} self.seededlist = [] self.winnerlist = [] self.loserlist = [] self.activeduel = [] self.CURRENT = 1 self.STARTED = 0 self.ORGANIZER = -1 self.RECRUIT = False self.TOURNEYROUND = 0 self.MISSING = -1 self.CANCEL = False for each in self.playerlist: each['register'] = 0 kwargs['Broadcast'].broadcast(\ "ExecScript GlobalSet var TR val 0;\ ExecScript GlobalClear; ExecScript GlobalSync") def getBye(self, **kwargs): #give the bye to the highest seeded player that doesn't have a bye lowest = -1 pick = None for each in self.seededlist: if each['bye'] == 1: continue ltarget = each['seed'] if (lowest < 0): lowest = ltarget # wouldn't work if the first player was the one to pick, so had to do this here pick = each continue if (lowest < ltarget): continue lowest = ltarget pick = each print pick pick['bye'] = 1 pick['advance'] = 1 def removePlayer(self, clinum, **kwargs): #remove a player when they have been defeated, if double elimination they have been moved to self.loserlist with single loss. for each in self.seededlist: if each['clinum'] == clinum: self.seededlist.remove(each) #for double elimination, remove them all together if they have two loses for each in self.loserlist: if each['clinum'] == clinum: if each['totalloses'] > 1: self.loserlist.remove(each) def spawnStatues(self, **kwargs): for each in self.statuelist: kwargs['Broadcast'].broadcast(\ "RemoveEntity #GetIndexFromName(player_%s)#;\ SpawnEntityAtEntity statue_%s Prop_Dynamic name player_%s maxhealth 999999999 model \"/world/props/arena/stone_legionnaire.mdf\" angles \"%s\" team 0 seed 0 scale 1.7627 propname %s"\ % (self.STATUE,self.STATUE,self.STATUE,self.statueangle[self.STATUE-1],each)) self.STATUE += 1 if self.STATUE > 6: self.STATUE = 1
class admin(ConsolePlugin): VERSION = "1.3.6" playerlist = [] adminlist = [] banlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in ini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") print config ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'commander' : False}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) client['sf'] = sf client['level'] = level client['active'] = True #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Send the chat message: ^rhelp ^cto see what commands you can perform."\ % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>."\ % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) #ADDED: more than 5 message in 1 second = kick tm = time.time() last = self.LASTMESSAGE['lasttime'] first = self.LASTMESSAGE['firsttime'] if (self.LASTMESSAGE['client'] == name): self.LASTMESSAGE['lasttime'] = tm #commanders are immune if not client['commander']: self.LASTMESSAGE['repeat'] += 1 print 'repeat' else: self.LASTMESSAGE['client'] = name self.LASTMESSAGE['firsttime'] = tm self.LASTMESSAGE['repeat'] = 0 if self.LASTMESSAGE['repeat'] > 4: if ((last - first) < 1): reason = "Spamming chat results in automatic kicking." kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (clinum, reason)) self.LASTMESSAGE['client'] = None self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 else: self.LASTMESSAGE['repeat'] = 0 self.LASTMESSAGE['client'] = None self.LASTMESSAGE['firsttime'] = 0 self.LASTMESSAGE['lasttime'] = 0 request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast("SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return #Pass to superCommand if the player is a superuser if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.onBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.getBalance, args=(clinum, None), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.reportBalance, args=(), kwargs=kwargs) balancethread.start() self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmi kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address till the end of the game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin slap playername ^wwill move the player. Use to get them off of structures if they are exploiting."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) def getBalance(self, *args, **kwargs): clinum = args[0] for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) def reportBalance(self, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo), 1) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) def superCommand(self, message, **kwargs): #This allows superuser to issue any console command supercommand = re.match("sudo (.*)", message, flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even self.onBalance(clinum, **kwargs) def onBalance(self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 time.sleep(2) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #Get Information about the teams teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) startstack = self.evaluateBalance(teamone, teamtwo) #Send message to admin that called the shuffle/balance kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yPrior to balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s" \ % (args[0], teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = self.evaluateBalance(teamone, teamtwo, player1, player2, True) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast(\ "echo unproductive balance") return #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #kwargs['Broadcast'].broadcast(\ # "SendMessage %s ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ # % (clinum, teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 800, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0
def __init__(self): master = MasterServer('Master2') master.run(['Slave21', 'Slave22'])
class mapvote(ConsolePlugin): VERSION = "0.0.1" ms = None PHASE = 0 playerlist = [] maplist = [] votelist = {'votes' : 0, 'playervotes' : []} TOTALPLAYERS = 0 VOTEPERCENT = 40 MINPLAYERS = 0 NEWMAP = None MAPVOTE = True def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) #for (name, value) in config.items('mapvote'): # if (name == "level"): # self._level = int(value) # if (name == "sf"): # self._sf = int(value) for (name, value) in ini.items('maps'): self.maplist.append({'name' : name, 'status' : value}) for (name, value) in ini.items('var'): if (name == "votepercent"): self.VOTEPERCENT = value if (name == "minplayers"): self.MINPLAYERS = value print self.MINPLAYERS, self.VOTEPERCENT pass def onStartServer(self, *args, **kwargs): print 'serverstarted' def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] self.playerlist.append ({'clinum' : id, 'acctid' : 0, 'name' : 'X', 'active' : 0}) def onSetName(self, *args, **kwargs): mapnames = [] for each in self.maplist: mapnames.append(each['name']) mapnames = ', '.join(mapnames) mapmessage = "^cThis server is currently equipped with the ability to vote for a map change. Before a game has started you can send the message to ^rALL ^cchat: ^ynextmap mapname" mapmessage2 = "^cThis will register your vote for that map." mapmessage3 = ("^cCurrent valid maps are: ^y%s" % (mapnames)) cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage2)) kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage3)) def onAccountId(self, *args, **kwargs): self.TOTALPLAYERS += 1 cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['active'] = 1 def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) for each in self.playerlist: if cli == each['clinum']: each['active'] = 0 #if a player has voted and disconnects, remove their vote for each in self.votelist['playervotes']: if each['player'] == client['name']: self.votelist['playervotes'].remove(each) self.votelist['votes'] -= 1 self.TOTALPLAYERS -= 1 def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.onGameEnd(**kwargs) if (phase == 6): self.clearMapVotes(*args, **kwargs) if (phase == 5): self.clearMapVotes(*args, **kwargs) def onNewGame(self, *args, **kwargs): if (self.PICKING == 1): print 'team picking has begun, do not clear team player lists' kwargs['Broadcast'].broadcast("echo team picking has begun, do not clear team player lists!") self.PICKING = 0 return def voteCheck(self, *args, **kwargs): tie = False totalplayers = self.TOTALPLAYERS totalvotes = self.votelist['votes'] minplayers = int(self.MINPLAYERS) threshold = int(self.VOTEPERCENT) votepercent = int(totalvotes/totalplayers) * 100 #At least this many players must be present to even trigger a map selection if totalplayers < minplayers: print totalplayers print 'minplayer abort' return #This percentage of the total number of players must vote to trigger a map selection if votepercent < threshold: print votepercent print 'percent abort' return #determine which map has the most votes d = {} for votes in self.votelist['playervotes']: maps = votes['mapvote'] d.setdefault(maps,0) d[maps] += 1 items = [(v, k) for k, v in d.items()] items.sort() items.reverse() size = len(items) if size > 1: if items[0][0] == items[1][0]: print 'we have a tie' tie = True if tie: kwargs['Broadcast'].broadcast("Serverchat ^cThere is a tie between ^r%s ^cand ^r%s. ^cIf you would like to change your vote you may do so." % (items[0][1], items[1][1])) return #We have a map winner newmap = items[0][1] self.ChangeMap(newmap, **kwargs) def ChangeMap(self, newmap, **kwargs): status = 'official' for each in self.maplist: if each['name'] == newmap: status = each['status'] if status == 'unofficial': kwargs['Broadcast'].broadcast("set svr_sendStats false; set svr_official false ") kwargs['Broadcast'].broadcast("changeworld %s" % (newmap)) self.clearMapVotes(*args, **kwargs) def onMessage(self, *args, **kwargs): voted = False votemap = None #ignore anything that isn't sent to ALL chat if args[0] != "ALL": return #if the game has started, or we are in end phase, ignore if self.PHASE == 5 or self.PHASE == 7: return name = args[1] message = args[2] client = self.getPlayerByName(name) mapvote = re.match("nextmap (\S+)", message, flags=re.IGNORECASE) formap = mapvote.group(1) if not mapvote: return if mapvote: voted = self.CheckVoted(client) for maps in self.maplist: if formap == maps['name']: votemap = formap if votemap == None: #Map name is invalid, tell them they got it wrong kwargs['Broadcast'].broadcast("SendMessage %s ^cMap name not recognized." % (client['clinum'])) return #player has already voted, just change their map selection if voted: for each in self.votelist['playervotes']: if each['player'] == client['name']: each['mapvote'] = votemap kwargs['Broadcast'].broadcast("SendMessage %s ^cYou have switched your vote to ^r%s." % (client['clinum'], votemap)) self.reportVotes(**kwargs) self.voteCheck(**kwargs) return #player has not yet voted, add to the total number of votes and add their selection to the list self.votelist['votes'] += 1 self.votelist['playervotes'].append({'player' : client['name'], 'mapvote' : votemap}) kwargs['Broadcast'].broadcast("SendMessage %s ^cYou have voted for ^r%s." % (client['clinum'], votemap)) self.reportVotes(**kwargs) #check to see if all the voting critera have been met self.voteCheck(**kwargs) def CheckVoted(self, client, **kwargs): for each in self.votelist['playervotes']: if each['player'] == client['name']: return True def clearMapVotes(self, *args, **kwargs): self.votelist = {'votes' : 0, 'playervotes' : []} self.TOTALPLAYERS = 0 def reportVotes(self, *args, **kwargs): d = {} for votes in self.votelist['playervotes']: maps = votes['mapvote'] d.setdefault(maps,0) d[maps] += 1 items = [(v, k) for k, v in d.items()] items.sort() items.reverse() for each in items: kwargs['Broadcast'].broadcast("Serverchat ^cVotes for ^r%s: ^c%s" % (each[1], each[0])) def onGameEnd(self, *args, **kwargs): kwargs['Broadcast'].broadcast("set svr_sendStats true; set svr_official true")
def __init__(self): master = MasterServer('Master1') master.run(['Slave11', 'Slave12'])
class admin(ConsolePlugin): VERSION = "1.6.3" playerlist = [] adminlist = [] banlist = [] fullbanlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} DLL = '2f4827b8' norunes = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(config) + "/ban.ini" banini.read (banconfig) ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ban'): self.fullbanlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): kwargs['Broadcast'].broadcast("Set norunes 0") kwargs['Broadcast'].broadcast("exec patch.cfg") self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") if self.norunes == 1: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _buyindex #GetIndexFromClientNum(|#_client|#)#;\ set _none \"\"; set _item #GetScriptParam(itemname)#;\ if #StringEquals(|#_item|#,|#_none|#)# TakeItem #_buyindex# #GetScriptParam(slot)#;\ if #StringEquals(|#_item|#,|#_none|#)# SendMessage #GetScriptParam(clientid)# ^yYou cannot equip persistent items on this server;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") else: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") kwargs['Broadcast'].broadcast("set con_showerr false; set con_showwarn false;") kwargs['Broadcast'].broadcast("Set Entity_NpcController_Name \"S2WRAPPER\"") #kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set kid #GetScriptParam(clientid)#; set kcheck _karmaflag#kid#; if [kcheck > 0] clientexecscript clientdo #kid# cmd \\\"set voice_disabled true\\\"; echo\" spawn") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave host_onload true; SetSave host_created 1; WriteConfigScript ~/startup.cfg\"" % (id)) kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"quit\"" % (id)) kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): client['ip'] = ip return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'karma' : 0,\ 'commander' : False,\ 'req' : 0,\ 'flood' : None,\ 'f_req' : 0,\ 'l_req' : 0,\ 'msgsum' : None}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] if playername == "": reason = "You dont seem to have a name, thats odd." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) karma = int(stats['karma']) client['sf'] = sf client['level'] = level client['karma'] = karma client['active'] = True #kwargs['Broadcast'].broadcast(\ #"clientexecscript %s clientdo cmd \"set _vr #StringLength(|#GetCheckSum(cgame.dll)|#)#; if [_vr > 0] \\\"SendScriptInput what DLL value #getchecksum(cgame.dll)#\\\"; Else \\\"SendScriptInput what DLL value NONE\\\"\"" % (client['clinum'])) if karma < 0: kwargs['Broadcast'].broadcast(\ "set _karmaflag%s 1" % (client['clinum'])) #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isBanned(client, **kwargs): kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave cl_packetSendFPS 1\"" % (cli)) if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Use ^radmin <command>^c to execute commands through chat.^c You can get help by sending ^radmin help ^cto chat." % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>." % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def isBanned(self, client, **kwargs): banned = False for each in self.fullbanlist: if client['name'].lower() == each['name']: if each['level'] == 'banned': banned = True return banned def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) # --- # MORE THEN FLOOD REPEATS(3)=4 A SEC(1) = kick FLOOD_REPEATS = 2 FLOOD_A_SEC = 0.5 if not client['flood']: client['flood'] = { 'time' : 0, 'count' : 0 } flood = client['flood'] print "flood: %s - %f - %f = %f" % (flood['count'], time.time (), flood['time'], (time.time ()-flood['time'])) # Sickened2: spam-check based on message length and checksum msglen = len(list(message)) if msglen > 100: # this should be a lookup table for checksums of typical spam messages spam1chksum = "ec10ca635bb6b956959830f4e652369d" m = hashlib.md5() m.update(message[:100]) chksum = m.hexdigest() if chksum == spam1chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) elif not client['msgsum']: client['msgsum'] = chksum #print "Checksum" #print client['msgsum'] elif client['msgsum'] == chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: client['msgsum'] = chksum # Sickened2: the following method is not as effective because # 1) for large messages (e.g. > 250 bytes) part of the message is returned. For the same message length the # size could vary. So we can't use the message length reliably # 2) if 2 chat packets are sent to the server and the 1st one arrives with delay but in the correct order, # the difference between the time of arrival between the two packets is shorter than the difference # between the departure time of the two packets ## Sickened2: additional spam check; user is not capable of manually typing more than ## MAX_TYPING_SPEED characters per second (avg) #MAX_TYPING_SPEED = 212; # chars/sec #msglen = len(list(message)) #print "msglen = %d" % msglen #timediff = time.time () - flood['time'] #print "timediff = %f" % timediff ##print("len(list(message)) / timediff ={0}".format(len(list(message)) / timediff)) #if msglen / timediff > MAX_TYPING_SPEED: # reason = "Sigh. Spamming results in automatic kicking." # kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) if (time.time () - flood['time']) < FLOOD_A_SEC: flood['count'] += 1 if flood['count'] > FLOOD_REPEATS: reason = "Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: flood['count'] = 0 flood['time'] = time.time () request = re.match("request admin", message, flags=re.IGNORECASE) if request: for each in self.playerlist: if each['active'] and each['admin']: kwargs['Broadcast'].broadcast("SendMessage %s Admin present: ^y%s" % (client['clinum'], each['name'])) #ignore everything else if it isn't from admin if not admin: return if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) timeout = re.match("admin timeout (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) micoff = re.match("admin micoff (\S+)", message, flags=re.IGNORECASE) micon = re.match("admin micon (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("admin help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) swap = re.match("admin swap (\S+)", message, flags=re.IGNORECASE) setteam = re.match("admin setteam (\S+) (\S+)", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if timeout: reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(timeout.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) banini.set ('ipban', kickclient['ip'], kickclient['name']) banini.write (open(banconfig, 'wb')) self.ipban.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure if self.PHASE != 5: return slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if micoff: #Turns off players mic with clientdo offclient = self.getPlayerByName(micoff.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled true\"" % (offclient['clinum'])) if micon: #Turns on players mic with clientdo onclient = self.getPlayerByName(micon.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled false\"" % (onclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,True,False), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,False), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,True), kwargs=kwargs) balancethread.start() if swap: #swap a player to a different team swapplayer = self.getPlayerByName(swap.group(1)) newteam = 0 team = swapplayer['team'] if team == 1: newteam = 2 if team == 2: newteam = 1 if newteam == 0: return kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (swapplayer['clinum'], newteam)) if setteam: #swap a player to x team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin timeout playername ^wwill remove a player for one game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address permenantly."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micoff playername ^wwill turn the players mic off. Use on mic spammers."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micon playername ^wwill turn the players mic on."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin swap playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin setteam x playername ^wwill set players team to x."\ % (client['clinum'])) def superCommand(self, message, **kwargs): supercommand = re.match("sudo (.*)", str(message), flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def doBalance(self, admin, doBalance=False, doReport=False, **kwargs): clinum = admin for each in self.playerlist: each['team'] = 0 time.sleep(1) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) startstack = abs(self.evaluateBalance(teamone, teamtwo)) if doReport: kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = abs(self.evaluateBalance(teamone, teamtwo, player1, player2, True)) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yUnproductive balance. No swapping scenario would improve the balance over its current state." % (admin)) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Balance will swap ^r%s ^yand ^r%s" \ % (clinum, pick1['name'], pick2['name'])) if not doBalance: index1 = map(itemgetter('clinum'), teamone).index(pick1['clinum']) index2 = map(itemgetter('clinum'), teamtwo).index(pick2['clinum']) teamone[index1]['team'] = 2 teamtwo[index2]['team'] = 1 teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) #kwargs['Broadcast'].broadcast(\ #"SendMessage %s ^cProposed change: ^y Team One (%s players) Avg. SF: ^r%s^y median SF: ^r%s^y, Team Two (%s players) Avg. SF: ^r%s^y median SF: ^r%s. ^yStack value: ^r%s" \ #% (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) return if doBalance: #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ % (teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase kwargs['Broadcast'].broadcast("echo SERVERVAR: norunes is #norunes#") if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team self.requestTracker(cli, **kwargs) def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even #self.onBalance(clinum, **kwargs) kwargs['Broadcast'].broadcast("Startgame") def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) if args[1] != "Player_Commander": return client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 1000, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0 def getMatchID(self, *args, **kwargs): matchid = args[0] kwargs['Broadcast'].broadcast("Set Entity_NpcController_Description %s" % (matchid)) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] self.requestTracker(caller, **kwargs) if event == 'DLL': if value == 'NONE': return if value != self.DLL: banthread = threading.Thread(target=self.banclient, args=(caller, None), kwargs=kwargs) banthread.start() def banclient(self, *args, **kwargs): clinum = args[0] kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"UICall game_options \\\"HTTPGetFile(\'http://masterserver.savage2.s2games.com/create.php?phrase=1\', \'~/null\');\\\"\"" % (clinum)) time.sleep(1) kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"quit\"" % (clinum)) def getServerVar(self, *args, **kwargs): var = args[0] if var == 'norunes': self.norunes = args[1] def requestTracker (self, cli, **kwargs): tm = time.time() client = self.getPlayerByClientNum(cli) #If player requests item purchase, team join, unit select more than 12 times in 1 second, boot them if (tm - client['f_req']) > 1: client['req'] = 0 client['f_req'] = tm return client['req'] += 1 if client['req'] > 10: reason = "Spamming server requests results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (client['clinum'], reason))
class pug(ConsolePlugin): VERSION = "0.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False playerlist = [] startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"") if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 1\"") def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername client ['play'] = True def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time/60 sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['active'] = True client ['clan'] = clan client ['newteam'] = 0 def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team def onGameStart (self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True if phase == 6: self.PICKING = False self.STARTED = False self.startinfo = {'h_captain' : None, 'h_ready' : False, 'h_first' : False, 'b_captain' : None, 'b_ready' : False, 'b_first' : False} kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set Pet_Shaman_Prerequisite 1;\ set sv_setupTimeCommander 600000000;\ Set sv_maxteamdifference 30;") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") if phase == 7: for each in self.playerlist: each['newteam'] = 0 def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) noplay = re.match("pug noplay", message, flags=re.IGNORECASE) if noplay: self.togglePlay(client, **kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast("SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] info = self.startinfo #Captain select if event == 'Captain': if caller == info['b_captain'] or caller == info['h_captain']: return if value == 'beasts': info['b_captain'] = caller kwargs['Broadcast'].broadcast("set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; SendMessage -1 ^r%s^w is Captain of the Beasts!" % (client['name'])) if not info['h_captain']: info['h_first'] = True else: self.beginpicking(**kwargs) if value == 'humans': info['h_captain'] = caller kwargs['Broadcast'].broadcast("set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; SendMessage -1 ^r%s^w is Captain of the Humans!" % (client['name'])) if not info['b_captain']: info['b_first'] = True else: self.beginpicking(**kwargs) print info #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) if caller == info['h_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (info['b_captain'], info['b_captain'])) if caller == info['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast("SendMessage %s ^rThat player has requested to not play in this match." % (client['name'])) return player['newteam'] = 2 client['newteam'] = 2 kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (info['h_captain'],info['h_captain'] )) #Ready if event == 'Ready': #TODO:only make the button do something if the minimum number of players are reached if self.STARTED: return if caller == info['h_captain']: info['h_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == info['b_captain']: info['b_ready'] = True kwargs['Broadcast'].broadcast("SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if info['h_ready'] and info['b_ready']: kwargs['Broadcast'].broadcast("set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) def beginpicking(self, **kwargs): self.PICKING = True #start by making the teams unjoinable: doesn't seem to work kwargs['Broadcast'].broadcast("set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";") #move everyone to spectator, but move captains to the appropriate team for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) #Set variables to get the first captain to start picking if self.startinfo['h_first']: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) else: kwargs['Broadcast'].broadcast("set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast("NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class sendstats(ConsolePlugin): base = None sent = None playerlist = [] login = None lpass = None broadcast = 0 serverid = 0 loaded = False def onPluginLoad(self, config): ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('paths'): if (name == "base"): self.base = value if (name == "sent"): self.sent = value def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) #Everytime we start a game, start a new thread to send all the stats to eaxs' script, and replays to stony if (phase == 6): uploadthread = thread.start_new_thread(self.uploadstats, ()) eventthread = thread.start_new_thread(self.uploadevent, ()) replaythread = thread.start_new_thread(self.uploadreplay, ()) if not self.loaded: kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_login is #svr_login#") kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_pass is #svr_pass#") kwargs['Broadcast'].broadcast( "echo SERVERVAR: svr_broadcast is #svr_broadcast#") self.loaded = True def uploadstats(self): print 'starting uploadstats' self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob(os.path.join(home, self.base, '*.stats')): print "Sending stat file: " + infile s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("stats=%s" % (decoded)) try: self.ss.s2gstats(statstring) self.ss.salvagestats(stats) self.ss.s2pstats(statstring) except: print 'upload failed. no stats sent' return try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def uploadevent(self): self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob(os.path.join(home, self.base, '*.event')): match = os.path.splitext(os.path.basename(infile))[0] s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("event%s=%s" % (match, decoded)) try: self.ss.s2pstats(stats) except: print 'upload failed. no stats sent' return try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer() if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid def uploadreplay(self): print 'starting uploadreplay' self.ss = StatsServers() home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) remotehost = '188.40.92.72' remotefile = 'incoming' port = 22522 for infile in glob.glob(os.path.join(home, self.base, '*.s2r')): print "Sending replay file: " + infile try: #self.ss.sendreplay(infile) os.system('scp -P "%s" "%s" scponly@"%s:%s"' % (port, infile, remotehost, remotefile)) except: print 'upload failed. replay not sent' continue print 'Sent replay' try: shutil.copy(infile, sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] self.playerlist.append({ 'clinum': id, 'acctid': 0, 'name': 'X', 'ip': ip }) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onAccountId(self, *args, **kwargs): self.ss = StatsServers() cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) name = client['name'] ip = client['ip'] server = self.serverid playerinfo = ("sync_user=1&username=%s&acc=%s&ip=%s&svr=%s" % (name, id, ip, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) acct = client['acctid'] name = client['name'] server = self.serverid playerinfo = ("sync_user=2&username=%s&acc=%s&svr=%s" % (name, id, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class extras(ConsolePlugin): VERSION = "1.2.2" ms = None CHAT_INTERVAL = 10 CHAT_STAMP = 0 playerlist = [] itemlist = [] followlist = [] FOLLOWERS = 4 MAPSIZE = 0 MAPSIZESET = False buildingprotect = False def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) pass def RegisterScripts(self, **kwargs): #Setup everything for following self.followlist = [] followers = 1 framestring = "" while followers <= self.FOLLOWERS: followstring = ("\ RegisterGlobalScript -1 \"set _follower{0} #GetIndexFromClientNum(|#_f{0}|#)#;\ set _followed{0} #GetIndexFromClientNum(|#_fd{0}|#)#;\ set _fx{0} #GetPosX(|#_followed{0}|#)#;\ set _fy{0} #GetPosY(|#_followed{0}|#)#;\ set _x{0} #GetPosX(|#_follower{0}|#)#;\ set _y{0} #GetPosY(|#_follower{0}|#)#;\ set _z{0} #GetPosZ(|#_follower{0}|#)#;\ set _zs{0} #_x{0}#, #_y{0}#;\ set _zt{0} #GetTerrainHeight(|#_zs{0}|#)#;\ if [_z{0} < _zt{0}] set _z{0} [_zt{0} + 50];\ set _followX{0} 200;\ set _followY{0} 200;\ SetPosition #_follower{0}# [_fx{0} + _followX{0}] [_fy{0} + _followY{0}] [_z{0}]\" follow{0}").format(followers) framestring += (";if [_f{0} >= 0] ExecScript follow{0}").format(followers) kwargs['Broadcast'].broadcast("%s" % (followstring)) f = "_f{0}".format(followers) fd = "_fd{0}".format(followers) kwargs['Broadcast'].broadcast("set %s -1; set %s -1" % (f, fd)) self.followlist.append({'follower' : -1, 'followed' : -1, 'f' : f, 'fd' : fd}) followers += 1 kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _ii 0%s\" frame" % (framestring)) def getPlayerByClientNum(self, cli): client = None for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if phase == 5: self.RegisterScripts(**kwargs) if phase == 6: self.RegisterScripts(**kwargs) #remove stuck for players for each in self.playerlist: each['stuck'] = False #set buildig protect scripts #TODO: make sure the place it moves them is a valid position if self.buildingprotect: kwargs['Broadcast'].broadcast("\ RegisterGlobalScript -1 \"RegisterEntityScript #GetScriptParam(index)# death \\\"Set _dead\ #GetScriptParam(index)#; ExecScript Death\\\";\ set _index #GetScriptParam(index)#; set _mz 350;\ set _type #GetScriptParam(type)#; echo #_type#; if #StringEquals(|#_type|#,Building_HumanHellShrine)#\ set _mz 2000; if #StringEquals(|#_type|#,Building_ArrowTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_CannonTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ChlorophilicSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_EntangleSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ShieldTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_StrataSpire)# set _mz 2000;\ set _x #GetPosX(|#_index|#)#;\ set _y #GetPosY(|#_index|#)#;\ set _z #GetPosZ(|#_index|#)#;\ SpawnEntityatEntity #_index# Trigger_Proximity model /core/null/null.mdf name DeathTrigger#_index# triggeronplayer 1 triggerradius\ 250 triggerenter\ \\\"set _domove 1; set _xindex #GetScriptParam(index)#;\ set _xtype #GetType(|#_xindex|#)#;\ if #StringEquals(|#_xtype|#,Player_Behemoth)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Malphas)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Devourer)# set _domove 0;\ set _xx #GetPosX(|#_xindex|#)#;\ set _xy #GetPosY(|#_xindex|#)#;\ set _xz #GetPosZ(|#_xindex|#)#;\ if [_domove == 1] SetPosition #_xindex# [_xx + 300] [_xy - 300] #_xz#\\\";\ SetPosition #GetIndexFromName(DeathTrigger|#_index|#)# #_x# #_y# [_z + _mz];\ echo\" buildingplaced") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"RemoveEntity #GetIndexFromName(DeathTrigger|#_dead|#)#; echo\" Death"); #get the map size #removing this for now as it is not used. Old55 2/10/12 #mapthread = threading.Thread(target=self.getMapSize, args=(), kwargs=kwargs) #mapthread.start() if phase == 7: for each in self.playerlist: each['team'] = 0 self.MAPSIZESET = False def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({ 'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'sf' : 0,\ 'lf' : 0,\ 'name' : 'X',\ 'team' : 0,\ 'stuck' : False,\ 'index' : 0,\ 'exp' : 2,\ 'value' : 150,\ 'prevent' : 0,\ 'active' : False,\ 'gamelevel' : 1}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False for each in self.followlist: if each ['follower'] == client['clinum'] or each['followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername mapmessage = "^cSpectators on this server can follow individual players. Send the message: ^rfollow playername. ^cTo stop following: ^rstop follow.\ ^cIf you get stuck on the map you can send the message: ^rstuck^c to nudge you out of your spot. This can be used once a game." kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['lf'] = lf client ['exp'] = exp client ['active'] = True def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team for each in self.followlist: if each ['follower'] == client['clinum'] or each['followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) #Various chat matches followed = re.match("follow (\S+)", message, flags=re.IGNORECASE) stopfollow = re.match("stop follow", message, flags=re.IGNORECASE) stuck = re.match("stuck", message, flags=re.IGNORECASE) if followed: action = 'start' followed_player = self.getPlayerByName(followed.group(1)) if followed_player == None: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cCould not find a player by that name." % (client['clinum'])) return if (followed_player ['team'] > 0) and (client ['team'] == 0): self.followaction(action, client, followed_player, **kwargs) if stopfollow: action = 'stop' self.followaction(action, client, followed_player=None, **kwargs) if stuck: if client['stuck']: return kwargs['Broadcast'].broadcast(\ "set _stuckindex #GetIndexFromClientNum(%s)#;\ set _X [rand*100]; echo #_X#;\ set _Y [rand*100]; echo #_Y#;\ set _stuckx #GetPosX(|#_stuckindex|#)#;\ set _stucky #GetPosY(|#_stuckindex|#)#;\ set _stuckz #GetPosZ(|#_stuckindex|#)#;\ SetPosition #_stuckindex# [_stuckx + _X] [_stucky + _Y] [_stuckz + 40]" % (client['clinum'])) client['stuck'] = True def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] if event == 'Follow': #Determine if it is follow or stop if value == 'stop': action = value self.followaction(action, client, followed_player=None, **kwargs) return else: action = 'start' followed_player = self.getPlayerByName(value) if (followed_player ['team'] > 0) and (client ['team'] == 0): self.followaction(action, client, followed_player, **kwargs) return #if event == 'SetMapPosition': # if client['team'] != 0: # return # maxcoord = ((self.MAPSIZE - 1) * 64 * 64) # print maxcoord # location = re.match("(0\.\d+)_(0.\d+)", value) # print location.group(1), location.group(2) # coordx = float(location.group(1))*maxcoord # coordy = float(location.group(2))*maxcoord # print coordx, coordy # kwargs['Broadcast'].broadcast(\ # "SetPosition #GetIndexFromClientNum(%s)# %s %s #GetPosZ(|#GetIndexFromClientNum(%s)|#)#" % (client['clinum'], coordx, coordy, client['clinum'])) def followaction(self, action, client, followed_player, **kwargs): if action == 'start': for each in self.followlist: #first check if they are already a follower if each ['follower'] == client['clinum']: each ['followed'] = followed_player['clinum'] self.follow(**kwargs) return for each in self.followlist: #if not already follower, grab the first available spot if each['follower'] == -1: each ['follower'] = client['clinum'] each ['followed'] = followed_player['clinum'] self.follow(**kwargs) return #If all the spots are filled, report it kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cThe follow list is full!" % (client['clinum'])) return if action == 'stop': for each in self.followlist: if each['follower'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def follow(self, **kwargs): for each in self.followlist: kwargs['Broadcast'].broadcast(\ "set %s %s; set %s %s" % (each['f'], each['follower'], each['fd'], each['followed'])) def getMapSize(self,**kwargs): checkdimension = 131071 self.MAPSIZE = 10 while not self.MAPSIZESET: time.sleep(0.5) self.MAPSIZESET = True checkdimension = checkdimension/2 kwargs['Broadcast'].broadcast("echo #GetTerrainHeight(%s,0)#" % (checkdimension)) print 'Map Size =', self.MAPSIZE time.sleep(1) def mapDimensions(self, *args, **kwargs): if self.MAPSIZE > 0: print 'made it to MAP DIMENSONS' self.MAPSIZE -= 1 self.MAPSIZESET = False def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class pug(ConsolePlugin): VERSION = "1.0.1" ms = None PHASE = 0 STARTSTAMP = 0 STARTED = False PICKING = False HUMANPICK = False playerlist = [] startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } teamlist = [] TIME = 0 def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) ''' for (name, value) in ini.items('var'): if (name == "clan1"): self.CLAN1 = value if (name == "clan2"): self.CLAN2 = value ''' pass def onStartServer(self, *args, **kwargs): self.PHASE = 0 self.playerlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'ip' : ip,\ 'sf' : 0,\ 'name' : 'X',\ 'active' : False,\ 'team' : 0,\ 'ping' : 0,\ 'clan' : 'X'}) #kwargs['Broadcast'].broadcast("SendMessage %s ^cTo toggle your PUG availability send the chat message ^rpug noplay" % (id)) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";" ) if self.PICKING: resetall(**kwargs) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";" ) if self.PICKING: resetall(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername client['play'] = True kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) exp = int(stats['exp']) time = int(stats['secs']) time = time / 60 #sf = int(exp/time) clan = stats['clan_tag'] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['level'] = level client['sf'] = sf client['active'] = True client['clan'] = clan client['newteam'] = 0 kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"showwidget pug_button\"" % (cli)) if self.PICKING: kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" % (cli)) def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team if self.PICKING: for each in self.teamlist: if (each['player'] == cli) and (team != each['team']): #don't let them switch kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['player'], each['team'])) return #kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['player'])) def onGameStart(self, *args, **kwargs): self.STARTSTAMP = args[1] def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if phase == 5: self.STARTSTAMP = args[1] self.STARTED = True self.PICKING = False if phase == 6: self.PICKING = False self.teamlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput" ) kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"" ) if phase == 7: for each in self.playerlist: each['newteam'] = 0 self.PICKING = False self.STARTED = False resetall(**kwargs) def togglePlay(self, client, playing=None, **kwargs): color = '^g' if self.PICKING: kwargs['Broadcast'].broadcast( "SendMessage %s ^rYou cannot toggle your status once picking has begun." % (client['clinum'])) return if not playing: if client['play']: client['play'] = False color = '^r' else: client['play'] = True else: client['play'] = playing if not client['play']: color = '^r' #kwargs['Broadcast'].broadcast("SendMessage %s ^cYour Playing Status: %s%s" % (client['clinum'], color, client['play'])) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] #info = self.startinfo #Captain initiated if event == 'Captain': #If they are already captain, do nothing if caller == self.startinfo[ 'b_captain'] or caller == self.startinfo['h_captain']: return #Beasts, set captain if value == 'beasts': self.startinfo['b_captain'] = caller kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 0\"; set Pet_BeastWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['h_captain']: self.startinfo['h_first'] = True #Humans, set captain if value == 'humans': self.startinfo['h_captain'] = caller kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 0\"; set Pet_HumanWorker_Inventory9 \"%s\"" % (client['name'])) if not self.startinfo['b_captain']: self.startinfo['b_first'] = True #Check if picking is initiated, if so determine who gets the next picking if self.PICKING: self.setpicking(**kwargs) return #Start picking process through the normal mechanism if self.startinfo['h_captain'] and self.startinfo['b_captain']: self.beginpicking(**kwargs) #Toggle player availability if event == 'Toggle': playing = False if value == 'true': playing = True self.togglePlay(client, playing, **kwargs) #Player select if event == 'Select': player = self.getPlayerByName(value) #switch everything to ingame_picking function if the game is already started if self.PHASE == 5: #pickthread = threading.Thread(target=self.ingame_picking, args=(caller, client, player, None), kwargs=kwargs) #pickthread.start() #self.ingame_picking(caller, client, player, **kwargs) print 'Will go to ingame picking' if caller == self.startinfo['h_captain']: #check players status if not player['play']: kwargs['Broadcast'].broadcast( "SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 1 client['newteam'] = 1 self.teamlist.append({ "player": player["clinum"], "team": 1 }) kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Humans!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (player['clinum'])) kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain'])) self.HUMANPICK = False if caller == self.startinfo['b_captain']: if not player['play']: kwargs['Broadcast'].broadcast( "SendMessage %s ^rThat player has requested to not play in this match." % (client['clinum'])) return player['newteam'] = 2 client['newteam'] = 2 self.teamlist.append({ "player": player["clinum"], "team": 2 }) kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has selected ^y%s ^wfor the Beasts!" % (client['name'], player['name'])) kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (player['clinum'])) kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) self.HUMANPICK = True if self.PICKING: self.setpicking(**kwargs) #Ready if event == 'Ready': if self.STARTED: return if caller == self.startinfo['h_captain']: if self.startinfo['h_ready']: return self.startinfo['h_ready'] = True kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has indicated that Humans are ready!" % (client['name'])) if caller == self.startinfo['b_captain']: if self.startinfo['b_ready']: return self.startinfo['b_ready'] = True kwargs['Broadcast'].broadcast( "SendMessage -1 ^r%s^w has indicated that Beasts are ready!" % (client['name'])) #Start the game if both captains say they are ready if self.startinfo['h_ready'] and self.startinfo['b_ready']: kwargs['Broadcast'].broadcast( "set State_ImpPoisoned_Name \"trigger UpdateSpeed 0\"") self.populate(**kwargs) if event == 'Resign': #if pick has begun and a captain resigns, just reset the whole damn thing if self.PICKING: self.resetall(**kwargs) if client['clinum'] == self.startinfo['h_captain']: self.startinfo['h_captain'] = None self.startinfo['h_ready'] = False kwargs['Broadcast'].broadcast( "set State_Interrupted_EffectPath \"trigger UpdateDetail 1\"; set Pet_HumanWorker_Inventory9 \"\";" ) if client['clinum'] == self.startinfo['b_captain']: self.startinfo['b_captain'] = None self.startinfo['b_ready'] = False kwargs['Broadcast'].broadcast( "set Gadget_Hail_ModelPath \"trigger UpdateError 1\"; set Pet_BeastWorker_Inventory9 \"\";" ) #self.setpicking(**kwargs) def resetall(self, **kwargs): self.PICKING = False self.teamlist = [] self.startinfo = { 'h_captain': None, 'h_ready': False, 'h_first': False, 'b_captain': None, 'b_ready': False, 'b_first': False } kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description -1;\ set State_Interrupted_EffectPath \"trigger UpdateDetail 1\";\ set Gadget_Hail_ModelPath \"trigger UpdateError 1\";\ set State_ImpPoisoned_Name \"trigger UpdateSpeed 1\";\ set Gadget_Hail_Description \"trigger UpdatePercent -1\";\ set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 1\";\ set maxteams 3;\ set sv_maxteamdifference 10;\ set Pet_Shaman_Prerequisite 1;\ set Pet_HumanWorker_Inventory9 \"\";\ set Pet_BeastWorker_Inventory9 \"\";") kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"showwidget team_button0; showwidget team_button1\"" ) for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0; SendMessage -1 ^yTeams are reset after captain resignation." % (each['clinum'])) def RegisterStart(self, **kwargs): self.PICKING = True def beginpicking(self, **kwargs): #move everyone to spec for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 0" % (each['clinum'])) self.teamlist = [] #start by making the teams unjoinable kwargs['Broadcast'].broadcast( "set sv_setupTimeCommander 600000000; set sv_maxteamdifference 1; set State_ImpPoisoned_ExpiredEffectPath \"trigger UpdateExtraction 0\";" ) kwargs['Broadcast'].broadcast( "ClientExecScript -1 clientdo cmd \"hidewidget team_button0; hidewidget team_button1\"" ) #move captains to the appropriate team and have them switch back to lobby for each in self.playerlist: if each['clinum'] == self.startinfo['h_captain']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 1" % (each['clinum'])) if each['clinum'] == self.startinfo['b_captain']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# 2" % (each['clinum'])) kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['h_captain'])) kwargs['Broadcast'].broadcast( "ClientExecScript %s clientdo cmd \"Action ToggleLobby\"" % (self.startinfo['b_captain'])) self.teamlist.append({ "player": self.startinfo['h_captain'], "team": 1 }) self.teamlist.append({ "player": self.startinfo['b_captain'], "team": 2 }) #Set variables to get the first captain to start picking if self.startinfo['h_first']: self.HUMANPICK = True self.setpicking(**kwargs) else: self.HUMANPICK = False self.setpicking(**kwargs) kwargs['Broadcast'].broadcast("echo STARTTOURNEY") def populate(self, **kwargs): for each in self.playerlist: if each['active']: kwargs['Broadcast'].broadcast( "set _index #GetIndexFromClientNum(%s)#; SetTeam #_index# %s" % (each['clinum'], each['newteam'])) #Send to the next phase kwargs['Broadcast'].broadcast( "NextPhase; set sv_setupTimeCommander 60000; PrevPhase") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] try: client = self.getPlayerByName(name) except: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) def onServerStatus(self, *args, **kwargs): if self.STARTED != 1: return pickthread = threading.Thread(target=self.ingame_picking, args=(), kwargs=kwargs) pickthread.start() def ingame_picking(self, *args, **kwargs): self.listClients(self, **kwargs) teamone = [] teamtwo = [] time.sleep(1) #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) #figure out who gets the pick team1 = len(teamone) team2 = len(teamtwo) if team1 > team2: self.HUMANPICK = False self.setpicking(**kwargs) if team2 > team1: self.HUMANPICK = True self.setpicking(**kwargs) if team1 == team2: return def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #TODO: listclients clinum is always double diget (00, 01, etc.) so this might be a problem acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def setpicking(self, **kwargs): if self.HUMANPICK: kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['h_captain'], self.startinfo['h_captain'])) else: kwargs['Broadcast'].broadcast( "set State_SuccessfulBlock_Description %s; set Gadget_Hail_Description \"trigger UpdatePercent %s\"" % (self.startinfo['b_captain'], self.startinfo['b_captain']))
def __init__(self): master = MasterServer('Master3') master.run(['Slave31', 'Slave32'])
class sendstats(ConsolePlugin): base = None sent = None playerlist = [] login = None lpass = None broadcast = 0 serverid = 0 loaded = False sending = False def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('paths'): if (name == "base"): self.base = value if (name == "sent"): self.sent = value def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if not self.loaded: kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_login is #svr_login#") kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_pass is #svr_pass#") kwargs['Broadcast'].broadcast("echo SERVERVAR: svr_broadcast is #svr_broadcast#") self.loaded = True #Everytime we start a game, start a new thread to send all the stats to eaxs' script, and replays to stony if (phase == 6): uploadthread = thread.start_new_thread(self.uploadstats, ()) #eventthread = thread.start_new_thread(self.uploadevent, ()) def uploadstats(self): print 'starting uploadstats' self.ss = StatsServers () home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob( os.path.join(home, self.base,'*.stats') ): print "Sending stat file: " + infile statstring_raw = open(infile, 'r') datastat = statstring_raw.readlines() statstring = datastat[1] replayname = os.path.splitext(os.path.basename(infile))[0] try: replaysize = os.path.getsize(os.path.join(home, self.base, replayname+'.s2r')) except: replaysize = 100000 statstring_replay = statstring + ("&file_name=%s.s2r&file_size=%s" % (replayname,replaysize)) try: self.ss.s2gstats(statstring_replay) except Exception as e: print e.message print 'upload failed. no stats sent' continue try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue #if not self.sending: #self.uploadreplay() def uploadevent(self): self.ss = StatsServers () home = os.environ['HOME'] path = os.path.join(home, self.base) sentdir = os.path.join(home, self.sent) for infile in glob.glob( os.path.join(home, self.base,'*.event') ): match = os.path.splitext(os.path.basename(infile))[0] s2pfile = infile statstring = open(infile, 'r').read() decoded = urllib.quote(statstring) stats = ("event%s=%s" % (match,decoded)) try: self.ss.s2pstats(stats) except: print 'upload failed. no stats sent' return try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue def getServerVar(self, *args, **kwargs): var = args[0] if var == 'svr_login': self.login = args[1] if var == 'svr_pass': self.lpass = args[1] if var == 'svr_broadcast': self.broadcast = int(args[1]) self.ms = MasterServer () if self.broadcast > 0: server = self.ms.getServer(self.login, self.lpass, self.broadcast) self.serverid = server['svr_id'] print self.serverid def uploadreplay(self): print 'starting uploadreplay' self.sending = True self.ss = StatsServers () home = os.environ['HOME'] sentdir = os.path.join(home, self.sent) time.sleep(1) for infile in glob.glob( os.path.join(home, self.base,'*.s2r') ): print "Sending replay file: " + infile with open(infile, 'rb') as f: data = f.read() encoded = base64.b64decode(data) replay = {'id':infile, 'login':self.login, 'pass':self.lpass, 'content':encoded} replayjson = json.dumps(replay) try: self.ss.replays(replayjson) except: print 'upload failed. replay not sent' continue print 'Sent replay' try: shutil.copy(infile,sentdir) os.remove(os.path.join(home, self.base, infile)) except: continue self.sending = False def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] self.playerlist.append ({'clinum' : id, 'acctid' : 0,'name' : 'X', 'ip' : ip}) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): self.ss = StatsServers () cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) name = client ['name'] ip = client['ip'] server = self.serverid playerinfo = ("sync_user=1&username=%s&acc=%s&ip=%s&svr=%s" % (name, id, ip, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) acct = client['acctid'] name = client['name'] server = self.serverid playerinfo = ("sync_user=2&username=%s&acc=%s&svr=%s" % (name, id, server)) #Send info to PS2 self.ss.salvagestats(playerinfo) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class extras(ConsolePlugin): VERSION = "1.2.2" ms = None CHAT_INTERVAL = 10 CHAT_STAMP = 0 playerlist = [] itemlist = [] followlist = [] FOLLOWERS = 4 MAPSIZE = 0 MAPSIZESET = False buildingprotect = False def onPluginLoad(self, config): self.ms = MasterServer() ini = ConfigParser.ConfigParser() ini.read(config) pass def RegisterScripts(self, **kwargs): #Setup everything for following self.followlist = [] followers = 1 framestring = "" while followers <= self.FOLLOWERS: followstring = ("\ RegisterGlobalScript -1 \"set _follower{0} #GetIndexFromClientNum(|#_f{0}|#)#;\ set _followed{0} #GetIndexFromClientNum(|#_fd{0}|#)#;\ set _fx{0} #GetPosX(|#_followed{0}|#)#;\ set _fy{0} #GetPosY(|#_followed{0}|#)#;\ set _x{0} #GetPosX(|#_follower{0}|#)#;\ set _y{0} #GetPosY(|#_follower{0}|#)#;\ set _z{0} #GetPosZ(|#_follower{0}|#)#;\ set _zs{0} #_x{0}#, #_y{0}#;\ set _zt{0} #GetTerrainHeight(|#_zs{0}|#)#;\ if [_z{0} < _zt{0}] set _z{0} [_zt{0} + 50];\ set _followX{0} 200;\ set _followY{0} 200;\ SetPosition #_follower{0}# [_fx{0} + _followX{0}] [_fy{0} + _followY{0}] [_z{0}]\" follow{0}" ).format(followers) framestring += ( ";if [_f{0} >= 0] ExecScript follow{0}").format(followers) kwargs['Broadcast'].broadcast("%s" % (followstring)) f = "_f{0}".format(followers) fd = "_fd{0}".format(followers) kwargs['Broadcast'].broadcast("set %s -1; set %s -1" % (f, fd)) self.followlist.append({ 'follower': -1, 'followed': -1, 'f': f, 'fd': fd }) followers += 1 kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"set _ii 0%s\" frame" % (framestring)) def getPlayerByClientNum(self, cli): client = None for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): client = None for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) if phase == 5: self.RegisterScripts(**kwargs) if phase == 6: self.RegisterScripts(**kwargs) #remove stuck for players for each in self.playerlist: each['stuck'] = False #set buildig protect scripts #TODO: make sure the place it moves them is a valid position if self.buildingprotect: kwargs['Broadcast'].broadcast("\ RegisterGlobalScript -1 \"RegisterEntityScript #GetScriptParam(index)# death \\\"Set _dead\ #GetScriptParam(index)#; ExecScript Death\\\";\ set _index #GetScriptParam(index)#; set _mz 350;\ set _type #GetScriptParam(type)#; echo #_type#; if #StringEquals(|#_type|#,Building_HumanHellShrine)#\ set _mz 2000; if #StringEquals(|#_type|#,Building_ArrowTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_CannonTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ChlorophilicSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_EntangleSpire)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_ShieldTower)# set _mz 2000;\ if #StringEquals(|#_type|#,Building_StrataSpire)# set _mz 2000;\ set _x #GetPosX(|#_index|#)#;\ set _y #GetPosY(|#_index|#)#;\ set _z #GetPosZ(|#_index|#)#;\ SpawnEntityatEntity #_index# Trigger_Proximity model /core/null/null.mdf name DeathTrigger#_index# triggeronplayer 1 triggerradius\ 250 triggerenter\ \\\"set _domove 1; set _xindex #GetScriptParam(index)#;\ set _xtype #GetType(|#_xindex|#)#;\ if #StringEquals(|#_xtype|#,Player_Behemoth)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Malphas)# set _domove 0;\ if #StringEquals(|#_xtype|#,Player_Devourer)# set _domove 0;\ set _xx #GetPosX(|#_xindex|#)#;\ set _xy #GetPosY(|#_xindex|#)#;\ set _xz #GetPosZ(|#_xindex|#)#;\ if [_domove == 1] SetPosition #_xindex# [_xx + 300] [_xy - 300] #_xz#\\\";\ SetPosition #GetIndexFromName(DeathTrigger|#_index|#)# #_x# #_y# [_z + _mz];\ echo\" buildingplaced") kwargs['Broadcast'].broadcast( "RegisterGlobalScript -1 \"RemoveEntity #GetIndexFromName(DeathTrigger|#_dead|#)#; echo\" Death" ) #get the map size #removing this for now as it is not used. Old55 2/10/12 #mapthread = threading.Thread(target=self.getMapSize, args=(), kwargs=kwargs) #mapthread.start() if phase == 7: for each in self.playerlist: each['team'] = 0 self.MAPSIZESET = False def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({ 'clinum' : id,\ 'acctid' : 0,\ 'level' : 0,\ 'sf' : 0,\ 'lf' : 0,\ 'name' : 'X',\ 'team' : 0,\ 'stuck' : False,\ 'index' : 0,\ 'exp' : 2,\ 'value' : 150,\ 'prevent' : 0,\ 'active' : False,\ 'gamelevel' : 1}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False for each in self.followlist: if each['follower'] == client['clinum'] or each[ 'followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername mapmessage = "^cSpectators on this server can follow individual players. Send the message: ^rfollow playername. ^cTo stop following: ^rstop follow.\ ^cIf you get stuck on the map you can send the message: ^rstuck^c to nudge you out of your spot. This can be used once a game." kwargs['Broadcast'].broadcast("SendMessage %s %s" % (client['clinum'], mapmessage)) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) client['level'] = level client['sf'] = sf client['lf'] = lf client['exp'] = exp client['active'] = True def onTeamChange(self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team for each in self.followlist: if each['follower'] == client['clinum'] or each[ 'followed'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) #Various chat matches followed = re.match("follow (\S+)", message, flags=re.IGNORECASE) stopfollow = re.match("stop follow", message, flags=re.IGNORECASE) stuck = re.match("stuck", message, flags=re.IGNORECASE) if followed: action = 'start' followed_player = self.getPlayerByName(followed.group(1)) if followed_player == None: kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cCould not find a player by that name." % (client['clinum'])) return if (followed_player['team'] > 0) and (client['team'] == 0): self.followaction(action, client, followed_player, **kwargs) if stopfollow: action = 'stop' self.followaction(action, client, followed_player=None, **kwargs) if stuck: if client['stuck']: return kwargs['Broadcast'].broadcast(\ "set _stuckindex #GetIndexFromClientNum(%s)#;\ set _X [rand*100]; echo #_X#;\ set _Y [rand*100]; echo #_Y#;\ set _stuckx #GetPosX(|#_stuckindex|#)#;\ set _stucky #GetPosY(|#_stuckindex|#)#;\ set _stuckz #GetPosZ(|#_stuckindex|#)#;\ SetPosition #_stuckindex# [_stuckx + _X] [_stucky + _Y] [_stuckz + 40]" % (client['clinum'])) client['stuck'] = True def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] if event == 'Follow': #Determine if it is follow or stop if value == 'stop': action = value self.followaction(action, client, followed_player=None, **kwargs) return else: action = 'start' followed_player = self.getPlayerByName(value) if (followed_player['team'] > 0) and (client['team'] == 0): self.followaction(action, client, followed_player, **kwargs) return #if event == 'SetMapPosition': # if client['team'] != 0: # return # maxcoord = ((self.MAPSIZE - 1) * 64 * 64) # print maxcoord # location = re.match("(0\.\d+)_(0.\d+)", value) # print location.group(1), location.group(2) # coordx = float(location.group(1))*maxcoord # coordy = float(location.group(2))*maxcoord # print coordx, coordy # kwargs['Broadcast'].broadcast(\ # "SetPosition #GetIndexFromClientNum(%s)# %s %s #GetPosZ(|#GetIndexFromClientNum(%s)|#)#" % (client['clinum'], coordx, coordy, client['clinum'])) def followaction(self, action, client, followed_player, **kwargs): if action == 'start': for each in self.followlist: #first check if they are already a follower if each['follower'] == client['clinum']: each['followed'] = followed_player['clinum'] self.follow(**kwargs) return for each in self.followlist: #if not already follower, grab the first available spot if each['follower'] == -1: each['follower'] = client['clinum'] each['followed'] = followed_player['clinum'] self.follow(**kwargs) return #If all the spots are filled, report it kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cThe follow list is full!" % (client['clinum'])) return if action == 'stop': for each in self.followlist: if each['follower'] == client['clinum']: each['follower'] = -1 each['followed'] = -1 self.follow(**kwargs) def follow(self, **kwargs): for each in self.followlist: kwargs['Broadcast'].broadcast(\ "set %s %s; set %s %s" % (each['f'], each['follower'], each['fd'], each['followed'])) def getMapSize(self, **kwargs): checkdimension = 131071 self.MAPSIZE = 10 while not self.MAPSIZESET: time.sleep(0.5) self.MAPSIZESET = True checkdimension = checkdimension / 2 kwargs['Broadcast'].broadcast("echo #GetTerrainHeight(%s,0)#" % (checkdimension)) print 'Map Size =', self.MAPSIZE time.sleep(1) def mapDimensions(self, *args, **kwargs): if self.MAPSIZE > 0: print 'made it to MAP DIMENSONS' self.MAPSIZE -= 1 self.MAPSIZESET = False def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class helper(ConsolePlugin): VERSION = "0.0.1" playerlist = [] helperlist = [] PHASE = 0 CONFIG = None def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level' : value}) pass def reload_config(self): self.helperlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level' : value}) def onStartServer(self, *args, **kwargs): self.playerlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'helper' : False,\ 'level' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client['sf'] = sf client['level'] = level client['active'] = True client['helper'] = False if client['level'] <= 10: self.helperNotify(client, **kwargs) for each in self.helperlist: if client['name'].lower() == each['name']: client['helper'] = True def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch helper list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/helper.ini') helperlist = response.read() f = open(self.CONFIG, 'w') f.write(helperlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() def helperNotify(self, client, **kwargs): activehelpers = [] for player in self.playerlist: if player['helper'] and player['active']: activehelpers.append(player['name']) activestring = ', '.join(activehelpers) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rATTENTION: ^cAs a new player it so good to get help from more experienced players. The following players on this server have \ indicated their willingness to help newer players: ^y%s. ^cYou can contact them by using chat (^wCTRL+ENTER^c) and whispering them (^y/w playername^c with your message)." % (client['clinum'], activestring)) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class admin(ConsolePlugin): VERSION = "1.6.4" playerlist = [] adminlist = [] banlist = [] fullbanlist = [] ipban = [] itemlist = [] PHASE = 0 CONFIG = None UPDATE = True NEEDRELOAD = False LASTMESSAGE = {'client' : None, 'firsttime' : 0, 'lasttime' : 0, 'repeat' : 0} DLL = '2f4827b8' norunes = 0 def onPluginLoad(self, config): self.ms = MasterServer () self.CONFIG = config ini = ConfigParser.ConfigParser() banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(config) + "/ban.ini" banini.read (banconfig) ini.read(config) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) pass def reload_config(self): self.adminlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) for (name, value) in ini.items('admin'): self.adminlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ban'): self.fullbanlist.append({'name': name, 'level' : value}) for (name, value) in banini.items('ipban'): self.ipban.append(name) def reload_plugins(self): config = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../s2wrapper.ini") ini = ConfigParser.ConfigParser() ini.read(config) for name in ini.options('plugins'): if name == 'admin': PluginsManager.reload(name) continue if ini.getboolean('plugins', name): PluginsManager.reload(name) def onStartServer(self, *args, **kwargs): kwargs['Broadcast'].broadcast("Set norunes 0") kwargs['Broadcast'].broadcast("exec patch.cfg") self.playerlist = [] self.banlist = [] def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"echo SCRIPT Client #GetScriptParam(clientid)# #GetScriptParam(what)# with value #GetScriptParam(value)#; echo\" scriptinput") #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") if self.norunes == 1: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _buyindex #GetIndexFromClientNum(|#_client|#)#;\ set _none \"\"; set _item #GetScriptParam(itemname)#;\ if #StringEquals(|#_item|#,|#_none|#)# TakeItem #_buyindex# #GetScriptParam(slot)#;\ if #StringEquals(|#_item|#,|#_none|#)# SendMessage #GetScriptParam(clientid)# ^yYou cannot equip persistent items on this server;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") else: kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#;\ echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") kwargs['Broadcast'].broadcast("set con_showerr false; set con_showwarn false;") kwargs['Broadcast'].broadcast("Set Entity_NpcController_Name \"S2WRAPPER\"") #kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set kid #GetScriptParam(clientid)#; set kcheck _karmaflag#kid#; if [kcheck > 0] clientexecscript clientdo #kid# cmd \\\"set voice_disabled true\\\"; echo\" spawn") def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByAcctId(self, acctid): for client in self.playerlist: if (client['acctid'] == acctid): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] ip = args[2] for each in self.ipban: if each == ip: reason = "You are banned from this server." kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave host_onload true; SetSave host_created 1; WriteConfigScript ~/startup.cfg\"" % (id)) kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"quit\"" % (id)) kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (id, reason)) return reason = "An administrator has removed you from this server. You may rejoin the server after the current game ends." for each in self.banlist: if each == ip: kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" % (id, reason)) for client in self.playerlist: if (client['clinum'] == id): client['ip'] = ip return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'ip' : ip,\ 'team' : 0,\ 'sf' : 0,\ 'active' : False,\ 'level' : 0,\ 'admin' : False,\ 'value' : 0,\ 'karma' : 0,\ 'commander' : False,\ 'req' : 0,\ 'flood' : None,\ 'f_req' : 0,\ 'l_req' : 0,\ 'msgsum' : None}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client ['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] if playername == "": reason = "You dont seem to have a name, thats odd." kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, reason)) client = self.getPlayerByClientNum(cli) client ['name'] = playername def getAccountInfo(self, *args, **kwargs): client = self.getPlayerByClientNum(args[0]) stats = self.ms.getStatistics (client['acctid']).get ('all_stats').get (client['acctid']) level = int(stats['level']) sf = int(stats['sf']) karma = int(stats['karma']) client['sf'] = sf client['level'] = level client['karma'] = karma client['active'] = True #kwargs['Broadcast'].broadcast(\ #"clientexecscript %s clientdo cmd \"set _vr #StringLength(|#GetCheckSum(cgame.dll)|#)#; if [_vr > 0] \\\"SendScriptInput what DLL value #getchecksum(cgame.dll)#\\\"; Else \\\"SendScriptInput what DLL value NONE\\\"\"" % (client['clinum'])) if karma < 0: kwargs['Broadcast'].broadcast(\ "set _karmaflag%s 1" % (client['clinum'])) #If client has disconnected, give them their gold back self.giveGold(False, client, **kwargs) def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] client = self.getPlayerByClientNum(cli) client['acctid'] = int(id) statthread = threading.Thread(target=self.getAccountInfo, args=(cli,None), kwargs=kwargs) statthread.start() if self.isBanned(client, **kwargs): kwargs['Broadcast'].broadcast(\ "clientexecscript %s clientdo cmd \"SetSave cl_packetSendFPS 1\"" % (cli)) if self.isAdmin(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as an administrator. Use ^radmin <command>^c to execute commands through chat.^c You can get help by sending ^radmin help ^cto chat." % (cli)) client['admin'] = True if self.isSuperuser(client, **kwargs): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou are registered as superuser on this server. You can send console commands with chat message: ^rsudo <command>." % (cli)) def isAdmin(self, client, **kwargs): admin = False for each in self.adminlist: if client['name'].lower() == each['name']: admin = True return admin def isSuperuser(self, client, **kwargs): superuser = False for each in self.adminlist: if client['name'].lower() == each['name']: if each['level'] == 'super': superuser = True return superuser def isBanned(self, client, **kwargs): banned = False for each in self.fullbanlist: if client['name'].lower() == each['name']: if each['level'] == 'banned': banned = True return banned def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) clinum = client['clinum'] admin = self.isAdmin(client, **kwargs) superuser = self.isSuperuser(client, **kwargs) # --- # MORE THEN FLOOD REPEATS(3)=4 A SEC(1) = kick FLOOD_REPEATS = 2 FLOOD_A_SEC = 0.5 if not client['flood']: client['flood'] = { 'time' : 0, 'count' : 0 } flood = client['flood'] print "flood: %s - %f - %f = %f" % (flood['count'], time.time (), flood['time'], (time.time ()-flood['time'])) # Sickened2: spam-check based on message length and checksum msglen = len(list(message)) if msglen > 100: # this should be a lookup table for checksums of typical spam messages spam1chksum = "ec10ca635bb6b956959830f4e652369d" m = hashlib.md5() m.update(message[:100]) chksum = m.hexdigest() if chksum == spam1chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) elif not client['msgsum']: client['msgsum'] = chksum #print "Checksum" #print client['msgsum'] elif client['msgsum'] == chksum: reason = "Attention! Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: client['msgsum'] = chksum # Sickened2: the following method is not as effective because # 1) for large messages (e.g. > 250 bytes) part of the message is returned. For the same message length the # size could vary. So we can't use the message length reliably # 2) if 2 chat packets are sent to the server and the 1st one arrives with delay but in the correct order, # the difference between the time of arrival between the two packets is shorter than the difference # between the departure time of the two packets ## Sickened2: additional spam check; user is not capable of manually typing more than ## MAX_TYPING_SPEED characters per second (avg) #MAX_TYPING_SPEED = 212; # chars/sec #msglen = len(list(message)) #print "msglen = %d" % msglen #timediff = time.time () - flood['time'] #print "timediff = %f" % timediff ##print("len(list(message)) / timediff ={0}".format(len(list(message)) / timediff)) #if msglen / timediff > MAX_TYPING_SPEED: # reason = "Sigh. Spamming results in automatic kicking." # kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) if (time.time () - flood['time']) < FLOOD_A_SEC: flood['count'] += 1 if flood['count'] > FLOOD_REPEATS: reason = "Spamming results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (clinum, reason)) else: flood['count'] = 0 flood['time'] = time.time () #ignore everything else if it isn't from admin if not admin: return if superuser: self.superCommand(message, **kwargs) #Matches for normal admins restart = re.match("admin restart", message, flags=re.IGNORECASE) shuffle = re.match("admin shuffle", message, flags=re.IGNORECASE) kick = re.match("admin kick (\S+)", message, flags=re.IGNORECASE) ban = re.match("admin ban (\S+)", message, flags=re.IGNORECASE) timeout = re.match("admin timeout (\S+)", message, flags=re.IGNORECASE) slap = re.match("admin slap (\S+)", message, flags=re.IGNORECASE) micoff = re.match("admin micoff (\S+)", message, flags=re.IGNORECASE) micon = re.match("admin micon (\S+)", message, flags=re.IGNORECASE) changeworld = re.match("admin changeworld (\S+)", message, flags=re.IGNORECASE) help = re.match("admin help", message, flags=re.IGNORECASE) balance = re.match("admin balance", message, flags=re.IGNORECASE) getbalance = re.match("admin get balance", message, flags=re.IGNORECASE) reportbal = re.match("admin report balance", message, flags=re.IGNORECASE) swap = re.match("admin swap (\S+)", message, flags=re.IGNORECASE) setteam = re.match("admin setteam (\S+) (\S+)", message, flags=re.IGNORECASE) if restart: #restarts server if something catastrophically bad has happened kwargs['Broadcast'].broadcast("restart") if shuffle: #artificial shuffle vote if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot shuffle until the game has started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has shuffled the game." % (name)) self.listClients(**kwargs) shufflethread = threading.Thread(target=self.onShuffle, args=(clinum,None), kwargs=kwargs) shufflethread.start() if kick: #kicks a player from the server reason = "An administrator has removed you from the server, probably for being annoying" kickclient = self.getPlayerByName(kick.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\""\ % (kickclient['clinum'], reason)) if timeout: reason = "An administrator has banned you from the server. You are banned till this game is over." kickclient = self.getPlayerByName(timeout.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) self.banlist.append(kickclient['ip']) if ban: #kicks a player from the server and temporarily bans that player's IP till the game is over reason = "An administrator has banned you from the server." kickclient = self.getPlayerByName(ban.group(1)) kwargs['Broadcast'].broadcast(\ "Kick %s \"%s\"" \ % (kickclient['clinum'], reason)) banini = ConfigParser.ConfigParser () banconfig = os.path.dirname(self.CONFIG) + "/ban.ini" banini.read (banconfig) banini.set ('ipban', kickclient['ip'], kickclient['name']) banini.write (open(banconfig, 'wb')) self.ipban.append(kickclient['ip']) if slap: #slap will move a player x+100, y+200 to get them off of a structure if self.PHASE != 5: return slapclient = self.getPlayerByName(slap.group(1)) kwargs['Broadcast'].broadcast(\ "set _slapindex #GetIndexFromClientNum(%s)#;\ set _sx #GetPosX(|#_slapindex|#)#; set _sy #GetPosY(|#_slapindex|#)#; set _sz #GetPosZ(|#_slapindex|#)#;\ SetPosition #_slapindex# [_sx + 200] [_sy + 200] #_sz#;\ SendMessage %s ^cAn adminstrator has moved you for jumping on buildings. YOU WILL BE BANNED if this action persists"\ % (slapclient['clinum'], slapclient['clinum'])) if micoff: #Turns off players mic with clientdo offclient = self.getPlayerByName(micoff.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled true\"" % (offclient['clinum'])) if micon: #Turns on players mic with clientdo onclient = self.getPlayerByName(micon.group(1)) kwargs['Broadcast'].broadcast("ClientExecScript %s clientdo cmd \"set voice_disabled false\"" % (onclient['clinum'])) if changeworld: #change the map kwargs['Broadcast'].broadcast(\ "changeworld %s"\ % (changeworld.group(1))) if balance: if self.PHASE != 5: kwargs['Broadcast'].broadcast(\ "SendMessage %s Cannot balance if the game has not started!"\ % (client['clinum'])) return kwargs['Broadcast'].broadcast("SendMessage -1 %s has balanced the game." % (name)) self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,True,False), kwargs=kwargs) balancethread.start() if getbalance: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,False), kwargs=kwargs) balancethread.start() if reportbal: self.listClients(**kwargs) balancethread = threading.Thread(target=self.doBalance, args=(clinum,False,True), kwargs=kwargs) balancethread.start() if swap: #swap a player to a different team swapplayer = self.getPlayerByName(swap.group(1)) newteam = 0 team = swapplayer['team'] if team == 1: newteam = 2 if team == 2: newteam = 1 if newteam == 0: return kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (swapplayer['clinum'], newteam)) if setteam: #swap a player to x team setplayer = self.getPlayerByName(setteam.group(2)) newteam = setteam.group(1) kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (setplayer['clinum'], newteam)) self.logCommand(client['name'],message) if help: kwargs['Broadcast'].broadcast(\ "SendMessage %s All commands on the server are done through server chat. All commands are logged to prevent you from abusing them.The following are commands and a short description of what they do."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin restart ^whard reset of the server. ONLY use in weird cases."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin shuffle ^wwill shuffle the game and set to previous phase."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin kick playername ^wwill remove a player from the server."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin timeout playername ^wwill remove a player for one game."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin ban playername ^wwill remove a player from the server and ban that IP address permenantly."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micoff playername ^wwill turn the players mic off. Use on mic spammers."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin micon playername ^wwill turn the players mic on."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin changeworld mapname ^wwill change the map to the desired map."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin swap playername ^wwill move a specific player to another team."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin balance ^wwill move two players to achieve balance."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin get balance ^wwill report avg. and median SF values for the teams as well as a stack value."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin report balance ^wwill send a message to ALL players that has the avg. and median SF values."\ % (client['clinum'])) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^radmin setteam x playername ^wwill set players team to x."\ % (client['clinum'])) def superCommand(self, message, **kwargs): supercommand = re.match("sudo (.*)", str(message), flags=re.IGNORECASE) if supercommand: kwargs['Broadcast'].broadcast("%s" % (supercommand.group(1))) def doBalance(self, admin, doBalance=False, doReport=False, **kwargs): clinum = admin for each in self.playerlist: each['team'] = 0 time.sleep(1) teamone = [] teamtwo = [] #populate current team lists: for each in self.playerlist: if not each['active']: continue if each['team'] == 1: teamone.append(each) if each['team'] == 2: teamtwo.append(each) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) startstack = abs(self.evaluateBalance(teamone, teamtwo)) if doReport: kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s.^y Stack value: ^r%s" \ % (teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'], 1), round(teamtwostats['median'],1), abs(stack))) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Team One (%s players) Avg. SF is ^r%s^y median is ^r%s^y, Team Two (%s players) Avg. SF is ^r%s^y median is ^r%s. ^yStack value: ^r%s" \ % (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) #Find the players to swap lowest = -1 pick1 = None pick2 = None for player1 in teamone: if player1['commander']: continue for player2 in teamtwo: if player2['commander']: continue #sort of inefficient to send the teamlist each time ltarget = abs(self.evaluateBalance(teamone, teamtwo, player1, player2, True)) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 #If the stack isn't improved, abort it if (lowest >= startstack): kwargs['Broadcast'].broadcast(\ "SendMessage %s ^yUnproductive balance. No swapping scenario would improve the balance over its current state." % (admin)) return kwargs['Broadcast'].broadcast(\ "SendMessage %s ^y Balance will swap ^r%s ^yand ^r%s" \ % (clinum, pick1['name'], pick2['name'])) if not doBalance: index1 = map(itemgetter('clinum'), teamone).index(pick1['clinum']) index2 = map(itemgetter('clinum'), teamtwo).index(pick2['clinum']) teamone[index1]['team'] = 2 teamtwo[index2]['team'] = 1 teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) stack = round(self.evaluateBalance(teamone, teamtwo),1) #kwargs['Broadcast'].broadcast(\ #"SendMessage %s ^cProposed change: ^y Team One (%s players) Avg. SF: ^r%s^y median SF: ^r%s^y, Team Two (%s players) Avg. SF: ^r%s^y median SF: ^r%s. ^yStack value: ^r%s" \ #% (clinum, teamonestats['size'], round(teamonestats['avg'],1), round(teamonestats['median'],1), teamtwostats['size'], round(teamtwostats['avg'],1), round(teamtwostats['median'], 1), abs(stack))) return if doBalance: #Do the switch kwargs['Broadcast'].broadcast(\ "set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 2;\ set _index #GetIndexFromClientNum(%s)#;\ SetTeam #_index# 1"\ % (pick1['clinum'], pick2['clinum'])) #Give them gold if needed self.giveGold(True, pick1, **kwargs) self.giveGold(True, pick2, **kwargs) teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) kwargs['Broadcast'].broadcast(\ "SendMessage -1 ^yAfter balance: Team One Avg. SF was ^r%s^y median was ^r%s^y, Team Two Avg. SF was ^r%s^y median was ^r%s"\ % (teamonestats['avg'], teamonestats['median'], teamtwostats['avg'], teamtwostats['median'])) def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase kwargs['Broadcast'].broadcast("echo SERVERVAR: norunes is #norunes#") if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False each['value'] = 0 if (phase == 6): if self.UPDATE: #fetch admin list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() #check if server is empty after 2 minutes pluginthread = threading.Thread(target=self.pluginreload, args=(), kwargs=kwargs) pluginthread.start() self.RegisterScripts(**kwargs) self.ItemList() if (phase == 4): kwargs['Broadcast'].broadcast("listclients") def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/admin.ini') adminlist = response.read() f = open(self.CONFIG, 'w') f.write(adminlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() if self.NEEDRELOAD: self.pluginreload(**kwargs) return #Update the wrapper try: gitpath = os.path.realpath(os.path.dirname (os.path.realpath (__file__)) + "/../.git") command = ["git","--git-dir",gitpath,"pull"] output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate() result = output[0].split("\n")[0] print 'result is %s' % result #TODO: make sure these work on all servers? notneeded = re.match("Already up-to-date.", result) needed = re.match("Updating .*", result) except: print 'error getting git update' return if notneeded: print 'update not needed' self.NEEDRELOAD = False return if needed: print 'update needed' self.NEEDRELOAD = True self.pluginreload(**kwargs) return def pluginreload(self, **kwargs): print 'pluginreload called' #Wait a couple minutes to allow clients to connect time.sleep(120) #Figure out how many clients are present kwargs['Broadcast'].broadcast("serverstatus") def onServerStatusResponse(self, *args, **kwargs): if self.NEEDRELOAD: gamemap = args[0] active = int(args[2]) if active == 0: self.reload_plugins() kwargs['Broadcast'].broadcast("NextPhase; PrevPhase") self.NEEDRELOAD = False def logCommand(self, client, message, **kwargs): localtime = time.localtime(time.time()) date = ("%s-%s-%s, %s:%s:%s" % (localtime[1], localtime[2], localtime[0], localtime[3], localtime[4], localtime[5])) f = open('admin.log', 'a') f.write("Timestamp: \"%s\", Admin: %s, Command: %s\n" % (date, client, message)) f.close def onTeamChange (self, *args, **kwargs): team = int(args[1]) cli = args[0] client = self.getPlayerByClientNum(cli) client['team'] = team self.requestTracker(cli, **kwargs) def onShuffle (self, *args, **kwargs): for each in self.playerlist: each['team'] = 0 each['value'] = 0 clinum = args[0] time.sleep(2) shufflelist = [] #Put all the active players in a list for each in self.playerlist: if not each['active']: continue if each['team'] > 0: shufflelist.append(each) #sort shufflelists based on SF shufflelist = sorted(shufflelist, key=itemgetter('sf', 'level', 'clinum'), reverse=True) #randomly choose if we begin with human or beast r = random.randint(1,2) #Assign new teams, just like the K2 way, but Ino won't always be on humans for each in shufflelist: #TODO: is there a cleaner, more pythonic way to do this? each['team'] = r if r == 1: r += 1 elif r == 2: r -=1 #Now actually do the shuffling for each in shufflelist: kwargs['Broadcast'].broadcast(\ "SetTeam #GetIndexFromClientNum(%s)# %s"\ % (each['clinum'], each['team'])) #Finish it off by going forward a phase kwargs['Broadcast'].broadcast(\ "nextphase") kwargs['Broadcast'].broadcast(\ "SendMessage %s You have shuffled the game." % (clinum)) #Run balancer to get it nice and even #self.onBalance(clinum, **kwargs) kwargs['Broadcast'].broadcast("Startgame") def getTeamInfo(self, teamlist, **kwargs): teamsf = [] combteamsf = float(0) #figure out current averages and set some commonly used variables: for each in teamlist: combteamsf += each['sf'] teamsf.append(each['sf']) sizeteam = len(teamlist) avgteam = combteamsf/sizeteam med = median(teamsf) teaminfo = {'size' : sizeteam, 'avg' : avgteam, 'total' : combteamsf, 'median' : med} return teaminfo def evaluateBalance(self, team1, team2, pick1=None, pick2=None, swap=False, **kwargs): #This function will swap out the picked players in a temporary list if swap is true and report the stack percent #If swap is false, it will just report the balance #First, make new lists that we can modify: teamone = list(team1) teamtwo = list(team2) if swap: #Remove those players from the lists... for each in teamone: if each['clinum'] == pick1['clinum']: teamone.remove(each) for each in teamtwo: if each['clinum'] == pick2['clinum']: teamtwo.remove(each) #Add to the lists teamone.append(pick2) teamtwo.append(pick1) #Get the new team stats... teamonestats = self.getTeamInfo(teamone) teamtwostats = self.getTeamInfo(teamtwo) #Evaluate team balance teamoneshare = teamonestats['total']/(teamonestats['total'] + teamtwostats['total']) diffmedone = teamonestats['median']/(teamonestats['median'] + teamtwostats['median']) stack = teamoneshare + diffmedone #positive if team one is stacked, negative if team two is stacked return (stack - 1) * 100 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) client['commander'] = False def onUnitChange(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) if args[1] != "Player_Commander": return client['commander'] = True def listClients(self, *args, **kwargs): kwargs['Broadcast'].broadcast("listclients") def onListClients(self, *args, **kwargs): clinum = int(args[0]) name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player and get stats #usually used when reloading plugin during a game acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs) client = self.getPlayerByName(name) client['active'] = True kwargs['Broadcast'].broadcast(\ "echo CLIENT %s is on TEAM #GetTeam(|#GetIndexFromClientNum(%s)|#)#"\ % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) client = self.getPlayerByClientNum(clinum) client['team'] = team def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 1000, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) self.requestTracker(cli, **kwargs) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def giveGold(self, balance, client, **kwargs): if client['value'] == 0: return gold = round(client['value']/2, 0) if balance: gold = client['value'] kwargs['Broadcast'].broadcast(\ "SendMessage %s ^cYou have been compensated %s gold for your lost items.; GiveGold %s %s"\ % (client['clinum'], gold, client['clinum'], gold)) client['value'] = 0 def getMatchID(self, *args, **kwargs): matchid = args[0] kwargs['Broadcast'].broadcast("Set Entity_NpcController_Description %s" % (matchid)) def onScriptEvent(self, *args, **kwargs): caller = args[0] client = self.getPlayerByClientNum(caller) event = args[1] value = args[2] self.requestTracker(caller, **kwargs) if event == 'DLL': if value == 'NONE': return if value != self.DLL: banthread = threading.Thread(target=self.banclient, args=(caller, None), kwargs=kwargs) banthread.start() def banclient(self, *args, **kwargs): clinum = args[0] kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"UICall game_options \\\"HTTPGetFile(\'http://masterserver.savage2.s2games.com/create.php?phrase=1\', \'~/null\');\\\"\"" % (clinum)) time.sleep(1) kwargs['Broadcast'].broadcast(\ "ClientExecScript %s clientdo cmd \"quit\"" % (clinum)) def getServerVar(self, *args, **kwargs): var = args[0] if var == 'norunes': self.norunes = args[1] def requestTracker (self, cli, **kwargs): tm = time.time() client = self.getPlayerByClientNum(cli) #If player requests item purchase, team join, unit select more than 12 times in 1 second, boot them if (tm - client['f_req']) > 1: client['req'] = 0 client['f_req'] = tm return client['req'] += 1 if client['req'] > 10: reason = "Spamming server requests results in automatic kicking." kwargs['Broadcast'].broadcast("Kick %s \"%s\"" % (client['clinum'], reason))
class helper(ConsolePlugin): VERSION = "0.0.1" playerlist = [] helperlist = [] PHASE = 0 CONFIG = None def onPluginLoad(self, config): self.ms = MasterServer() self.CONFIG = config ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level': value}) pass def reload_config(self): self.helperlist = [] self.ipban = [] ini = ConfigParser.ConfigParser() ini.read(self.CONFIG) for (name, value) in ini.items('helpers'): self.helperlist.append({'name': name, 'level': value}) def onStartServer(self, *args, **kwargs): self.playerlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): return self.playerlist.append ({'clinum' : id,\ 'acctid' : 0,\ 'name' : 'X',\ 'active' : False,\ 'helper' : False,\ 'level' : 0}) def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) client['active'] = False def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client['name'] = playername def onAccountId(self, *args, **kwargs): cli = args[0] id = args[1] stats = self.ms.getStatistics(id).get('all_stats').get(int(id)) level = int(stats['level']) sf = int(stats['sf']) client = self.getPlayerByClientNum(cli) client['sf'] = sf client['level'] = level client['active'] = True client['helper'] = False if client['level'] <= 10: self.helperNotify(client, **kwargs) for each in self.helperlist: if client['name'].lower() == each['name']: client['helper'] = True def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.banlist = [] for each in self.playerlist: each['team'] = 0 each['commander'] = False if (phase == 6): #fetch helper list and reload at the start of each game updatethread = threading.Thread(target=self.update, args=(), kwargs=kwargs) updatethread.start() def update(self, **kwargs): response = urllib2.urlopen('http://188.40.92.72/helper.ini') helperlist = response.read() f = open(self.CONFIG, 'w') f.write(helperlist) f.close f.flush() os.fsync(f.fileno()) self.reload_config() def helperNotify(self, client, **kwargs): activehelpers = [] for player in self.playerlist: if player['helper'] and player['active']: activehelpers.append(player['name']) activestring = ', '.join(activehelpers) kwargs['Broadcast'].broadcast(\ "SendMessage %s ^rATTENTION: ^cAs a new player it so good to get help from more experienced players. The following players on this server have \ indicated their willingness to help newer players: ^y%s. ^cYou can contact them by using chat (^wCTRL+ENTER^c) and whispering them (^y/w playername^c with your message)." % (client['clinum'], activestring)) def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] ip = args[1] client = self.getPlayerByName(name) if not client: #if a player is missing from the list this will put them as an active player acct = self.ms.getAccount(name) acctid = acct[name] self.onConnect(clinum, 0000, ip, 0000, **kwargs) self.onSetName(clinum, name, **kwargs) self.onAccountId(clinum, acctid, **kwargs)
class balancer(ConsolePlugin): VERSION = "1.0.8" ms = None TIME = 0 THRESHOLD = 6 JOINTHRESHOLD = 8 DIFFERENCE = -1 GAMESTARTED = 0 STARTSTAMP = 0 DENY = 0 OPTION = 0 PICKING = 0 CHAT_INTERVAL = 10 CHAT_STAMP = 0 PHASE = 0 TOTAL1 = 0 TOTAL2 = 0 STAMPS = 0 reason = "Your Skill Factor is 0. Please play some matches on official beginner servers to get some stats before you join this server." playerlist = [] itemlist = [] balancereport = [] teamOne = {'size' : 0, 'avgBF' : -1, 'combinedBF' : 0, 'players' : []} teamTwo = {'size' : 0, 'avgBF' : -1, 'combinedBF' : 0, 'players' : []} game = {'size' : 0, 'avgBF' : -1} switchlist = [] followlist = [] def onPluginLoad(self, config): self.ms = MasterServer () ini = ConfigParser.ConfigParser() ini.read(config) for (name, value) in ini.items('balancer'): if (name == "threshold"): self.THRESHOLD = int(value) if (name == "jointhreshold"): self.JOINTHRESHOLD = int(value) pass def onStartServer(self, *args, **kwargs): self.TIME = 0 self.THRESHOLD = 6 self.DIFFERENCE = -1 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.PICKING = 0 self.CHAT_INTERVAL = 10 self.CHAT_STAMP = 0 self.PHASE = 0 self.TOTAL1 = 0 self.TOTAL2 = 0 self.STAMPS = 0 self.playerlist = [] self.itemlist = [] self.balancereport = [] self.teamOne = {'size' : 0, 'avgBF' : -1, 'combinedBF' : 0, 'players' : []} self.teamTwo = {'size' : 0, 'avgBF' : -1, 'combinedBF' : 0, 'players' : []} self.game = {'size' : 0, 'avgBF' : -1} self.switchlist = [] self.followlist = [] def getPlayerByClientNum(self, cli): for client in self.playerlist: if (client['clinum'] == cli): return client def getPlayerByName(self, name): for client in self.playerlist: if (client['name'].lower() == name.lower()): return client def onRefresh(self, *args, **kwargs): del self.teamOne ['players'][:] del self.teamTwo ['players'][:] self.teamOne ['size'] = 0 self.teamTwo ['size'] = 0 for client in self.playerlist: if (client['active'] == 1): kwargs['Broadcast'].broadcast("set _idx #GetIndexFromClientNum(%s)#; set _team #GetTeam(|#_idx|#)#; echo CLIENT %s is on TEAM #_team#" % (client['clinum'], client['clinum'])) def onRefreshTeams(self, *args, **kwargs): clinum = args[0] team = int(args[1]) if (team > 0): client = self.getPlayerByClientNum(clinum) teamlists = self.GetTeamLists(client, team) fromteam = teamlists ['fromteam'] self.addTeamMember(client, fromteam, team, **kwargs) return def onConnect(self, *args, **kwargs): id = args[0] for client in self.playerlist: if (client['clinum'] == id): #added 10/12. If a player DCs and reconnects, they are auto-joined to their old team #but there is no team join message. This automatically adds them back to the balancer team list. print 'already have entry with that clientnum!' team = int(client['team']) if (team > 0): teamlists = self.GetTeamLists(client, team) toteam = teamlists ['toteam'] fromteam = teamlists ['fromteam'] self.addTeamMember(client, fromteam, team, **kwargs) client ['active'] = 1 return return self.playerlist.append ({'clinum' : id, 'acctid' : 0, 'level' : 0, 'sf' : 0, 'bf' : 0, 'lf' : 0, 'name' : 'X', 'team' : 0, 'moved' : 0, 'index' : 0, 'exp' : 2, 'value' : 150, 'prevent' : 0, 'active' : 0, 'gamelevel' : 1}) def onSetName(self, *args, **kwargs): cli = args[0] playername = args[1] client = self.getPlayerByClientNum(cli) client ['name'] = playername def onAccountId(self, *args, **kwargs): doKick = False cli = args[0] id = args[1] stats = self.ms.getStatistics (id).get ('all_stats').get (int(id)) level = int(stats['level']) sf = int(stats['sf']) lf = int(stats['lf']) exp = int(stats['exp']) time = int(stats['secs']) if sf == 0 and exp > 500: time = time/60 sf = int(exp/time) client = self.getPlayerByClientNum(cli) client ['acctid'] = int(id) client ['level'] = level client ['sf'] = sf client ['lf'] = lf client ['exp'] = exp client ['active'] = 1 if sf == 0: doKick = True if doKick: kwargs['Broadcast'].broadcast("kick %s \"%s\"" % (cli, self.reason)) self.retrieveLevels(cli, **kwargs) def checkForSpectator (self, cli): player = self.getPlayerByClientNum(cli) if (player['team'] > 0): return cli else: return -1 def getTeamMember (self, item, cli, fromteam): indice = -1 for player in fromteam['players']: indice += 1 if (player['clinum'] == cli): return indice def getPlayerIndex (self, cli): indice = -1 for player in self.playlist: indice += 1 if (player['clinum'] == cli): return indice def removeTeamMember (self, client, fromteam, team, **kwargs): print 'Removing player....' client ['team'] = team cli = client ['clinum'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) fromteam ['combinedBF'] -= fromteam['players'][PLAYER_INDICE]['bf'] del fromteam['players'][PLAYER_INDICE] self.getGameInfo(**kwargs) def addTeamMember (self, client, toteam, team, **kwargs): print 'Adding player....' cli = client['clinum'] client ['active'] = 1 NAME = client['name'] level = client['level'] SF = client['sf'] #BF = SF + level + (client ['gamelevel'] * 4) BF = SF + (client ['gamelevel'] * 4) LF = client['lf'] + 10 moved = client['moved'] client ['team'] = team client ['bf'] = BF toteam ['players'].append ({'clinum' : cli, 'name' : NAME, 'sf' : SF, 'lf' : LF, 'level' : level, 'moved' : moved, 'bf' : BF}) self.getGameInfo(**kwargs) def GetTeamLists (self, client, team): currentteam = client ['team'] L = {'toteam' : '0', 'fromteam' : '0'} if (int(currentteam) == 1): L ['fromteam'] = self.teamOne L ['toteam'] = self.teamTwo return L if (int(currentteam) == 2): L ['fromteam'] = self.teamTwo L ['toteam'] = self.teamOne return L if (int(team) == 1): L ['toteam'] = self.teamOne if (int(team) == 2): L ['toteam'] = self.teamTwo return L #don't think I need this but I am leaving it in del L [0] def onTeamChange (self, *args, **kwargs): spec = -1 team = int(args[1]) cli = args[0] self.retrieveLevels(cli, **kwargs) client = self.getPlayerByClientNum(cli) currentteam = client ['team'] prevented = int(client ['prevent']) teamlists = self.GetTeamLists(client, team) toteam = teamlists ['toteam'] fromteam = teamlists ['fromteam'] if (self.DENY == 1): self.DIFFERENCE = abs(self.evaluateBalance()) diff = self.DIFFERENCE #check to see if the player is on a team and going to spectator. spec = -1 unless the player is already on a team if (int(team) == 0): spec = self.checkForSpectator(cli) #need to have this to avoid having players added multiple times as I have seen happen if (spec == -1) and (int(currentteam) == int(team)): return #if the player is switching teams, add them to the new team and remove from the old if (spec == -1) and (int(currentteam) > 0): self.addTeamMember(client, toteam, team, **kwargs) self.removeTeamMember(client, fromteam, team, **kwargs) #if the player hasn't joined a team yet, go ahead and add them to the team elif (spec == -1): self.addTeamMember(client, toteam, team, **kwargs) self.getGameInfo(**kwargs) #Players are prevented from joining in the deny phase if they will cause greater than a 10% stack #this applies to both even and uneven games. The player is forced back to team 0. if (self.DENY == 1): self.DIFFERENCE = abs(self.evaluateBalance()) if (self.DIFFERENCE > self.JOINTHRESHOLD) and (self.DIFFERENCE > diff): action = 'PREVENT' self.retrieveIndex(client, action, **kwargs) return #There may be an issue if the player is forced back to team 0 that they can't join a team #even if conditions are met. This just forcibly puts the player on the team they are are trying to join #provided the above critera is not true. if (prevented == 1): action = 'ALLOW' self.retrieveIndex(client, action, **kwargs) #if the player is going to spec, just remove them from the team if (spec > -1): self.removeTeamMember(client, fromteam, team, **kwargs) self.OPTION = 0 def onDisconnect(self, *args, **kwargs): cli = args[0] client = self.getPlayerByClientNum(cli) team = client ['team'] if (int(team) > 0): teamlist = self.GetTeamLists(client, team) fromteam = teamlist ['fromteam'] self.removeTeamMember(client, fromteam, team, **kwargs) #self.sendGameInfo(**kwargs) client ['active'] = 0 def onCommResign(self, *args, **kwargs): name = args[0] client = self.getPlayerByName(name) team = client['team'] cli = client['clinum'] teamlist = self.GetTeamLists(client, team) fromteam = teamlist ['fromteam'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) fromteam['players'][PLAYER_INDICE]['bf'] = client['sf'] + (client['gamelevel']*4) #fromteam['players'][PLAYER_INDICE]['bf'] = int(client['sf'] + client['level'] + (client['gamelevel']*4)) fromteam['players'][PLAYER_INDICE]['moved'] = 0 client ['moved'] = 0 def onUnitChange(self, *args, **kwargs): if args[1] != "Player_Commander": return cli = args[0] client = self.getPlayerByClientNum(cli) team = client['team'] teamlist = self.GetTeamLists(client, team) fromteam = teamlist ['fromteam'] item = 'clinum' PLAYER_INDICE = self.getTeamMember(item, cli, fromteam) #fromteam['players'][PLAYER_INDICE]['bf'] = client ['lf'] fromteam['players'][PLAYER_INDICE]['bf'] = fromteam['players'][PLAYER_INDICE]['lf'] fromteam['players'][PLAYER_INDICE]['moved'] = 1 #set moved to 1 to prevent the player from being auto-swapped as commander client['moved'] = 1 def onPhaseChange(self, *args, **kwargs): phase = int(args[0]) self.PHASE = phase if (phase == 7): self.onGameEnd(**kwargs) if (phase == 5): self.onGameStart(*args, **kwargs) self.PICKING = 0 if (phase == 3): self.PICKING = 1 if (phase == 6): self.onNewGame(*args, **kwargs) def onGameEnd(self, *args, **kwargs): avg1 = int(self.TOTAL1/self.STAMPS) avg2 = int(self.TOTAL2/self.STAMPS) print avg1, avg2, self.STAMPS kwargs['Broadcast'].broadcast("Serverchat ^cHow stacked was this game from start to finish? Humans had an average combined BF of ^r%s^c, Beasts had an average combined BF of ^r%s ^cfrom a total of ^y%s ^ctime points." % (avg1, avg2, self.STAMPS)) #clear out the team dictionary info and globals when the map is reloaded del self.teamOne ['players'][:] del self.teamTwo ['players'][:] for player in self.playerlist: player ['active'] = 0 player ['team'] = 0 player ['gamelevel'] = 1 player ['bf'] = int(player ['sf'] + player ['level']) player ['value'] = 150 self.teamOne ['size'] = 0 self.teamOne ['avgBF'] = -1 self.teamOne ['combinedBF'] = 0 self.teamTwo ['size'] = 0 self.teamTwo ['avgBF'] = -1 self.teamTwo ['combinedBF'] = 0 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.DIFFERENCE = -1 self.PICKING = 0 self.balancereport = [] #self.playerlist = [] self.TOTAL1 = 0 self.TOTAL2 = 0 self.STAMPS = 0 def onNewGame(self, *args, **kwargs): if (self.PICKING == 1): print 'team picking has begun, do not clear team player lists' kwargs['Broadcast'].broadcast("echo team picking has begun, do not clear team player lists!") self.PICKING = 0 return #clear out the team dictionary info and globals when the map is reloaded del self.teamOne ['players'][:] del self.teamTwo ['players'][:] for player in self.playerlist: player ['active'] = 0 player ['team'] = 0 player ['gamelevel'] = 1 player ['bf'] = int(player ['sf'] + player ['level']) player ['value'] = 150 self.teamOne ['size'] = 0 self.teamOne ['avgBF'] = -1 self.teamOne ['combinedBF'] = 0 self.teamTwo ['size'] = 0 self.teamTwo ['avgBF'] = -1 self.teamTwo ['combinedBF'] = 0 self.GAMESTARTED = 0 self.STARTSTAMP = 0 self.DENY = 0 self.OPTION = 0 self.DIFFERENCE = -1 self.RegisterScripts(**kwargs) def RegisterScripts(self, **kwargs): #any extra scripts that need to go in can be done here #these are for identifying bought and sold items kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# SOLD #_item#; echo\" sellitem") kwargs['Broadcast'].broadcast("RegisterGlobalScript -1 \"set _client #GetScriptParam(clientid)#; set _item #GetScriptParam(itemname)#; echo ITEM: Client #_client# BOUGHT #_item#; echo\" buyitem") #this makes sure we get an update every thirty seconds. kwargs['Broadcast'].broadcast("set sv_statusNotifyTime 30000") def ItemList(self, *args, **kwargs): self.itemlist = { 'Advanced Sights' : 700, 'Ammo Pack' : 500, 'Ammo Satchel' : 200, 'Chainmail' : 300, 'Gust of Wind' : 450, 'Magic Amplifier' : 700, 'Brain of Maliken' : 750, 'Heart of Maliken' : 950, 'Lungs of Maliken' : 800, 'Mana Crystal' : 500, 'Mana Stone' : 200, 'Platemail' : 650, 'Power Absorption' : 350, 'Shield of Wisdom' : 650, 'Stone Hide' : 650, 'Tough Skin' : 300, 'Trinket of Restoration' : 575 } def onItemTransaction(self, *args, **kwargs): #adjust 'value' in playerlist to reflect what the player has bought or sold cli = args[0] trans = args[1] newitem = args[2] client = self.getPlayerByClientNum(cli) try: value = self.itemlist[newitem] except: return if (trans == 'BOUGHT'): client['value'] += value elif (trans == 'SOLD'): client['value'] -= value def retrieveIndex(self, mover, action, **kwargs): #Use this for any manipulations when you need to get the current player index from the server. This is used for MOVE, PREVENT, ALLOW cli = mover['clinum'] client = self.getPlayerByClientNum(cli) kwargs['Broadcast'].broadcast("set _value #GetIndexFromClientNum(%s)#; echo Sv: Client %s index is #_value#. ACTION: %s" % (cli, cli, action)) def onRetrieveIndex(self, *args, **kwargs): #get stuff from parser clinum = args[0] index = args[1] action = args[2] if (action == 'MOVE'): self.move(clinum, index, **kwargs) if (action == 'PREVENT'): self.prevent(clinum, index, **kwargs) if (action == 'ALLOW'): self.allow(clinum, index, **kwargs) if (action == 'LEVEL'): self.level(clinum, index, **kwargs) def runBalancer (self, **kwargs): #determines if it is even or uneven balancer #3-23-11 - If there are fewer than 8 players, don't bother with balancer if (self.teamOne['size'] + self.teamTwo['size']) < 8: return diff = self.teamOne['size'] - self.teamTwo['size'] print diff if (diff == 0): self.EvenTeamBalancer(**kwargs) #uneven balancer if there is a difference between 1-3. if it more than that, it would be best to restart, but that has not been implemented elif (abs(diff) > 0 and abs(diff) < 4): self.UnEvenTeamBalancer(**kwargs) else: return def onGameStart (self, *args, **kwargs): self.ItemList() self.STARTSTAMP = args[1] self.GAMESTARTED = 1 kwargs['Broadcast'].broadcast("echo GAMESTARTED") self.sendGameInfo(**kwargs) kwargs['Broadcast'].broadcast("ServerChat ^cIf necessary, the teams will be auto-balanced at 1, 3, and 6 minutes of game time.") kwargs['Broadcast'].broadcast("ServerChat ^cAfter 6 minutes, joining will be limited to players that do not generate imbalance.") kwargs['Broadcast'].broadcast("ServerChat ^cAt 5 minute increments starting at minute 10, the server will check for imbalance and notify players that they will be switched in one minute unless they reject the move.") kwargs['Broadcast'].broadcast("ServerChat ^cSelected players may send the message 'reject' to ^bALL ^cchat to prevent the change.") self.RegisterScripts(**kwargs) self.startFollow(**kwargs) def onServerStatus(self, *args, **kwargs): CURRENTSTAMP = int(args[1]) self.TIME = int(CURRENTSTAMP) - int(self.STARTSTAMP) #self.getTeamLevels(**kwargs) kwargs['Broadcast'].broadcast("set _team1num #GetNumClients(1)#; set _team2num #GetNumClients(2)#; echo SERVER-SIDE client count, Team 1 #_team1num#, Team 2 #_team2num#") if (self.GAMESTARTED == 1): self.TOTAL1 += self.teamOne['combinedBF'] self.TOTAL2 += self.teamTwo['combinedBF'] self.STAMPS += 1 def evaluateBalance(self, BF1=0.0, BF2=0.0, moving=False, **kwargs): large = self.getLargeTeam() small = self.getSmallTeam() largebf = float(large ['combinedBF']) smallbf = float(small ['combinedBF']) totalbf = largebf + smallbf largeshare = (largebf - BF1 + BF2) / totalbf smallshare = (smallbf + BF1 - BF2) / totalbf largesize = float(large ['size']) smallsize = float(small ['size']) totalsize = largesize + smallsize if moving: largesize = float(large ['size']) - 1.0 smallsize = float(small ['size']) + 1.0 sizediff = largesize / totalsize largepercent = largeshare #largepercent = largeshare + sizediff return (largepercent - 0.5) * 100 #return (largepercent - 1) * 100 def getClosestPersonToTarget (self, team, **kwargs): lowest = -1 pick = None for player1 in team ['players']: if (player1['moved'] == 1): continue ltarget = abs(self.evaluateBalance (float(player1 ['bf']), 0.0, True)) print ltarget if (lowest < 0): lowest = ltarget # wouldn't work if the first player was the one to pick, so had to do this here pick = player1 continue if (lowest < ltarget): continue lowest = ltarget pick = player1 print pick if (pick == None): kwargs['Broadcast'].broadcast("echo BALANCER: UNEVEN balancer was not happy for some reason I can't figure out") return kwargs['Broadcast'].broadcast("echo BALANCER: UNEVEN balancer selections: Client %s with bf %s for a starting BF stacking of %s to %s" % (pick['clinum'], pick['bf'], self.DIFFERENCE, lowest)) #if the selected option doesn't actually improve anything, terminate if (lowest > self.DIFFERENCE): kwargs['Broadcast'].broadcast("echo BALANCER: unproductive UNEVEN balance") return if (self.OPTION == 0): #get the player index and move them action = 'MOVE' self.retrieveIndex(pick, action, **kwargs) return if (self.OPTION == 1): self.switchlist.append ({'name' : pick ['name'], 'clinum' : pick ['clinum'], 'accept' : 0}) print self.switchlist self.giveOption (**kwargs) def getClosestTwoToTarget (self, team1, team2, **kwargs): lowest = -1 pick1 = None pick2 = None for player1 in team1 ['players']: if (player1['moved'] == 1): continue for player2 in team2 ['players']: if (player2['moved'] == 1): continue ltarget = abs(self.evaluateBalance (float(player1 ['bf']), float(player2 ['bf']))) if (lowest < 0): lowest = ltarget pick1 = player1 pick2 = player2 continue if (lowest < ltarget): continue lowest = ltarget pick1 = player1 pick2 = player2 print pick1, pick2 kwargs['Broadcast'].broadcast("echo Balancer selections: Clients %s, %s with BF %s, %s." % (pick1['clinum'], pick2['clinum'], pick1['bf'], pick2['bf'])) if (lowest >= self.DIFFERENCE): print 'unproductive balance. terminate' kwargs['Broadcast'].broadcast("echo unproductive EVEN balance") return if (self.OPTION == 0): action = 'MOVE' self.retrieveIndex(pick1, action, **kwargs) self.retrieveIndex(pick2, action, **kwargs) return if (self.OPTION == 1): self.switchlist.append ({'name' : pick1['name'], 'clinum' : pick1['clinum'], 'accept' : 0}) self.switchlist.append ({'name' : pick2['name'], 'clinum' : pick2['clinum'], 'accept' : 0}) print self.switchlist self.giveOption (**kwargs) def giveOption(self, **kwargs): index = -1 playermessage = "^cYou have been selected to change teams to promote balance. You have one minute to REJECT this change by sending the message 'reject' to ^bALL ^cchat." for player in self.switchlist: index += 1 kwargs['Broadcast'].broadcast("SendMessage %s %s" % (player['clinum'], playermessage)) if (index == 0): kwargs['Broadcast'].broadcast("Serverchat ^cTeams are currently unbalanced. ^r%s ^chas been selected to improve balance. They will automatically switch teams in one minute unless they reject the move by sending the message 'reject' to ^bALL ^cchat, or another player joins." % (self.switchlist[0]['name'])) else: kwargs['Broadcast'].broadcast("Serverchat ^cTeams are currently unbalanced. ^r%s ^cand ^r%s ^chave been selected to improve balance. They will automatically switch teams in one minute unless one of them rejects the move by sending the message 'reject' to ^bALL ^cchat, or another player joins." % (self.switchlist[0]['name'], self.switchlist[1]['name'])) def onMessage(self, *args, **kwargs): name = args[1] message = args[2] client = self.getPlayerByName(name) if (args[0] == "SQUAD") and (message == 'report balance'): self.getGameInfo() kwargs['Broadcast'].broadcast("SendMessage %s Balance Report: ^yTeam 1 combined: ^g%s (%s players, %s BF average), ^yTeam 2 combined: ^g%s (%s players, %s BF average). ^yStack percentage: ^r%s. ^yCurrent Phase: ^c%s. ^yCurrent time stamp: ^c%s. ^yBalancer active = ^r%s" % (client['clinum'], self.teamOne ['combinedBF'], self.teamOne ['size'], self.teamOne ['avgBF'], self.teamTwo ['combinedBF'], self.teamTwo ['size'], self.teamTwo ['avgBF'], round(self.evaluateBalance(), 1), self.PHASE, self.TIME, self.GAMESTARTED)) for moves in self.balancereport: kwargs['Broadcast'].broadcast("SendMessage %s BALANCER: Balanced move for: %s at time %s" % (client['clinum'],moves ['name'], moves ['time'])) if (args[0] == "SQUAD") and (message == 'report team one'): for player in self.teamOne ['players']: kwargs['Broadcast'].broadcast("SendMessage %s Team One Report: Player: ^c%s ^rBF: ^y%s" % (client['clinum'], player['name'], player['bf'])) if (args[0] == "SQUAD") and (message == 'report team two'): for player in self.teamTwo ['players']: kwargs['Broadcast'].broadcast("SendMessage %s Team Two Report: Player: ^c%s ^rBF: ^y%s" % (client['clinum'], player['name'], player['bf'])) if (args[0] == "SQUAD") and (message == 'report playerlist'): for active in self.playerlist: if (active ['active'] == 1): kwargs['Broadcast'].broadcast("SendMessage %s Active Player List: Player: ^c%s ^rSF: ^y%s" % (client['clinum'], active['name'], active['sf'])) if (args[0] == "SQUAD") and (message == 'report version'): kwargs['Broadcast'].broadcast("SendMessage %s Balancer version: ^y%s" % (client['clinum'], self.VERSION)) if args[0] != "ALL": return if re.match(".*tell\s+(?:me\s+)?(?:the\s+)?(?:SFs?|balance)(?:\W.*)?$", message, flags=re.IGNORECASE): tm = time.time() if (tm - self.CHAT_STAMP) < self.CHAT_INTERVAL: return self.CHAT_STAMP = tm return self.sendGameInfo(**kwargs) if (self.OPTION == 1) and (message == 'reject'): for player in self.switchlist: if (player['name'] == name): kwargs['Broadcast'].broadcast("ServerChat ^r%s ^chas rejected a move to promote balance between the teams." % (name)) del self.switchlist[:] def optionCheck(self, **kwargs): if (self.OPTION == 1): for player in self.switchlist: action = 'MOVE' self.retrieveIndex(player, action, **kwargs) del self.switchlist[:] def move(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) client ['moved'] = 1 name = client ['name'] #only have to move players that are already on a team, and since they can only go to the other team we can use this if (int(client['team']) == 1): newteam = 2 else: newteam = 1 kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, newteam)) kwargs['Broadcast'].broadcast("Serverchat ^r%s ^chas switched teams to promote balance." % (name)) kwargs['Broadcast'].broadcast("ResetAttributes %s" % (index)) self.balancereport.append ({'time' : self.TIME, 'client' : name}) self.moveNotify(clinum, **kwargs) def prevent(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) client ['prevent'] = 1 newteam = 0 kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, newteam)) self.preventNotify(clinum, **kwargs) def allow(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) team = client ['team'] kwargs['Broadcast'].broadcast("SetTeam %s %s" % (index, team)) client ['prevent'] = 0 def level(self, clinum, index, **kwargs): client = self.getPlayerByClientNum(clinum) team = client ['team'] kwargs['Broadcast'].broadcast("set _plevel #GetLevel(%s)#; set team%s_level [team%s_level + _plevel]" % (index, team, team)) def moveNotify(self, clinum, **kwargs): #this lets the player know the have been moved and compensates them for their purchased items. There is current no way to know #how much gold a player holds, though I think gold may actually transfer. Not 100% sure. client = self.getPlayerByClientNum(clinum) value = client ['value'] kwargs['Broadcast'].broadcast("SendMessage %s ^cYou have automatically switched teams to promote balance." % (clinum)) kwargs['Broadcast'].broadcast("SendMessage %s ^cYou have been compensated ^g%s ^cgold for your non-consumable items and your attributes have been reset." % (clinum, value)) kwargs['Broadcast'].broadcast("GiveGold %s %s" % (clinum, value)) client ['value'] = 0 def preventNotify(self, clinum, **kwargs): kwargs['Broadcast'].broadcast("SendMessage %s ^cYou cannot join that team as it will create imbalance. Please wait for another player to join or leave." % (clinum)) def getSmallTeam (self): #writing these all out explicitly because I was having trouble with them if (self.teamOne ['size'] < self.teamTwo ['size']): return self.teamOne if (self.teamTwo ['size'] < self.teamOne ['size']): return self.teamTwo if (self.teamTwo ['size'] == self.teamOne ['size']): return self.teamTwo def getLargeTeam (self): #writing these all out explicitly because I was having trouble with them if (self.teamOne ['size'] > self.teamTwo ['size']): return self.teamOne if (self.teamTwo ['size'] > self.teamOne ['size']): return self.teamTwo if (self.teamTwo ['size'] == self.teamOne ['size']): return self.teamOne def getHighTeam (self): if (self.teamOne ['avgBF'] > self.teamTwo ['avgBF']): return self.teamOne return self.teamTwo def getLowTeam (self): if (self.teamOne ['avgBF'] > self.teamTwo ['avgBF']): return self.teamTwo return self.teamOne def getTeamOne (self): return self.teamOne def getTeamTwo (self): return self.teamTwo def getTeamAvg (self, team): #this updates the info for a team team ['combinedBF'] = 0 team ['size'] = 0 for clients in team ['players']: team ['combinedBF'] += clients ['bf'] team ['size'] += 1 if (team ['size'] > 0): team ['avgBF'] = (team ['combinedBF'] / team ['size']) else: team ['avgBF'] = 0 def getGameInfo (self, **kwargs): self.getTeamAvg (self.teamOne) self.getTeamAvg (self.teamTwo) self.game ['size'] = (self.teamOne ['size'] + self.teamTwo ['size']) self.game ['avgBF'] = ((self.teamOne ['avgBF'] + self.teamTwo ['avgBF']) / 2) def sendGameInfo (self, **kwargs): self.getGameInfo(**kwargs) if (self.GAMESTARTED == 1): self.DIFFERENCE = abs(self.evaluateBalance()) if self.GAMESTARTED == 1: kwargs['Broadcast'].broadcast("ServerChat ^cCurrent balance: ^yTeam 1 Avg. BF: ^g%s (%s players), ^yTeam 2 Avg. BF: ^g%s (%s players). Stack percentage: ^r%s" % (self.teamOne ['avgBF'], self.teamOne ['size'], self.teamTwo ['avgBF'], self.teamTwo ['size'], round(self.DIFFERENCE, 1) )) def EvenTeamBalancer(self, **kwargs): self.getGameInfo(**kwargs) #added these to prevent any moves if there is an error in BF calculation that has sprung up on occasion for clients in self.teamOne['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return for clients in self.teamTwo['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return self.DIFFERENCE = abs(self.evaluateBalance()) print(self.DIFFERENCE) if (self.DIFFERENCE > self.THRESHOLD): self.getClosestTwoToTarget (self.getLargeTeam (), self.getSmallTeam (), **kwargs) else: kwargs['Broadcast'].broadcast("Serverchat ^cEven team balancer initiated but current balance percentage of ^y%s ^cdoes not meet the threshold of ^y%s" % (round(self.DIFFERENCE, 1), self.THRESHOLD)) def UnEvenTeamBalancer(self, **kwargs): self.getGameInfo(**kwargs) #added these to prevent any moves if there is an error in BF calculation that has sprung up on occasion for clients in self.teamOne['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return for clients in self.teamTwo['players']: if clients['bf'] > 1000: kwargs['Broadcast'].broadcast("echo refresh") return overcheck = self.evaluateBalance() self.DIFFERENCE = abs(self.evaluateBalance()) #In this scenario, the larger team has a much lower BF, so do a player swap instead of a single move. if (overcheck < 0) and (self.DIFFERENCE > self.THRESHOLD): self.getClosestTwoToTarget (self.getLargeTeam (), self.getSmallTeam (), **kwargs) kwargs['Broadcast'].broadcast("echo BALANCER: ^cUneven team balancer with swap initiated") return #In this scenario, the larger team has greater BF, so do a single mvoe. if (overcheck > 0) and (self.DIFFERENCE > self.THRESHOLD): self.getClosestPersonToTarget (self.getLargeTeam (), **kwargs) else: print 'threshold not met' kwargs['Broadcast'].broadcast("Serverchat ^cUneven team balancer initiated, but current balance percentage of ^y%s ^cdoes not meet the threshold of ^y%s" % (round(self.DIFFERENCE, 1), self.THRESHOLD)) def onTeamCheck(self, *args, **kwargs): if (self.TIME % (60 * 1000)) == 0: self.sendGameInfo(**kwargs) if (self.teamOne ['size'] == int(args[0])) and (self.teamTwo ['size'] == int(args[1])): kwargs['Broadcast'].broadcast("echo BALANCER: Team 1 count is correct") kwargs['Broadcast'].broadcast("echo BALANCER: Team 2 count is correct") if (self.PHASE == 5): self.GAMESTARTED = 1 if (self.TIME == (1 * 60 * 1000)): self.runBalancer (**kwargs) elif (self.TIME == (3 * 60 * 1000)): self.runBalancer (**kwargs) elif (self.TIME == (6 * 60 * 1000)): self.runBalancer (**kwargs) if (self.TIME >= (6 * 60 * 1000)): self.DENY = 1 self.optionCheck(**kwargs) self.OPTION = 1 if (self.TIME % (5 * 60 * 1000)) == 0: self.runBalancer (**kwargs) return else: #kwargs['Broadcast'].broadcast("Serverchat ^cBalancer is currently off until player counts can be verified.") kwargs['Broadcast'].broadcast("ListClients") kwargs['Broadcast'].broadcast("echo refresh") #this initiates turns balancer off and tries to refresh the teams to get the proper count self.GAMESTARTED = 0 self.DENY = 0 def retrieveLevels(self, cli, **kwargs): kwargs['Broadcast'].broadcast("set _index #GetIndexFromClientNum(%s)#; set _plevel #GetLevel(|#_index|#)#;echo CLIENT %s is LEVEL #_plevel#; set _plevel 1" % (cli, cli)) def getTeamLevels(self, **kwargs): if (self.GAMESTARTED == 1): for player1 in self.teamOne ['players']: self.retrieveLevels(player1 ['clinum'], **kwargs) for player2 in self.teamTwo ['players']: self.retrieveLevels(player2 ['clinum'], **kwargs) def onGetLevels(self, *args, **kwargs): clinum = args[0] level = int(args[1]) client = self.getPlayerByClientNum(clinum) client ['gamelevel'] = level client ['bf'] = client ['sf'] + client ['level'] + (4*level) if (client ['team'] == 1): for player in self.teamOne ['players']: if client ['clinum'] == player ['clinum']: player ['bf'] = client ['bf'] if (client ['team'] == 2): for player in self.teamTwo ['players']: if client ['clinum'] == player ['clinum']: player ['bf'] = client ['bf'] def onListClients(self, *args, **kwargs): clinum = args[0] name = args[2] print 'making client active' client = self.getPlayerByName(name) client ['active'] = 1 def onMapReset(self, *args, **kwargs): if (self.PHASE == 5): kwargs['Broadcast'].broadcast("prevphase") self.GAMESTARTED = 0 else: return def startFollow(self, **kwargs): for followings in self.followlist: kwargs['Broadcast'].broadcast("set _follower #GetIndexFromClientNum(%s)#; set _followed #GetIndexFromClientNum(%s)#; set _x #GetPosX(|#_followed|#)#; set _y #GetPosY(|#_followed|#)#; set _z #GetPosZ(|#_followed|#)#; SetPosition #_follower# [_x + 200] [_y + 200] [_z + 200]" % (followings ['follower'], followings ['followed']))