GoldenEye: Source Forums

Editing and Customization => Community Content => Topic started by: Joe on October 26, 2012, 09:59:19 pm

Title: [Gameplay] Freeze Tag Mode
Post by: Joe on October 26, 2012, 09:59:19 pm
Hi,

I think MOHAA's "Freeze Tag" mode (http://www.youtube.com/watch?v=lo4h-ITpRXo) would be a fun mode to play in GE:S, so I'm going to try to make a mode script for it.

"Freeze Tag" mode is a team play elimination mode in which eliminated players can be resurrected by their team mates.

The latest version of this mode can be downloaded from here: http://forums.geshl2.com/index.php/board,139.0.html (http://forums.geshl2.com/index.php/board,139.0.html)
Title: Re: [Gameplay] Freeze Tag Mode
Post by: major on October 26, 2012, 11:00:32 pm
hmm I kinda like it.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on October 27, 2012, 01:18:14 pm
Unfortunately we don't provide a way to "freeze" players using the Python API interface. You would have to combine the python code with a standard server plugin to provide the freezing effect.

You could accomplish this using server-side custom events to pass information across:

GEUtils.EmitGameplayEvent( ... )

Here is the wiki article: http://wiki.geshl2.com/index.php/GoldenEye:_Source_Plugin_Support#gameplay_event
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on October 28, 2012, 11:27:11 am
Unfortunately we don't provide a way to "freeze" players using the Python API interface. You would have to combine the python code with a standard server plugin to provide the freezing effect.

You could accomplish this using server-side custom events to pass information across:

GEUtils.EmitGameplayEvent( ... )

Here is the wiki article: http://wiki.geshl2.com/index.php/GoldenEye:_Source_Plugin_Support#gameplay_event

Thanks for your help.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 01, 2012, 12:07:39 pm
When players die in this mode I want the game to spawn an entity at the vector where they died so that their team mates can interact with this entity to trigger their resurrection. I would like the entity to use the victim's character model.

I've not seen a function in in the token manager class which can spawn a token entity at a given vector, so I've thought that tokens can only be spawned at spawn point entities.

I can see that there is a function in GEUtil which creates a temporary entity at a given vector ( CreateTempEnt(type,vector) ). I've got 2 questions about this function:
1) How is the created entity temporary? (or is a temporary entity a type of entity?)
2) How can a script reference an entity object which has been created by this function?

Title: Re: [Gameplay] Freeze Tag Mode
Post by: liamcadhain on November 01, 2012, 08:34:44 pm
That sounds like an interesting enough game mode if it can be implemented properly in the mod
Title: Re: [Gameplay] Freeze Tag Mode
Post by: kraid on November 01, 2012, 09:14:29 pm
Naming suggestion: Die another Day... not sure if it was allready taken by another gamemode, or if it was just an achivement.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 01, 2012, 10:17:07 pm
I'm curious in how players are able to resurrect their frozen team mates?  Have you thought about someone getting killed in midair and his team mate unable to reach him?
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 02, 2012, 01:30:56 pm
Naming suggestion: Die another Day... not sure if it was allready taken by another gamemode, or if it was just an achivement.
Good idea, I would like this mode to use that title but unfortunately there is a Die Another Day achievement. I personally don't think having a mode and achievement with the same name matters. So if the GE:S developers and community don't mind I now want this mode's title to be Die Another Day.

I'm curious in how players are able to resurrect their frozen team mates?  Have you thought about someone getting killed in midair and his team mate unable to reach him?

Players' character models will not  be frozen still when they are killed, so the victim's corpse would fall to the ground and then disappear normally. When their corpse disappears a resurrection entity will be spawned at the vector where their corpse disappeared and it will appear on their team mates' radars. If possible, I think these resurrection entities should use their eliminated player's character model in a standing up stance like the resurrection entities in MOHAA Freeze Tag.

Like in MOHAA Freeze Tag I think there should be 2 ways to resurrect a player:
1) By standing next to the resurrection entity for x seconds (Maybe creating a capture area around the entity would be the best way to implement this).
2) By aiming at the resurrection entity and holding down a button for x seconds.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: kraid on November 02, 2012, 03:08:16 pm
Still there are maps like cradle, caves, runway, complex, etc. where players are able to fall into areas that are not part of the regulary playable map.

