Editing and Customization > Community Content

[Gameplay] Freeze Tag Mode

<< < (7/10) > >>

Joe:

--- Quote from: killermonkey on November 13, 2012, 12:28:08 am ---You cannot move entities from Python. The reason for this is so that you don't inadvertently break something in the game (like moving a player into a wall) or moving an entity into a player. I am not sure how the capture points will react to being moved, but they should be ok. They were not designed to be moved after being placed.

You would have to create a sourcepawn script to handle this.

I am pretty interested to see what you do with this. If it works out I may move some of the sourcepawn script stuff into Python so you can do it all in Python.

BTW, did you end up getting the timers to work? You should use Capture The Key as an example of using advanced timers.

--- End quote ---

Thanks for the helpful post, I will use a source pawn script to move the resurrection areas.

I've got the timers working along with the timer tracker.

This is the code for the latest development version:

--- Code: ---
from . import GEScenario
from GamePlay.Utils.GEPlayerTracker import GEPlayerTracker
from Utils.GETimer import TimerTracker, Timer
from collections import defaultdict

from collections import deque

import GEPlayer, GEUtil, GEMPGameRules, GEGlobal

USING_API = GEGlobal.API_VERSION_1_0_0

'''
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.

@author: Joe
@version: Dev 12.00
'''

