Exemplo n.º 1
0
 def _initAudio(self):
     self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles,
                                            Globals.SfxFiles,
                                            camera,
                                            cutoff=Globals.AudioCutoff)
     self._quakeSfx1 = self._audioMgr.createSfx('quake')
     self._quakeSfx2 = self._audioMgr.createSfx('quake')
Exemplo n.º 2
0
 def load(self):
     self.accept(self.distGame.getRemoteActionEventName(), self.handleRemoteAction)
     self.audioMgr = CogdoGameAudioManager(Globals.Audio.MusicFiles, Globals.Audio.SfxFiles, base.localAvatar, cutoff=Globals.Audio.Cutoff)
     factory = CogdoFlyingLevelFactory(render, Globals.Level.QuadLengthUnits, Globals.Level.QuadVisibilityAhead, Globals.Level.QuadVisibilityBehind, rng=RandomNumGen(self.distGame.doId))
     self.level = factory.createLevel(self.distGame.getSafezoneId())
     self.level.setCamera(camera)
     self.guiMgr = CogdoFlyingGuiManager(self.level)
     self.levelFog = factory.createLevelFog()
     self._initLegalEagles()
 def load(self):
     self.accept(self.distGame.getRemoteActionEventName(), self.handleRemoteAction)
     self.audioMgr = CogdoGameAudioManager(Globals.Audio.MusicFiles, Globals.Audio.SfxFiles, base.localAvatar, cutoff=Globals.Audio.Cutoff)
     factory = CogdoFlyingLevelFactory(render, Globals.Level.QuadLengthUnits, Globals.Level.QuadVisibilityAhead, Globals.Level.QuadVisibilityBehind, rng=RandomNumGen(self.distGame.doId))
     self.level = factory.createLevel(self.distGame.getSafezoneId())
     self.level.setCamera(camera)
     self.guiMgr = CogdoFlyingGuiManager(self.level)
     self.levelFog = factory.createLevelFog()
     self._initLegalEagles()