A solution might be that instead of having the players respawn at the place where they were killed, placing the resurrection entity on a token spawner or player start.
Instead of the T-posed Body, i'd rather see something like a gravestone there.

Also, what if you'd need to collect something like 1up items in order to be resurrectable.
Everyone starts with one extra life, as soon as he needs to be resurrected, he looses this extra to the one who resurrected him.
Maybe you could also be allowed to resurrect players from the other team, stealing their lifes that way.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 02, 2012, 06:27:57 pm
Still there are maps like cradle, caves, runway, complex, etc. where players are able to fall into areas that are not part of the regulary playable map.

A solution might be that instead of having the players respawn at the place where they were killed, placing the resurrection entity on a token spawner or player start.
Thanks for the helpful suggestion, I didn't know about the map problem you mentioned. I think spawning resurrection entities at spawn points would be the best alternative to spawning them at player death locations.

I want this mode's game play to be as similar to MOHAA Freeze Tag's game play as possible because that has always been a popular mode and by making DAD's game play different I would risk making it less enjoyable than Mefy's MOHAA Freeze Tag mode. I think making resurrection entities spawn at spawn points rather than randomly located player death locations would make DAD's game play different from MOHAA Freeze Tag's game play.

So I don't want to make resurrection entities spawn at spawn points unless I have to.

These are some ideas I've had for dealing with the inaccessible map area problem:

Also, what if you'd need to collect something like 1up items in order to be resurectable.
Everyone starts with one extra life, as soon as he needs to be resurrected, he looses this extra to the one who resurrected him.
Maybe you could also be allowed to resurrect players from the other team, stealing their lifes that way.
Although I don't want DAD's game play to be different from MOHAA Freeze Tag's game play for the reason I gave above, I do like your item ideas and I think I would enjoy playing a mode which was like DAD but also used your game play ideas.

I don't mind if any of the code I write is reused by other mode script authors. So if you want to reuse code from my DAD script in your own items DAD mode script or implement this mode idea by editing a copy of my DAD script, feel free.

If you don't want to make a script for an items DAD mode yourself, I would be willing to do the coding for you and you could have the final say over what was done in your mode's script.

Instead of the T-posed Body, i'd rather see something like a gravestone there.
I would like resurrection entities to use a character model which is in an unarmed standing stance with its arms down at its sides. Can character models use this stance?[/list]
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 02, 2012, 11:41:12 pm
These are some ideas I've had for dealing with the inaccessible map area problem:
  • Jumping could be disabled in this mode.
  • Player could have their resurrection entity spawn at a spawn point or accessible map area when:
    • They fall to their death.
    • When they use a suicide chat command.

Players will not have to wait for rounds to end when they join a DAD game, instead they could join a round before it ended if a team mate interacted with the new player's associated resurrection entity. So I'm not going to implement the things I mentioned in the above quote because players who are unlucky enough to die by falling into inaccessible map areas could move their resurrection entity to an accessible map area by simply rejoining a game.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on November 03, 2012, 03:49:51 am
I can see that there is a function in GEUtil which creates a temporary entity at a given vector ( CreateTempEnt(type,vector) ). I've got 2 questions about this function:
1) How is the created entity temporary? (or is a temporary entity a type of entity?)
2) How can a script reference an entity object which has been created by this function?

This is a special use function, it ONLY creates the ring type tempent which is a visual indicator. You cannot create arbitrary entities from Python.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 03, 2012, 01:07:20 pm
Thanks for your help.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 04, 2012, 01:07:07 pm
I'm confident I will have finished this mode's script by Wednesday.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 04, 2012, 08:44:44 pm
I'm anxious to see it as I don't think it will work.  If an admin turns on jump, then it sounds like the mode will be ruined.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: kraid on November 05, 2012, 05:41:09 am
you don't even need jumping enabled to fall into the decent on the end of runway or beyond the bridges in caves or complex so you surely need to spawn ppl on something like a token- or playerspawn.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 05, 2012, 05:53:20 am
Yea, that's true as well.  If someone is falling into a pit, and they're killed, the game mode would fail.  It would be worthless to unfreeze them.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 07, 2012, 01:01:04 pm
Yea, that's true as well.  If someone is falling into a pit, and they're killed, the game mode would fail.  It would be worthless to unfreeze them.
I've decided that I'm going to make resurrection entities spawn at player spawn points because of this map problem and because resurrection entities could block doors if they spawn at player corpses.