class DieAnotherDay( GEScenario ):
    MRE_MODEL = "models/players/bond/bond.mdl"
    JRE_MODEL = "models/players/jaws/jaws.mdl"
   
    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.4
    MBountyPBY = 0
   
    JBountyPBX = 0.6
    JBountyPBY = 0
   
    ResurrectionPBX = -1
    ResurrectionPBY = 0.6
    #-------------------------
   
    resurrectionTime = 5.0
   
    TR_ELIMINATED = "eliminated"
    TR_SPAWNED = "spawned"
   
    TOKEN_MI6 = 'token_mi6'
    TOKEN_JANUS = 'token_janus'
   
    resurrectionAreaID = 0
   
    #Progress Bar Indexs
    MBountyPBIndex = 0
    JBountyPBIndex = 1
    ResurrectionPBIndex = 2

    def __init__( self ):
        super( DieAnotherDay, self ).__init__()

        self.waitingForPlayers = False
        self.radarSet = False
        self.mi6Bounty = 0
        self.janusBounty = 0
        self.pltracker = GEPlayerTracker( self )
       
        self.timerTracker = TimerTracker( self )
        self.tokenManager = GEMPGameRules.GetTokenMgr()
        self.inUseResurrectionAreas = defaultdict(list)
        self.rAreaIDs = []
       
        self.inPlayMPlayers = []
        self.inPlayJPlayers = []
       
        self.mResurrectionQueue = deque()
        self.jResurrectionQueue = deque()
       
    def OnLoadGamePlay( self ):
        GEUtil.PrecacheModel( self.MRE_MODEL )
        GEUtil.PrecacheModel( self.JRE_MODEL )

    def Cleanup( self ):
        super( DieAnotherDay, self ).Cleanup()
        self.pltracker = None

    def GetPrintName( self ):
        return "Die Another Day" #TODO use UI Language Files

    def GetScenarioHelp( self, help_obj ):
        #TODO use UI Language Files:
        help_obj.SetDescription(
                                 """
Based on: Mefy's MOHAA Freeze Tag Mode
Version: Dev 12.00

*Eliminate the opposing team.
*Resurrect your eliminated team mates.
*To resurrect a team mate stand next
to them.
   
The ability to resurrect players from
a long distance will be added in
version 2.00, if it can be implemented.
                                 """)
       
    def GetGameDescription( self ):
            return "Die Another Day"

    def OnPlayerConnect( self, player ):
        self.pltracker.SetValue( player, self.TR_SPAWNED, False )

    #TODO
    def OnPlayerDisconnect( self, player ):
        if player.GetTeamNumber() != GEGlobal.TEAM_SPECTATOR:
            self.UpdatePlayerBountyKilled( player )

    def CanPlayerChangeTeam( self, player, oldTeam, newTeam ):
        if GEMPGameRules.IsRoundLocked():
            if  self.IsInPlay( player ) and oldTeam != GEGlobal.TEAM_SPECTATOR:
                self.UpdatePlayerBountyKilled( player )
            elif oldTeam == GEGlobal.TEAM_SPECTATOR:
                GEUtil.PopupMessage( player, "#GES_GPH_CANTJOIN_TITLE", "#GES_GPH_CANTJOIN", "", 5.0, False )
            else:
                GEUtil.PopupMessage( player, "#GES_GPH_ELIMINATED_TITLE", "#GES_GPH_ELIMINATED", "", 5.0, False )

            # Changing teams will automatically eliminate you
            self.pltracker.SetValue( player, self.TR_ELIMINATED, True )

        return True

    def OnPlayerSpawn( self, player ):
        # Record us as "spawned"
        if player.GetTeamNumber() != GEGlobal.TEAM_SPECTATOR:
            self.pltracker.SetValue( player, self.TR_SPAWNED, True )

        if player.IsInitialSpawn():
            # If we spawned mid-round let them know why they can't play
            if not self.IsInPlay( player ):
                GEUtil.PopupMessage( player, "#GES_GPH_CANTJOIN_TITLE", "#GES_GPH_CANTJOIN" )

            #TODO Use UI Language Files
            GEUtil.PopupMessage( player, "Die Another Day", "Eliminate your opponents and resurrect your eliminated team mates." )
       
        #Why does this not work? :
        #Only show team mates on the local player's radar
        if(GEMPGameRules.GetRadar().IsRadarContact(player)):
            if(player.GetTeamNumber() != GEPlayer.GetMPPlayer(1).GetTeamNumber()):
                GEMPGameRules.GetRadar().DropRadarContact(player)

    def OnRoundBegin( self ):
        if(not self.waitingForPlayers):
            self.mi6Bounty = 0
            self.janusBounty = 0
   
            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 ):
        GEMPGameRules.GetRadar().DropAllContacts()
       
        GEUtil.RemoveHudProgressBar( None, self.MBountyPBIndex )
        GEUtil.RemoveHudProgressBar( None, self.JBountyPBIndex )
        GEUtil.RemoveHudProgressBar( None, self.ResurrectionPBIndex ) #TODO what if user doesn't have PB?
       
        self.timerTracker.RemoveTimer(None) #Stop all timers
       
        #Delete all capture areas:
        for areaID in self.rAreaIDs:       #rAreaIDs will only contains IDs for areas which exist
            self.tokenManager.RemoveCaptureArea(areaID)

    def OnPlayerKilled( self, victim, killer, weapon ):
        super( DieAnotherDay, self ).OnPlayerKilled( victim, killer, weapon )
       
        #Don't allow player's to accidentally/intentionally eliminate their team mates
        #CVAR option will be added in version 2.
        if(killer.GetTeamNumber() != victim.GetTeamNumber()):
            #Prevent the killed player from respawning.
            self.pltracker.SetValue( victim, self.TR_ELIMINATED, True )
       
            #Create a resurrection area entity & add dead player to resurrection queue
            areaID = str(self.resurrectionAreaID)
            self.resurrectionAreaID += 1
       
            if(victim.GetTeamNumber() == GEGlobal.TEAM_MI6):
                self.tokenManager.SetupCaptureArea(areaID,
                                           model=self.MRE_MODEL,
                                           limit=1, location=GEGlobal.SPAWN_PLAYER,
                                           rqd_team=GEGlobal.TEAM_MI6)
               
                self.mResurrectionQueue.append(victim)
           
            else:
                self.tokenManager.SetupCaptureArea(areaID,
                                           model=self.JRE_MODEL,
                                           limit=1, location=GEGlobal.SPAWN_PLAYER,
                                           rqd_team=GEGlobal.TEAM_JANUS)
               
                self.jResurrectionQueue.append(victim)
               
            self.rAreaIDs.append(areaID)
               
            #Added to radar in captureAreaSpawned()
           
            #Emit "Player Eliminated" event
            GEUtil.EmitGameplayEvent( "DieAnotherDay_eliminated", "%i" % victim.GetUserID(), "%i" % ( killer.GetUserID() if killer else -1 ) ) #TODO
           
            #Tell the victim That they've been eliminated
            GEUtil.ClientPrint( None, GEGlobal.HUD_PRINTTALK, "#GES_GP_YOLT_ELIMINATED", victim.GetPlayerName() ) #TODO use UI Language Files
           
            #Tell the other players that a player has been eliminated
            GEUtil.PopupMessage( victim, "#GES_GPH_ELIMINATED_TITLE", "You have been eliminated. You could be resurrected by a team mate." ) # TODO use UI Language Files         
   
            #Update the displayed count of survivors on the victim's team:
            self.InitializePlayerBounty()
            self.UpdatePlayerBountyKilled(victim)

    def OnCaptureAreaSpawned( self, area ):
        #Don't show enemy resurrection areas on the local players radar
        if(area.GetTeamNumber() == GEPlayer.GetMPPlayer(1).GetTeamNumber()):
            team = None
           
            if(area.getSide() == GEGlobal.TEAM_MI6):team = GEGlobal.TEAM_MI6
            else:team = GEGlobal.TEAM_JANUS
               
            GEMPGameRules.GetRadar().AddRadarContact(area,GEGlobal.RADAR_TYPE_OBJECTIVE,True,"sprites/hud/radar/capture_point",team)
   
    def OnCaptureAreaEntered( self, area, player, token ):
        if(area.GetTeamNumber() == player.GetTeamNumber()):
            #Add player to area's user list
            self.inUseResurrectionAreas[area.GetGroupName()].append(player)
           
            #Create & configure resurrection timer & Give it the area's name and team
            resurrectionTimer = self.timerTracker.CreateTimer(str(area.GetTeamNumber())  + "," + area.GetGroupName())
            resurrectionTimer.SetUpdateCallback(self.ResurrectionTimerTick,1.0)
            resurrectionTimer.SetAgeRate(1.0,0)
           
            #Create a resurrection progress bar on the player's screen TODO: use language files
            GEUtil.InitHudProgressBar(player,self.ResurrectionPBIndex, "Resurrecting Team Mate...", GEGlobal.HUDPB_SHOWVALUE, self.resurrectionTime, self.ResurrectionPBX, self.ResurrectionPBY, 120, 16, GEUtil.CColor( 220, 220, 220, 240 ) )
           
            #Start Resurrection Timer
            resurrectionTimer.Start(self.resurrectionTime,False)
       
    def OnCaptureAreaExited( self, area, player ):
        if(area.GetTeamNumber() == player.GetTeamNumber()):
            #Remove player from the area's user list
            self.inUseResurrectionAreas[area.GetGroupName()].remove(player)
               
            #Remove the resurrection progress progress bar from the player's screen
            GEUtil.RemoveHudProgressBar(player,self.ResurrectionPBIndex)
           
            #If the area's user list is now empty, delete it
            if(len(self.inUseResurrectionAreas[area.GetGroupName()]) == 0):
                del self.inUseResurrectionAreas[area.GetGroupName()]

    def ResurrectionTimerTick( self, timer, update_type ):
        areasName = timer.GetName()[2:]

        #Area still in use?
        if(update_type != Timer.UPDATE_STOP and self.inUseResurrectionAreas.has_key(areasName)):
            #Update each user's resurrection progress GUI
            for areaUser in self.inUseResurrectionAreas[areasName]:
                if(update_type == Timer.UPDATE_FINISH):
                    GEUtil.RemoveHudProgressBar(areaUser,self.ResurrectionPBIndex)
                else:
                    GEUtil.UpdateHudProgressBar(areaUser,self.ResurrectionPBIndex,int(timer.GetCurrentTime()))
       
            if(update_type == Timer.UPDATE_FINISH):
                #Get area's team
                areasTeam = int(timer.GetName()[0])
               
                #Resurrect player
                resurrectedPlayer = None
                teamString = ""
               
                if(areasTeam == GEGlobal.TEAM_MI6):
                    resurrectedPlayer = self.mResurrectionQueue.popleft()
                    teamString = "MI6"       
                else:
                    resurrectedPlayer = self.jResurrectionQueue.popleft()
                    teamString = "Janus"   
               
                self.resurrectPlayer(resurrectedPlayer)
               
                #Update player bounty
                self.UpdatePlayerBountyResurrection(resurrectedPlayer)
               
                #Emit player resurrected event
                if(resurrectedPlayer.__class__.__name__ != "CGEBotPlayer"):
                    GEUtil.EmitGameplayEvent("DieAnotherDay_resurrection", "%s" % resurrectedPlayer.GetName(),"%i" % resurrectedPlayer.GetTeamNumber())
               
                #Announce event in console
                if(resurrectedPlayer.__class__.__name__ != "CGEBotPlayer"):
                    GEUtil.Msg("Player resurrected: " + resurrectedPlayer.GetName() + "  " + teamString)
                       
                #Delete the resurrection area
                del self.inUseResurrectionAreas[areasName]
                self.tokenManager.RemoveCaptureArea(areasName)
                #WARNING:The following statement MUST be executed before this function can be interrupted for the execution of the OnRoundEnd() function:
                self.rAreaIDs.remove(areasName)
           
        #Activated if the timer hasn't expired in this tick and it's area no longer has users:
        elif(update_type != Timer.UPDATE_STOP):
            timer.Stop()

    def resurrectPlayer(self,player):
        self.pltracker.SetValue(player,self.TR_ELIMINATED,False)
   
    def getTeamsRadarColor(self,teamNumber):
        if(teamNumber == GEGlobal.TEAM_MI6): return self.COLOR_MI6_RADAR
        else: return self.COLOR_JANUS_RADAR

    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...
        self.inPlayMPlayers = []
        self.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:
                    self.inPlayMPlayers.append( player )
                elif player.GetTeamNumber() == GEGlobal.TEAM_JANUS:
                    self.inPlayJPlayers.append( player )

        numMI6Players = len( self.inPlayMPlayers )
        numJanusPlayers = len( self.inPlayJPlayers )

        if numMI6Players == 0 and numJanusPlayers == 0:
            GEMPGameRules.EndRound()

        elif numMI6Players == 0 and numJanusPlayers > 0:
            janus = GEMPGameRules.GetTeam( GEGlobal.TEAM_JANUS )
            janus.IncrementMatchScore( 5 )
            GEMPGameRules.SetTeamWinner( janus )
            GEMPGameRules.EndRound()

        elif numMI6Players > 0 and numJanusPlayers == 0:
            mi6 = GEMPGameRules.GetTeam( GEGlobal.TEAM_MI6 )
            mi6.IncrementMatchScore( 5 )
            GEMPGameRules.SetTeamWinner( mi6 )
            GEMPGameRules.EndRound()

    def CanPlayerRespawn( self, player ):
        if self.pltracker.GetValue( player, self.TR_ELIMINATED ):
            player.SetScoreBoardColor( GEGlobal.SB_COLOR_ELIMINATED )
            return False

        player.SetScoreBoardColor( GEGlobal.SB_COLOR_NORMAL )
        return True

    def InitializePlayerBounty( self ):
        if self.mi6Bounty == 0 and self.janusBounty == 0:
            self.mi6Bounty = GEMPGameRules.GetNumInRoundTeamPlayers( GEGlobal.TEAM_MI6 )
            self.janusBounty = GEMPGameRules.GetNumInRoundTeamPlayers( GEGlobal.TEAM_JANUS )

            GEUtil.InitHudProgressBar( GEGlobal.TEAM_MI6, self.MBountyPBIndex, "Janus: ", GEGlobal.HUDPB_SHOWVALUE, self.janusBounty, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)
            GEUtil.InitHudProgressBar( GEGlobal.TEAM_MI6, self.JBountyPBIndex, "MI6: ", GEGlobal.HUDPB_SHOWVALUE, self.mi6Bounty, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)

            GEUtil.InitHudProgressBar( GEGlobal.TEAM_JANUS, self.MBountyPBIndex, "Janus: ", GEGlobal.HUDPB_SHOWVALUE, self.janusBounty, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)
            GEUtil.InitHudProgressBar( GEGlobal.TEAM_JANUS, self.JBountyPBIndex, "MI6: ", GEGlobal.HUDPB_SHOWVALUE, self.mi6Bounty, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)

    def UpdatePlayerBountyKilled( self, victim ):
        if victim.GetTeamNumber() == GEGlobal.TEAM_JANUS:
            self.janusBounty -= 1
        else:
            self.mi6Bounty -= 1

        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_MI6, self.JBountyPBIndex, self.janusBounty )
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_MI6, self.MBountyPBIndex, self.mi6Bounty )
       
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_JANUS, self.JBountyPBIndex, self.janusBounty )
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_JANUS, self.MBountyPBIndex, self.mi6Bounty )
       
    def UpdatePlayerBountyResurrection( self, player ):
        if player.GetTeamNumber() == GEGlobal.TEAM_JANUS:
            self.janusBounty += 1
        else:
            self.mi6Bounty += 1

        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_MI6, self.JBountyPBIndex, self.janusBounty )
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_MI6, self.MBountyPBIndex, self.mi6Bounty )
       
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_JANUS, self.JBountyPBIndex, self.janusBounty )
        GEUtil.UpdateHudProgressBar( GEGlobal.TEAM_JANUS, self.MBountyPBIndex, self.mi6Bounty )

    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
 