class CogdoFlyingGame(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingGame')
    UpdateTaskName = 'CogdoFlyingGameUpdate'
    FirstPressOfCtrlTaskName = 'FirstPressOfCtrlTask'

    def __init__(self, distGame):
        self.distGame = distGame
        self.toonId2Player = {}
        self.players = []
        self.index2LegalEagle = {}
        self.legalEagles = []
        self.isGameComplete = False
        self.localPlayer = None
        self._hints = {'targettedByEagle': False,
         'invulnerable': False}

    def _initLegalEagles(self):
        nestIndex = 1
        nests = self.level.root.findAllMatches('**/%s;+s' % Globals.Level.LegalEagleNestName)
        for nest in nests:
            legalEagle = CogdoFlyingLegalEagle(nest, nestIndex)
            self.legalEagles.append(legalEagle)
            self.index2LegalEagle[nestIndex] = legalEagle
            nestIndex += 1

    def initPlayers(self):
        for toonId in self.distGame.getToonIds():
            toon = self.distGame.getToon(toonId)
            i = self.distGame.getToonIds().index(toon.doId)
            if toon is not None:
                if toon.isLocal():
                    player = CogdoFlyingLocalPlayer(toon, self, self.level, self.guiMgr)
                    self.localPlayer = player
                    self.localPlayer.setPlayerNumber(i)
                else:
                    player = CogdoFlyingPlayer(toon)
                player.enable()
                self._addPlayer(player)
                self.guiMgr.addToonToProgressMeter(toon)

        return

    def placeEntranceElevator(self, elevator):
        loc = self.level.startPlatform._model.find('**/door_loc')
        offset = loc.getPos(render)
        elevator.setPos(render, offset)

    def load(self):
        self.accept(self.distGame.getRemoteActionEventName(), self.handleRemoteAction)
        self.audioMgr = CogdoGameAudioManager(Globals.Audio.MusicFiles, Globals.Audio.SfxFiles, base.localAvatar, cutoff=Globals.Audio.Cutoff)
        factory = CogdoFlyingLevelFactory(render, Globals.Level.QuadLengthUnits, Globals.Level.QuadVisibilityAhead, Globals.Level.QuadVisibilityBehind, rng=RandomNumGen(self.distGame.doId))
        self.level = factory.createLevel(self.distGame.getSafezoneId())
        self.level.setCamera(camera)
        self.guiMgr = CogdoFlyingGuiManager(self.level)
        self.levelFog = factory.createLevelFog()
        self._initLegalEagles()

    def unload(self):
        self.guiMgr.destroy()
        del self.guiMgr
        self.__stopUpdateTask()
        for player in self.players:
            player.unload()

        del self.players[:]
        self.toonId2Player.clear()
        del self.localPlayer
        for eagle in self.legalEagles:
            eagle.destroy()

        del self.legalEagles[:]
        self.index2LegalEagle.clear()
        self.levelFog.destroy()
        del self.levelFog
        self.level.destroy()
        del self.level
        self.audioMgr.destroy()
        del self.audioMgr
        self.ignoreAll()
        del self.distGame

    def onstage(self):
        self.level.onstage()
        self.levelFog.setVisible(True)
        for eagle in self.legalEagles:
            eagle.onstage()

        self.localPlayer.request('Inactive')

    def offstage(self):
        self.__stopUpdateTask()
        for eagle in self.legalEagles:
            eagle.offstage()

        self.level.offstage()
        self.levelFog.setVisible(False)

    def startIntro(self):
        self._movie = CogdoFlyingGameIntro(self.level, RandomNumGen(self.distGame.doId))
        self._movie.load()
        self._movie.play()
        self.audioMgr.playMusic('normal')

    def endIntro(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        base.camLens.setMinFov(ToontownGlobals.CogdoFov/(4./3.))
        self.localPlayer.ready()
        self.level.update(0.0)

    def startFinish(self):
        self._movie = CogdoFlyingGameFinish(self.level, self.players)
        self._movie.load()
        self._movie.play()
        self.audioMgr.playMusic('end')

    def endFinish(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        self.audioMgr.stopMusic()

    def start(self):
        self.level.start(self.distGame.getStartTime())
        self.accept(CogdoFlyingObstacle.EnterEventName, self.handleLocalToonEnterObstacle)
        self.accept(CogdoFlyingObstacle.ExitEventName, self.handleLocalToonExitObstacle)
        self.accept(CogdoFlyingGatherable.EnterEventName, self.handleLocalToonEnterGatherable)
        self.accept(CogdoFlyingLegalEagle.RequestAddTargetEventName, self.handleLocalToonEnterLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.RequestAddTargetAgainEventName, self.handleLocalToonAgainLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.RequestRemoveTargetEventName, self.handleLocalToonExitLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.EnterLegalEagle, self.handleLocalToonEnterLegalEagle)
        self.accept(CogdoFlyingLegalEagle.ChargingToAttackEventName, self.handlePlayerBackpackAttacked)
        self.accept(CogdoFlyingLegalEagle.LockOnToonEventName, self.handlePlayerBackpackTargeted)
        self.accept(CogdoFlyingLegalEagle.CooldownEventName, self.handlePlayerBackpackNormal)
        self.accept(CogdoFlyingGuiManager.EagleTargetingLocalPlayerEventName, self.handleLocalPlayerTargetedByEagle)
        self.accept(CogdoFlyingGuiManager.EagleAttackingLocalPlayerEventName, self.handleLocalPlayerAttackedByEagle)
        self.accept(CogdoFlyingGuiManager.ClearMessageDisplayEventName, self.handleClearGuiMessage)
        self.accept(CogdoFlyingGuiManager.InvulnerableEventName, self.handleLocalPlayerInvulnerable)
        self.acceptOnce(CogdoFlyingGuiManager.FirstPressOfCtrlEventName, self.handleLocalPlayerFirstPressOfCtrl)
        self.acceptOnce(CogdoFlyingGuiManager.PickedUpFirstPropellerEventName, self.handleLocalPlayerPickedUpFirstPropeller)
        self.acceptOnce(CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName, self.handleTimeRunningOut)
        self.acceptOnce(CogdoFlyingLocalPlayer.PlayWaitingMusicEventName, self.handlePlayWaitingMusic)
        self.acceptOnce(CogdoFlyingLocalPlayer.RanOutOfTimeEventName, self.handleLocalPlayerRanOutOfTime)
        self.__startUpdateTask()
        self.isGameComplete = False

        for eagle in self.legalEagles:
            eagle.gameStart(self.distGame.getStartTime())

        for player in self.players:
            player.start()

        self.guiMgr.onstage()
        if not Globals.Dev.InfiniteTimeLimit:
            self.guiMgr.startTimer(Globals.Gameplay.SecondsUntilGameOver, self._handleTimerExpired)

    def exit(self):
        self.ignore(CogdoFlyingObstacle.EnterEventName)
        self.ignore(CogdoFlyingObstacle.ExitEventName)
        self.ignore(CogdoFlyingGatherable.EnterEventName)
        self.ignore(CogdoFlyingLegalEagle.ChargingToAttackEventName)
        self.ignore(CogdoFlyingLegalEagle.LockOnToonEventName)
        self.ignore(CogdoFlyingLegalEagle.CooldownEventName)
        self.ignore(CogdoFlyingLocalPlayer.RanOutOfTimeEventName)
        taskMgr.remove(CogdoFlyingGame.FirstPressOfCtrlTaskName)
        self.__stopUpdateTask()
        self.ignore(CogdoFlyingLegalEagle.EnterLegalEagle)
        self.ignore(CogdoFlyingLegalEagle.RequestAddTargetEventName)
        self.ignore(CogdoFlyingLegalEagle.RequestAddTargetAgainEventName)
        self.ignore(CogdoFlyingLegalEagle.RequestRemoveTargetEventName)
        self.ignore(CogdoFlyingLocalPlayer.PlayWaitingMusicEventName)
        self.level.update(0.0)
        for eagle in self.legalEagles:
            eagle.gameEnd()

        for player in self.players:
            player.exit()

        self.guiMgr.offstage()

    def _handleTimerExpired(self):
        self.localPlayer.handleTimerExpired()

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player
        toon = player.toon
        self.accept(toon.uniqueName('disable'), self._removePlayer, extraArgs=[toon.doId])

    def _removePlayer(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            self.players.remove(player)
            del self.toonId2Player[toonId]
            self.guiMgr.removeToonFromProgressMeter(player.toon)
            player.exit()
            player.unload()

    def setToonSad(self, toonId):
        player = self.toonId2Player[toonId]
        self.forceClearLegalEagleInterestInToon(toonId)
        if player == self.localPlayer:
            player.goSad()
            self.exit()
        else:
            player.exit()

    def setToonDisconnect(self, toonId):
        player = self.toonId2Player[toonId]
        self.forceClearLegalEagleInterestInToon(toonId)
        if player == self.localPlayer:
            self.exit()
        else:
            player.exit()

    def handleRemoteAction(self, action, data):
        if data != self.localPlayer.toon.doId:
            if action == Globals.AI.GameActions.GotoWinState:
                if self.localPlayer.state in ['WaitingForWin']:
                    self.localPlayer.request('Win')

    def toonDied(self, toonId, elapsedTime):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.died(elapsedTime)
        return

    def toonSpawn(self, toonId, elapsedTime):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.spawn(elapsedTime)
        return

    def toonResetBlades(self, toonId):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.resetBlades()
        return

    def toonSetBlades(self, toonId, fuelState):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.setBlades(fuelState)
        return

    def toonBladeLost(self, toonId):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.bladeLost()
        return

    def handleLocalToonEnterGatherable(self, gatherable):
        if gatherable.wasPickedUp():
            return
        if gatherable.isPowerUp() and gatherable.wasPickedUpByToon(self.localPlayer.toon):
            return
        if gatherable.type in [Globals.Level.GatherableTypes.LaffPowerup, Globals.Level.GatherableTypes.InvulPowerup]:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)
        elif gatherable.type == Globals.Level.GatherableTypes.Memo:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)
            gatherable.disable()
        elif gatherable.type == Globals.Level.GatherableTypes.Propeller and self.localPlayer.fuel < 1.0:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)

    def pickUp(self, toonId, pickupNum, elapsedTime = 0.0):
        self.notify.debugCall()
        player = self.toonId2Player[toonId]
        gatherable = self.level.getGatherable(pickupNum)
        if gatherable is not None:
            if not gatherable.isPowerUp() and not gatherable.wasPickedUp() or gatherable.isPowerUp() and not gatherable.wasPickedUpByToon(player.toon):
                gatherable.pickUp(player.toon, elapsedTime)
                player.handleEnterGatherable(gatherable, elapsedTime)
                if gatherable.type in [Globals.Level.GatherableTypes.InvulPowerup]:
                    if player.toon.isLocal():
                        self.audioMgr.playMusic('invul')
                taskMgr.doMethodLater(30, lambda task: self.debuffPowerup(toonId, gatherable.type, elapsedTime), 'gatherable-timeout')
        else:
            self.notify.warning('Trying to pickup gatherable nonetype:%s' % pickupNum)
        return

    def debuffPowerup(self, toonId, pickupType, elapsedTime):
        self.notify.debugCall()
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            if player.isBuffActive(pickupType):
                if pickupType in [Globals.Level.GatherableTypes.InvulPowerup]:
                    if self.guiMgr.isTimeRunningOut():
                        self.audioMgr.playMusic('timeRunningOut')
                    else:
                        self.audioMgr.playMusic('normal')
                    player.handleDebuffPowerup(pickupType, elapsedTime)

    def handleLocalToonEnterLegalEagle(self, eagle, collEntry):
        if not self.localPlayer.isEnemyHitting() and not self.localPlayer.isInvulnerable():
            collPos = collEntry.getSurfacePoint(render)
            self.localPlayer.handleEnterEnemyHit(eagle, collPos)
            self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitLegalEagle, 0)

    def handleLocalToonEnterObstacle(self, obstacle, collEntry):
        if self.localPlayer.isInvulnerable():
            return
        if obstacle.type == Globals.Level.ObstacleTypes.Whirlwind:
            self.localPlayer.handleEnterWhirlwind(obstacle)
            self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitWhirlwind, 0)
        if obstacle.type == Globals.Level.ObstacleTypes.Fan:
            self.localPlayer.handleEnterFan(obstacle)
        if obstacle.type == Globals.Level.ObstacleTypes.Minion:
            if not self.localPlayer.isEnemyHitting():
                collPos = collEntry.getSurfacePoint(render)
                self.localPlayer.handleEnterEnemyHit(obstacle, collPos)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitMinion, 0)

    def handleLocalToonExitObstacle(self, obstacle, collEntry):
        if obstacle.type == Globals.Level.ObstacleTypes.Fan:
            self.localPlayer.handleExitFan(obstacle)

    def __startUpdateTask(self):
        self.__stopUpdateTask()
        taskMgr.add(self.__updateTask, CogdoFlyingGame.UpdateTaskName, 45)

    def __stopUpdateTask(self):
        taskMgr.remove(CogdoFlyingGame.UpdateTaskName)

    def handleTimeRunningOut(self):
        if self.localPlayer.state not in ['WaitingForWin']:
            self.audioMgr.playMusic('timeRunningOut')
        self.guiMgr.presentTimerGui()
        self.guiMgr.setTemporaryMessage(TTLocalizer.CogdoFlyingGameTimeIsRunningOut)

    def handlePlayWaitingMusic(self):
        self.audioMgr.playMusic('waiting')

    def handleLocalPlayerFirstPressOfCtrl(self):
        self.doMethodLater(3.0, self.guiMgr.setMessage, CogdoFlyingGame.FirstPressOfCtrlTaskName, extraArgs=[''])

    def handleLocalPlayerRanOutOfTime(self):
        self.guiMgr.setMemoCount(0)
        self.distGame.d_sendRequestAction(Globals.AI.GameActions.RanOutOfTimePenalty, 0)
        self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameTakingMemos)

    def handleClearGuiMessage(self):
        if not self.localPlayer.isInvulnerable():
            self.guiMgr.setMessage('')

    def handleLocalPlayerInvulnerable(self):
        if not self._hints['invulnerable']:
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameYouAreInvincible)
            self._hints['invulnerable'] = True

    def handleLocalPlayerPickedUpFirstPropeller(self):
        self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGamePressCtrlToFly)
        self.guiMgr.presentRefuelGui()

    def handleLocalPlayerTargetedByEagle(self):
        if not self.localPlayer.isInvulnerable() and not self._hints['targettedByEagle']:
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameLegalEagleTargeting)
            self._hints['targettedByEagle'] = True

    def handleLocalPlayerAttackedByEagle(self):
        if not self.localPlayer.isInvulnerable():
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameLegalEagleAttacking)

    def handlePlayerBackpackAttacked(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Attacked)

    def handlePlayerBackpackTargeted(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Targeted)

    def handlePlayerBackpackNormal(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Normal)

    def handleLocalToonEnterLegalEagleInterest(self, index):
        if index in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[index]
            if not self.localPlayer.isLegalEagleInterestRequestSent(index) and not self.localPlayer.isLegalEagleTarget():
                if self.localPlayer.state in ['WaitingForWin', 'Win']:
                    return
                self.localPlayer.setLegalEagleInterestRequest(index)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestEnterEagleInterest, index)
        else:
            self.notify.warning("Legal eagle %i isn't in index2LegalEagle dict" % index)

    def handleLocalToonAgainLegalEagleInterest(self, index):
        self.handleLocalToonEnterLegalEagleInterest(index)

    def handleLocalToonExitLegalEagleInterest(self, index):
        if index in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[index]
            if self.localPlayer.isLegalEagleInterestRequestSent(index):
                self.localPlayer.clearLegalEagleInterestRequest(index)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestExitEagleInterest, index)
        else:
            self.notify.warning("Legal eagle %i isn't in index2LegalEagle dict" % index)

    def forceClearLegalEagleInterestInToon(self, toonId):
        player = self.toonId2Player[toonId]
        if player:
            for legalEagle in self.legalEagles:
                index = legalEagle.index
                if player.toon.isLocal():
                    if self.localPlayer.isLegalEagleInterestRequestSent(index):
                        self.localPlayer.clearLegalEagleInterestRequest(index)
                        self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestExitEagleInterest, index)
                self.toonClearAsEagleTarget(toonId, index, 0)

    def toonSetAsEagleTarget(self, toonId, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            if toonId in self.toonId2Player:
                player = self.toonId2Player[toonId]
                player.setAsLegalEagleTarget(legalEagle)
                legalEagle.setTarget(player.toon, elapsedTime)

    def toonClearAsEagleTarget(self, toonId, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            if toonId in self.toonId2Player:
                player = self.toonId2Player[toonId]
                player.removeAsLegalEagleTarget(legalEagle)
                if legalEagle.getTarget() == player.toon:
                    legalEagle.clearTarget(elapsedTime)

    def eagleExitCooldown(self, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            legalEagle.leaveCooldown(elapsedTime)

    def gameComplete(self):
        self.localPlayer.request('Win')

    def __updateTask(self, task):
        dt = globalClock.getDt()
        self.localPlayer.update(dt)
        self.level.update(dt)
        for eagle in self.legalEagles:
            eagle.update(dt, self.localPlayer)

        self.guiMgr.update()
        return Task.cont
Exemplo n.º 5
0
class CogdoCraneGame(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingGame')

    def __init__(self, distGame):
        self.distGame = distGame
        self.toonId2Player = {}
        self.players = []

    def _initAudio(self):
        self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles,
                                               Globals.SfxFiles,
                                               camera,
                                               cutoff=Globals.AudioCutoff)

    def _destroyAudio(self):
        self._audioMgr.destroy()
        del self._audioMgr

    def load(self):
        self._initAudio()

    def unload(self):
        self._destroyAudio()
        del self.toonId2Player

    def onstage(self):
        pass

    def offstage(self):
        pass

    def startIntro(self):
        self._audioMgr.playMusic('normal')

    def endIntro(self):
        for player in self.players:
            self.placePlayer(player)
            if player.toon is localAvatar:
                localAvatar.sendCurrentPosition()
            player.request('Ready')

    def startFinish(self):
        pass

    def endFinish(self):
        pass

    def start(self):
        for player in self.players:
            player.handleGameStart()
            player.request('Normal')

    def exit(self):
        for player in self.players:
            player.request('Done')

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player

    def _removePlayer(self, player):
        if player in self.players:
            self.players.remove(player)
        else:
            for cPlayer in self.players:
                if cPlayer.toon == player.toon:
                    self.players.remove(cPlayer)
                    break

        if self.toonId2Player.has_key(player.toon.doId):
            del self.toonId2Player[player.toon.doId]

    def handleToonLeft(self, toonId):
        self._removePlayer(self.toonId2Player[toonId])
Exemplo n.º 6
0
 def _initAudio(self):
     self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles,
                                            Globals.SfxFiles,
                                            camera,
                                            cutoff=Globals.AudioCutoff)
Exemplo n.º 7
0
class CogdoMazeGame(DirectObject):
    notify = directNotify.newCategory('CogdoMazeGame')
    UpdateTaskName = 'CogdoMazeGameUpdateTask'
    RemoveGagTaskName = 'CogdoMazeGameRemoveGag'
    PlayerCoolerCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName,
                                            Globals.WaterCoolerCollisionName)
    PlayerDropCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName,
                                          Globals.DropCollisionName)

    def __init__(self, distGame):
        self.distGame = distGame
        self._allowSuitsHitToons = base.config.GetBool(
            'cogdomaze-suits-hit-toons', True)

    def load(self, cogdoMazeFactory, numSuits, bossCode):
        self._initAudio()
        self.maze = cogdoMazeFactory.createCogdoMaze()
        suitSpawnSpot = self.maze.createRandomSpotsList(
            numSuits, self.distGame.randomNumGen)
        self.guiMgr = CogdoMazeGuiManager(self.maze, bossCode)
        self.suits = []
        self.suitsById = {}
        self.shakers = []
        self.toonsThatRevealedDoor = []
        self.quake = 0
        self.dropCounter = 0
        self.drops = {}
        self.gagCounter = 0
        self.gags = []
        self.hackTemp = False
        self.dropGen = RandomNumGen(self.distGame.doId)
        self.gagTimeoutTasks = []
        self.finished = False
        self.lastBalloonTimestamp = None
        difficulty = self.distGame.getDifficulty()
        serialNum = 0
        for i in xrange(numSuits[0]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeBossSuit(serialNum,
                                     self.maze,
                                     suitRng,
                                     difficulty,
                                     startTile=suitSpawnSpot[0][i])
            self.addSuit(suit)
            self.guiMgr.mazeMapGui.addSuit(suit.suit)
            serialNum += 1

        for i in xrange(numSuits[1]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeFastMinionSuit(serialNum,
                                           self.maze,
                                           suitRng,
                                           difficulty,
                                           startTile=suitSpawnSpot[1][i])
            self.addSuit(suit)
            serialNum += 1

        for i in xrange(numSuits[2]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeSlowMinionSuit(serialNum,
                                           self.maze,
                                           suitRng,
                                           difficulty,
                                           startTile=suitSpawnSpot[2][i])
            self.addSuit(suit)
            serialNum += 1

        self.toonId2Door = {}
        self.keyIdToKey = {}
        self.players = []
        self.toonId2Player = {}
        cellPos = (int(self.maze.width / 2), self.maze.height - 1)
        pos = self.maze.tile2world(*cellPos)
        self._exit = CogdoMazeExit()
        self._exit.reparentTo(render)
        self._exit.setPos(self.maze.exitPos)
        self._exit.stash()
        self.guiMgr.mazeMapGui.placeExit(*cellPos)
        self._collNode2waterCooler = {}
        for waterCooler in self.maze.getWaterCoolers():
            pos = waterCooler.getPos(render)
            tpos = self.maze.world2tile(pos[0], pos[1])
            self.guiMgr.mazeMapGui.addWaterCooler(*tpos)
            self._collNode2waterCooler[waterCooler.collNode] = waterCooler

        self.pickups = []
        self.gagModel = CogdoUtil.loadMazeModel('waterBalloon')
        self._movie = CogdoMazeGameIntro(self.maze, self._exit,
                                         self.distGame.randomNumGen)
        self._movie.load()
        return

    def _initAudio(self):
        self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles,
                                               Globals.SfxFiles,
                                               camera,
                                               cutoff=Globals.AudioCutoff)
        self._quakeSfx1 = self._audioMgr.createSfx('quake')
        self._quakeSfx2 = self._audioMgr.createSfx('quake')

    def _destroyAudio(self):
        self._quakeSfx1.destroy()
        self._quakeSfx2.destroy()
        del self._quakeSfx1
        del self._quakeSfx2
        self._audioMgr.destroy()
        del self._audioMgr

    def addSuit(self, suit):
        id = suit.serialNum
        self.suits.append(suit)
        if suit.type == Globals.SuitTypes.Boss:
            self.shakers.append(suit)
        self.suitsById[id] = suit

    def removeSuit(self, suit):
        id = suit.serialNum
        del self.suitsById[id]
        if suit.type == Globals.SuitTypes.Boss:
            self.shakers.remove(suit)
            self.guiMgr.showBossCode(id)
            self.guiMgr.mazeMapGui.removeSuit(suit.suit)
        self.suits.remove(suit)
        suit.destroy()

    def unload(self):
        self.toonsThatRevealedDoor = []
        for suit in self.suits:
            suit.destroy()

        del self.suits
        for id in self.drops.keys():
            self.cleanupDrop(id)

        self.__stopUpdateTask()
        self.ignoreAll()
        self.maze.destroy()
        del self.maze
        self._exit.destroy()
        del self._exit
        self.guiMgr.destroy()
        del self.guiMgr
        for player in self.players:
            player.destroy()

        del self.players
        del self.toonId2Player
        del self.localPlayer
        for pickup in self.pickups:
            pickup.destroy()

        self._destroyAudio()
        del self.distGame

    def onstage(self):
        self._exit.onstage()
        self.maze.onstage()

    def offstage(self):
        self.maze.offstage()
        self._exit.offstage()
        for suit in self.suits:
            suit.offstage()

    def startIntro(self):
        self._movie.play()
        self._audioMgr.playMusic('normal')

    def endIntro(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        base.camLens.setMinFov(ToontownGlobals.DefaultCameraFov / (4.0 / 3.0))
        for player in self.players:
            self.placePlayer(player)
            if player.toon is localAvatar:
                localAvatar.sendCurrentPosition()
            player.request('Ready')

    def startFinish(self):
        self._movie = CogdoMazeGameFinish(self.localPlayer, self._exit)
        self._movie.load()
        self._movie.play()

    def endFinish(self):
        self._movie.end()
        self._movie.unload()
        del self._movie

    def placeEntranceElevator(self, elevator):
        pos = self.maze.elevatorPos
        elevator.setPos(pos)
        tpos = self.maze.world2tile(pos[0], pos[1])
        self.guiMgr.mazeMapGui.placeEntrance(*tpos)

    def initPlayers(self):
        for toonId in self.distGame.getToonIds():
            toon = self.distGame.getToon(toonId)
            if toon is not None:
                if toon.isLocal():
                    player = CogdoMazeLocalPlayer(len(self.players),
                                                  base.localAvatar, self,
                                                  self.guiMgr)
                    self.localPlayer = player
                else:
                    player = CogdoMazePlayer(len(self.players), toon)
                self._addPlayer(player)

        return

    def start(self):
        self.accept(self.PlayerDropCollision, self.handleLocalToonMeetsDrop)
        self.accept(self.PlayerCoolerCollision,
                    self.handleLocalToonMeetsWaterCooler)
        self.accept(CogdoMazeExit.EnterEventName,
                    self.handleLocalToonEntersDoor)
        self.accept(CogdoMemo.EnterEventName, self.handleLocalToonMeetsPickup)
        if self._allowSuitsHitToons:
            self.accept(CogdoMazeSuit.COLLISION_EVENT_NAME,
                        self.handleLocalToonMeetsSuit)
        self.accept(CogdoMazePlayer.GagHitEventName, self.handleToonMeetsGag)
        self.accept(CogdoMazeSuit.GagHitEventName,
                    self.handleLocalSuitMeetsGag)
        self.accept(CogdoMazeSuit.DeathEventName, self.handleSuitDeath)
        self.accept(CogdoMazeSuit.ThinkEventName, self.handleSuitThink)
        self.accept(CogdoMazeBossSuit.ShakeEventName, self.handleBossShake)
        self.accept(CogdoMazePlayer.RemovedEventName, self._removePlayer)
        self.__startUpdateTask()
        for player in self.players:
            player.handleGameStart()
            player.request('Normal')

        for suit in self.suits:
            suit.onstage()
            suit.gameStart(self.distGame.getStartTime())

    def exit(self):
        self._quakeSfx1.stop()
        self._quakeSfx2.stop()
        for suit in self.suits:
            suit.gameEnd()

        self.ignore(self.PlayerDropCollision)
        self.ignore(self.PlayerCoolerCollision)
        self.ignore(CogdoMazeExit.EnterEventName)
        self.ignore(CogdoMemo.EnterEventName)
        self.ignore(CogdoMazeSuit.COLLISION_EVENT_NAME)
        self.ignore(CogdoMazePlayer.GagHitEventName)
        self.ignore(CogdoMazeSuit.GagHitEventName)
        self.ignore(CogdoMazeSuit.DeathEventName)
        self.ignore(CogdoMazeSuit.ThinkEventName)
        self.ignore(CogdoMazeBossSuit.ShakeEventName)
        self.ignore(CogdoMazePlayer.RemovedEventName)
        self.__stopUpdateTask()
        for timeoutTask in self.gagTimeoutTasks:
            taskMgr.remove(timeoutTask)

        self.finished = True
        self.localPlayer.handleGameExit()
        for player in self.players:
            player.request('Done')

        self.guiMgr.hideTimer()
        self.guiMgr.hideMazeMap()
        self.guiMgr.hideBossGui()

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player

    def _removePlayer(self, player):
        if player in self.players:
            self.players.remove(player)
        else:
            for cPlayer in self.players:
                if cPlayer.toon == player.toon:
                    self.players.remove(cPlayer)
                    break

        if player.toon.doId in self.toonId2Player:
            del self.toonId2Player[player.toon.doId]
        self.guiMgr.mazeMapGui.removeToon(player.toon)

    def handleToonLeft(self, toonId):
        self._removePlayer(self.toonId2Player[toonId])

    def __startUpdateTask(self):
        self.__stopUpdateTask()
        taskMgr.add(self.__updateTask, CogdoMazeGame.UpdateTaskName, 45)

    def __stopUpdateTask(self):
        taskMgr.remove(CogdoMazeGame.UpdateTaskName)
        taskMgr.remove('loopSecondQuakeSound')

    def __updateTask(self, task):
        dt = globalClock.getDt()
        self.localPlayer.update(dt)
        for player in self.players:
            curTX, curTY = self.maze.world2tileClipped(player.toon.getX(),
                                                       player.toon.getY())
            self.guiMgr.mazeMapGui.updateToon(player.toon, curTX, curTY)

        self.__updateGags()
        if Globals.QuakeSfxEnabled:
            self.__updateQuakeSound()
        for pickup in self.pickups:
            pickup.update(dt)

        MazeSuit.thinkSuits(self.suits, self.distGame.getStartTime())
        return Task.cont

    def __updateGags(self):
        remove = []
        for i in xrange(len(self.gags)):
            balloon = self.gags[i]
            if balloon.isSingleton():
                remove.append(i)
            elif balloon.getParent() == render:
                loc = self.maze.world2tile(balloon.getX(), balloon.getY())
                if not self.maze.isAccessible(loc[0], loc[1]):
                    self.removeGag(balloon)

        remove.reverse()
        for i in remove:
            self.gags.pop(i)

    def __updateQuakeSound(self):
        shake = self.localPlayer.getCameraShake()
        if shake < 1.0:
            shake = 1.0
        volume = 3.0 * shake / Globals.CameraShakeMax
        if volume > 3.0:
            volume = 3.0
        if self._quakeSfx1.getAudioSound().status(
        ) != self._quakeSfx1.getAudioSound().PLAYING:
            self._quakeSfx1.loop(volume=volume)
        else:
            self._quakeSfx1.getAudioSound().setVolume(volume)
        volume = shake * shake / Globals.CameraShakeMax
        if not self.hackTemp and self._quakeSfx2.getAudioSound().status(
        ) != self._quakeSfx2.getAudioSound().PLAYING:
            taskMgr.doMethodLater(1.5,
                                  self._quakeSfx2.loop,
                                  'loopSecondQuakeSound',
                                  extraArgs=[])
            self.hackTemp = True
        else:
            self._quakeSfx2.getAudioSound().setVolume(volume)

    def handleLocalToonMeetsSuit(self, suitType, suitNum):
        if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
            self.distGame.b_toonHitBySuit(suitType, suitNum)

    def toonHitBySuit(self, toonId, suitType, suitNum, elapsedTime=0.0):
        player = self.toonId2Player[toonId]
        if player.state == 'Normal':
            player.request('Hit', elapsedTime)

    def handleSuitDeath(self, suitType, suitNum):
        suit = self.suitsById[suitNum]
        self.dropMemos(suit)
        self.removeSuit(suit)

    def dropMemos(self, suit):
        numDrops = suit.memos
        if numDrops > 0:
            start = math.radians(random.randint(0, 360))
            step = math.radians(360.0 / numDrops)
            radius = 2.0
            for i in xrange(numDrops):
                angle = start + i * step
                x = radius * math.cos(angle) + suit.suit.getX()
                y = radius * math.sin(angle) + suit.suit.getY()
                self.generatePickup(x, y)

    def handleSuitThink(self, suit, TX, TY):
        if suit in self.shakers:
            self.guiMgr.mazeMapGui.updateSuit(suit.suit, TX, TY)
            suit.dropTimer += 1
            if suit.dropTimer >= Globals.DropFrequency:
                self.doDrop(suit)
                suit.dropTimer = 0

    def doDrop(self, boss):
        dropLoc = boss.pickRandomValidSpot()
        self.generateDrop(dropLoc[0], dropLoc[1])

    def handleBossShake(self, suit, strength):
        if Globals.BossShakeEnabled:
            self.shakeCamera(suit.suit, strength, Globals.BossMaxDistance)

    def randomDrop(self, centerTX, centerTY, radius):
        dropArray = []
        for i in xrange(1, distance):
            dropArray.append(i)
            dropArray.append(-1 * i)

        offsetTX = self.distGame.randomNumGen.choice(dropArray)
        offsetTY = self.distGame.randomNumGen.choice(dropArray)
        dropTX = sourceTX + offsetTX
        dropTY = sourceTY + offsetTY
        if self.maze.isWalkable(dropTX, dropTY):
            self.generateDrop(dropTX, dropTY)

    def generateDrop(self, TX, TY):
        drop = self.maze.tile2world(TX, TY)
        ival = self.createDrop(drop[0], drop[1])
        ival.start()

    def createDrop(self, x, y):
        self.dropCounter = self.dropCounter + 1
        id = self.dropCounter
        drop = CogdoMazeDrop(self, id, x, y)
        self.drops[id] = drop
        return drop.getDropIval()

    def cleanupDrop(self, id):
        if id in self.drops.keys():
            drop = self.drops[id]
            drop.destroy()
            del self.drops[id]

    def dropHit(self, node, id):
        if self.finished:
            return
        if Globals.DropShakeEnabled:
            self.shakeCamera(node, Globals.DropShakeStrength,
                             Globals.DropMaxDistance)

    def shakeCamera(self, node, strength, distanceCutoff=60.0):
        distance = self.localPlayer.toon.getDistance(node)
        shake = strength * (1 - distance / distanceCutoff)
        if shake > 0:
            self.localPlayer.shakeCamera(shake)

    def handleLocalToonMeetsDrop(self, collEntry):
        fcabinet = collEntry.getIntoNodePath()
        if fcabinet.getTag('isFalling') == str('False'):
            return
        if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
            self.distGame.b_toonHitByDrop()

    def toonHitByDrop(self, toonId):
        player = self.toonId2Player[toonId]
        player.hitByDrop()

    def handleLocalToonMeetsGagPickup(self, collEntry):
        if self.localPlayer.equippedGag != None:
            return
        else:
            into = collEntry.getIntoNodePath()
            if into.hasPythonTag('id'):
                id = into.getPythonTag('id')
                self.distGame.d_sendRequestGagPickUp(id)
            return

    def hasGag(self, toonId, elapsedTime=0.0):
        player = self.toonId2Player[toonId]
        player.equipGag()

    def handleLocalToonMeetsWaterCooler(self, collEntry):
        if self.localPlayer.equippedGag != None:
            return
        else:
            if self.lastBalloonTimestamp and globalClock.getFrameTime(
            ) - self.lastBalloonTimestamp < Globals.BalloonDelay:
                return
            collNode = collEntry.getIntoNode()
            waterCooler = self._collNode2waterCooler[collNode]
            self.lastBalloonTimestamp = globalClock.getFrameTime()
            self.distGame.d_sendRequestGag(waterCooler.serialNum)
            return

    def requestUseGag(self, x, y, h):
        self.distGame.b_toonUsedGag(x, y, h)

    def toonUsedGag(self, toonId, x, y, h, elapsedTime=0.0):
        player = self.toonId2Player[toonId]
        heading = h
        pos = Point3(x, y, 0)
        gag = player.showToonThrowingGag(heading, pos)
        if gag is not None:
            self.gags.append(gag)
        return

    def handleToonMeetsGag(self, playerId, gag):
        self.removeGag(gag)
        self.distGame.b_toonHitByGag(playerId)

    def toonHitByGag(self, toonId, hitToon, elapsedTime=0.0):
        if toonId not in self.toonId2Player.keys(
        ) or hitToon not in self.toonId2Player.keys():
            return
        player = self.toonId2Player[hitToon]
        player.hitByGag()

    def handleLocalSuitMeetsGag(self, suitType, suitNum, gag):
        self.removeGag(gag)
        self.localPlayer.hitSuit(suitType)
        self.distGame.b_suitHitByGag(suitType, suitNum)

    def suitHitByGag(self, toonId, suitType, suitNum, elapsedTime=0.0):
        if suitType == Globals.SuitTypes.Boss:
            self.guiMgr.showBossHit(suitNum)
        if suitNum in self.suitsById.keys():
            suit = self.suitsById[suitNum]
            suit.hitByGag()

    def removeGag(self, gag):
        gag.detachNode()

    def toonRevealsDoor(self, toonId):
        self._exit.revealed = True

    def openDoor(self, timeLeft):
        self._audioMgr.playMusic('timeRunningOut')
        if not self._exit.isOpen():
            self._exit.open()
            self.localPlayer.handleOpenDoor(self._exit)
            self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)
            self.guiMgr.mazeMapGui.showExit()
            self.guiMgr.mazeMapGui.revealAll()

    def countdown(self, timeLeft):
        self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)

    def timeAlert(self):
        self._audioMgr.playMusic('timeRunningOut')

    def _handleTimerExpired(self):
        self.localPlayer.request('Done')

    def toonEntersDoor(self, toonId):
        player = self.toonId2Player[toonId]
        self.guiMgr.mazeMapGui.removeToon(player.toon)
        self._exit.playerEntersDoor(player)
        self.localPlayer.handleToonEntersDoor(toonId, self._exit)
        player.request('Done')

    def generatePickup(self, x, y):
        pickup = CogdoMemo(len(self.pickups), pitch=-90)
        self.pickups.append(pickup)
        pickup.reparentTo(self.maze.maze)
        pickup.setPos(x, y, 1)
        pickup.enable()

    def handleLocalToonMeetsPickup(self, pickup):
        pickup.disable()
        self.distGame.d_sendRequestPickUp(pickup.serialNum)

    def pickUp(self, toonId, pickupNum, elapsedTime=0.0):
        self.notify.debugCall()
        player = self.toonId2Player[toonId]
        pickup = self.pickups[pickupNum]
        if not pickup.wasPickedUp():
            pickup.pickUp(player.toon, elapsedTime)
            self.localPlayer.handlePickUp(toonId)

    def placePlayer(self, player):
        toonIds = self.distGame.getToonIds()
        if player.toon.doId not in toonIds:
            return
        i = toonIds.index(player.toon.doId)
        x = int(self.maze.width / 2.0) - int(len(toonIds) / 2.0) + i
        y = 2
        while not self.maze.isAccessible(x, y):
            y += 1

        pos = self.maze.tile2world(x, y)
        player.toon.setPos(pos[0], pos[1], 0)
        self.guiMgr.mazeMapGui.addToon(player.toon, x, y)

    def handleLocalToonEntersDoor(self, door):
        localToonId = self.localPlayer.toon.doId
        if self._exit.isOpen():
            self.distGame.d_sendRequestAction(Globals.GameActions.EnterDoor, 0)
        else:
            if localToonId not in self.toonsThatRevealedDoor:
                self.toonsThatRevealedDoor.append(localToonId)
                self.localPlayer.handleToonRevealsDoor(localToonId, self._exit)
            if not self._exit.revealed:
                self.toonRevealsDoor(localToonId)
                self.distGame.d_sendRequestAction(
                    Globals.GameActions.RevealDoor, 0)

    def handleToonWentSad(self, toonId):
        if toonId == self.localPlayer.toon.doId:
            for player in self.players:
                player.removeGag()

        elif toonId in self.toonId2Player.keys():
            player = self.toonId2Player[toonId]
            player.removeGag()

    def handleToonDisconnected(self, toonId):
        if toonId == self.localPlayer.toon.doId:
            pass
        elif toonId in self.toonId2Player.keys():
            player = self.toonId2Player[toonId]
            self._removePlayer(player)
 def _initAudio(self):
     self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles, Globals.SfxFiles, camera, cutoff=Globals.AudioCutoff)
     self._quakeSfx1 = self._audioMgr.createSfx('quake')
     self._quakeSfx2 = self._audioMgr.createSfx('quake')