I also now think that resurrection token entities should use a grave stone model, if tokens can only use T-posed character models.

I still haven't finished this mode's script because I haven't spent much time working on it since I said I was confident I would have it finished by today.

I'm stuck at the moment because I want to use the Timer Tracker class but there is an error I've not been able to fix.

I've been trying to make it work in a simple DM test script:

Code: [Select]
from GamePlay import GEScenario
from Utils.GETimer import EndRoundCallback, TimerTracker, Timer
import GEEntity, GEPlayer, GEUtil, GEWeapon, GEMPGameRules, GEGlobal

USING_API = GEGlobal.API_VERSION_1_0_0

class Test( GEScenario ):
def GetPrintName( self ):
return "Test"

def GetScenarioHelp( self, help_obj ):
help_obj.SetDescription( "#GES_GP_DEATHMATCH_HELP" )

def GetGameDescription( self ):
if GEMPGameRules.IsTeamplay():
return "Team Deathmatch"
else:
return "Deathmatch"

def __init__( self ):
self.timerTracker = TimerTracker( self )

def GetTeamPlay( self ):
return GEGlobal.TEAMPLAY_TOGGLE

def OnLoadGamePlay( self ):
GEMPGameRules.SetAllowTeamSpawns( False )
self.CreateCVar( "dm_fraglimit", "0", "Enable frag limit for DeathMatch." )

timer = self.timerTracker.CreateTimer( "timer" )
timer.SetAgeRate( 1.0, 1.0 )
timer.SetUpdateCallback( self.TimerUpdate, 1.0 )

def TimerUpdate( self, timer, update_type ):
GEUtil.Msg("Timer Updated")

def OnThink( self ):
fragLimit = int( GEUtil.GetCVarValue( "dm_fraglimit" ) )
if fragLimit != 0:
if GEMPGameRules.IsTeamplay():

teamJ = GEMPGameRules.GetTeam( GEGlobal.TEAM_JANUS );
teamM = GEMPGameRules.GetTeam( GEGlobal.TEAM_MI6 );

jScore = teamJ.GetRoundScore() + teamJ.GetMatchScore()
mScore = teamM.GetRoundScore() + teamM.GetMatchScore()

if jScore >= fragLimit or mScore >= fragLimit:
GEMPGameRules.EndMatch()
else:
for i in range( 32 ):

if not GEPlayer.IsValidPlayerIndex( i ):
continue

player = GEPlayer.GetMPPlayer( i )

if  ( player.GetMatchScore() + player.GetScore() ) >= fragLimit:
GEMPGameRules.EndMatch()

Quote
Traceback (most recent call last):
  File "c:\program files\steam\steamapps\sourcemods\gesource\scripts\python\GamePlayManager.py", line 23, in SetGamePlay
    scenario = getattr( sys.modules[module], ident )()

  File "c:\program files\steam\steamapps\sourcemods\gesource\scripts\python\GamePlay\Test.py", line 21, in __init__
    self.timerTracker = TimerTracker( self )

  File "c:\program files\steam\steamapps\sourcemods\gesource\scripts\python\GamePlay\Utils\GETimer.py", line 20, in __init__
    parent.RegisterEventHook( EventHooks.GP_THINK, self.AgeTimers )

  File "c:\program files\steam\steamapps\sourcemods\gesource\scripts\python\GamePlay\__init__.py", line 22, in RegisterEventHook
    if not self.__hooks.has_key( hook ):
AttributeError: 'Test' object has no attribute '_GEScenario__hooks'
Scenario loading failed for scenario Test
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 08, 2012, 05:01:04 pm
I've still not found a solution to the problem I mentioned in my previous post but I have been implementing parts of the script which don't need timers.

I would like to implement resurrection entities using capture area entities but I've not found a way to associate a capture area entity a player enters, with its reference in the token manager. In order for the token manager to delete a specific capture area it needs to be given the capture area's name and I've not been able to get the name from a capture area object by using the functions in CBaseEntity.  The token manager doesn't have a function for returning its capture area entity objects, so I've not been able to map a capture area object to its name in a Python dictionary.

I think the only alternative way for implementing resurrection entities would be to use token entities. However this would allow players to interact with resurrection entities by picking them up instead of standing near them. So player's would not resurrect players in the same way that they would resurrect players in MOHAA's freeze tag mode, which could make this mode less enjoyable than that popular mode.