--- End code ---

I want to do 2 things to this script before I release version 1.00:
1) Prevent players from seeing enemy players on their radar.
2) Fix the displayed number of MI6 and Janus survivors.

The last statements in the OnPlayerSpawn() function are meant to remove enemies from the local player's radar, but they are failing to do this:

--- Code: ---
def OnPlayerSpawn( self, player ):
        # Record us as "spawned"
        if player.GetTeamNumber() != GEGlobal.TEAM_SPECTATOR:
            self.pltracker.SetValue( player, self.TR_SPAWNED, True )

        if player.IsInitialSpawn():
            # If we spawned mid-round let them know why they can't play
            if not self.IsInPlay( player ):
                GEUtil.PopupMessage( player, "#GES_GPH_CANTJOIN_TITLE", "#GES_GPH_CANTJOIN" )

            #TODO Use UI Language Files
            GEUtil.PopupMessage( player, "Die Another Day", "Eliminate your opponents and resurrect your eliminated team mates." )
       
        #Why does this not work? :
        #Only show team mates on the local player's radar
        if(GEMPGameRules.GetRadar().IsRadarContact(player)):
            if(player.GetTeamNumber() != GEPlayer.GetMPPlayer(1).GetTeamNumber()):
                GEMPGameRules.GetRadar().DropRadarContact(player)