class CogdoMazeGame(DirectObject):
    notify = directNotify.newCategory('CogdoMazeGame')
    UpdateTaskName = 'CogdoMazeGameUpdateTask'
    RemoveGagTaskName = 'CogdoMazeGameRemoveGag'
    PlayerCoolerCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName, Globals.WaterCoolerCollisionName)
    PlayerDropCollision = '%s-into-%s' % (Globals.LocalPlayerCollisionName, Globals.DropCollisionName)

    def __init__(self, distGame):
        self.distGame = distGame
        self._allowSuitsHitToons = base.config.GetBool('cogdomaze-suits-hit-toons', True)

    def load(self, cogdoMazeFactory, numSuits, bossCode):
        self._initAudio()
        self.maze = cogdoMazeFactory.createCogdoMaze()
        suitSpawnSpot = self.maze.createRandomSpotsList(numSuits, self.distGame.randomNumGen)
        self.guiMgr = CogdoMazeGuiManager(self.maze, bossCode)
        self.suits = []
        self.suitsById = {}
        self.shakers = []
        self.toonsThatRevealedDoor = []
        self.quake = 0
        self.dropCounter = 0
        self.drops = {}
        self.gagCounter = 0
        self.gags = []
        self.hackTemp = False
        self.dropGen = RandomNumGen(self.distGame.doId)
        self.gagTimeoutTasks = []
        self.finished = False
        self.lastBalloonTimestamp = None
        difficulty = self.distGame.getDifficulty()
        serialNum = 0
        for i in range(numSuits[0]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeBossSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[0][i])
            self.addSuit(suit)
            self.guiMgr.mazeMapGui.addSuit(suit.suit)
            serialNum += 1

        for i in range(numSuits[1]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeFastMinionSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[1][i])
            self.addSuit(suit)
            serialNum += 1

        for i in range(numSuits[2]):
            suitRng = RandomNumGen(self.distGame.doId + serialNum * 10)
            suit = CogdoMazeSlowMinionSuit(serialNum, self.maze, suitRng, difficulty, startTile=suitSpawnSpot[2][i])
            self.addSuit(suit)
            serialNum += 1

        self.toonId2Door = {}
        self.keyIdToKey = {}
        self.players = []
        self.toonId2Player = {}
        cellPos = (int(self.maze.width / 2), self.maze.height - 1)
        pos = self.maze.tile2world(*cellPos)
        self._exit = CogdoMazeExit()
        self._exit.reparentTo(render)
        self._exit.setPos(self.maze.exitPos)
        self._exit.stash()
        self.guiMgr.mazeMapGui.placeExit(*cellPos)
        self._collNode2waterCooler = {}
        for waterCooler in self.maze.getWaterCoolers():
            pos = waterCooler.getPos(render)
            tpos = self.maze.world2tile(pos[0], pos[1])
            self.guiMgr.mazeMapGui.addWaterCooler(*tpos)
            self._collNode2waterCooler[waterCooler.collNode] = waterCooler

        self.pickups = []
        self.gagModel = CogdoUtil.loadMazeModel('waterBalloon')
        self._movie = CogdoMazeGameIntro(self.maze, self._exit, self.distGame.randomNumGen)
        self._movie.load()
        return

    def _initAudio(self):
        self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles, Globals.SfxFiles, camera, cutoff=Globals.AudioCutoff)
        self._quakeSfx1 = self._audioMgr.createSfx('quake')
        self._quakeSfx2 = self._audioMgr.createSfx('quake')

    def _destroyAudio(self):
        self._quakeSfx1.destroy()
        self._quakeSfx2.destroy()
        del self._quakeSfx1
        del self._quakeSfx2
        self._audioMgr.destroy()
        del self._audioMgr

    def addSuit(self, suit):
        id = suit.serialNum
        self.suits.append(suit)
        if suit.type == Globals.SuitTypes.Boss:
            self.shakers.append(suit)
        self.suitsById[id] = suit

    def removeSuit(self, suit):
        id = suit.serialNum
        del self.suitsById[id]
        if suit.type == Globals.SuitTypes.Boss:
            self.shakers.remove(suit)
            self.guiMgr.showBossCode(id)
            self.guiMgr.mazeMapGui.removeSuit(suit.suit)
        self.suits.remove(suit)
        suit.destroy()

    def unload(self):
        self.toonsThatRevealedDoor = []
        for suit in self.suits:
            suit.destroy()

        del self.suits
        for id in self.drops.keys():
            self.cleanupDrop(id)

        self.__stopUpdateTask()
        self.ignoreAll()
        self.maze.destroy()
        del self.maze
        self._exit.destroy()
        del self._exit
        self.guiMgr.destroy()
        del self.guiMgr
        for player in self.players:
            player.destroy()

        del self.players
        del self.toonId2Player
        del self.localPlayer
        for pickup in self.pickups:
            pickup.destroy()

        self._destroyAudio()
        del self.distGame

    def onstage(self):
        self._exit.onstage()
        self.maze.onstage()

    def offstage(self):
        self.maze.offstage()
        self._exit.offstage()
        for suit in self.suits:
            suit.offstage()

    def startIntro(self):
        self._movie.play()
        self._audioMgr.playMusic('normal')

    def endIntro(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        for player in self.players:
            self.placePlayer(player)
            if player.toon is localAvatar:
                localAvatar.sendCurrentPosition()
            player.request('Ready')

    def startFinish(self):
        self._movie = CogdoMazeGameFinish(self.localPlayer, self._exit)
        self._movie.load()
        self._movie.play()

    def endFinish(self):
        self._movie.end()
        self._movie.unload()
        del self._movie

    def placeEntranceElevator(self, elevator):
        pos = self.maze.elevatorPos
        elevator.setPos(pos)
        tpos = self.maze.world2tile(pos[0], pos[1])
        self.guiMgr.mazeMapGui.placeEntrance(*tpos)

    def initPlayers(self):
        for toonId in self.distGame.getToonIds():
            toon = self.distGame.getToon(toonId)
            if toon is not None:
                if toon.isLocal():
                    player = CogdoMazeLocalPlayer(len(self.players), base.localAvatar, self, self.guiMgr)
                    self.localPlayer = player
                else:
                    player = CogdoMazePlayer(len(self.players), toon)
                self._addPlayer(player)

        return

    def start(self):
        self.accept(self.PlayerDropCollision, self.handleLocalToonMeetsDrop)
        self.accept(self.PlayerCoolerCollision, self.handleLocalToonMeetsWaterCooler)
        self.accept(CogdoMazeExit.EnterEventName, self.handleLocalToonEntersDoor)
        self.accept(CogdoMemo.EnterEventName, self.handleLocalToonMeetsPickup)
        if self._allowSuitsHitToons:
            self.accept(CogdoMazeSuit.COLLISION_EVENT_NAME, self.handleLocalToonMeetsSuit)
        self.accept(CogdoMazePlayer.GagHitEventName, self.handleToonMeetsGag)
        self.accept(CogdoMazeSuit.GagHitEventName, self.handleLocalSuitMeetsGag)
        self.accept(CogdoMazeSuit.DeathEventName, self.handleSuitDeath)
        self.accept(CogdoMazeSuit.ThinkEventName, self.handleSuitThink)
        self.accept(CogdoMazeBossSuit.ShakeEventName, self.handleBossShake)
        self.accept(CogdoMazePlayer.RemovedEventName, self._removePlayer)
        self.__startUpdateTask()
        for player in self.players:
            player.handleGameStart()
            player.request('Normal')

        for suit in self.suits:
            suit.onstage()
            suit.gameStart(self.distGame.getStartTime())

    def exit(self):
        self._quakeSfx1.stop()
        self._quakeSfx2.stop()
        for suit in self.suits:
            suit.gameEnd()

        self.ignore(self.PlayerDropCollision)
        self.ignore(self.PlayerCoolerCollision)
        self.ignore(CogdoMazeExit.EnterEventName)
        self.ignore(CogdoMemo.EnterEventName)
        self.ignore(CogdoMazeSuit.COLLISION_EVENT_NAME)
        self.ignore(CogdoMazePlayer.GagHitEventName)
        self.ignore(CogdoMazeSuit.GagHitEventName)
        self.ignore(CogdoMazeSuit.DeathEventName)
        self.ignore(CogdoMazeSuit.ThinkEventName)
        self.ignore(CogdoMazeBossSuit.ShakeEventName)
        self.ignore(CogdoMazePlayer.RemovedEventName)
        self.__stopUpdateTask()
        for timeoutTask in self.gagTimeoutTasks:
            taskMgr.remove(timeoutTask)

        self.finished = True
        self.localPlayer.handleGameExit()
        for player in self.players:
            player.request('Done')

        self.guiMgr.hideTimer()
        self.guiMgr.hideMazeMap()
        self.guiMgr.hideBossGui()

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player

    def _removePlayer(self, player):
        if player in self.players:
            self.players.remove(player)
        else:
            for cPlayer in self.players:
                if cPlayer.toon == player.toon:
                    self.players.remove(cPlayer)
                    break

        if self.toonId2Player.has_key(player.toon.doId):
            del self.toonId2Player[player.toon.doId]
        self.guiMgr.mazeMapGui.removeToon(player.toon)

    def handleToonLeft(self, toonId):
        self._removePlayer(self.toonId2Player[toonId])

    def __startUpdateTask(self):
        self.__stopUpdateTask()
        taskMgr.add(self.__updateTask, CogdoMazeGame.UpdateTaskName, 45)

    def __stopUpdateTask(self):
        taskMgr.remove(CogdoMazeGame.UpdateTaskName)
        taskMgr.remove('loopSecondQuakeSound')

    def __updateTask(self, task):
        dt = globalClock.getDt()
        self.localPlayer.update(dt)
        for player in self.players:
            curTX, curTY = self.maze.world2tileClipped(player.toon.getX(), player.toon.getY())
            self.guiMgr.mazeMapGui.updateToon(player.toon, curTX, curTY)

        self.__updateGags()
        if Globals.QuakeSfxEnabled:
            self.__updateQuakeSound()
        for pickup in self.pickups:
            pickup.update(dt)

        MazeSuit.thinkSuits(self.suits, self.distGame.getStartTime())
        return Task.cont

    def __updateGags(self):
        remove = []
        for i in range(len(self.gags)):
            balloon = self.gags[i]
            if balloon.isSingleton():
                remove.append(i)
            elif balloon.getParent() == render:
                loc = self.maze.world2tile(balloon.getX(), balloon.getY())
                if not self.maze.isAccessible(loc[0], loc[1]):
                    self.removeGag(balloon)

        remove.reverse()
        for i in remove:
            self.gags.pop(i)

    def __updateQuakeSound(self):
        shake = self.localPlayer.getCameraShake()
        if shake < 1.0:
            shake = 1.0
        volume = 3.0 * shake / Globals.CameraShakeMax
        if volume > 3.0:
            volume = 3.0
        if self._quakeSfx1.getAudioSound().status() != self._quakeSfx1.getAudioSound().PLAYING:
            self._quakeSfx1.loop(volume=volume)
        else:
            self._quakeSfx1.getAudioSound().setVolume(volume)
        volume = shake * shake / Globals.CameraShakeMax
        if not self.hackTemp and self._quakeSfx2.getAudioSound().status() != self._quakeSfx2.getAudioSound().PLAYING:
            taskMgr.doMethodLater(1.5, self._quakeSfx2.loop, 'loopSecondQuakeSound', extraArgs=[])
            self.hackTemp = True
        else:
            self._quakeSfx2.getAudioSound().setVolume(volume)

    def handleLocalToonMeetsSuit(self, suitType, suitNum):
        if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
            self.distGame.b_toonHitBySuit(suitType, suitNum)

    def toonHitBySuit(self, toonId, suitType, suitNum, elapsedTime = 0.0):
        player = self.toonId2Player[toonId]
        if player.state == 'Normal':
            player.request('Hit', elapsedTime)

    def handleSuitDeath(self, suitType, suitNum):
        suit = self.suitsById[suitNum]
        self.dropMemos(suit)
        self.removeSuit(suit)

    def dropMemos(self, suit):
        numDrops = suit.memos
        if numDrops > 0:
            start = math.radians(random.randint(0, 360))
            step = math.radians(360.0 / numDrops)
            radius = 2.0
            for i in range(numDrops):
                angle = start + i * step
                x = radius * math.cos(angle) + suit.suit.getX()
                y = radius * math.sin(angle) + suit.suit.getY()
                self.generatePickup(x, y)

    def handleSuitThink(self, suit, TX, TY):
        if suit in self.shakers:
            self.guiMgr.mazeMapGui.updateSuit(suit.suit, TX, TY)
            suit.dropTimer += 1
            if suit.dropTimer >= Globals.DropFrequency:
                self.doDrop(suit)
                suit.dropTimer = 0

    def doDrop(self, boss):
        dropLoc = boss.pickRandomValidSpot()
        self.generateDrop(dropLoc[0], dropLoc[1])

    def handleBossShake(self, suit, strength):
        if Globals.BossShakeEnabled:
            self.shakeCamera(suit.suit, strength, Globals.BossMaxDistance)

    def randomDrop(self, centerTX, centerTY, radius):
        dropArray = []
        for i in xrange(1, distance):
            dropArray.append(i)
            dropArray.append(-1 * i)

        offsetTX = self.distGame.randomNumGen.choice(dropArray)
        offsetTY = self.distGame.randomNumGen.choice(dropArray)
        dropTX = sourceTX + offsetTX
        dropTY = sourceTY + offsetTY
        if self.maze.isWalkable(dropTX, dropTY):
            self.generateDrop(dropTX, dropTY)

    def generateDrop(self, TX, TY):
        drop = self.maze.tile2world(TX, TY)
        ival = self.createDrop(drop[0], drop[1])
        ival.start()

    def createDrop(self, x, y):
        self.dropCounter = self.dropCounter + 1
        id = self.dropCounter
        drop = CogdoMazeDrop(self, id, x, y)
        self.drops[id] = drop
        return drop.getDropIval()

    def cleanupDrop(self, id):
        if id in self.drops.keys():
            drop = self.drops[id]
            drop.destroy()
            del self.drops[id]

    def dropHit(self, node, id):
        if self.finished:
            return
        if Globals.DropShakeEnabled:
            self.shakeCamera(node, Globals.DropShakeStrength, Globals.DropMaxDistance)

    def shakeCamera(self, node, strength, distanceCutoff = 60.0):
        distance = self.localPlayer.toon.getDistance(node)
        shake = strength * (1 - distance / distanceCutoff)
        if shake > 0:
            self.localPlayer.shakeCamera(shake)

    def handleLocalToonMeetsDrop(self, collEntry):
        fcabinet = collEntry.getIntoNodePath()
        if fcabinet.getTag('isFalling') == str('False'):
            return
        if self.localPlayer.state == 'Normal' and not self.localPlayer.invulnerable:
            self.distGame.b_toonHitByDrop()

    def toonHitByDrop(self, toonId):
        player = self.toonId2Player[toonId]
        player.hitByDrop()

    def handleLocalToonMeetsGagPickup(self, collEntry):
        if self.localPlayer.equippedGag != None:
            return
        into = collEntry.getIntoNodePath()
        if into.hasPythonTag('id'):
            id = into.getPythonTag('id')
            self.distGame.d_sendRequestGagPickUp(id)
        return

    def hasGag(self, toonId, elapsedTime = 0.0):
        player = self.toonId2Player[toonId]
        player.equipGag()

    def handleLocalToonMeetsWaterCooler(self, collEntry):
        if self.localPlayer.equippedGag != None:
            return
        if self.lastBalloonTimestamp and globalClock.getFrameTime() - self.lastBalloonTimestamp < Globals.BalloonDelay:
            return
        collNode = collEntry.getIntoNode()
        waterCooler = self._collNode2waterCooler[collNode]
        self.lastBalloonTimestamp = globalClock.getFrameTime()
        self.distGame.d_sendRequestGag(waterCooler.serialNum)
        return

    def requestUseGag(self, x, y, h):
        self.distGame.b_toonUsedGag(x, y, h)

    def toonUsedGag(self, toonId, x, y, h, elapsedTime = 0.0):
        player = self.toonId2Player[toonId]
        heading = h
        pos = Point3(x, y, 0)
        gag = player.showToonThrowingGag(heading, pos)
        if gag is not None:
            self.gags.append(gag)
        return

    def handleToonMeetsGag(self, playerId, gag):
        self.removeGag(gag)
        self.distGame.b_toonHitByGag(playerId)

    def toonHitByGag(self, toonId, hitToon, elapsedTime = 0.0):
        if toonId not in self.toonId2Player.keys() or hitToon not in self.toonId2Player.keys():
            return
        player = self.toonId2Player[hitToon]
        player.hitByGag()

    def handleLocalSuitMeetsGag(self, suitType, suitNum, gag):
        self.removeGag(gag)
        self.localPlayer.hitSuit(suitType)
        self.distGame.b_suitHitByGag(suitType, suitNum)

    def suitHitByGag(self, toonId, suitType, suitNum, elapsedTime = 0.0):
        if suitType == Globals.SuitTypes.Boss:
            self.guiMgr.showBossHit(suitNum)
        if suitNum in self.suitsById.keys():
            suit = self.suitsById[suitNum]
            suit.hitByGag()

    def removeGag(self, gag):
        gag.detachNode()

    def toonRevealsDoor(self, toonId):
        self._exit.revealed = True

    def openDoor(self, timeLeft):
        self._audioMgr.playMusic('timeRunningOut')
        if not self._exit.isOpen():
            self._exit.open()
            self.localPlayer.handleOpenDoor(self._exit)
            self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)
            self.guiMgr.mazeMapGui.showExit()
            self.guiMgr.mazeMapGui.revealAll()

    def countdown(self, timeLeft):
        self.guiMgr.showTimer(timeLeft, self._handleTimerExpired)

    def timeAlert(self):
        self._audioMgr.playMusic('timeRunningOut')

    def _handleTimerExpired(self):
        self.localPlayer.request('Done')

    def toonEntersDoor(self, toonId):
        player = self.toonId2Player[toonId]
        self.guiMgr.mazeMapGui.removeToon(player.toon)
        self._exit.playerEntersDoor(player)
        self.localPlayer.handleToonEntersDoor(toonId, self._exit)
        player.request('Done')

    def generatePickup(self, x, y):
        pickup = CogdoMemo(len(self.pickups), pitch=-90)
        self.pickups.append(pickup)
        pickup.reparentTo(self.maze.maze)
        pickup.setPos(x, y, 1)
        pickup.enable()

    def handleLocalToonMeetsPickup(self, pickup):
        pickup.disable()
        self.distGame.d_sendRequestPickUp(pickup.serialNum)

    def pickUp(self, toonId, pickupNum, elapsedTime = 0.0):
        self.notify.debugCall()
        player = self.toonId2Player[toonId]
        pickup = self.pickups[pickupNum]
        if not pickup.wasPickedUp():
            pickup.pickUp(player.toon, elapsedTime)
            self.localPlayer.handlePickUp(toonId)

    def placePlayer(self, player):
        toonIds = self.distGame.getToonIds()
        if player.toon.doId not in toonIds:
            return
        i = toonIds.index(player.toon.doId)
        x = int(self.maze.width / 2.0) - int(len(toonIds) / 2.0) + i
        y = 2
        while not self.maze.isAccessible(x, y):
            y += 1

        pos = self.maze.tile2world(x, y)
        player.toon.setPos(pos[0], pos[1], 0)
        self.guiMgr.mazeMapGui.addToon(player.toon, x, y)

    def handleLocalToonEntersDoor(self, door):
        localToonId = self.localPlayer.toon.doId
        if self._exit.isOpen():
            self.distGame.d_sendRequestAction(Globals.GameActions.EnterDoor, 0)
        else:
            if localToonId not in self.toonsThatRevealedDoor:
                self.toonsThatRevealedDoor.append(localToonId)
                self.localPlayer.handleToonRevealsDoor(localToonId, self._exit)
            if not self._exit.revealed:
                self.toonRevealsDoor(localToonId)
                self.distGame.d_sendRequestAction(Globals.GameActions.RevealDoor, 0)

    def handleToonWentSad(self, toonId):
        if toonId == self.localPlayer.toon.doId:
            for player in self.players:
                player.removeGag()

        elif toonId in self.toonId2Player.keys():
            player = self.toonId2Player[toonId]
            player.removeGag()

    def handleToonDisconnected(self, toonId):
        if toonId == self.localPlayer.toon.doId:
            pass
        elif toonId in self.toonId2Player.keys():
            player = self.toonId2Player[toonId]
            self._removePlayer(player)
