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.
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 )
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'
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 = {}
self.mResurrectionQueue = []
self.jResurrectionQueue = []
self.eliminatedSpectators = []
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 ):
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)
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:
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:
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)
def spectatorWantsToJoinTeam(self,player,newTeam):
if self.isEliminatedPlayer(player):
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):
GEUtil.EmitGameplayEvent( "DieAnotherDay_eliminated", "%i" % victim.GetUserID(), "%i" % killer.GetUserID())
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):
newAreasID = str(victim.GetUserID())
self.spawnResurrectionEntity(newAreasID,team)
if team == GEGlobal.TEAM_MI6: self.mAreaIDs.append(newAreasID)
else: self.jAreaIDs.append(newAreasID)
def respawnResurrectionEntity(self,areaID,team):
self.tokenManager.RemoveCaptureArea(areaID)
self.spawnResurrectionEntity(areaID,team)
def spawnResurrectionEntity(self,areaID,team):
modelName = None
if team == GEGlobal.TEAM_MI6: modelName = self.MRE_MODEL
else: modelName = self.JRE_MODEL
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):
self.updateTeamsMaxPlayers(playersTeam)
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)
else:
self.pltracker.SetValue( player, self.TR_SPAWNED,True)
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)
GEUtil.RemoveHudProgressBar( None,self.MBountyPBIndex)
GEUtil.RemoveHudProgressBar( None,self.JBountyPBIndex)
GEUtil.RemoveHudProgressBar( None,self.ResurrectionPBIndex)
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()
victimsTeam = victim.GetTeamNumber()
if killer.GetTeamNumber()!= victimsTeam:
self.eliminatePlayer(victim)
self.announceElimination(victim,killer)
self.decreaseTeamBounty(victimsTeam)
teamsSurvivors = 0
if victimsTeam == GEGlobal.TEAM_MI6: teamsSurvivors = self.mi6Bounty
else: teamsSurvivors = self.janusBounty
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)
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()
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()
self.resurrectionAreaUserLists[area.GetGroupName()].append(player)
resurrectionTimer = self.timerTracker.CreateTimer(str(areasTeam) + "," + area.GetGroupName())
resurrectionTimer.SetUpdateCallback(self.ResurrectionTimerTick,1.0)
resurrectionTimer.SetAgeRate(1.0,0)
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 ) )
resurrectionTimer.Start(self.resurrectionTime,False)
def OnCaptureAreaExited( self, area, player ):
areasTeam = area.GetTeamNumber()
areasName = area.GetGroupName()
if areasTeam == player.GetTeamNumber():
self.resurrectionAreaUserLists[areasName].remove(player)
GEUtil.RemoveHudProgressBar(player,self.ResurrectionPBIndex)
def ResurrectionTimerTick( self, timer, update_type ):
areasID = timer.GetName()[2:]
if update_type != Timer.UPDATE_STOP and self.areaInUse(areasID):
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:
areasTeam = int(timer.GetName()[0])
teamString = self.getTeamString(areasTeam)
self.deleteResurrectionArea(areasID,areasTeam)
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 resurrectedPlayer != None:
self.resurrectPlayer(resurrectedPlayer)
self.increaseTeamBounty(areasTeam)
self.resurrectionQueueUpdateNotify(areasTeam)
if self.playerNotBot(resurrectedPlayer):
GEUtil.RemoveHudProgressBar(resurrectedPlayer,self.ResurrectionPBIndex)
GEUtil.EmitGameplayEvent("DieAnotherDay_resurrection", "%s" % resurrectedPlayer.GetName(),"%s" % teamString)
GEUtil.Msg("A " + teamString + " player has been resurrected: " + resurrectedPlayer.GetName())
GEUtil.ClientPrint(None, GEGlobal.HUD_PRINTTALK,"A " + teamString + " player has been resurrected.")
numberOfMPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_MI6)
numberOfJPlayers = GEMPGameRules.GetNumInRoundTeamPlayers(GEGlobal.TEAM_JANUS)
if numberOfMPlayers == self.mi6Bounty and numberOfJPlayers == self.janusBounty: self.eliminatedSpectators = False
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, "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 )
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