--- End code ---

Will the statement: " GEPlayer.GetMPPlayer(1) " always return the local player?

killermonkey:
Your level of rigor is most impressive!

To answer your question, you cannot use the notion of "local player" when you are on the server. There is no such thing. The local player only exists from the client's side. There is a console command to disable enemy teams being shown on the radar (ge_radar_showenemyteam 0). Add this command to your script's config file:

gesource/cfg/dieanotherday.cfg

When you call GEPlayer.GetMPPlayer(1) you are actually looking at entity slot 1 and if a player is in that slot it returns the player instance. As your code is written, if three people are in the server and the first player to have joined quits, the code will throw an AttributeError because you will then be accessing a NoneType object.

Do you have any suggestions for API improvement?

Joe:

--- Quote from: killermonkey on November 16, 2012, 02:25:04 am ---Your level of rigor is most impressive!

To answer your question, you cannot use the notion of "local player" when you are on the server. There is no such thing. The local player only exists from the client's side. There is a console command to disable enemy teams being shown on the radar (ge_radar_showenemyteam 0). Add this command to your script's config file:

gesource/cfg/dieanotherday.cfg

When you call GEPlayer.GetMPPlayer(1) you are actually looking at entity slot 1 and if a player is in that slot it returns the player instance. As your code is written, if three people are in the server and the first player to have joined quits, the code will throw an AttributeError because you will then be accessing a NoneType object.

--- End quote ---

Thanks for your help, I will finish version 1.00 today.


--- Quote from: killermonkey on November 16, 2012, 02:25:04 am ---Do you have any suggestions for API improvement?

--- End quote ---

I don't have any suggestions.

Troy:
Is 1.00 finished yet?

Joe:
It's still not finished, I ended up making a lot of changes to the script after I said I would finish it on the 16th and I've not spent much time working on it since I made these changes, so I've still not finished version 1.00.

I will now spend a lot more time working on this script and I will release a beta version asap.

This is the code for the latest development version:


--- Code: ---
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

'''
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.

Unresolved bugs:
* When an eliminated & unspawned player changes their team to spectator, there is a problem with their spectator view.
* Multiple resurrection entities can spawn at the same spawn point.

@author: Joe
@version: Dev 21.00 (19/11/12 16:03 GMT)
'''

