Inspired by game mode in metroid prime hunters called Prime Hunter
Basically this is how the game mode works. This is a ffa style game mode and at the beginning of the match everyone is a standard player but, as soon as someone gets a kill they are labeled by the script as 'The Ace'. As the Ace you get damage boosts/resistances(configurable in the map.txt). However as time passes the Ace takes damage so the only way to stay alive is to kill more players which rewards the ace with more health. Also, You can't switch classes or teams as the Ace and you can not build or destroy blocks. When someone kills the Ace they inherit the status. If the Ace is not killed from a player then killing anybody will give the status again.
summary:
- ffa style(no team play)
- killing anyone gives you points
- get to max score to win
- the ace gets damage/defense boosts
- killing the ace passes on the title to the killer
- the ace can only get ammo from tents (no healing)
- the ace is unable to build/destroy blocks
- the ace loses health over time
- the ace is healed for every kill
Code: Select all
"""
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