So if anyone knows how I could get the name for a capture area please let me know.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: WNxEuphonic on November 08, 2012, 07:25:09 pm
Hey, check out my Uplink gameplay for how capture areas work (and the older version archived somewhere around here for how to use tokens for a similar effect, the trick is to deny pickup). My advice would be to have two lists (deadJANUS and deadMI6) that keep track of dead players then create capture zones in a number equal to the length of those lists. When a player enters a capture zone, remove it and then remove the top player from the list. Players inside the list are denied spawning, keeping them eliminated until someone hits a capture zone.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 08, 2012, 09:31:07 pm
Hey, check out my Uplink gameplay for how capture areas work (and the older version archived somewhere around here for how to use tokens for a similar effect, the trick is to deny pickup). My advice would be to have two lists (deadJANUS and deadMI6) that keep track of dead players then create capture zones in a number equal to the length of those lists. When a player enters a capture zone, remove it and then remove the top player from the list. Players inside the list are denied spawning, keeping them eliminated until someone hits a capture zone.

Thanks for your advice, I will have a look at how capture areas work in your Uplink mode script.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: TriDefiance on November 09, 2012, 12:16:30 am
Hope you can get this gamemode to work! :D
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 09, 2012, 12:39:48 pm
I will try to finish the first playable version of this Mode's script by Monday. This version won't allow players to resurrect their team mates from a long distance, so they will have to stand next to their team mates' resurrection entities.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 09, 2012, 02:39:16 pm
I've now added a % development progress guesstimate to the first post in this forum topic, I will occasionally update it.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 09, 2012, 08:24:08 pm
I hope you're good at Sourcepawn.  Better yet, you could just use someone else's code for the freeze.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 10, 2012, 01:07:54 pm
I hope you're good at Sourcepawn.  Better yet, you could just use someone else's code for the freeze.

I don't want to freeze players in this mode.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 11, 2012, 07:44:32 pm
I will release the script for version 1 tomorrow when it's ready to be released.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 12, 2012, 10:36:34 pm
I'm very close to having a releasable script but I'm not going to release a script today because I want to spend more time testing it tomorrow and I want to make an important change.

Having played this mode with bots today I now think that spawning resurrection entities at player corpses is important because imo spawning them any where else makes this mode less enjoyable than MOHAA Freeze Tag.

I now know that players can move through character models when they are used as capture area models, so if a capture area entity could be moved from its spawn point to a player's corpse there would be no risk of it blocking a door. I guess moving a capture area entity may not be possible but maybe a script could move spawned tokens.

So I'm going to try to make an eliminated player's resurrection entity appear at their corpse.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: 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.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 15, 2012, 03:07:43 pm
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.

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: [Select]
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
 

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: [Select]
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)

Will the statement: " GEPlayer.GetMPPlayer(1) " always return the local player?
Title: Re: [Gameplay] Freeze Tag Mode
Post by: 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.

Do you have any suggestions for API improvement?
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 16, 2012, 12:57:11 pm
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.

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

Do you have any suggestions for API improvement?

I don't have any suggestions.

Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 20, 2012, 11:51:37 pm
Is 1.00 finished yet?
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 21, 2012, 04:51:37 pm
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: [Select]
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

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.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on November 21, 2012, 05:38:03 pm
I can add getting the steam id to my list of python API enhancements.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 21, 2012, 09:09:04 pm
I can add getting the steam id to my list of python API enhancements.

Thanks
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 22, 2012, 01:27:25 pm
I've fixed 2 bugs in the latest development version and I've improved the script's code.

The spectator view bug is now the only bug I need to fix before I can release beta 1.0.

Code: [Select]
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.

