I'm sorry I still haven't released Beta 1.02, it still has bugs which need to be fixed.
Thanks for the help, I will do this. 
Does anyone know why telling the token manager to delete a capture area in the Beta 1.02 script's OnCaptureAreaSpawned() function is making GE:S regularly crash?
This bug will crash GE:S every 4-10 minutes on the Silo map with 31 bots.
from . import GEScenario
from GamePlay.Utils.GEPlayerTracker import GEPlayerTracker
from Utils.GETimer import TimerTracker, Timer
from collections import defaultdict
import GEPlayer, GEUtil, GEMPGameRules, GEGlobal
USING_API = GEGlobal.API_VERSION_1_0_0
'''
This mode is based on Mefy's MOHAA Freeze Tag Mode.
I chose to implement this mode by editing the "You Only Live Twice" mode script. So
this script uses lots of code that was created by the author(s) of the YOLT script.
I've also reused code from the "Capture The Key" mode's script.
The gravestones were created by Kraid.
The up and down arrows in the crucifix RE icon were taken from the run icons.
@author: Joe
@version: Crash Bug Demo
'''
class DieAnotherDay( GEScenario ):
    ResurrectionTime = 5.0
    CompletedResPBRemovalDelay = 1.0
    
    MREModel = "models/gameplay/gravestone.mdl"
    JREModel = "models/gameplay/gravestone.mdl"
    
    MRESkin = 0
    JRESkin = 1
    
    RERadarIcon = "sprites/hud/radar/RE"
    
    REObjectiveIconFadeOutDistance = 200
    
    COLOR_MI6_RADAR = GEUtil.Color( 94, 171, 231, 255 )
    COLOR_JANUS_RADAR = GEUtil.Color( 206, 43, 43, 255 )
    
    JBountyFontColour = GEUtil.CColor( 206, 43, 43, 255 )
    MBountyFontColour = GEUtil.CColor( 100, 184, 234, 220 )
    
    #Progress bar positions
    MBountyPBX = 0.315
    MBountyPBY = 0.03
    
    JBountyPBX = 0.515
    JBountyPBY = 0.03
    
    ResurrectionPBX = -1
    ResurrectionPBY = 0.6
    #-------------------------
    
    TR_ELIMINATED = "eliminated"
    TR_SPAWNED = "spawned"
    
    TOKEN_MI6 = 'token_mi6'
    TOKEN_JANUS = 'token_janus'
    
    #Progress Bar Indexs
    MBountyPBIndex = 0
    JBountyPBIndex = 1
    ResurrectionPBIndex = 2
    def __init__( self ):
        super( DieAnotherDay, self ).__init__()
        
        self.radar = None
        
        self.eliminateNewPlayers = False
        self.waitingForPlayers = False
        self.mBounty = 0
        self.jBounty = 0
        self.pltracker = GEPlayerTracker( self )
        
        self.bountiesInitialised = False
        
        self.mBountyMaxPlayers = 0
        self.jBountyMaxPlayers = 0
        
        self.timerTracker = TimerTracker( self )
        self.tokenManager = GEMPGameRules.GetTokenMgr()
        
        #Eliminated player collections
        self.mResurrectionQueue = []
        self.jResurrectionQueue = []
        
        #Collections related to resurrection area entities
        self.mAreaIDs = []
        self.jAreaIDs = []
        
        self.mAreaLocations = {}
        self.jAreaLocations = {}
        
        self.REResTimers = defaultdict(list)
        
        #TODO remove when REs are moved from spawn points to player death locations:
        self.multiResurrectionRE = {}
        
        #Needed because deleting a RE in onCaptureAreaSpawned makes GE:S regularly crash.
        #Emptied in onCaptureAreaEntered.
        #self.REBin = []
        
    def OnLoadGamePlay( self ):
        GEUtil.PrecacheModel( self.MREModel )
        GEUtil.PrecacheModel( self.JREModel )
        
        self.radar = GEMPGameRules.GetRadar()
    def Cleanup( self ):
        super( DieAnotherDay, self ).Cleanup()
        self.pltracker = None
    def GetPrintName( self ):
        return "Die Another Day"
    def GetScenarioHelp( self, help_obj ):
        #TODO use UI Language Files: 
        help_obj.SetDescription( 
                                 """-- Version: Crash Bug Demo --
Eliminate your opponents.
To resurrect a team mate: stand next 
to one of your team's gravestones.
---------- Credits ---------
Based on Mefy's MOHAA Freeze Tag Mode. 
Kraid created the gravestones.
                                 """)
        
    def GetGameDescription( self ):
        return "Die Another Day"
    def OnPlayerConnect( self, player ):
        self.pltracker.SetValue( player, self.TR_SPAWNED, False )
    def OnPlayerDisconnect( self, player ):
        team = player.GetTeamNumber()
        
        if team != GEGlobal.TEAM_SPECTATOR:
            self.decrementTeamsPlayerCount(team)
            
            if self.isEliminatedPlayer(player): 
                self.deleteNotInUseResurrectionEntityFromTeam(team)
                self.removePlayerFromTeamsRQueue(player,team)
            else: self.decreaseTeamBounty(team)
            
            if self.bountiesInitialised: self.updateTeamsDisplayedMaxPlayers(team)
                
    def isEliminatedPlayer(self,player):
        return self.pltracker.GetValue(player,self.TR_ELIMINATED)
    
    #------------------------------- 
    def CanPlayerChangeTeam(self,player,oldTeam,newTeam ):
        if oldTeam == GEGlobal.TEAM_NONE: return True
        elif oldTeam == GEGlobal.TEAM_SPECTATOR and player.IsInitialSpawn(): self.newPlayerWantsToJoinTeam(player,newTeam)
        elif oldTeam == GEGlobal.TEAM_SPECTATOR: self.spectatorWantsToJoinTeam(player,newTeam)
        elif oldTeam != GEGlobal.TEAM_SPECTATOR and newTeam != GEGlobal.TEAM_SPECTATOR: self.playerWantsToChangeTheirTeam(player,oldTeam,newTeam)
        elif newTeam == GEGlobal.TEAM_SPECTATOR: 
            if self.isEliminatedPlayer(player): self.eliminatedPlayerWantsToBecomeSpectator(player,oldTeam)
            else: self.playerWantsToBecomeSpectator(player,oldTeam)
        
        return True
    def newPlayerWantsToJoinTeam(self,player,newTeam):
        self.incrementTeamsPlayerCount(newTeam)
        
        if self.eliminateNewPlayers:
            #TODO use language files
            GEUtil.PopupMessage(player, "You Can't Spawn Yet","New players won't spawn until a team mate spawns them, this prevents resurrection rejoins.")
            self.eliminatePlayer(player)
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
            if self.playerNotBot(player): self.tellPlayerWhatTheirResurrectionQueuePositionIs(player,newTeam)
            
        else: self.increaseTeamBounty(newTeam)
        
        if self.bountiesInitialised: self.updateTeamsDisplayedMaxPlayers(newTeam)
    
    def playerWantsToChangeTheirTeam(self,player,oldTeam,newTeam):
        self.decrementTeamsPlayerCount(oldTeam)
        self.incrementTeamsPlayerCount(newTeam)
        
        if self.isEliminatedPlayer(player): 
            #Old team
            self.deleteNotInUseResurrectionEntityFromTeam(oldTeam)
            self.removePlayerFromTeamsRQueue(player,oldTeam)
            self.resurrectionQueueUpdateNotify(oldTeam)
            
            #New Team
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
            if self.playerNotBot(player): self.tellPlayerWhatTheirResurrectionQueuePositionIs(player,newTeam)
            
        else:
            self.decreaseTeamBounty(oldTeam)
            self.increaseTeamBounty(newTeam)
            
        if self.bountiesInitialised: 
            self.updateTeamsDisplayedMaxPlayers(oldTeam)
            self.updateTeamsDisplayedMaxPlayers(newTeam)
            
    def eliminatedPlayerWantsToBecomeSpectator(self,player,oldTeam):
        self.decrementTeamsPlayerCount(oldTeam)
        
        self.deleteNotInUseResurrectionEntityFromTeam(oldTeam)
        self.removePlayerFromTeamsRQueue(player,oldTeam)
        self.resurrectionQueueUpdateNotify(oldTeam)
        
        #Prevent GE:S spectator view bug from being triggered (this bug will be fixed in the next patch):
        self.resurrectPlayer(player)
        player.ForceRespawn()
        self.eliminatePlayer(player) #Doesn't kill them but does set eliminated? attribute to true.
        
        if self.bountiesInitialised: self.updateTeamsDisplayedMaxPlayers(oldTeam)
    
    def playerWantsToBecomeSpectator(self,player,oldTeam):
        self.decrementTeamsPlayerCount(oldTeam)
        self.decreaseTeamBounty(oldTeam)
        
        if self.bountiesInitialised: self.updateTeamsDisplayedMaxPlayers(oldTeam)
    
    def spectatorWantsToJoinTeam(self,player,newTeam):
        self.incrementTeamsPlayerCount(newTeam)
        
        if self.isEliminatedPlayer(player): 
            #TODO use language files
            GEUtil.PopupMessage(player, "You Can't Spawn Yet","You won't spawn until a team mate spawns you because you were eliminated before you became a spectator.")
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
            if self.playerNotBot(player): self.tellPlayerWhatTheirResurrectionQueuePositionIs(player,newTeam)
            
        else: self.increaseTeamBounty(newTeam)
        
        if self.bountiesInitialised: self.updateTeamsDisplayedMaxPlayers(newTeam)
        
    #-------------------------------    
    def incrementTeamsPlayerCount(self,team):
        if team == GEGlobal.TEAM_MI6: self.mBountyMaxPlayers += 1
        else: self.jBountyMaxPlayers += 1
        
    def decrementTeamsPlayerCount(self,team):
        if team == GEGlobal.TEAM_MI6: self.mBountyMaxPlayers -= 1
        else: self.jBountyMaxPlayers -= 1
    
    def deleteNotInUseResurrectionEntityFromTeam(self,team):
        teamsResurrectionAreaIDs = None
        if team == GEGlobal.TEAM_MI6: teamsResurrectionAreaIDs = self.mAreaIDs
        else: teamsResurrectionAreaIDs = self.jAreaIDs
        
        for areaID in teamsResurrectionAreaIDs:
            if not self.areaInUse(areaID):
                self.deleteResurrectionArea(areaID,team)
                break
            
    def areaInUse(self,areaID):
        return len(self.REResTimers[areaID]) > 0
    
    def deleteResurrectionArea(self,areasID,areasTeam):
        if self.multiResurrectionRE.has_key(areasID): del self.multiResurrectionRE[areasID]
        
        if areasTeam == GEGlobal.TEAM_MI6: 
            self.mAreaIDs.remove(areasID)
            del self.mAreaLocations[areasID]
        else: 
            self.jAreaIDs.remove(areasID)
            del self.jAreaLocations[areasID]
            
        del self.REResTimers[areasID]
        self.tokenManager.RemoveCaptureArea(areasID)
        
    def eliminatePlayer(self,player):
        self.pltracker.SetValue(player,self.TR_ELIMINATED,True)
        
    def announceElimination(self,victim,killer):
        #Emit "Player Eliminated" event
        GEUtil.EmitGameplayEvent( "DieAnotherDay_eliminated", "%i" % victim.GetUserID(), "%i" % killer.GetUserID())
        
        #Tell the other players that a player has been eliminated #TODO use UI Language Files
        GEUtil.ClientPrint(None,GEGlobal.HUD_PRINTTALK, "A " + self.getTeamString(victim.GetTeamNumber()) + " player has been eliminated.") 
        
    def getTeamString(self,teamNumber):
        if(teamNumber == GEGlobal.TEAM_MI6): return "MI6"
        elif(teamNumber == GEGlobal.TEAM_JANUS): return "Janus"    
        else: return "Spectator"
        
    def addPlayerToResurrectionQueue(self,player,team):
        if team == GEGlobal.TEAM_MI6: self.mResurrectionQueue.append(player)
        else: self.jResurrectionQueue.append(player)
        
    def removePlayerFromTeamsRQueue(self,player,team):
        if team == GEGlobal.TEAM_MI6: self.mResurrectionQueue.remove(player)
        else: self.jResurrectionQueue.remove(player)
            
    def spawnNewResurrectionEntity(self,victim,team):
        #Create a new resurrection area id
        newAreasID = str(victim.GetUserID())
        
        #Spawn a new resurrection area
        self.spawnResurrectionEntity(newAreasID,team)
        
        #Create entries for the new area in resurrection entity collections
        if team == GEGlobal.TEAM_MI6: self.mAreaIDs.append(newAreasID)
        else: self.jAreaIDs.append(newAreasID)
        
        #Added to radar in CaptureAreaSpawned()
    
    def respawnResurrectionEntity(self,areaID,team):
        self.tokenManager.RemoveCaptureArea(areaID)
        self.spawnResurrectionEntity(areaID,team)
        
    def spawnResurrectionEntity(self,areaID,team):
        #Get Model Name
        modelName = None
        skinNumber = None
        
        if team == GEGlobal.TEAM_MI6: 
            modelName = self.MREModel
            skinNumber = self.MRESkin
        else: 
            modelName = self.JREModel
            skinNumber = self.JRESkin
        
        #Spawn resurrection entity
        self.tokenManager.SetupCaptureArea(areaID, 
                                   model=modelName,
                                   skin=skinNumber,
                                   limit=1, location=GEGlobal.SPAWN_PLAYER,
                                   rqd_team=team)
    def OnPlayerSpawn(self,player):
        if player.GetTeamNumber() != GEGlobal.TEAM_SPECTATOR: self.pltracker.SetValue(player,self.TR_SPAWNED,True)  
            
        #TODO Use UI Language Files
        if player.IsInitialSpawn(): GEUtil.PopupMessage( player, "Die Another Day", "Eliminate your opponents and resurrect your eliminated team mates." )
    def OnRoundBegin( self ):
        self.mBounty = 0 
        self.jBounty = 0
        
        if not self.waitingForPlayers:
            for i in range( 32 ):
                if not GEPlayer.IsValidPlayerIndex( i ):
                    continue
                self.pltracker.SetValue( GEPlayer.GetMPPlayer( i ), self.TR_ELIMINATED, False )
    
            GEMPGameRules.ResetAllPlayerDeaths()
            GEMPGameRules.ResetAllPlayersScores()
    def OnRoundEnd( self ):
        GEUtil.Msg("One Round End----")
        self.eliminateNewPlayers = False
        self.radar.DropAllContacts()
        self.timerTracker.RemoveTimer(None) #Stop all timers
        
        #Remove all progress bars
        self.bountiesInitialised = False
        
        GEUtil.RemoveHudProgressBar( None,self.MBountyPBIndex) 
        GEUtil.RemoveHudProgressBar( None,self.JBountyPBIndex) 
        GEUtil.RemoveHudProgressBar( None,self.ResurrectionPBIndex)
        
        #Empty resurrection queues
        del self.mResurrectionQueue[:]
        del self.jResurrectionQueue[:]
        
        self.deleteAllCaptureAreasAndTheirCollections()
    def deleteAllCaptureAreasAndTheirCollections(self):
        for areaID in self.mAreaIDs: self.tokenManager.RemoveCaptureArea(areaID)
        for areaID in self.jAreaIDs: self.tokenManager.RemoveCaptureArea(areaID)
        
        del self.mAreaIDs[:]
        del self.jAreaIDs[:]
        
        self.mAreaLocations.clear()
        self.jAreaLocations.clear()
        
        self.REResTimers.clear()
    def OnPlayerKilled( self, victim, killer, weapon ):
        super( DieAnotherDay, self ).OnPlayerKilled( victim, killer, weapon )
        self.InitializePlayerBounty() #if not initialised already
        
        victimsTeam = victim.GetTeamNumber()
        
        #Don't allow players to accidentally/intentionally eliminate their team mates
        if killer.GetTeamNumber()!= victimsTeam: 
            self.eliminatePlayer(victim)
            self.announceElimination(victim,killer)
            
            self.decreaseTeamBounty(victimsTeam)
         
            #Get the survivor count for the victim's team.
            teamsSurvivors = 0
            if victimsTeam == GEGlobal.TEAM_MI6: teamsSurvivors = self.mBounty
            else: teamsSurvivors = self.jBounty
            
            #If the victim was the last player alive on their team then don't create a resurrection area because
            #the game will be ended by OnThink() when this function has finished.
            if teamsSurvivors > 0:
                self.eliminateNewPlayers = True
                self.spawnNewResurrectionEntity(victim,victimsTeam)
                self.addPlayerToResurrectionQueue(victim,victimsTeam)
                
                if self.playerNotBot(victim):
                    self.tellPlayerWhatTheirResurrectionQueuePositionIs(victim)
                
            elif teamsSurvivors < 0: GEUtil.Msg("ERROR:OnPlayerKilled():teamsSurvivors < 0: = " + str(teamsSurvivors))
    def OnCaptureAreaSpawned( self, area ):
        areasID = area.GetGroupName()
        areasTeam = area.GetTeamNumber()
        location = area.GetAbsOrigin() 
            
        #TODO remove when REs are moved to player death locations:
        #Don't allow a MI6 and Janus RE to be located at the same player spawn point.
        if areasTeam == GEGlobal.TEAM_MI6 and location in self.jAreaLocations.values() or areasTeam == GEGlobal.TEAM_JANUS and location in self.mAreaLocations.values():
            self.respawnResurrectionEntity(areasID,areasTeam) #Recursive Function Call Loop
            return
        
        #TODO modify the following statements when REs are moved to player death locations:
        #Deal with the situation of 2 or more RE from the same side being located at the same spawn point (the resurrection function
        #is also responsible for dealing with this situation):
        if location in self.mAreaLocations.values() or location in self.jAreaLocations.values():
            GEUtil.Msg("------- Same Team RE Location Overlap -------")
            #Deleting the area in this callback function makes GE:S regularly crash, on Silo when it has 31 bots.
	    #(it will crash once every 4 - 10 minutes)
            self.tokenManager.RemoveCaptureArea(areasID)
            if area.GetTeamNumber() == GEGlobal.TEAM_MI6: self.mAreaIDs.remove(areasID)
            else: self.jAreaIDs.remove(areasID)
            
            areaIDAssociatedWithLocation = self.getREAreaIDAssociatedWithLocation(location,areasTeam)
            if not self.multiResurrectionRE.has_key(areaIDAssociatedWithLocation): self.multiResurrectionRE[areaIDAssociatedWithLocation] = 1
            
            self.multiResurrectionRE[areaIDAssociatedWithLocation] += 1
        
        else:
            colour = self.getSidesColour(areasTeam)
            
            if areasTeam == GEGlobal.TEAM_MI6: self.mAreaLocations[areasID] = location
            else: self.jAreaLocations[areasID] = location
                    
            self.radar.AddRadarContact(area,GEGlobal.RADAR_TYPE_OBJECTIVE,True,self.RERadarIcon,colour)
            self.radar.SetupObjective(area,areasTeam,"", "",colour,self.REObjectiveIconFadeOutDistance, False)
    
    #TODO remove when REs are moved to player death locations
    def getREAreaIDAssociatedWithLocation(self,location,side):
        sidesAreaLocations = None
        if side == GEGlobal.TEAM_MI6: sidesAreaLocations = self.mAreaLocations
        else: sidesAreaLocations = self.jAreaLocations
        
        for areaID in sidesAreaLocations.keys():
            if sidesAreaLocations[areaID] == location: return areaID
    
    def OnCaptureAreaEntered( self, area, player, token ):
        if area.GetTeamNumber() == player.GetTeamNumber():
            #TODO remove
            GEUtil.ClientPrint(None,GEGlobal.HUD_PRINTNOTIFY,"Multi RE entered")
            
            #Create a new resurrection timer and add it to the resurrection timer collection
            resurrectionTimer = DieAnotherDay.ResurrectionTimer(self,area,player)
            resurrectionTimer.create()
            self.REResTimers[area.GetGroupName()].append(resurrectionTimer)
            
            #Create a resurrection progress bar on the player's screen TODO: use language files
            GEUtil.InitHudProgressBar(player,self.ResurrectionPBIndex, "Resurrecting:", GEGlobal.HUDPB_SHOWBAR, self.ResurrectionTime, self.ResurrectionPBX, self.ResurrectionPBY, 120, 16,self.getSidesColour(area.GetTeamNumber()))
            
            resurrectionTimer.start()
    