class DieAnotherDay( GEScenario ):
    MRE_MODEL = "models/players/bond/bond.mdl"
    JRE_MODEL = "models/players/jaws/jaws.mdl"
   
    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.4
    MBountyPBY = 0
   
    JBountyPBX = 0.6
    JBountyPBY = 0
   
    ResurrectionPBX = -1
    ResurrectionPBY = 0.6
    #-------------------------
   
    resurrectionTime = 5.0
   
    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.eliminateNewPlayers = False

        self.waitingForPlayers = False
        self.radarSet = False
        self.mi6Bounty = 0
        self.janusBounty = 0
        self.pltracker = GEPlayerTracker( self )
       
        self.timerTracker = TimerTracker( self )
        self.tokenManager = GEMPGameRules.GetTokenMgr()
       
        self.inPlayMPlayers = []
        self.inPlayJPlayers = []
       
        self.changingTeamPlayers = {}
       
        #Eliminated player collections
        self.mResurrectionQueue = []
        self.jResurrectionQueue = []
        self.eliminatedSpectators = []
       
        #Collections related to resurrection area entities
        self.mAreas = {}
        self.jAreas = {}
       
        self.resurrectionAreaUserLists = defaultdict(list)
        self.mResurrectionAreasUseStates = {}
        self.jResurrectionAreasUseStates = {}
       
    def OnLoadGamePlay( self ):
        GEUtil.PrecacheModel( self.MRE_MODEL )
        GEUtil.PrecacheModel( self.JRE_MODEL )

    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(
                                 """
Based on: Mefy's MOHAA Freeze Tag Mode
Version: Dev 19.00

*Eliminate the opposing team.
*Resurrect your eliminated team mates.
*To resurrect a team mate stand next
to them.
   
The ability to resurrect players from
a long distance will be added in
version 2.00, if it can be implemented.
                                 """)
       
    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.updateTeamsMaxPlayers(team) #Will the diconnecting player still be counted?
           
            if self.isEliminatedPlayer(player): self.deleteNotInUseResurrectionEntityFromTeam(team)
            else: self.decreaseTeamBounty(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 oldTeam != GEGlobal.TEAM_SPECTATOR and newTeam == GEGlobal.TEAM_SPECTATOR:
            #EPILEPSY WARNING: The view bug caused by an eliminated player becoming a spectator may be capable of causing epileptic seizures.
            if self.isEliminatedPlayer(player):
                GEUtil.PopupMessage(player, "You can't become a spectator","If eliminated players became spectators in this version, a bug would occur.")
                GEUtil.ClientPrint(player,GEGlobal.HUD_PRINTTALK,"You can't become a spectator:A bug would occur if eliminated players could become spectators.")
                return False
            else: self.playerWantsToBecomeSpectator(player,oldTeam)
       
        return True

    def newPlayerWantsToJoinTeam(self,player,newTeam):
        if self.eliminateNewPlayers:
            #TODO use language files
            GEUtil.PopupMessage(player, "You Can't Spawn Yet","To prevent resurrection rejoins, new players won't spawn until a team mate spawns them.")
            self.eliminatePlayer(player)
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
           
        else: self.increaseTeamBounty(newTeam)
   
    def playerWantsToChangeTheirTeam(self,player,oldTeam,newTeam):
        self.changingTeamPlayers[player] = oldTeam
       
        if self.isEliminatedPlayer(player):
            self.deleteNotInUseResurrectionEntityFromTeam(oldTeam)
            self.removePlayerFromTeamsRQueue(player,oldTeam)
           
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
           
        else:
            self.decreaseTeamBounty(oldTeam)
            self.increaseTeamBounty(newTeam)
   
    def playerWantsToBecomeSpectator(self,player,oldTeam):
        self.changingTeamPlayers[player] = GEGlobal.TEAM_SPECTATOR
        self.decreaseTeamBounty(oldTeam)
       
        #if self.isEliminatedPlayer(player):
            #self.deleteNotInUseResurrectionEntityFromTeam(oldTeam)
            #self.removePlayerFromTeamsRQueue(player,oldTeam)
        #else: self.decreaseTeamBounty(oldTeam)
   
    def spectatorWantsToJoinTeam(self,player,newTeam):
        if self.isEliminatedPlayer(player):
            #TODO use language files
            GEUtil.PopupMessage(player, "You Can't Spawn Yet","You will have to wait for a team mate to spawn you because you were eliminated before becoming a specator.")
            self.spawnNewResurrectionEntity(player,newTeam)
            self.addPlayerToResurrectionQueue(player,newTeam)
           
        else: self.increaseTeamBounty(newTeam)
       
    #-------------------------------   
    def deleteNotInUseResurrectionEntityFromTeam(self,entitysTeam):
        teamsResurrectionAreaUseStates = None
       
        if entitysTeam == GEGlobal.TEAM_MI6: teamsResurrectionAreaUseStates = self.mResurrectionAreasUseStates
        else: teamsResurrectionAreaUseStates = self.jResurrectionAreasUseStates
       
        for currentAreaKey in teamsResurrectionAreaUseStates.keys():
            if teamsResurrectionAreaUseStates[currentAreaKey] == False: #== not in use
                teamsResurrectionAreaUseStates.pop(currentAreaKey)
                self.deleteResurrectionArea(currentAreaKey,entitysTeam)
                break
   
    def deleteResurrectionArea(self,areasName,areasTeam):
        if areasTeam == GEGlobal.TEAM_MI6: del self.mAreas[areasName]
        else: del self.jAreas[areasName]
       
        self.tokenManager.RemoveCaptureArea(areasName)
       
        if areasName in self.resurrectionAreaUserLists: del self.resurrectionAreaUserLists[areasName]
       
        #Delete the resurrection area's use record if it hasn't been deleted already:
        if self.mResurrectionAreasUseStates.has_key(areasName) or self.jResurrectionAreasUseStates.has_key(areasName):
            if areasTeam == GEGlobal.TEAM_MI6: del self.mResurrectionAreasUseStates[areasName]
            else: del self.jResurrectionAreasUseStates[areasName]
       
    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 victim that they've been eliminated
        GEUtil.PopupMessage( victim, "Eliminated", "You have been eliminated. You could be resurrected by a team mate." ) # TODO use UI Language Files
       
        #Tell the other players that a player has been eliminated
        #GEUtil.ClientPrint(None,GEGlobal.HUD_PRINTTALK, "An %s player has been eliminated.",teamString) #TODO use UI Language Files
       
    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
        areaID = str(victim.GetUserID())
       
        #Spawn a new resurrection area
        self.spawnResurrectionEntity(areaID,team)
       
        if team == GEGlobal.TEAM_MI6: self.mResurrectionAreasUseStates[areaID] = False
        else: self.jResurrectionAreasUseStates[areaID] = False
       
        #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
       
        if team == GEGlobal.TEAM_MI6: modelName = self.MRE_MODEL
        else: modelName = self.JRE_MODEL
       
        #Spawn resurrection entity
        self.tokenManager.SetupCaptureArea(areaID,
                                   model=modelName,
                                   limit=1, location=GEGlobal.SPAWN_PLAYER,
                                   rqd_team=team)

    def OnPlayerSpawn(self,player):
        playersTeam = player.GetTeamNumber()
       
        if playersTeam != GEGlobal.TEAM_SPECTATOR:
            if self.changingTeamPlayers.has_key(player):
                #update the max players in their new team's bounty progress bar:
                self.updateTeamsMaxPlayers(playersTeam)
                #update the max players in their old team's bounty progress bar:
                if self.changingTeamPlayers[player] != GEGlobal.TEAM_SPECTATOR: self.updateTeamsMaxPlayers(self.changingTeamPlayers[player])
               
                self.changingTeamPlayers.remove(player)
           
            if player in self.eliminatedSpectators:
                self.spawnNewResurrectionEntity(player,playersTeam)
                self.updateTeamsMaxPlayers(playersTeam)
               
                self.eliminatedSpectators.remove(player)
               
            #If can spawn:
            else:
                self.pltracker.SetValue( player, self.TR_SPAWNED,True)
           
        #TODO Use UI Language Files
        GEUtil.PopupMessage( player, "Die Another Day", "Eliminate your opponents and resurrect your eliminated team mates." )

    def OnRoundBegin( self ):
        self.mi6Bounty = 0
        self.janusBounty = 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 ):
        self.eliminateNewPlayers = False
        GEMPGameRules.GetRadar().DropAllContacts()
        self.timerTracker.RemoveTimer(None) #Stop all timers
       
        #Remove all progress bars
        GEUtil.RemoveHudProgressBar( None,self.MBountyPBIndex)
        GEUtil.RemoveHudProgressBar( None,self.JBountyPBIndex)
        GEUtil.RemoveHudProgressBar( None,self.ResurrectionPBIndex)
       
        #Empty resurrection qeues
        del self.mResurrectionQueue[:]
        del self.jResurrectionQueue[:]
       
        self.deleteAllCaptureAreasAndTheirCollections()

    def deleteAllCaptureAreasAndTheirCollections(self):
        for areaID in self.mAreas.keys(): self.tokenManager.RemoveCaptureArea(areaID)
        for areaID in self.jAreas.keys(): self.tokenManager.RemoveCaptureArea(areaID)       
       
        self.resurrectionAreaUserLists.clear()
        self.mResurrectionAreasUseStates.clear()
        self.jResurrectionAreasUseStates.clear()
        self.mAreas.clear()
        self.jAreas.clear()

    def OnPlayerKilled( self, victim, killer, weapon ):
        super( DieAnotherDay, self ).OnPlayerKilled( victim, killer, weapon )
       
        self.InitializePlayerBounty()
        self.eliminateNewPlayers = True
       
        #Don't allow player's to accidentally/intentionally eliminate their team mates
        if killer.GetTeamNumber() != victim.GetTeamNumber():
            victimsTeam = victim.GetTeamNumber()
       
            self.eliminatePlayer(victim)
            self.spawnNewResurrectionEntity(victim,victimsTeam)
            self.addPlayerToResurrectionQueue(victim,victimsTeam)
            self.announceElimination(victim,killer)
           
            self.decreaseTeamBounty(victim.GetTeamNumber())
           
            if self.playerNotBot(victim):
                queuePosition = None
                if victimsTeam == GEGlobal.TEAM_MI6: queuePosition = self.mResurrectionQueue.index(victim)
                else: queuePosition = self.jResurrectionQueue.index(victim)
           
                #TODO use language files
                self.tellPlayerWhatTheirResurrectionQueuePositionIs(victim,queuePositionP=queuePosition)

    def OnCaptureAreaSpawned( self, area ):
        areasTeam = area.GetTeamNumber()
       
        #Map the new area object to its name a collection
        if areasTeam == GEGlobal.TEAM_MI6: self.mAreas[area.GetGroupName()] = area
        else: self.jAreas[area.GetGroupName()] = area
       
        colour = None
        radar = GEMPGameRules.GetRadar()
           
        if area.GetTeamNumber() == GEGlobal.TEAM_MI6: colour = self.COLOR_MI6_RADAR
        else: colour = self.COLOR_JANUS_RADAR
               
        radar.AddRadarContact(area,GEGlobal.RADAR_TYPE_OBJECTIVE,True,"sprites/hud/radar/capture_point",colour)
        radar.SetupObjective(area,area.GetTeamNumber(),"", "",colour, 0, False )
   
    def OnCaptureAreaEntered( self, area, player, token ):
        if area.GetTeamNumber() == player.GetTeamNumber():
            areasTeam = area.GetTeamNumber()
           
            #Add player to area's user list
            self.resurrectionAreaUserLists[area.GetGroupName()].append(player)
           
            #Set areas associated use state to: in use
            if areasTeam == GEGlobal.TEAM_MI6: self.mResurrectionAreasUseStates[area.GetGroupName()] = True
            else: self.jResurrectionAreasUseStates[area.GetGroupName()] = True
           
            #Create & configure resurrection timer & Give it the area's name and team
            resurrectionTimer = self.timerTracker.CreateTimer(str(areasTeam)  + "," + area.GetGroupName())
            resurrectionTimer.SetUpdateCallback(self.ResurrectionTimerTick,1.0)
            resurrectionTimer.SetAgeRate(1.0,0)
           
            #Create a resurrection progress bar on the player's screen TODO: use language files
            GEUtil.InitHudProgressBar(player,self.ResurrectionPBIndex, "Resurrecting Team Mate...", GEGlobal.HUDPB_SHOWVALUE, self.resurrectionTime, self.ResurrectionPBX, self.ResurrectionPBY, 120, 16, GEUtil.CColor( 220, 220, 220, 240 ) )
           
            #Start the resurrection timer
            resurrectionTimer.Start(self.resurrectionTime,False)
       
    def OnCaptureAreaExited( self, area, player ):
        areasTeam = area.GetTeamNumber()
       
        if areasTeam == player.GetTeamNumber():
            #Remove player from the area's user list
            self.resurrectionAreaUserLists[area.GetGroupName()].remove(player)
               
            #Remove the resurrection progress progress bar from the player's screen
            GEUtil.RemoveHudProgressBar(player,self.ResurrectionPBIndex)
           
            #If the area's now has no users
            if len(self.resurrectionAreaUserLists[area.GetGroupName()]) == 0:
                #Delete its user list
                del self.resurrectionAreaUserLists[area.GetGroupName()]
                #Set its associated use state to: not in use
                if areasTeam == GEGlobal.TEAM_MI6: self.mResurrectionAreasUseStates[area.GetGroupName()] = False
                else: self.jResurrectionAreasUseStates[area.GetGroupName()] = False

    def ResurrectionTimerTick( self, timer, update_type ):
        areasName = timer.GetName()[2:]

        #Area still in use?
        if update_type != Timer.UPDATE_STOP and self.resurrectionAreaUserLists.has_key(areasName):
            #Update each user's resurrection progress GUI
            for areaUser in self.resurrectionAreaUserLists[areasName]:
                if update_type == Timer.UPDATE_FINISH:
                    GEUtil.RemoveHudProgressBar(areaUser,self.ResurrectionPBIndex)
                else:
                    GEUtil.UpdateHudProgressBar(areaUser,self.ResurrectionPBIndex,int(timer.GetCurrentTime()))
       
            if update_type == Timer.UPDATE_FINISH:
                #Get area's team
                areasTeam = int(timer.GetName()[0])
               
                teamString = self.getTeamString(areasTeam)
               
                #Delete the resurrection area
                self.deleteResurrectionArea(areasName,areasTeam)
               
                #Choose player to be resurrected.
                resurrectedPlayer = None
                if areasTeam == GEGlobal.TEAM_MI6 and len(self.mResurrectionQueue) != 0: resurrectedPlayer = self.mResurrectionQueue.pop(0)
                elif len(self.jResurrectionQueue) != 0: resurrectedPlayer = self.jResurrectionQueue.pop(0)
               
                #If for some reason there is no player to resurrect, don't resurrect anyone.
                if resurrectedPlayer != None:
                    #Resurrect player and respond to their resurrection
                    self.resurrectPlayer(resurrectedPlayer)
                   
                    #Update player bounty
                    self.increaseTeamBounty(areasTeam)
                   
                    #Update resurrection queue progress bars for team mates
                    self.resurrectionQueueUpdateNotify(areasTeam)
                   
                    if self.playerNotBot(resurrectedPlayer):
                        #Remove resurrected player's resurrection queue progress bar
                        GEUtil.RemoveHudProgressBar(resurrectedPlayer,self.ResurrectionPBIndex)
                       
                        #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.mi6Bounty and numberOfJPlayers == self.janusBounty: self.eliminatedSpectators = False
           
        #Activated if the timer hasn't expired in this tick and it's area no longer has users:
        elif update_type != Timer.UPDATE_STOP:
            timer.Stop()
           
    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,queueP=resurrectionQueue)
           
    def tellPlayerWhatTheirResurrectionQueuePositionIs(self,player,queueP=None,queuePositionP=None):
        if queuePositionP == None and queueP != None: queuePositionP = queueP.index(player)
        if queuePositionP != None :
            GEUtil.ClientPrint(player,GEGlobal.HUD_PRINTCONSOLE,"Team mates who will be resurrected before you = ")
            GEUtil.PopupMessage(player, "Resurrection Queue", "Team mates who will be resurrected before you = " + str(queuePositionP))       
           
    def playerNotBot(self,player):
        return player.__class__.__name__ != "CGEBotPlayer"

    def resurrectPlayer(self,player):
        self.pltracker.SetValue(player,self.TR_ELIMINATED,False)
   
    def getTeamsRadarColor(self,teamNumber):
        if teamNumber == GEGlobal.TEAM_MI6: return self.COLOR_MI6_RADAR
        else: return self.COLOR_JANUS_RADAR

    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...
        self.inPlayMPlayers = []
        self.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:
                    self.inPlayMPlayers.append( player )
                elif player.GetTeamNumber() == GEGlobal.TEAM_JANUS:
                    self.inPlayJPlayers.append( player )

        numMI6Players = len( self.inPlayMPlayers )
        numJanusPlayers = len( self.inPlayJPlayers )

        if numMI6Players == 0 and numJanusPlayers == 0:
            GEMPGameRules.EndRound()

        elif numMI6Players == 0 and numJanusPlayers > 0:
            janus = GEMPGameRules.GetTeam( GEGlobal.TEAM_JANUS )
            janus.IncrementMatchScore( 5 )
            GEMPGameRules.SetTeamWinner( janus )
            GEMPGameRules.EndRound()

        elif numMI6Players > 0 and numJanusPlayers == 0:
            mi6 = GEMPGameRules.GetTeam( GEGlobal.TEAM_MI6 )
            mi6.IncrementMatchScore( 5 )
            GEMPGameRules.SetTeamWinner( mi6 )
            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.mi6Bounty == 0 and self.janusBounty == 0:
            self.mi6Bounty = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_MI6)
            self.janusBounty = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_JANUS)
   
            GEUtil.InitHudProgressBar(None,self.MBountyPBIndex,"MI6: ",GEGlobal.HUDPB_SHOWVALUE, self.mi6Bounty, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)
            GEUtil.InitHudProgressBar(None,self.JBountyPBIndex,"Janus: ",GEGlobal.HUDPB_SHOWVALUE, self.janusBounty, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)

    def updateTeamsMaxPlayers(self,team):
        numberOfPlayersInTeam = GEMPGameRules.GetNumInRoundTeamPlayers(team)
       
        if team == GEGlobal.TEAM_MI6:
            GEUtil.RemoveHudProgressBar(None,self.MBountyPBIndex)
            GEUtil.InitHudProgressBar(None, self.MBountyPBIndex,"MI6: ", GEGlobal.HUDPB_SHOWVALUE,numberOfPlayersInTeam, self.MBountyPBX,self.MBountyPBY, 0, 10, self.MBountyFontColour)
        else:
            GEUtil.RemoveHudProgressBar(None,self.JBountyPBIndex)
            GEUtil.InitHudProgressBar(None,self.JBountyPBIndex,"Janus: ", GEGlobal.HUDPB_SHOWVALUE,numberOfPlayersInTeam, self.JBountyPBX,self.JBountyPBY, 0, 10,self.JBountyFontColour)     

    def decreaseTeamBounty(self,team):
        if team == GEGlobal.TEAM_JANUS: self.janusBounty -= 1
        else: self.mi6Bounty -= 1
        self.updateDisplayedBounties()
       
    def increaseTeamBounty(self,team):
        if team == GEGlobal.TEAM_JANUS: self.janusBounty += 1
        else: self.mi6Bounty += 1
        self.updateDisplayedBounties()
       
    def updateDisplayedBounties(self):
        GEUtil.UpdateHudProgressBar(None,self.JBountyPBIndex,self.janusBounty)
        GEUtil.UpdateHudProgressBar(None,self.MBountyPBIndex,self.mi6Bounty)

    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

