from direct.showbase.DirectObject import DirectObject from direct.task.Task import Task from direct.showbase.RandomNumGen import RandomNumGen from direct.interval.FunctionInterval import Wait from direct.interval.IntervalGlobal import Func from direct.interval.MetaInterval import Sequence, Parallel from toontown.toonbase import TTLocalizer, ToontownGlobals import CogdoFlyingGameGlobals as Globals from CogdoFlyingLocalPlayer import CogdoFlyingLocalPlayer from CogdoGameAudioManager import CogdoGameAudioManager from CogdoFlyingPlayer import CogdoFlyingPlayer from CogdoFlyingObjects import CogdoFlyingGatherable from CogdoFlyingObstacles import CogdoFlyingObstacle from CogdoFlyingLegalEagle import CogdoFlyingLegalEagle from CogdoFlyingGuiManager import CogdoFlyingGuiManager from CogdoFlyingLevel import CogdoFlyingLevelFactory from CogdoFlyingGameMovies import CogdoFlyingGameIntro, CogdoFlyingGameFinish 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) if __debug__ 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') 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