#    def emptyREBin(self):
#        if len(self.REBin) != 0: 
#            for RE in self.REBin:
#                areasID = RE.GetGroupName()
#                if RE.GetTeamNumber() == GEGlobal.TEAM_MI6: self.mAreaIDs.remove(areasID)   
#                else: self.jAreaIDs.remove(areasID)
#                
#                self.tokenManager.RemoveCaptureArea(areasID)
            
    def getSidesColour(self,side):
        if side == GEGlobal.TEAM_MI6: return self.COLOR_MI6_RADAR
        else: return self.COLOR_JANUS_RADAR
        
    def OnCaptureAreaExited( self, area, player ):
        if area.GetTeamNumber() == player.GetTeamNumber(): 
            if self.getREUsersResurrectionTimer(area,player) != None:
                self.getREUsersResurrectionTimer(area,player).cancel()
            
    def getREUsersResurrectionTimer(self,area,userP):
        for resurrectionTimer in self.REResTimers[area.GetGroupName()]: 
            if resurrectionTimer.user == userP: return resurrectionTimer
            
        return None
            
    class ResurrectionTimer:
        def __init__(self,DADP,areaP,userP):
            self.timer = None
            self.DAD = DADP
            self.area = areaP
            self.user = userP
            
        def create(self):
            self.timer = self.DAD.timerTracker.CreateTimer(self.area.GetGroupName())
            self.timer.SetUpdateCallback(self.TimerTick,1)
            self.timer.SetAgeRate(1.0,0)
            
        def start(self):
            self.timer.Start(DieAnotherDay.ResurrectionTime,False)
            
        def cancel(self):
            self.timer.Stop()
            self.removeUsersResurrectionPB()
            self.delete()
            
        def delete(self):
            self.DAD.timerTracker.RemoveTimer(self.timer.GetName())
            self.DAD.REResTimers[self.area.GetGroupName()].remove(self)
            
        def TimerTick( self, timer, update_type ):
            if update_type != Timer.UPDATE_STOP:
                self.updateUsersResurrectionPB()
                
                if update_type == Timer.UPDATE_FINISH:
                    self.cancelTimerAreasOtherResTimers()
                    self.startUsersResurrectionPBsDelayedRemovalTimer(self.area.GetGroupName())
                    self.resurrectPlayerFromTimersTeam()
                    self.delete() #Must be called before deleteResurrectionArea()
                    self.DAD.deleteResurrectionArea(self.area.GetGroupName(),self.area.GetTeamNumber()) 
        
        def cancelTimerAreasOtherResTimers(self):
            for resurrectionTimer in self.DAD.REResTimers[self.area.GetGroupName()]:
                if resurrectionTimer != self: resurrectionTimer.cancel()
        
        def removeUsersResurrectionPB(self):
            GEUtil.RemoveHudProgressBar(self.user,DieAnotherDay.ResurrectionPBIndex)
            
        def updateUsersResurrectionPB(self):
            GEUtil.UpdateHudProgressBar(self.user,DieAnotherDay.ResurrectionPBIndex,int(self.timer.GetCurrentTime()))
        
        def startUsersResurrectionPBsDelayedRemovalTimer(self,timerID):
            resPBRemoveTimer = self.DAD.timerTracker.CreateTimer(timerID)
            resPBRemoveTimer.SetUpdateCallback(self.DelayedResurrectionPBRemoval,1)
            resPBRemoveTimer.SetAgeRate(1.0,0)
            
            resPBRemoveTimer.Start(DieAnotherDay.CompletedResPBRemovalDelay,False)
            
        def DelayedResurrectionPBRemoval(self,timer,update_type ):
            if update_type == Timer.UPDATE_FINISH: self.removeUsersResurrectionPB()
                    
        def resurrectPlayerFromTimersTeam(self):
            areasTeam = self.area.GetTeamNumber()
            areasID = self.area.GetGroupName()
            
            #Get team string
            teamString = None
            if areasTeam == GEGlobal.TEAM_MI6: teamString = "MI6"
            else: teamString = "Janus"
            
            #TODO modify when REs are moved from spawn points to death locations:
            numberOfPlayersToResurrect = 1
            if self.DAD.multiResurrectionRE.has_key(areasID): numberOfPlayersToResurrect = self.DAD.multiResurrectionRE[areasID]
            
            #For each resurrection...
            while numberOfPlayersToResurrect > 0:
                numberOfPlayersToResurrect -= 1
                
                #TODO remove
                if numberOfPlayersToResurrect > 1: GEUtil.Msg("*** Multi Resurrection: " + str(numberOfPlayersToResurrect) + " ***")
                
                #Choose player to be resurrected.
                resurrectedPlayer = None
                if areasTeam == GEGlobal.TEAM_MI6 and len(self.DAD.mResurrectionQueue) != 0: resurrectedPlayer = self.DAD.mResurrectionQueue.pop(0)
                elif areasTeam == GEGlobal.TEAM_JANUS and len(self.DAD.jResurrectionQueue) != 0: resurrectedPlayer = self.DAD.jResurrectionQueue.pop(0) 
                
                #If for some reason there is no player to resurrect, don't resurrect anyone.
                if resurrectedPlayer != None:
                    #Resurrect player
                    self.DAD.resurrectPlayer(resurrectedPlayer)
                    
                    #Update player bounty
                    self.DAD.increaseTeamBounty(areasTeam)
                    
                    #Update resurrection queue progress bars for team mates
                    self.DAD.resurrectionQueueUpdateNotify(areasTeam)
                    
                    if self.DAD.playerNotBot(resurrectedPlayer):
                        #Emit player resurrected event
                        GEUtil.EmitGameplayEvent("DieAnotherDay_resurrection", "%s" % resurrectedPlayer.GetName(),"%s" % teamString)
                    
                        #Announce event in console
                        GEUtil.Msg("A " + teamString + " player has been resurrected: " + resurrectedPlayer.GetName())
                    
                    #Announce resurrection
                    GEUtil.ClientPrint(None, GEGlobal.HUD_PRINTTALK,"A " + teamString + " player has been resurrected.")
                    
            #If there are now no eliminated players, allow new players to join without needing to be spawned by their team mates.
            numberOfMPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_MI6)
            numberOfJPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_JANUS)
                                    
            if numberOfMPlayers == self.DAD.mBounty and numberOfJPlayers == self.DAD.jBounty: self.DAD.eliminateNewPlayers = False
    
    #Only called when a resurrection has taken place.
    def DelayedResurrectionPBRemoval( self, timer, update_type ):
        timersAreasID = timer.getName()
        timersUser = self.resurrectionAreaUserLists[timersAreasID][0]
        GEUtil.RemoveHudProgressBar(timersUser,self.ResurrectionPBIndex)
            
    def resurrectionQueueUpdateNotify(self,team):
        resurrectionQueue = None
        if(team == GEGlobal.TEAM_MI6): resurrectionQueue = self.mResurrectionQueue
        else: resurrectionQueue = self.jResurrectionQueue
        
        for player in resurrectionQueue:
            if self.playerNotBot(player):
                self.tellPlayerWhatTheirResurrectionQueuePositionIs(player)
            
    def tellPlayerWhatTheirResurrectionQueuePositionIs(self,player,team=None):
        if team == None: team = player.GetTeamNumber()
        
        queuePosition = None
        if team == GEGlobal.TEAM_MI6: queuePosition = self.mResurrectionQueue.index(player)
        else: queuePosition = self.jResurrectionQueue.index(player)
        
        #TODO use language files
        GEUtil.ClientPrint(player,GEGlobal.HUD_PRINTCONSOLE,"Team mates who will be resurrected before you = ")
        GEUtil.PopupMessage(player, "You've Been Eliminated", "Team mates who will be resurrected before you = " + str(queuePosition))       
            
    def playerNotBot(self,player):
        return player.__class__.__name__ != "CGEBotPlayer"
    def resurrectPlayer(self,player):
        self.pltracker.SetValue(player,self.TR_ELIMINATED,False)
    def OnThink( self ):
        if GEMPGameRules.GetNumActivePlayers() < 2:
            self.waitingForPlayers = True
            return
        if self.waitingForPlayers:
            self.waitingForPlayers = False
            GEUtil.HudMessage( None, "#GES_GP_GETREADY", -1, -1, GEUtil.CColor( 255, 255, 255, 255 ), 2.5 )
            GEMPGameRules.EndRound( False )
        #Check to see if the round is over!:
        
        #check to see if each team has a player...
        inPlayMPlayers = []
        inPlayJPlayers = []
        for i in range( 32 ):
            if not GEPlayer.IsValidPlayerIndex( i ):
                continue
            player = GEPlayer.GetMPPlayer( i )
            if self.IsInPlay( player ):
                if player.GetTeamNumber() == GEGlobal.TEAM_MI6:
                    inPlayMPlayers.append( player )
                elif player.GetTeamNumber() == GEGlobal.TEAM_JANUS:
                    inPlayJPlayers.append( player )
        numMI6Players = len(inPlayMPlayers)
        numJanusPlayers = len(inPlayJPlayers)
        if numMI6Players == 0 and numJanusPlayers == 0: GEMPGameRules.EndRound()
        elif numMI6Players == 0 and numJanusPlayers > 0: self.teamWins(GEGlobal.TEAM_JANUS)
        elif numMI6Players > 0 and numJanusPlayers == 0: self.teamWins(GEGlobal.TEAM_MI6)
            
    def teamWins(self,teamNumber):
        team = GEMPGameRules.GetTeam(teamNumber)
        team.IncrementMatchScore( 5 )
        GEMPGameRules.SetTeamWinner(team)
        GEMPGameRules.EndRound()
    def CanPlayerRespawn( self, player ):
        if self.isEliminatedPlayer(player):
            player.SetScoreBoardColor( GEGlobal.SB_COLOR_ELIMINATED )
            return False
        player.SetScoreBoardColor( GEGlobal.SB_COLOR_NORMAL )
        
        return True
    def InitializePlayerBounty( self ):
        if self.mBounty == 0 and self.jBounty == 0:
            self.mBountyMaxPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_MI6)
            self.jBountyMaxPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_JANUS)
            
            self.mBounty = self.mBountyMaxPlayers
            self.jBounty = self.jBountyMaxPlayers
    
            GEUtil.InitHudProgressBar(None,self.MBountyPBIndex,"MI6:",GEGlobal.HUDPB_SHOWVALUE, self.mBountyMaxPlayers, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)
            GEUtil.InitHudProgressBar(None,self.JBountyPBIndex,"Janus:",GEGlobal.HUDPB_SHOWVALUE, self.jBountyMaxPlayers, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)
            
            self.bountiesInitialised = True
    def getTeamsPlayerCount(self,team):
        if team == GEGlobal.TEAM_MI6: return self.mBountyMaxPlayers
        else: return self.jBountyMaxPlayers        
    def updateTeamsDisplayedMaxPlayers(self,team):
        numberOfPlayersInTeam = self.getTeamsPlayerCount(team)
        
        if team == GEGlobal.TEAM_MI6: 
            GEUtil.InitHudProgressBar(None, self.MBountyPBIndex,"MI6:", GEGlobal.HUDPB_SHOWVALUE,numberOfPlayersInTeam, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)
            GEUtil.UpdateHudProgressBar(None,self.MBountyPBIndex,self.mBounty)
        else:
            GEUtil.InitHudProgressBar(None,self.JBountyPBIndex,"Janus:", GEGlobal.HUDPB_SHOWVALUE,numberOfPlayersInTeam, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)
            GEUtil.UpdateHudProgressBar(None,self.JBountyPBIndex,self.jBounty)     
    def decreaseTeamBounty(self,team):
        if team == GEGlobal.TEAM_JANUS: self.jBounty -= 1
        else: self.mBounty -= 1
        self.updateDisplayedBounties()
        
    def increaseTeamBounty(self,team):
        if team == GEGlobal.TEAM_JANUS: self.jBounty += 1
        else: self.mBounty += 1
        self.updateDisplayedBounties()
        
    def updateDisplayedBounties(self):
        GEUtil.UpdateHudProgressBar(None,self.JBountyPBIndex,self.jBounty)
        GEUtil.UpdateHudProgressBar(None,self.MBountyPBIndex,self.mBounty)
    def IsInPlay( self, player ):
        return player.GetTeamNumber() is not GEGlobal.TEAM_SPECTATOR and self.pltracker.GetValue( player, self.TR_SPAWNED ) and not self.pltracker.GetValue( player, self.TR_ELIMINATED )
    def GetTeamPlay(self):
        return GEGlobal.TEAMPLAY_ALWAYS