--- End code ---

Some significant changes in this version:
1. This script now has code in the CanPlayerChangeTeam() function which will prevent players from resurrecting themselves by changing their team and by becoming a spectator and then rejoining their team. This function also now has code which is required for updating the count of survivors on each team and for removing a resurrection entity from a team when an eliminated player leaves it.
2. This function now also has code which will prevent players from resurrecting themselves by rejoining a server. Players who join a server when a round has started and 1 or more players has been eliminated, will now have to wait for a team mate to spawn them. When a round has no eliminated players, this spawning restriction will be disabled.
3. The displayed count of survivors on each team is now correct.
4. The EliminatePlayer() function is no longer responsible for controlling what happens when a player is eliminated, it simply sets a eliminated player's "eliminated?" attribute to true, making the CanPlayerSpawn() function prevent them from respawning.
5. Eliminated players are now told what their position is in their side's resurrection queue, when they are eliminated and when their team mates are resurrected.

2: If I could get a player's Steam ID then I could eliminate resurrection rejoiners when they try to spawn, without preventing new players from spawning as soon as they've joined a team. If mode scripts can't get a player's Steam ID then I think a SourceMod script might be able to get it and prevent resurrection rejoiners from being spawned. I don't want to identify resurrection rejoiners by using their IP address because players with dynamic IP addresses can change their IP address by restarting their modem.

I don't want to release a beta version of this mode until the spectator view bug is fixed. This view bug makes the spectator view flicker as it tries to display two different views. It occurs when an eliminated & unspawned player changes their team to spectator.

I think I will have to release the first version of this mode as a beta version because I won't be able to guarantee that it will not have bugs because to be properly tested, I think the first version will have to be tested on a server which has many human players.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version