Exemplo n.º 10
0
class CogdoFlyingGame(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingGame')
    UpdateTaskName = 'CogdoFlyingGameUpdate'
    FirstPressOfCtrlTaskName = 'FirstPressOfCtrlTask'

    def __init__(self, distGame):
        self.distGame = distGame
        self.toonId2Player = {}
        self.players = []
        self.index2LegalEagle = {}
        self.legalEagles = []
        self.isGameComplete = False
        self._hints = {'targettedByEagle': False, 'invulnerable': False}

    def _initLegalEagles(self):
        nestIndex = 1
        nests = self.level.root.findAllMatches('**/%s;+s' % Globals.Level.LegalEagleNestName)
        for nest in nests:
            legalEagle = CogdoFlyingLegalEagle(nest, nestIndex)
            self.legalEagles.append(legalEagle)
            self.index2LegalEagle[nestIndex] = legalEagle
            nestIndex += 1

    def initPlayers(self):
        for toonId in self.distGame.getToonIds():
            toon = self.distGame.getToon(toonId)
            i = self.distGame.getToonIds().index(toon.doId)
            if toon is not None:
                if toon.isLocal():
                    player = CogdoFlyingLocalPlayer(toon, self, self.level, self.guiMgr)
                    self.localPlayer = player
                    self.localPlayer.setPlayerNumber(i)
                else:
                    player = CogdoFlyingPlayer(toon)
                player.enable()
                self._addPlayer(player)
                self.guiMgr.addToonToProgressMeter(toon)

        return

    def placeEntranceElevator(self, elevator):
        loc = self.level.startPlatform._model.find('**/door_loc')
        offset = loc.getPos(render)
        elevator.setPos(render, offset)

    def load(self):
        self.accept(self.distGame.getRemoteActionEventName(), self.handleRemoteAction)
        self.audioMgr = CogdoGameAudioManager(Globals.Audio.MusicFiles, Globals.Audio.SfxFiles, base.localAvatar, cutoff=Globals.Audio.Cutoff)
        factory = CogdoFlyingLevelFactory(render, Globals.Level.QuadLengthUnits, Globals.Level.QuadVisibilityAhead, Globals.Level.QuadVisibilityBehind, rng=RandomNumGen(self.distGame.doId))
        self.level = factory.createLevel(self.distGame.getSafezoneId())
        self.level.setCamera(camera)
        self.guiMgr = CogdoFlyingGuiManager(self.level)
        self.levelFog = factory.createLevelFog()
        self._initLegalEagles()

    def unload(self):
        self.guiMgr.destroy()
        del self.guiMgr
        self.__stopUpdateTask()
        for player in self.players:
            player.unload()

        del self.players[:]
        self.toonId2Player.clear()
        del self.localPlayer
        for eagle in self.legalEagles:
            eagle.destroy()

        del self.legalEagles[:]
        self.index2LegalEagle.clear()
        self.levelFog.destroy()
        del self.levelFog
        self.level.destroy()
        del self.level
        self.audioMgr.destroy()
        del self.audioMgr
        self.ignoreAll()
        del self.distGame

    def onstage(self):
        self.level.onstage()
        self.levelFog.setVisible(True)
        for eagle in self.legalEagles:
            eagle.onstage()

        self.localPlayer.request('Inactive')

    def offstage(self):
        self.__stopUpdateTask()
        for eagle in self.legalEagles:
            eagle.offstage()

        self.level.offstage()
        self.levelFog.setVisible(False)

    def startIntro(self):
        self._movie = CogdoFlyingGameIntro(self.level, RandomNumGen(self.distGame.doId))
        self._movie.load()
        self._movie.play()
        self.audioMgr.playMusic('normal')

    def endIntro(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        base.camLens.setMinFov(ToontownGlobals.DefaultCameraFov / (4.0 / 3.0))
        self.localPlayer.ready()
        self.level.update(0.0)

    def startFinish(self):
        self._movie = CogdoFlyingGameFinish(self.level, self.players)
        self._movie.load()
        self._movie.play()
        self.audioMgr.playMusic('end')

    def endFinish(self):
        self._movie.end()
        self._movie.unload()
        del self._movie
        self.audioMgr.stopMusic()

    def start(self):
        self.level.start(self.distGame.getStartTime())
        self.accept(CogdoFlyingObstacle.EnterEventName, self.handleLocalToonEnterObstacle)
        self.accept(CogdoFlyingObstacle.ExitEventName, self.handleLocalToonExitObstacle)
        self.accept(CogdoFlyingGatherable.EnterEventName, self.handleLocalToonEnterGatherable)
        self.accept(CogdoFlyingLegalEagle.RequestAddTargetEventName, self.handleLocalToonEnterLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.RequestAddTargetAgainEventName, self.handleLocalToonAgainLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.RequestRemoveTargetEventName, self.handleLocalToonExitLegalEagleInterest)
        self.accept(CogdoFlyingLegalEagle.EnterLegalEagle, self.handleLocalToonEnterLegalEagle)
        self.accept(CogdoFlyingLegalEagle.ChargingToAttackEventName, self.handlePlayerBackpackAttacked)
        self.accept(CogdoFlyingLegalEagle.LockOnToonEventName, self.handlePlayerBackpackTargeted)
        self.accept(CogdoFlyingLegalEagle.CooldownEventName, self.handlePlayerBackpackNormal)
        self.accept(CogdoFlyingGuiManager.EagleTargetingLocalPlayerEventName, self.handleLocalPlayerTargetedByEagle)
        self.accept(CogdoFlyingGuiManager.EagleAttackingLocalPlayerEventName, self.handleLocalPlayerAttackedByEagle)
        self.accept(CogdoFlyingGuiManager.ClearMessageDisplayEventName, self.handleClearGuiMessage)
        self.accept(CogdoFlyingGuiManager.InvulnerableEventName, self.handleLocalPlayerInvulnerable)
        self.acceptOnce(CogdoFlyingGuiManager.FirstPressOfCtrlEventName, self.handleLocalPlayerFirstPressOfCtrl)
        self.acceptOnce(CogdoFlyingGuiManager.PickedUpFirstPropellerEventName, self.handleLocalPlayerPickedUpFirstPropeller)
        self.acceptOnce(CogdoFlyingGuiManager.StartRunningOutOfTimeMusicEventName, self.handleTimeRunningOut)
        self.acceptOnce(CogdoFlyingLocalPlayer.PlayWaitingMusicEventName, self.handlePlayWaitingMusic)
        self.acceptOnce(CogdoFlyingLocalPlayer.RanOutOfTimeEventName, self.handleLocalPlayerRanOutOfTime)
        self.__startUpdateTask()
        self.isGameComplete = False
        if 0 and base.config.GetBool('schellgames-dev', True):
            self.acceptOnce('end', self.guiMgr.forceTimerDone)

            def toggleFog():
                self.levelFog.setVisible(not self.levelFog.isVisible())

            self.accept('home', toggleFog)
        for eagle in self.legalEagles:
            eagle.gameStart(self.distGame.getStartTime())

        for player in self.players:
            player.start()

        self.guiMgr.onstage()
        if not Globals.Dev.InfiniteTimeLimit:
            self.guiMgr.startTimer(Globals.Gameplay.SecondsUntilGameOver, self._handleTimerExpired, keepHidden=False)

    def exit(self):
        self.ignore(CogdoFlyingObstacle.EnterEventName)
        self.ignore(CogdoFlyingObstacle.ExitEventName)
        self.ignore(CogdoFlyingGatherable.EnterEventName)
        self.ignore(CogdoFlyingLegalEagle.ChargingToAttackEventName)
        self.ignore(CogdoFlyingLegalEagle.LockOnToonEventName)
        self.ignore(CogdoFlyingLegalEagle.CooldownEventName)
        self.ignore(CogdoFlyingLocalPlayer.RanOutOfTimeEventName)
        taskMgr.remove(CogdoFlyingGame.FirstPressOfCtrlTaskName)
        self.__stopUpdateTask()
        self.ignore(CogdoFlyingLegalEagle.EnterLegalEagle)
        self.ignore(CogdoFlyingLegalEagle.RequestAddTargetEventName)
        self.ignore(CogdoFlyingLegalEagle.RequestAddTargetAgainEventName)
        self.ignore(CogdoFlyingLegalEagle.RequestRemoveTargetEventName)
        self.ignore(CogdoFlyingLocalPlayer.PlayWaitingMusicEventName)
        if 0 and base.config.GetBool('schellgames-dev', True):
            self.ignore('end')
            self.ignore('home')
        self.level.update(0.0)
        for eagle in self.legalEagles:
            eagle.gameEnd()

        for player in self.players:
            player.exit()

        self.guiMgr.offstage()

    def _handleTimerExpired(self):
        self.localPlayer.handleTimerExpired()

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player
        toon = player.toon
        self.accept(toon.uniqueName('disable'), self._removePlayer, extraArgs=[toon.doId])

    def _removePlayer(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            self.players.remove(player)
            del self.toonId2Player[toonId]
            self.guiMgr.removeToonFromProgressMeter(player.toon)
            player.exit()
            player.unload()

    def setToonSad(self, toonId):
        player = self.toonId2Player[toonId]
        self.forceClearLegalEagleInterestInToon(toonId)
        if player == self.localPlayer:
            player.goSad()
            self.exit()
        else:
            player.exit()

    def setToonDisconnect(self, toonId):
        player = self.toonId2Player[toonId]
        self.forceClearLegalEagleInterestInToon(toonId)
        if player == self.localPlayer:
            self.exit()
        else:
            player.exit()

    def handleRemoteAction(self, action, data):
        if data != self.localPlayer.toon.doId:
            if action == Globals.AI.GameActions.GotoWinState:
                if self.localPlayer.state in ('WaitingForWin', ):
                    self.localPlayer.request('Win')

    def toonDied(self, toonId, elapsedTime):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.died(elapsedTime)
        return

    def toonSpawn(self, toonId, elapsedTime):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.spawn(elapsedTime)
        return

    def toonResetBlades(self, toonId):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.resetBlades()
        return

    def toonSetBlades(self, toonId, fuelState):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.setBlades(fuelState)
        return

    def toonBladeLost(self, toonId):
        player = self.toonId2Player[toonId]
        if player is not None:
            player.bladeLost()
        return

    def handleLocalToonEnterGatherable(self, gatherable):
        if gatherable.wasPickedUp():
            return
        if gatherable.isPowerUp() and gatherable.wasPickedUpByToon(self.localPlayer.toon):
            return
        if gatherable.type in [Globals.Level.GatherableTypes.LaffPowerup, Globals.Level.GatherableTypes.InvulPowerup]:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)
        elif gatherable.type == Globals.Level.GatherableTypes.Memo:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)
            gatherable.disable()
        elif gatherable.type == Globals.Level.GatherableTypes.Propeller and self.localPlayer.fuel < 1.0:
            self.distGame.d_sendRequestPickup(gatherable.serialNum, gatherable.type)

    def pickUp(self, toonId, pickupNum, elapsedTime=0.0):
        self.notify.debugCall()
        player = self.toonId2Player[toonId]
        gatherable = self.level.getGatherable(pickupNum)
        if gatherable is not None:
            if not gatherable.isPowerUp() and not gatherable.wasPickedUp() or gatherable.isPowerUp() and not gatherable.wasPickedUpByToon(player.toon):
                gatherable.pickUp(player.toon, elapsedTime)
                player.handleEnterGatherable(gatherable, elapsedTime)
                if gatherable.type in [Globals.Level.GatherableTypes.InvulPowerup]:
                    if player.toon.isLocal():
                        self.audioMgr.playMusic('invul')
        else:
            self.notify.warning('Trying to pickup gatherable nonetype:%s' % pickupNum)
        return

    def debuffPowerup(self, toonId, pickupType, elapsedTime):
        self.notify.debugCall()
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            if player.isBuffActive(pickupType):
                if pickupType in [Globals.Level.GatherableTypes.InvulPowerup]:
                    if self.guiMgr.isTimeRunningOut():
                        self.audioMgr.playMusic('timeRunningOut')
                    else:
                        self.audioMgr.playMusic('normal')
                    player.handleDebuffPowerup(pickupType, elapsedTime)

    def handleLocalToonEnterLegalEagle(self, eagle, collEntry):
        if not self.localPlayer.isEnemyHitting() and not self.localPlayer.isInvulnerable():
            collPos = collEntry.getSurfacePoint(render)
            self.localPlayer.handleEnterEnemyHit(eagle, collPos)
            self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitLegalEagle, 0)

    def handleLocalToonEnterObstacle(self, obstacle, collEntry):
        if self.localPlayer.isInvulnerable():
            return
        if obstacle.type == Globals.Level.ObstacleTypes.Whirlwind:
            self.localPlayer.handleEnterWhirlwind(obstacle)
            self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitWhirlwind, 0)
        if obstacle.type == Globals.Level.ObstacleTypes.Fan:
            self.localPlayer.handleEnterFan(obstacle)
        if obstacle.type == Globals.Level.ObstacleTypes.Minion:
            if not self.localPlayer.isEnemyHitting():
                collPos = collEntry.getSurfacePoint(render)
                self.localPlayer.handleEnterEnemyHit(obstacle, collPos)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.HitMinion, 0)

    def handleLocalToonExitObstacle(self, obstacle, collEntry):
        if obstacle.type == Globals.Level.ObstacleTypes.Fan:
            self.localPlayer.handleExitFan(obstacle)

    def __startUpdateTask(self):
        self.__stopUpdateTask()
        taskMgr.add(self.__updateTask, CogdoFlyingGame.UpdateTaskName, 45)

    def __stopUpdateTask(self):
        taskMgr.remove(CogdoFlyingGame.UpdateTaskName)

    def handleTimeRunningOut(self):
        if self.localPlayer.state not in ('WaitingForWin', ):
            self.audioMgr.playMusic('timeRunningOut')
        self.guiMgr.presentTimerGui()
        self.guiMgr.setTemporaryMessage(TTLocalizer.CogdoFlyingGameTimeIsRunningOut)

    def handlePlayWaitingMusic(self):
        self.audioMgr.playMusic('waiting')

    def handleLocalPlayerFirstPressOfCtrl(self):
        self.doMethodLater(3.0, self.guiMgr.setMessage, CogdoFlyingGame.FirstPressOfCtrlTaskName, extraArgs=[''])

    def handleLocalPlayerRanOutOfTime(self):
        self.guiMgr.setMemoCount(0)
        self.distGame.d_sendRequestAction(Globals.AI.GameActions.RanOutOfTimePenalty, 0)
        self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameTakingMemos)

    def handleClearGuiMessage(self):
        if not self.localPlayer.isInvulnerable():
            self.guiMgr.setMessage('')

    def handleLocalPlayerInvulnerable(self):
        if not self._hints['invulnerable']:
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameYouAreInvincible)
            self._hints['invulnerable'] = True

    def handleLocalPlayerPickedUpFirstPropeller(self):
        self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGamePressCtrlToFly)
        self.guiMgr.presentRefuelGui()

    def handleLocalPlayerTargetedByEagle(self):
        if not self.localPlayer.isInvulnerable() and not self._hints['targettedByEagle']:
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameLegalEagleTargeting)
            self._hints['targettedByEagle'] = True

    def handleLocalPlayerAttackedByEagle(self):
        if not self.localPlayer.isInvulnerable():
            self.guiMgr.setMessage(TTLocalizer.CogdoFlyingGameLegalEagleAttacking)

    def handlePlayerBackpackAttacked(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Attacked)

    def handlePlayerBackpackTargeted(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Targeted)

    def handlePlayerBackpackNormal(self, toonId):
        if toonId in self.toonId2Player:
            player = self.toonId2Player[toonId]
            player.setBackpackState(Globals.Gameplay.BackpackStates.Normal)

    def handleLocalToonEnterLegalEagleInterest(self, index):
        if index in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[index]
            if not self.localPlayer.isLegalEagleInterestRequestSent(index) and not self.localPlayer.isLegalEagleTarget():
                if self.localPlayer.state in ('WaitingForWin', 'Win'):
                    return
                self.localPlayer.setLegalEagleInterestRequest(index)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestEnterEagleInterest, index)
        else:
            self.notify.warning("Legal eagle %i isn't in index2LegalEagle dict" % index)

    def handleLocalToonAgainLegalEagleInterest(self, index):
        self.handleLocalToonEnterLegalEagleInterest(index)

    def handleLocalToonExitLegalEagleInterest(self, index):
        if index in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[index]
            if self.localPlayer.isLegalEagleInterestRequestSent(index):
                self.localPlayer.clearLegalEagleInterestRequest(index)
                self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestExitEagleInterest, index)
        else:
            self.notify.warning("Legal eagle %i isn't in index2LegalEagle dict" % index)

    def forceClearLegalEagleInterestInToon(self, toonId):
        player = self.toonId2Player[toonId]
        if player:
            for legalEagle in self.legalEagles:
                index = legalEagle.index
                if player.toon.isLocal():
                    if self.localPlayer.isLegalEagleInterestRequestSent(index):
                        self.localPlayer.clearLegalEagleInterestRequest(index)
                        self.distGame.d_sendRequestAction(Globals.AI.GameActions.RequestExitEagleInterest, index)
                self.toonClearAsEagleTarget(toonId, index, 0)

    def toonSetAsEagleTarget(self, toonId, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            if toonId in self.toonId2Player:
                player = self.toonId2Player[toonId]
                player.setAsLegalEagleTarget(legalEagle)
                legalEagle.setTarget(player.toon, elapsedTime)

    def toonClearAsEagleTarget(self, toonId, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            if toonId in self.toonId2Player:
                player = self.toonId2Player[toonId]
                player.removeAsLegalEagleTarget(legalEagle)
                if legalEagle.getTarget() == player.toon:
                    legalEagle.clearTarget(elapsedTime)

    def eagleExitCooldown(self, eagleId, elapsedTime):
        if eagleId in self.index2LegalEagle:
            legalEagle = self.index2LegalEagle[eagleId]
            legalEagle.leaveCooldown(elapsedTime)

    def gameComplete(self):
        self.localPlayer.request('Win')

    def __updateTask(self, task):
        dt = globalClock.getDt()
        self.localPlayer.update(dt)
        self.level.update(dt)
        for eagle in self.legalEagles:
            eagle.update(dt, self.localPlayer)

        self.guiMgr.update()
        return Task.cont
Exemplo n.º 11
0
class CogdoCraneGame(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingGame')

    def __init__(self, distGame):
        self.distGame = distGame
        self.toonId2Player = {}
        self.players = []

    def _initAudio(self):
        self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles, Globals.SfxFiles, camera, cutoff=Globals.AudioCutoff)

    def _destroyAudio(self):
        self._audioMgr.destroy()
        del self._audioMgr

    def load(self):
        self._initAudio()

    def unload(self):
        self._destroyAudio()
        del self.toonId2Player

    def onstage(self):
        pass

    def offstage(self):
        pass

    def startIntro(self):
        self._audioMgr.playMusic('normal')

    def endIntro(self):
        for player in self.players:
            self.placePlayer(player)
            if player.toon is localAvatar:
                localAvatar.sendCurrentPosition()
            player.request('Ready')

    def startFinish(self):
        pass

    def endFinish(self):
        pass

    def start(self):
        for player in self.players:
            player.handleGameStart()
            player.request('Normal')

    def exit(self):
        for player in self.players:
            player.request('Done')

    def _addPlayer(self, player):
        self.players.append(player)
        self.toonId2Player[player.toon.doId] = player

    def _removePlayer(self, player):
        if player in self.players:
            self.players.remove(player)
        else:
            for cPlayer in self.players:
                if cPlayer.toon == player.toon:
                    self.players.remove(cPlayer)
                    break

        if self.toonId2Player.has_key(player.toon.doId):
            del self.toonId2Player[player.toon.doId]

    def handleToonLeft(self, toonId):
        self._removePlayer(self.toonId2Player[toonId])
Exemplo n.º 12
0
 def _initAudio(self):
     self._audioMgr = CogdoGameAudioManager(Globals.MusicFiles, Globals.SfxFiles, camera, cutoff=Globals.AudioCutoff)