@author: Joe
@version: Dev 24.00 (22/11/12 0:31 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.radar = None
       
        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.changingTeamPlayers = {}
       
        #Eliminated player collections
        self.mResurrectionQueue = []
        self.jResurrectionQueue = []
       
        self.eliminatedSpectators = []
       
        #Collections related to resurrection area entities
        self.mAreaIDs = []
        self.jAreaIDs = []
       
        self.mAreaLocations = []
        self.jAreaLocations = []
       
        self.resurrectionAreaUserLists = defaultdict(list)
       
    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 24.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,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 deleteResurrectionArea(self,areasID,areasTeam):
        self.resurrectionAreaUserLists.pop(areasID)
           
        if areasTeam == GEGlobal.TEAM_MI6: self.mAreaIDs.remove(areasID)
        else: self.jAreaIDs.remove(areasID)
           
        self.tokenManager.RemoveCaptureArea(areasID)
       
    def areaInUse(self,areasID):
        return len(self.resurrectionAreaUserLists[areasID]) > 0
       
    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
       
        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
       
        self.radar = GEMPGameRules.GetRadar()
       
        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
        self.radar.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 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)
       
        self.resurrectionAreaUserLists.clear()
        del self.mAreaIDs[:]
        del self.jAreaIDs[:]

    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 player's 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.mi6Bounty
            else: teamsSurvivors = self.janusBounty
           
            #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):
                    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)
               
            elif teamsSurvivors < 0: GEUtil.Msg("ERROR:OnPlayerKilled():teamsSurvivors < 0: = " + str(teamsSurvivors))

    def OnCaptureAreaSpawned( self, area ):
        areasTeam = area.GetTeamNumber()
        location = area.GetAbsOrigin()
           
        #Recusrive Function Call Loop:
        #If the area has spawned at an enemy resurrection area's location respawn it and exit this function call
        #because this function will be called again when the area respawns and should only execute statements
        #after the respawn IF block, when it is called for an area which has an acceptable location.
        if areasTeam == GEGlobal.TEAM_MI6 and location in self.jAreaLocations or areasTeam == GEGlobal.TEAM_JANUS and location in self.mAreaLocations:
            self.respawnResurrectionEntity(area.GetGroupName(),areasTeam)
            return
       
        colour = None
        if area.GetTeamNumber() == GEGlobal.TEAM_MI6:
            self.mAreaLocations.append(location)
            colour = self.COLOR_MI6_RADAR
        else:
            self.jAreaLocations.append(location)
            colour = self.COLOR_JANUS_RADAR
               
        self.radar.AddRadarContact(area,GEGlobal.RADAR_TYPE_OBJECTIVE,True,"sprites/hud/radar/capture_point",colour)
        self.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, creating if it hasn't been created already
            self.resurrectionAreaUserLists[area.GetGroupName()].append(player)
           
            #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()
        areasName = area.GetGroupName()
       
        if areasTeam == player.GetTeamNumber():
            #Remove player from the area's user list
            self.resurrectionAreaUserLists[areasName].remove(player)
               
            #Remove the resurrection progress progress bar from the player's screen
            GEUtil.RemoveHudProgressBar(player,self.ResurrectionPBIndex)

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

        #Area still in use?
        if update_type != Timer.UPDATE_STOP and self.areaInUse(areasID):
            #Update each user's resurrection progress GUI
            for areaUser in self.resurrectionAreaUserLists[areasID]:
                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(areasID,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 :
            #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(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...
        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.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
       
       
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 22, 2012, 10:34:38 pm
I've still not been able to fix the spectator view bug.

I've tested this bug on the Runway map instead of the Facility and I've found that it manifests itself differently. Instead of making the spectator view try to show two different views, it locks the view in to one position making it unmovable when a player is on the spectator team. This view position is shown in the attached image.

If a GE:S developer can tell me why the spectator view behaved strangely in the following test, then I might be able to find a solution to the spectator view bug.

Runway View Bug Test

EPILEPSY WARNING: The script used in the following test allows the spectator view bug to occur, this view bug can make the spectator view rapidly flicker as it tries to display 3 different views on the Facility Map.
http://en.wikipedia.org/wiki/Photosensitive_epilepsy (http://en.wikipedia.org/wiki/Photosensitive_epilepsy)

Script used: Dev 25 with 2 changed functions shown below:
Code: [Select]
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: self.playerWantsToBecomeSpectator(player,oldTeam)
       
        #self.eliminatePlayer(player)
       
        return True

def CanPlayerRespawn( self, player ):
        #if self.isEliminatedPlayer(player):
            #player.SetScoreBoardColor( GEGlobal.SB_COLOR_ELIMINATED )
            #return False

        #player.SetScoreBoardColor( GEGlobal.SB_COLOR_NORMAL )
       
        return False

This is the Dev 25 script with these changed functions:
Code: [Select]
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.

@author: Joe
@version: Bug Test Version
'''

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.radar = None
       
        self.eliminateNewPlayers = False

        self.waitingForPlayers = False
        self.radarSet = False
        self.mBounty = 0
        self.jBounty = 0
        self.pltracker = GEPlayerTracker( self )
       
        self.mBountyMaxPlayers = 0
        self.jBountyMaxPlayers = 0
       
        self.timerTracker = TimerTracker( self )
        self.tokenManager = GEMPGameRules.GetTokenMgr()
       
        #Eliminated player collections
        self.mResurrectionQueue = []
        self.jResurrectionQueue = []
       
        self.eliminatedSpectators = []
       
        #Collections related to resurrection area entities
        self.mAreaIDs = []
        self.jAreaIDs = []
       
        self.mAreaLocations = []
        self.jAreaLocations = []
       
        self.resurrectionAreaUserLists = defaultdict(list)
       
    def OnLoadGamePlay( self ):
        GEUtil.PrecacheModel( self.MRE_MODEL )
        GEUtil.PrecacheModel( self.JRE_MODEL )
       
        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(
                                 """
Based on: Mefy's MOHAA Freeze Tag Mode
Version: Bug Test Version

*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.decrementTeamsPlayerCount(team)
            self.updateTeamsDisplayedMaxPlayers(team)
           
            if self.isEliminatedPlayer(player):
                self.deleteNotInUseResurrectionEntityFromTeam(team)
                self.removePlayerFromTeamsRQueue(player,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: self.playerWantsToBecomeSpectator(player,oldTeam)
       
        #self.eliminatePlayer(player)
       
        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","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.incrementTeamsPlayerCount(newTeam)
        self.decrementTeamsPlayerCount(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.decrementTeamsPlayerCount(oldTeam)
       
        if self.isEliminatedPlayer(player):
            self.deleteNotInUseResurrectionEntityFromTeam(oldTeam)
            self.removePlayerFromTeamsRQueue(player,oldTeam)
        else: self.decreaseTeamBounty(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 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 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 deleteResurrectionArea(self,areasID,areasTeam):
        self.resurrectionAreaUserLists.pop(areasID)
           
        if areasTeam == GEGlobal.TEAM_MI6: self.mAreaIDs.remove(areasID)
        else: self.jAreaIDs.remove(areasID)
           
        self.tokenManager.RemoveCaptureArea(areasID)
       
    def areaInUse(self,areasID):
        return len(self.resurrectionAreaUserLists[areasID]) > 0
       
    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
       
        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 player in self.eliminatedSpectators:
                self.spawnNewResurrectionEntity(player,playersTeam)
                self.updateTeamsDisplayedMaxPlayers(playersTeam)
               
                self.eliminatedSpectators.remove(player)
               
            #If can spawn:
            else:
                GEUtil.Msg("*** NON spectator spawned ***") #TODO remove
                self.pltracker.SetValue( player, self.TR_SPAWNED,True)
               
        else: GEUtil.Msg("*** Spectator spawned ***") #TODO remove
           
        #TODO Use UI Language Files
        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 ):
        self.eliminateNewPlayers = False
        self.radar.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 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)
       
        self.resurrectionAreaUserLists.clear()
        del self.mAreaIDs[:]
        del self.jAreaIDs[:]

    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 player's 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):
                    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)
               
            elif teamsSurvivors < 0: GEUtil.Msg("ERROR:OnPlayerKilled():teamsSurvivors < 0: = " + str(teamsSurvivors))

    def OnCaptureAreaSpawned( self, area ):
        areasTeam = area.GetTeamNumber()
        location = area.GetAbsOrigin()
           
        #Recusrive Function Call Loop:
        #If the area has spawned at an enemy resurrection area's location respawn it and exit this function call
        #because this function will be called again when the area respawns and should only execute statements
        #after the respawn IF block, when it is called for an area which has an acceptable location.
        if areasTeam == GEGlobal.TEAM_MI6 and location in self.jAreaLocations or areasTeam == GEGlobal.TEAM_JANUS and location in self.mAreaLocations:
            self.respawnResurrectionEntity(area.GetGroupName(),areasTeam)
            return
       
        colour = None
        if area.GetTeamNumber() == GEGlobal.TEAM_MI6:
            self.mAreaLocations.append(location)
            colour = self.COLOR_MI6_RADAR
        else:
            self.jAreaLocations.append(location)
            colour = self.COLOR_JANUS_RADAR
               
        self.radar.AddRadarContact(area,GEGlobal.RADAR_TYPE_OBJECTIVE,True,"sprites/hud/radar/capture_point",colour)
        self.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, creating if it hasn't been created already
            self.resurrectionAreaUserLists[area.GetGroupName()].append(player)
           
            #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()
        areasName = area.GetGroupName()
       
        if areasTeam == player.GetTeamNumber():
            #Remove player from the area's user list
            self.resurrectionAreaUserLists[areasName].remove(player)
               
            #Remove the resurrection progress progress bar from the player's screen
            GEUtil.RemoveHudProgressBar(player,self.ResurrectionPBIndex)

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

        #Area still in use?
        if update_type != Timer.UPDATE_STOP and self.areaInUse(areasID):
            #Update each user's resurrection progress GUI
            for areaUser in self.resurrectionAreaUserLists[areasID]:
                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(areasID,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.mBounty and numberOfJPlayers == self.jBounty: 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 :
            #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(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...
        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 False

    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)

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

       

Game settings:
I was the only player.

The Test:
1.When the map had loaded and the team choice menu appeared, I chose to be a spectator: I was then able to move my view around the map normally.
2.I then opened the team menu and chose to join MI6: I was able to move my view around the map normally.
3.I then changed my team to Janus: I was still able to move my view around the map normally.
4.I then changed my team to Spectator: I was able to move my view around the map normally for a few seconds, but then my view changed to the view shown in the attached screen shot and I was no longer able to move it.
5.I then changed my team to MI6: I was then able to move my view around the map normally again.
6.I finally changed my team back to Spectator: The view problem from step 4 reoccurred.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on November 22, 2012, 11:24:37 pm
Does this happen when there are other players (or bots) in the server?

If it does NOT, than I know what is going wrong.

Either way, you can't fix this from python so don't worry about it.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Troy on November 23, 2012, 01:34:24 am
GE:S bug.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 23, 2012, 04:46:27 pm
I've not been able to test this bug with bots enabled because they don't join when I'm a spectator and they immediately leave when I become a spectator. I've not found a console command to make them stay. I will check the script later to see if something in the script is making them leave.

I would release this script without fixing the spectator view bug, if I wasn't worried that its affect on the Facility's spectator view might be capable of causing epileptic seizures.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on November 23, 2012, 06:53:20 pm
Epileptic seizures?? If someone is prone to them than they should know the risks and shouldn't be playing intense games to begin with. Not to mention it only affects a very small section of the population. Also, GES has a very bright flashing white screen when you get hit, if that doesn't cause seizures than I don't know what will.

Although I see what you mean by the bug, it is rather rude haha.

Anyway, you can spawn bots when you are a spectator by setting the ge_bot_threshold to -1 then use ge_bot to spawn bots.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Proxie on November 23, 2012, 10:48:31 pm
Kidx had a seizure and dusted everyone on the server.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: killermonkey on November 24, 2012, 02:51:22 am
I have fixed the spectator bug and it will be out in the next patch.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 24, 2012, 03:58:06 pm
I think I will be able to prevent this script from triggering that GE:S bug by simply making it spawn an eliminated player before allowing them to become a spectator.

I have fixed the spectator bug and it will be out in the next patch.

Thanks, when this patch is released I will update this mode's script.

If I can prevent this script from triggering that GE:S bug, then I will release a beta version today.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Joe on November 24, 2012, 05:10:57 pm
I think I will be able to prevent this script from triggering that GE:S bug by simply making it spawn an eliminated player before allowing them to become a spectator.
This workaround worked.

I will release beta 1.00 later after I've done some final bug tests. I will now only make bug correcting changes to the code in the beta 1.00 script.

Although I see what you mean by the bug, it is rather rude haha.
Sorry

Anyway, you can spawn bots when you are a spectator by setting the ge_bot_threshold to -1 then use ge_bot to spawn bots.
Thanks, now that I know how to do this I will be able to do some extra bug tests.
Title: Re: [Gameplay] Freeze Tag Mode
Post by: Mangley on November 24, 2012, 08:38:25 pm
I never liked Freeze Tag in MoH:AA, it just clashed with the way the game was designed way too much, particularly on the more linear objective maps. CKR Realism in Objective mode was always MoH:AA at it's finest!

Anyway I think it would probably work pretty well in GE:S, so I look forward to seeing how it works out.