""" The Ace inspired by gamemode in Metroid Prime Hunters by Desert Storm """ #You may modify this and post it elsewhere, however please leave the by Desert #Storm part alone #To get this working just set the game mode to "The Ace" don't include as #a script #I made this very dynamic so you can customize almost every attribute. #Here is what you map.txt and/or config file can have included. #Please note that anything that is in the map.txt file will override anything in the config file #All options that are not map specific can be placed in your config file like so. #"TheAce" : { # stuff goes in here #} #'ta':value not used(just use 0) #if ALWS_ENBL is set to true BAM, The Ace is enabled. If it has this #extension no matter what the value may be it is enabled #'ta-heal':#>=0 #this is the amount of health that the ace gets when they kill someone. #it can not be a negative value #'ta-hit':#>=1 #this is the amount of damage that is dealt to The Ace when a clock interval is #completed. The interval is explained below #'ta-hit-interval':#>=1 #this is the amount of time in seconds that it takes for the ace to take passive damage #'ta-damage-table':(#,#,#,#,#, #,#,#,#,#)>=1 #this is the damage table the values are Rifle, Smg, Shotgun, Grenade, #and Spade in that order. #the first five numbers are the multipliers applied to tha Aces' damage. #the last five are the divisors for the damage that the ace takes. #if a value is less than 1 it stays at the defualt #'ta-score-table':(#,#,#,#)>=1 #this is the score table.the first number is a standard player on player kill. #the second value when a player kills the Ace. thethird is when the ace kills #a player. Finally the last value is the score that the ace gains after every #hit interval #'ta-max-score':#>=50 #this is the score that players must reach to win. #'ta-build':True/False #sets whether players are allowed to build/destroy blocks or not. Defaults to True #'ta-spawns':[(x,y,z),(x1,y1,x2,y2),(x,y)] #map specific #If you want, you can define a set of spawn points which will be picked at random when a player spawns. #There are three types of spawn points that you can define. Remember that y in AoS is not elevation. #1. (x1, y1, x2, y2) - This will pick a random non-water location in the range of (x1,y1)-(x2,y2) #2. (x, y, z) - This will just plop that player at the location #3. (x, y) - If you just want the player to spawn at the highest point then use this. Also save space #'ta-cp-spawns':[(x,y,z),(x,y,z)] #map specific #This is a list which must include two(2) pairs of xyz coordinates for the green and blue base respecively #'ta-top-interval':#>=30 or #=0 #The time in seconds that players will be notified of the top scores. #If zero(0) then the automated scoreboard message will be disabled #'ta-top-num':#>0 #This is the number of players that are displayed by the automatic scoreboard or when a player calls 'ta-scores' from operator import itemgetter import random from twisted.internet.task import LoopingCall from pyspades.server import Flag, Base from pyspades.constants import CTF_MODE, MELEE_KILL, GRENADE_KILL, SPADE_DESTROY, BLUE_BASE, GREEN_BASE from pyspades.collision import vector_collision from commands import get_player, alias, name, admin, add HIDE_COORD = (0, 0, 0) ALWS_ENBL = False MSG_TA_ACE = 'the ace is {ta}' MSG_TA_ACE_SELF = 'You have lost the ability to build or destroy blocks' MSG_TA_NO_ACE = 'No one is the Ace' MSG_TA_DEAD = 'The Ace is dead.' MSG_TA_KILLED = '{player} is the new Ace.' MSG_TA_TOP = '{rank}. {player} with a score of {score}' MSG_TA_YOU = 'You have a score of {score} and are in position {rank}' MSG_TA_SWITCH = 'You cant switch {switch} while you are the Ace' MSG_TA_REFILL = 'You cant get health from base as the Ace. Kill someone to heal' MSG_TA_WON = '{player} has won the Match' MSG_TA_EXPLAIN = ['If there is no Ace kill someone to gain the status.', 'if there is an Ace kill them.', 'While you are the ace you take damage over time, but recieve a damage boost/resistance.', 'Reach {score} to win!'] @alias('tat') @name('tatoggle') @admin def the_ace_toggle(connection): protocol = connection.protocol protocol.ta_enbl = not protocol.ta_enbl if protocol.ta_enbl: if protocol.ta_ace[0]: protocol.ta_hit_loop.start(protocol.ta_hit_interval, False) if protocol.ta_top_interval > 0: protocol.ta_top_loop.start(protocol.ta_top_interval, False) protocol.send_chat('The Ace match has been started') else: if protocol.ta_hit_loop.running: protocol.ta_hit_loop.stop() if protocol.ta_top_loop.running: protocol.ta_top_loop.stop(); protocol.send_chat('The Ace match has been paused') connection.protocol.ta_reset_flags() return @alias('tas') @name('tascores') def the_ace_scores(connection): protocol = connection.protocol scr = protocol.ta_scores[connection.name] scrs = protocol.ta_scores.items() scrs.sort(key=itemgetter(1), reverse=True) protocol.ta_top(connection) return MSG_TA_YOU.format(score = scr, rank = scrs.index((connection.name,scr))+1) @alias('tah') @name('tahelp') def the_ace_help(connection): msgs = [] for i in MSG_TA_EXPLAIN: if i == MSG_TA_EXPLAIN[len(MSG_TA_EXPLAIN)-1]: msgs.append(i.format(score = connection.protocol.ta_score_max)) else: msgs.append(i) connection.send_lines(msgs) return @alias('ta') @name('theace') def the_ace(connection): protocol = connection.protocol msg = None if protocol.ta_ace[0]: msg = MSG_TA_ACE.format(ta = protocol.ta_ace[0]) else: msg = MSG_TA_NO_ACE return msg add(the_ace) add(the_ace_help) add(the_ace_scores) add(the_ace_toggle) def apply_script(protocol, connection, config): ta_config = config.get('TheAce', {}) class tac(connection): def on_spawn_location(self, pos): protocol = self.protocol newPos = None if protocol.ta_spawns: spawn = random.choice(protocol.ta_spawns) if len(spawn) == 4: newPos = protocol.get_random_location(True, spawn) elif len(spawn) == 2: z = protocol.map.get_height(spawn[0], spawn[1]) newPos = (spawn[0], spawn[1], z); else: newPos = spawn else: zne = None if protocol.ta_ace[0]: player = get_player(protocol, '#' + str(protocol.ta_ace[1]), False) loc = player.get_location() zne = ((max(0, min(511,loc[0]-90))), (max(0, min(511,loc[1]-90))), (max(0, min(511,loc[0]+90))), (max(0, min(511,loc[1]+90)))) else: zne = (0, 0, 511, 511) newPos = protocol.get_random_location(True, zne) return newPos def on_hit(self, damage, player, type, grenade): protocol = self.protocol if protocol.ta_enbl and player != self: weapon = self.weapon newDamage = damage if self.player_id == protocol.ta_ace[1]: if type == GRENADE_KILL and grenade != None: newDamage *= protocol.ta_damage_table[3] elif type == MELEE_KILL: newDamage *= protocol.ta_damage_table[4] else: newDamage *= protocol.ta_damage_table[weapon] elif player.player_id == protocol.ta_ace[1]: if type == GRENADE_KILL and grenade != None: newDamage /= protocol.ta_damage_table[8] elif type == MELEE_KILL: newDamage /= protocol.ta_damage_table[9] else: newDamage /= protocol.ta_damage_table[weapon+5] if connection.on_hit(self, newDamage, player, type, grenade) == False: return False return newDamage return connection.on_hit(self, damage, player, type, grenade) def grenade_exploded(self, grenade): for player in self.team.get_players(): if player == self: continue damage = grenade.get_damage(player.world_object.position) if damage != 0: returned = self.on_hit(damage, player, GRENADE_KILL, grenade) if returned != False: player.set_hp(player.hp - damage, self, hit_indicator = grenade.position.get(), type = GRENADE_KILL, grenade = grenade) return connection.grenade_exploded(self, grenade) def on_kill(self, killer, type, grenade): protocol = self.protocol if protocol.ta_enbl: if killer != self and killer != None: if self.player_id == protocol.ta_ace[1]: protocol.kill_ace(self, killer) protocol.ta_scores[killer.name] += protocol.ta_score_table[1] elif killer.player_id == protocol.ta_ace[1]: protocol.ta_scores[killer.name] += protocol.ta_score_table[2] hp = killer.hp + protocol.ta_heal killer.set_hp(hp) else: if not protocol.ta_ace[0]: protocol.kill_ace(self, killer) protocol.ta_scores[killer.name] += protocol.ta_score_table[0] killer.protocol.ta_check_score(killer) elif self.player_id == protocol.ta_ace[1]: protocol.kill_ace(self) return connection.on_kill(self, killer, type, grenade) def on_login(self, name): self.protocol.ta_scores[name] = 0 return connection.on_login(self, name) def on_weapon_set(self, value): if self.protocol.ta_enbl and self.player_id == self.protocol.ta_ace[1]: self.send_chat(MSG_TA_SWITCH.format(switch = 'weapons')) return False return connection.on_weapon_set(self, value) def on_team_join(self, team): if self.protocol.ta_enbl and self.player_id == self.protocol.ta_ace[1]: if team != self.team: self.send_chat(MSG_TA_SWITCH.format(switch = 'teams')) return False return connection.on_team_join(self, team) def on_block_build_attempt(self, x,y,z): if self.protocol.ta_enbl and (!self.protocol.ta_build or self.player_id == self.protocol.ta_ace[1]): if !self.protocol.ta_build: self.send_chat('Building is disabled!') return False return connection.on_block_build_attempt(self, x,y,z) def on_block_destroy(self, x,y,z, mode): if self.protocol.ta_enbl and (!self.protocol.ta_build or self.player_id == self.protocol.ta_ace[1]): if !self.protocol.ta_build and mode == SPADE_DESTROY: self.send_chat('Building is disabled!') return False return connection.on_block_destroy(self, x,y,z, mode) def on_refill(self): if self.protocol.ta_enbl and self.player_id == self.protocol.ta_ace[1]: self.send_chat(MSG_TA_REFILL) hp = self.hp self.refill() self.set_hp(hp) return False return connection.on_refill(self) def on_position_update(self): if vector_collision(self.world_object.position, self.team.other.base): self.check_refill() if self.protocol.ta_enbl: if self.player_id == self.protocol.ta_ace[1]: team = self.team loc = self.get_location() loc = (loc[0], loc[1], 0) team.flag.set(*loc) team.flag.update() return connection.on_position_update(self) def on_flag_drop(self): self.protocol.ta_reset_flags() return connection.on_flag_drop(self) def on_flag_take(self): if self.protocol.ta_enbl and self.player_id != self.protocol.ta_ace[1]: return False return connection.on_flag_take(self) def on_flag_capture(self): if self.protocol.ta_enbl: if self.protocol.ta_scores[self.name] < self.protocol.ta_score_max: return False return connection.on_flag_capture(self) def on_reset(self): if self.protocol.ta_enbl and self.player_id == self.protocol.ta_ace[1]: self.protocol.kill_ace(self) if self.name in self.protocol.ta_scores: del self.protocol.ta_scores[self.name] return connection.on_reset(self) class tap(protocol): game_mode = CTF_MODE ta_ace = [None, None] ta_enbl = False ta_hit = 5 ta_hit_loop = None ta_hit_interval = 4 ta_top_loop = None ta_top_interval = 90 ta_top_num = 3 ta_scores = {} ta_score_table = [1, 15, 5, 1] ta_damage_table = [1.4, 1, 1.3, 1.2, 2, 1.5, 1.5, 1.5, 2, 1.4] ta_score_max = 150 ta_spawns = None ta_cp_spawns = None ta_build = True def ta_reset(self): for i in self.ta_scores: self.ta_scores[i] = 0 if self.ta_hit_loop.running: self.ta_hit_loop.stop() self.ta_ace = [None, None] def ta_check_score(self, winner): if self.ta_scores[winner.name] >= self.ta_score_max: winner.team.score = self.max_score-1 winner.team.other.flag.player = winner self.ta_ace = [winner.name, winner.player_id] winner.capture_flag() self.ta_reset() self.send_chat(MSG_TA_WON.format(player = winner.name)) return def ta_reset_flags(self): if self.ta_enbl: flags = [self.green_team.flag, self.blue_team.flag] for i in flags: i.set(*HIDE_COORD) i.update() else: teams = [self.green_team, self.blue_team] for i in teams: loc = i.get_random_location(True) i.flag.set(*loc) i.flag.update() return def ta_top(self, player = None): scores = self.ta_scores.items() scores.sort(key=itemgetter(1), reverse=True) for i in range(len(scores)): if i >= self.ta_top_num: break if player: player.send_chat(MSG_TA_TOP.format(player = scores[i][0], rank = i+1, score = scores[i][1])) else: self.send_chat(MSG_TA_TOP.format(player = scores[i][0], rank = i+1, score = scores[i][1])) return def kill_ace(self, player, killer = None): if player.player_id == self.ta_ace[1]: player.drop_flag() if killer == None or killer == player: self.ta_ace = [None, None] self.send_chat(MSG_TA_DEAD) if self.ta_hit_loop.running: self.ta_hit_loop.stop() else: self.ta_ace = [killer.name, killer.player_id] self.ta_scores[killer.name] += self.ta_score_table[1] self.send_chat(MSG_TA_KILLED.format(player = killer.name)) killer.send_chat(MSG_TA_ACE_SELF) killer.take_flag() if self.ta_hit_loop.running: self.ta_hit_loop.stop() self.ta_hit_loop.start(self.ta_hit_interval, False) return def hit_ace(self): if self.ta_ace[0]: player = get_player(self, "#" + str(self.ta_ace[1]), False) if player and player.name in self.ta_scores: hp = player.hp player.set_hp(hp - self.ta_hit, type = MELEE_KILL) self.ta_scores[player.name] += self.ta_score_table[3] return def on_map_change(self, map): if not self.ta_hit_loop: self.ta_hit_loop = LoopingCall(self.hit_ace) if self.ta_hit_loop.running: self.ta_hit_loop.stop() if not self.ta_top_loop: self.ta_top_loop = LoopingCall(self.ta_top) if self.ta_top_loop.running: self.ta_top_loop.stop() ext = self.map_info.extensions self.ta_ace = [None, None] self.ta_scores.clear() self.ta_enbl = False self.ta_heal = 20 self.ta_hit = 5 self.ta_hit_interval = 4 self.ta_top_interval = 90 self.ta_top_num = 3 self.ta_score_table = [1,15,5,1] self.ta_damage_table = [1.4,1,1.3,1.2,2, 1.5,1.5,1.5,2,1.4] self.ta_score_max = 150 self.ta_spawns = None self.ta_cp_spawns = None self.ta_build = True if 'ta-hit' in ext: if ext['ta-hit'] >= 1: self.ta_hit = ext['ta-hit'] elif 'ta-hit' in ta_config: if ta_config['ta-hit'] >= 1: self.ta_hit = ta_config['ta-hit'] if 'ta-damage-table' in ext: for i in ext['ta-damage-table']: if ext['ta-damage-table'][i] >= 1: self.ta_damage_table[i] = ext['ta-damage-table'][i] elif 'ta-damage-table' in ta_config: for i in ta_config['ta-damage-table']: if ta_config['ta-damage-table'][i] >= 1: self.ta_damage_table[i] = ta_config['ta-damage-table'][i] if 'ta-heal' in ext: if ext['ta-heal'] >= 0: self.ta_heal = ext['ta-heal'] elif 'ta-heal' in ta_config: if ta_config['ta-heal'] >= 0: self.ta_heal = ta_config['ta-heal'] if 'ta-hit-interval' in ext: if ext['ta-hit-interval'] >= 1: self.ta_hit_interval = ext['ta-hit-interval'] elif 'ta-hit-interval' in ta_config: if ta_config['ta-hit-interval'] >= 1: self.ta_hit_interval = ta_config['ta-hit-interval'] if 'ta-score-table' in ext: for i in ext['ta-score-table']: if ext['ta-score-table'][i] >= 1: self.ta_score_table[i] = ext['ta-score-table'][i] elif 'ta-score-table' in ta_config: for i in ta_config['ta-score-table']: if ta_config['ta-score-table'][i] >= 1: self.ta_score_table[i] = ta_config['ta-score-table'][i] if 'ta-max-score' in ext: if ext['ta-max-score'] >= 50: self.ta_score_max = ext['ta-max-score'] elif 'ta-max-score' in ta_config: if ta_config['ta-max-score'] >= 50: self.ta_score_max = ta_config['ta-max-score'] if 'ta-build' in ext: self.ta_build = ext['ta-build'] elif 'ta-build' in ta_config: self.ta_build = ta_config['ta-build'] if 'ta-spawns' in ext: self.ta_spawns = ext['ta-spawns'] if 'ta-cp-spawns' in ext: self.ta_cp_spawns = ext['ta-cp-spawns'] if 'ta-top-interval' in ext: if ext['ta-top-interval'] >= 30 or ext['ta-top-interval'] == 0: self.ta_top_interval = ext['ta-top-interval'] elif 'ta-top-interval' in ta_config: if ta_config['ta-top-interval'] >= 30 or ta_config['ta-top-interval'] == 0: self.ta_top_interval = ta_config['ta-top-interval'] if 'ta-top-num' in ext: if ext['ta-top-num'] > 0: self.ta_top_num = ext['ta-top-num']; elif 'ta-top-num' in ta_config: if ta_config['ta-top-num'] > 0: self.ta_top_num = ta_config['ta-top-num']; if ALWS_ENBL or 'ta' in ext or 'ta' in ta_config: self.ta_enbl = True if self.ta_top_interval > 0: self.ta_top_loop.start(self.ta_top_interval, False) self.friendly_fire = self.ta_enbl return protocol.on_map_change(self, map) def on_base_spawn(self, x, y, z, base, entity_id): if self.ta_enbl and self.ta_cp_spawns: if entity_id == GREEN_BASE: return self.ta_cp_spawns[0] elif entity_id == BLUE_BASE: return self.ta_cp_spawns[1] return protocol.on_base_spawn(self, x, y, z, base, entity_id) def on_flag_spawn(self, x, y, z, flag, entity_id): if self.ta_enbl: return HIDE_COORD return protocol.on_base_spawn(self, x, y, z, flag, entity_id) return tap, tac