from pandac.PandaModules import * from toontown.toonbase.ToonBaseGlobal import * from toontown.toonbase.ToontownGlobals import GlobalDialogColor from DistributedMinigame import * from direct.fsm import ClassicFSM, State from direct.fsm import State from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownTimer import TravelGameGlobals import math from pandac.PandaModules import rad2Deg from toontown.toontowngui import TTDialog from direct.interval.IntervalGlobal import * import VoteResultsPanel import VoteResultsTrolleyPanel IconDict = {ToontownGlobals.RaceGameId: 'mg_trolley_sign_race', ToontownGlobals.CannonGameId: 'mg_trolley_sign_cannon', ToontownGlobals.TagGameId: 'mg_trolley_sign_tag', ToontownGlobals.PatternGameId: 'mg_trolley_sign_minnie', ToontownGlobals.RingGameId: 'mg_trolley_sign_ring', ToontownGlobals.MazeGameId: 'mg_trolley_sign_maze', ToontownGlobals.TugOfWarGameId: 'mg_trolley_sign_tugawar', ToontownGlobals.CatchGameId: 'mg_trolley_sign_catch', ToontownGlobals.DivingGameId: 'mg_trolley_sign_dive', ToontownGlobals.TargetGameId: 'mg_trolley_sign_umbrella', ToontownGlobals.PairingGameId: 'mg_trolley_sign_card', ToontownGlobals.VineGameId: 'mg_trolley_sign_vine', ToontownGlobals.IceGameId: 'mg_trolley_sign_ice', ToontownGlobals.PhotoGameId: 'mg_trolley_sign_photo', ToontownGlobals.TwoDGameId: 'mg_trolley_sign_2d', ToontownGlobals.CogThiefGameId: 'mg_trolley_sign_theif'} MinigameNameDict = {ToontownGlobals.RaceGameId: TTLocalizer.RaceGameTitle, ToontownGlobals.CannonGameId: TTLocalizer.CannonGameTitle, ToontownGlobals.TagGameId: TTLocalizer.TagGameTitle, ToontownGlobals.PatternGameId: TTLocalizer.PatternGameTitle, ToontownGlobals.RingGameId: TTLocalizer.RingGameTitle, ToontownGlobals.MazeGameId: TTLocalizer.MazeGameTitle, ToontownGlobals.TugOfWarGameId: TTLocalizer.TugOfWarGameTitle, ToontownGlobals.CatchGameId: TTLocalizer.CatchGameTitle, ToontownGlobals.DivingGameId: TTLocalizer.DivingGameTitle, ToontownGlobals.TargetGameId: TTLocalizer.TargetGameTitle, ToontownGlobals.PairingGameId: TTLocalizer.PairingGameTitle, ToontownGlobals.VineGameId: TTLocalizer.VineGameTitle, ToontownGlobals.TravelGameId: TTLocalizer.TravelGameTitle, ToontownGlobals.IceGameId: TTLocalizer.IceGameTitle, ToontownGlobals.PhotoGameId: TTLocalizer.PhotoGameTitle, ToontownGlobals.TwoDGameId: TTLocalizer.TwoDGameTitle, ToontownGlobals.CogThiefGameId: TTLocalizer.CogThiefGameTitle} def makeLabel(itemName, itemNum, *extraArgs): intVersion = int(itemName) if intVersion < 0: textColor = Vec4(0, 0, 1, 1) intVersion = -intVersion elif intVersion == 0: textColor = Vec4(0, 0, 0, 1) else: textColor = Vec4(1, 0, 0, 1) return DirectLabel(text=str(intVersion), text_fg=textColor, relief=DGG.RIDGE, frameSize=(-1.2, 1.2, -0.225, 0.8), scale=1.0) def map3dToAspect2d(node, point): p3 = base.cam.getRelativePoint(node, point) p2 = Point2() if not base.camLens.project(p3, p2): return None r2d = Point3(p2[0], 0, p2[1]) a2d = aspect2d.getRelativePoint(render2d, r2d) return a2d def invertTable(table): index = {} for key in table.keys(): value = table[key] if not index.has_key(value): index[value] = key return index class DistributedTravelGame(DistributedMinigame): notify = directNotify.newCategory('DistributedTravelGame') idToNames = MinigameNameDict TrolleyMoveDuration = 3 UseTrolleyResultsPanel = True FlyCameraUp = True FocusOnTrolleyWhileMovingUp = False def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedTravelGame', [State.State('off', self.enterOff, self.exitOff, ['inputChoice']), State.State('inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices', 'displayVotes', 'cleanup']), State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['displayVotes', 'cleanup']), State.State('displayVotes', self.enterDisplayVotes, self.exitDisplayVotes, ['moveTrolley', 'cleanup']), State.State('moveTrolley', self.enterMoveTrolley, self.exitMoveTrolley, ['inputChoice', 'winMovie', 'cleanup']), State.State('winMovie', self.enterWinMovie, self.exitWinMovie, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.currentVotes = {} self.cameraTopView = (100, -20, 280, 0, -89, 0) self.timer = None self.timerStartTime = None self.currentSwitch = 0 self.destSwitch = 0 self.minigameLabels = [] self.minigameIcons = [] self.bonusLabels = [] self.trolleyAwaySfx = base.loader.loadSfx('phase_4/audio/sfx/SZ_trolley_away.mp3') self.trolleyBellSfx = base.loader.loadSfx('phase_4/audio/sfx/SZ_trolley_bell.mp3') self.turntableRotateSfx = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_turntble_rotate_2.mp3') self.wonGameSfx = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_bonus.mp3') self.lostGameSfx = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_no_bonus_2.mp3') self.noWinnerSfx = base.loader.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_no_bonus.mp3') self.boardIndex = 0 self.avNames = [] self.disconnectedAvIds = [] return def getTitle(self): return TTLocalizer.TravelGameTitle def getInstructions(self): return TTLocalizer.TravelGameInstructions def getMaxDuration(self): return 0 def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.sky = loader.loadModel('phase_3.5/models/props/TT_sky') self.gameBoard = loader.loadModel('phase_4/models/minigames/toon_cannon_gameground') self.gameBoard.setPosHpr(100, 0, 0, 0, 0, 0) self.gameBoard.setScale(1.0) station = loader.loadModel('phase_4/models/modules/trolley_station_TT.bam') self.trolleyCar = station.find('**/trolley_car') self.trolleyCar.reparentTo(hidden) self.trolleyCarOrigPos = self.trolleyCar.getPos() self.trolleyCarOrigHpr = self.trolleyCar.getHpr() self.trolleyCar.setPosHpr(0, 0, 0, 0, 0, 0) self.trolleyCar.setScale(1.0) self.trolleyCar.setX(self.trolleyCar.getX() - TravelGameGlobals.xInc) station.removeNode() self.keys = self.trolleyCar.findAllMatches('**/key') self.numKeys = self.keys.getNumPaths() self.keyInit = [] self.keyRef = [] for i in range(self.numKeys): key = self.keys[i] key.setTwoSided(1) ref = self.trolleyCar.attachNewNode('key' + `i` + 'ref') ref.iPosHpr(key) self.keyRef.append(ref) self.keyInit.append(key.getTransform()) self.frontWheels = self.trolleyCar.findAllMatches('**/front_wheels') self.numFrontWheels = self.frontWheels.getNumPaths() self.frontWheelInit = [] self.frontWheelRef = [] for i in range(self.numFrontWheels): wheel = self.frontWheels[i] ref = self.trolleyCar.attachNewNode('frontWheel' + `i` + 'ref') ref.iPosHpr(wheel) self.frontWheelRef.append(ref) self.frontWheelInit.append(wheel.getTransform()) self.backWheels = self.trolleyCar.findAllMatches('**/back_wheels') self.numBackWheels = self.backWheels.getNumPaths() self.backWheelInit = [] self.backWheelRef = [] for i in range(self.numBackWheels): wheel = self.backWheels[i] ref = self.trolleyCar.attachNewNode('backWheel' + `i` + 'ref') ref.iPosHpr(wheel) self.backWheelRef.append(ref) self.backWheelInit.append(wheel.getTransform()) trolleyAnimationReset = Func(self.resetAnimation) self.trainSwitches = {} self.trainTracks = {} self.tunnels = {} self.extraTrainTracks = [] turnTable = loader.loadModel('phase_4/models/minigames/trolley_game_turntable') minPoint = Point3(0, 0, 0) maxPoint = Point3(0, 0, 0) turnTable.calcTightBounds(minPoint, maxPoint) self.fullLength = maxPoint[0] for key in TravelGameGlobals.BoardLayouts[self.boardIndex].keys(): info = TravelGameGlobals.BoardLayouts[self.boardIndex][key] switchModel = turnTable.find('**/turntable1').copyTo(render) switchModel.setPos(*info['pos']) switchModel.reparentTo(hidden) self.trainSwitches[key] = switchModel zAdj = 0 for otherSwitch in info['links']: info2 = TravelGameGlobals.BoardLayouts[self.boardIndex][otherSwitch] x1, y1, z1 = info['pos'] x2, y2, z2 = info2['pos'] linkKey = (key, otherSwitch) trainTrack = self.loadTrainTrack(x1, y1, x2, y2, zAdj) trainTrack.reparentTo(hidden) self.trainTracks[linkKey] = trainTrack zAdj += 0.005 rootInfo = TravelGameGlobals.BoardLayouts[self.boardIndex][0] rootX, rootY, rootZ = rootInfo['pos'] startX = rootX - TravelGameGlobals.xInc trainTrack = self.loadTrainTrack(startX, rootY, rootX, rootY) self.extraTrainTracks.append(trainTrack) tunnelX = None for key in TravelGameGlobals.BoardLayouts[self.boardIndex].keys(): if self.isLeaf(key): info = TravelGameGlobals.BoardLayouts[self.boardIndex][key] switchX, switchY, switchZ = info['pos'] endX = switchX + TravelGameGlobals.xInc trainTrack = self.loadTrainTrack(switchX, switchY, endX, switchY) self.extraTrainTracks.append(trainTrack) tempModel = loader.loadModel('phase_4/models/minigames/trolley_game_turntable') tunnel = tempModel.find('**/tunnel1') tunnel.reparentTo(render) tempModel.removeNode() if not tunnelX: minTrackPoint = Point3(0, 0, 0) maxTrackPoint = Point3(0, 0, 0) trainTrack.calcTightBounds(minTrackPoint, maxTrackPoint) tunnelX = maxTrackPoint[0] tunnel.setPos(tunnelX, switchY, 0) tunnel.wrtReparentTo(trainTrack) self.tunnels[key] = tunnel turnTable.removeNode() self.loadGui() self.introMovie = self.getIntroMovie() self.music = base.loadMusic('phase_4/audio/bgm/MG_Travel.mid') self.flashWinningBeansTrack = None return def loadTrainTrack(self, x1, y1, x2, y2, zAdj = 0): turnTable = loader.loadModel('phase_4/models/minigames/trolley_game_turntable') trainPart = turnTable.find('**/track_a2') trackHeight = 0.03 trainTrack = render.attachNewNode('trainTrack%d%d%d%d' % (x1, y1, x2, y2)) trainTrack.setPos(x1, y1, trackHeight) xDiff = abs(x2 - x1) yDiff = abs(y2 - y1) angleInRadians = math.atan((float(y2) - y1) / (x2 - x1)) angle = rad2Deg(angleInRadians) desiredLength = math.sqrt(xDiff * xDiff + yDiff * yDiff) lengthToGo = desiredLength partIndex = 0 lengthCovered = 0 while lengthToGo > self.fullLength / 2.0: onePart = trainPart.copyTo(trainTrack) onePart.setX(lengthCovered) lengthToGo -= self.fullLength lengthCovered += self.fullLength trainTrack.setH(angle) newX = x1 + (x2 - x1) / 2.0 newY = y1 + (y2 - y1) / 2.0 trainTrack.setPos(x1, y1, trackHeight + zAdj) turnTable.removeNode() return trainTrack def loadGui(self): scoreText = [str(self.currentVotes[self.localAvId])] self.gui = DirectFrame() self.remainingVotesFrame = DirectFrame(parent=self.gui, relief=None, geom=DGG.getDefaultDialogGeom(), geom_color=GlobalDialogColor, geom_scale=(7, 1, 1), pos=(-0.9, 0, 0.8), scale=0.1, text=TTLocalizer.TravelGameRemainingVotes, text_align=TextNode.ALeft, text_scale=TTLocalizer.DTGremainingVotesFrame, text_pos=(-3.4, -0.1, 0.0)) self.localVotesRemaining = DirectLabel(parent=self.remainingVotesFrame, relief=None, text=scoreText, text_fg=VBase4(0, 0.5, 0, 1), text_align=TextNode.ARight, text_scale=0.7, pos=(3.2, 0, -0.15)) guiModel = loader.loadModel('phase_3.5/models/gui/friendslist_gui') self.choiceFrame = DirectFrame(parent=self.gui, relief=None, pos=(-0.55, 0, -0.85), image=DGG.getDefaultDialogGeom(), image_scale=(1.4, 1, 0.225), image_color=GlobalDialogColor) self.useLabel = DirectLabel(text=TTLocalizer.TravelGameUse, parent=self.choiceFrame, pos=(-0.59, 0, -0.01), text_scale=TTLocalizer.DTGuseLabel, relief=None) self.votesPeriodLabel = DirectLabel(text=TTLocalizer.TravelGameVotesWithPeriod, parent=self.choiceFrame, pos=(-0.21, 0, -0.01), text_scale=TTLocalizer.DTGvotesPeriodLabel, relief=None, text_align=TextNode.ALeft) self.votesToGoLabel = DirectLabel(text=TTLocalizer.TravelGameVotesToGo, parent=self.choiceFrame, pos=(-0.21, 0, -0.01), text_scale=TTLocalizer.DTGvotesToGoLabel, relief=None, text_align=TextNode.ALeft) self.upLabel = DirectLabel(text=TTLocalizer.TravelGameUp, parent=self.choiceFrame, pos=(0.31, 0, -0.01), text_scale=TTLocalizer.DTGupLabel, text_fg=Vec4(0, 0, 1, 1), relief=None, text_align=TextNode.ALeft) self.downLabel = DirectLabel(text=TTLocalizer.TravelGameDown, parent=self.choiceFrame, pos=(0.31, 0, -0.01), text_scale=TTLocalizer.DTGdownLabel, text_fg=Vec4(1, 0, 0, 1), relief=None, text_align=TextNode.ALeft) self.scrollList = DirectScrolledList(parent=self.choiceFrame, relief=None, pos=(-0.36, 0, -0.02), incButton_image=(guiModel.find('**/FndsLst_ScrollUp'), guiModel.find('**/FndsLst_ScrollDN'), guiModel.find('**/FndsLst_ScrollUp_Rllvr'), guiModel.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_pos=(0.0, 0.0, -0.04), incButton_image3_color=Vec4(0.6, 0.6, 0.6, 0.6), incButton_scale=(1.0, 1.0, -1.0), decButton_image=(guiModel.find('**/FndsLst_ScrollUp'), guiModel.find('**/FndsLst_ScrollDN'), guiModel.find('**/FndsLst_ScrollUp_Rllvr'), guiModel.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_pos=(0.0, 0.0, 0.095), decButton_image3_color=Vec4(0.6, 0.6, 0.6, 0.6), itemFrame_pos=(0.0, 0.0, 0.0), itemFrame_relief=DGG.GROOVE, numItemsVisible=1, itemMakeFunction=makeLabel, items=[], scrollSpeed=3.0, itemFrame_scale=0.1, command=self.scrollChoiceChanged) self.putChoicesInScrollList() buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui') okImageList = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')) self.voteButton = DirectButton(parent=self.choiceFrame, relief=None, image=okImageList, image_scale=3.0, pos=(0.85, 0, 0.0), text=TTLocalizer.TravelGameVoteWithExclamation, text_scale=TTLocalizer.DTGvoteButton, text_pos=(0, 0), command=self.handleInputChoice) self.waitingChoicesLabel = DirectLabel(text=TTLocalizer.TravelGameWaitingChoices, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.2, 0, -0.85), scale=0.075) self.waitingChoicesLabel.hide() self.gui.hide() return def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) self.introMovie.finish() del self.introMovie self.gameBoard.removeNode() del self.gameBoard self.sky.removeNode() del self.sky self.trolleyCar.removeNode() del self.trolleyCar for key in self.trainSwitches.keys(): self.trainSwitches[key].removeNode() del self.trainSwitches[key] self.trainSwitches = {} for key in self.tunnels.keys(): self.tunnels[key].removeNode() del self.tunnels[key] self.tunnels = {} for key in self.trainTracks.keys(): self.trainTracks[key].removeNode() del self.trainTracks[key] self.trainTracks = {} for trainTrack in self.extraTrainTracks: trainTrack.removeNode() del trainTrack self.extraTrainTracks = [] self.gui.removeNode() del self.gui self.waitingChoicesLabel.destroy() del self.waitingChoicesLabel if self.flashWinningBeansTrack: self.flashWinningBeansTrack.finish() del self.flashWinningBeansTrack for label in self.minigameLabels: label.destroy() del label self.minigameLabels = [] for icon in self.minigameIcons: icon.destroy() icon.removeNode() self.minigameIcons = [] if hasattr(self, 'mg_icons'): del self.mg_icons for label in self.bonusLabels: label.destroy() del label self.bonusLabels = [] self.scrollList.destroy() del self.scrollList self.voteButton.destroy() del self.voteButton self.removeChildGameFSM(self.gameFSM) del self.gameFSM del self.music def moveCameraToTop(self): camera.reparentTo(render) p = self.cameraTopView camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5]) def moveCameraToTrolley(self): camera.reparentTo(self.trolleyCar) camera.setPos(-25, 0, 7.5) camera.setHpr(-90, 0, 0) def onstage(self): self.notify.debug('onstage') NametagGlobals.setOnscreenChatForced(1) DistributedMinigame.onstage(self) self.gameBoard.reparentTo(render) self.sky.reparentTo(render) self.moveCameraToTop() self.trolleyCar.reparentTo(render) for key in self.trainSwitches.keys(): self.trainSwitches[key].reparentTo(render) for key in self.trainTracks.keys(): self.trainTracks[key].reparentTo(render) for trainTrack in self.extraTrainTracks: trainTrack.reparentTo(render) base.transitions.irisIn(0.4) base.setBackgroundColor(0.1875, 0.7929, 0) base.playMusic(self.music, looping=1, volume=0.9) self.introMovie.start() def offstage(self): self.notify.debug('offstage') NametagGlobals.setOnscreenChatForced(0) base.setBackgroundColor(ToontownGlobals.DefaultBackgroundColor) self.introMovie.finish() self.gameBoard.hide() self.sky.hide() self.trolleyCar.hide() self.gui.hide() self.hideMinigamesAndBonuses() for key in self.trainSwitches.keys(): self.trainSwitches[key].hide() for key in self.trainTracks.keys(): self.trainTracks[key].hide() for trainTrack in self.extraTrainTracks: trainTrack.hide() DistributedMinigame.offstage(self) if base.localAvatar.laffMeter: base.localAvatar.laffMeter.start() self.music.stop() def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return for index in range(self.numPlayers): avId = self.avIdList[index] name = '' avatar = self.getAvatar(avId) if avatar: avatar.reparentTo(self.trolleyCar) avatar.animFSM.request('Sit') avatar.setPosHpr(-4, -4.5 + index * 3, 2.8, 90, 0, 0) name = avatar.getName() self.avNames.append(name) self.trolleyCar.setH(90) def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) self.introMovie.finish() self.gameFSM.request('inputChoice') def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterInputChoice(self): self.notify.debug('enterInputChoice') NametagGlobals.setOnscreenChatForced(1) self.timer = ToontownTimer.ToontownTimer() self.timer.hide() if self.timerStartTime != None: self.startTimer() if base.localAvatar.laffMeter: base.localAvatar.laffMeter.stop() self.gui.show() self.showMinigamesAndBonuses() return def exitInputChoice(self): NametagGlobals.setOnscreenChatForced(0) if self.timer != None: self.timer.destroy() self.timer = None self.timerStartTime = None self.gui.hide() return def enterWaitServerChoices(self): self.notify.debug('enterWaitServerChoices') self.waitingChoicesLabel.show() self.gui.hide() def exitWaitServerChoices(self): self.waitingChoicesLabel.hide() def enterDisplayVotes(self, votes, directions, directionToGo, directionReason): if self.UseTrolleyResultsPanel: self.moveCameraToTrolley() self.hideMinigamesAndBonuses() else: self.moveCameraToTop() self.resultVotes = votes self.resultDirections = directions self.directionToGo = directionToGo self.directionReason = directionReason self.resultsStr = '' directionTotals = [0] * TravelGameGlobals.MaxDirections for index in range(len(votes)): if index < len(self.avNames): avId = self.avIdList[index] dir = directions[index] numVotes = votes[index] directionTotals[dir] += numVotes curStr = TTLocalizer.TravelGameOneToonVote % {'name': self.avNames[index], 'numVotes': numVotes, 'dir': TTLocalizer.TravelGameDirections[dir]} if not (numVotes == 0 and avId in self.disconnectedAvIds): self.resultsStr += curStr directionStr = TTLocalizer.TravelGameTotals for index in range(len(directionTotals)): directionStr += ' ' + TTLocalizer.TravelGameDirections[index] + ':' directionStr += str(directionTotals[index]) directionStr += '\n' self.resultsStr += directionStr reasonStr = '' if directionReason == TravelGameGlobals.ReasonVote: if directionToGo == 0: losingDirection = 1 else: losingDirection = 0 diffVotes = directionTotals[directionToGo] - directionTotals[losingDirection] reasonStr = '' if diffVotes > 1: reasonStr = TTLocalizer.TravelGameReasonVotesPlural % {'dir': TTLocalizer.TravelGameDirections[directionToGo], 'numVotes': diffVotes} else: reasonStr = TTLocalizer.TravelGameReasonVotesSingular % {'dir': TTLocalizer.TravelGameDirections[directionToGo], 'numVotes': diffVotes} elif directionReason == TravelGameGlobals.ReasonRandom: reasonStr = TTLocalizer.TravelGameReasonRandom % {'dir': TTLocalizer.TravelGameDirections[directionToGo], 'numVotes': directionTotals[directionToGo]} elif directionReason == TravelGameGlobals.ReasonPlaceDecider: reasonStr = TravelGameReasonPlace % {'name': 'TODO NAME', 'dir': TTLocalizer.TravelGameDirections[directionToGo]} self.resultsStr += reasonStr self.dialog = TTDialog.TTDialog(text=self.resultsStr, command=self.__cleanupDialog, style=TTDialog.NoButtons, pos=(0, 0, 1)) self.dialog.hide() if self.UseTrolleyResultsPanel: self.votesPanel = VoteResultsTrolleyPanel.VoteResultsTrolleyPanel(len(self.avIdList), self.avIdList, votes, directions, self.avNames, self.disconnectedAvIds, directionToGo, directionReason, directionTotals) else: self.votesPanel = VoteResultsPanel.VoteResultsPanel(len(self.avIdList), self.avIdList, votes, directions, self.avNames, self.disconnectedAvIds, directionToGo, directionReason, directionTotals) self.votesPanel.startMovie() numPlayers = len(self.avIdList) if TravelGameGlobals.SpoofFour: numPlayers = 4 delay = TravelGameGlobals.DisplayVotesTimePerPlayer * (numPlayers + 1) taskMgr.doMethodLater(delay, self.displayVotesTimeoutTask, self.taskName('displayVotes-timeout')) curSwitch = TravelGameGlobals.BoardLayouts[self.boardIndex][self.currentSwitch] self.destSwitch = curSwitch['links'][directionToGo] self.updateCurrentVotes() def exitDisplayVotes(self): taskMgr.remove(self.taskName('displayVotes-timeout')) self.__cleanupDialog(0) if not self.UseTrolleyResultsPanel: self.showMinigamesAndBonuses() self.votesPanel.destroy() def enterMoveTrolley(self): self.notify.debug('enterMoveTrolley') camera.wrtReparentTo(render) keyAngle = round(self.TrolleyMoveDuration) * 360 dist = Vec3(self.trainSwitches[self.destSwitch].getPos() - self.trainSwitches[self.currentSwitch].getPos()).length() wheelAngle = dist / (2.0 * math.pi * 0.95) * 360 trolleyAnimateInterval = LerpFunctionInterval(self.animateTrolley, duration=self.TrolleyMoveDuration, blendType='easeInOut', extraArgs=[keyAngle, wheelAngle], name='TrolleyAnimate') moveTrolley = Sequence() moveTrolley.append(Func(self.resetAnimation)) newPos = self.trainSwitches[self.destSwitch].getPos() linkKey = (self.currentSwitch, self.destSwitch) origHeading = self.trainTracks[linkKey].getH() heading = origHeading + 90 firstTurn = Parallel() firstTurn.append(LerpHprInterval(self.trolleyCar, 1, Vec3(heading, 0, 0))) firstTurn.append(LerpHprInterval(self.trainSwitches[self.currentSwitch], 1, Vec3(origHeading, 0, 0))) firstTurn.append(LerpHprInterval(self.trainSwitches[self.destSwitch], 1, Vec3(origHeading, 0, 0))) moveTrolley.append(firstTurn) moveTrolley.append(Parallel(LerpPosInterval(self.trolleyCar, self.TrolleyMoveDuration, newPos, blendType='easeInOut'), trolleyAnimateInterval)) secondTurn = Parallel() secondTurn.append(LerpHprInterval(self.trolleyCar, 1, Vec3(90, 0, 0))) secondTurn.append(LerpHprInterval(self.trainSwitches[self.currentSwitch], 1, Vec3(0, 0, 0))) secondTurn.append(LerpHprInterval(self.trainSwitches[self.destSwitch], 1, Vec3(0, 0, 0))) moveTrolley.append(secondTurn) soundTrack = Sequence() trolleyExitBellInterval = Parallel(SoundInterval(self.trolleyBellSfx, duration=1), SoundInterval(self.turntableRotateSfx, duration=1, volume=0.5)) trolleyExitAwayInterval = SoundInterval(self.trolleyAwaySfx, duration=3) soundTrack.append(trolleyExitBellInterval) soundTrack.append(trolleyExitAwayInterval) soundTrack.append(trolleyExitBellInterval) self.moveTrolleyIval = Parallel(moveTrolley, soundTrack) duration = self.moveTrolleyIval.getDuration() def focusOnTrolley(t, self = self): pos = self.trolleyCar.getPos() pos.setZ(pos.getZ() + 7.5) camera.lookAt(pos) self.lastFocusHpr = camera.getHpr() setRightHprTime = 0 if self.FlyCameraUp: setRightHprTime = 1.0 camIval1 = Parallel() camIval1.append(LerpFunc(focusOnTrolley, duration - setRightHprTime, name='focusOnTrolley')) finalPos = Vec3(self.cameraTopView[0], self.cameraTopView[1], self.cameraTopView[2]) finalHpr = Vec3(self.cameraTopView[3], self.cameraTopView[4], self.cameraTopView[5]) if self.FlyCameraUp: if self.FocusOnTrolleyWhileMovingUp: camIval1.append(LerpPosInterval(camera, duration - setRightHprTime, finalPos, name='cameraMove')) camIval2 = Sequence(LerpHprInterval(camera, setRightHprTime, finalHpr, name='cameraHpr')) else: camIval2 = Sequence(LerpPosHprInterval(camera, setRightHprTime, finalPos, finalHpr, blendType='easeIn', name='cameraHpr')) camIval = Sequence(camIval1, camIval2) else: camIval = Sequence(camIval1) if self.UseTrolleyResultsPanel: self.moveTrolleyIval.append(camIval) temp = self.moveTrolleyIval self.moveTrolleyIval = Sequence(temp) if self.isLeaf(self.destSwitch): self.moveTrolleyIval.append(Func(self.gameFSM.request, 'winMovie')) else: self.moveTrolleyIval.append(Func(self.gameFSM.request, 'inputChoice')) self.moveTrolleyIval.start() def exitMoveTrolley(self): self.notify.debug('exitMoveTrolley') self.currentSwitch = self.destSwitch self.moveTrolleyIval.finish() self.moveCameraToTop() self.showMinigamesAndBonuses() def enterWinMovie(self): resultStr = TTLocalizer.TravelGamePlaying % {'game': self.idToNames[self.switchToMinigameDict[self.currentSwitch]]} numToons = 0 for avId in self.avIdList: if avId not in self.disconnectedAvIds: numToons += 1 if numToons <= 1: resultStr = TTLocalizer.TravelGameGoingBackToShop reachedGoalStr = None localAvatarWon = False localAvatarLost = False noWinner = True for avId in self.avIdBonuses.keys(): name = '' avatar = self.getAvatar(avId) if avatar: name = avatar.getName() if self.avIdBonuses[avId][0] == self.currentSwitch: noWinner = False reachedGoalStr = TTLocalizer.TravelGameGotBonus % {'name': name, 'numBeans': self.avIdBonuses[avId][1]} if avId == base.localAvatar.doId: if not TravelGameGlobals.ReverseWin: self.wonGameSfx.play() bonusLabel = self.switchToBonusLabelDict[self.currentSwitch] self.flashWinningBeansTrack = Sequence(LerpColorScaleInterval(bonusLabel, 0.75, Vec4(0.5, 1, 0.5, 1)), LerpColorScaleInterval(bonusLabel, 0.75, Vec4(1, 1, 1, 1))) self.flashWinningBeansTrack.loop() else: self.lostGameSfx.play() elif not TravelGameGlobals.ReverseWin: self.lostGameSfx.play() else: self.wonGameSfx.play() if noWinner: self.noWinnerSfx.play() resultStr += '\n\n' resultStr += TTLocalizer.TravelGameNoOneGotBonus if reachedGoalStr: resultStr += '\n\n' resultStr += reachedGoalStr self.winDialog = TTDialog.TTDialog(text=resultStr, command=self.__cleanupWinDialog, style=TTDialog.NoButtons) info = TravelGameGlobals.BoardLayouts[self.boardIndex][self.currentSwitch] leafX, leafY, leafZ = info['pos'] endX = leafX + TravelGameGlobals.xInc heading = 90 moveTrolley = Sequence() moveTrolley.append(LerpHprInterval(self.trolleyCar, 1, Vec3(heading, 0, 0))) moveTrolley.append(LerpPosInterval(self.trolleyCar, 3, Vec3(endX + 20, leafY, 0))) soundTrack = Sequence() trolleyExitBellInterval = SoundInterval(self.trolleyBellSfx, duration=1) trolleyExitAwayInterval = SoundInterval(self.trolleyAwaySfx, duration=3) soundTrack.append(trolleyExitBellInterval) soundTrack.append(trolleyExitAwayInterval) soundTrack.append(trolleyExitBellInterval) self.moveTrolleyIval = Parallel(moveTrolley, soundTrack) self.moveTrolleyIval.start() delay = 8 taskMgr.doMethodLater(delay, self.gameOverCallback, self.taskName('playMovie')) return def exitWinMovie(self): taskMgr.remove(self.taskName('playMovie')) self.moveTrolleyIval.finish() def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass def setStartingVotes(self, startingVotesArray): if not len(startingVotesArray) == len(self.avIdList): self.notify.error('length does not match, startingVotes=%s, avIdList=%s' % (startingVotesArray, self.avIdList)) return for index in range(len(self.avIdList)): avId = self.avIdList[index] self.startingVotes[avId] = startingVotesArray[index] if not self.currentVotes.has_key(avId): self.currentVotes[avId] = startingVotesArray[index] self.notify.debug('starting votes = %s' % self.startingVotes) def startTimer(self): now = globalClock.getFrameTime() elapsed = now - self.timerStartTime self.timer.setPos(1.16, 0, -0.83) self.timer.setTime(TravelGameGlobals.InputTimeout) self.timer.countdown(TravelGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout) self.timer.show() def setTimerStartTime(self, timestamp): if not self.hasLocalToon: return self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp) if self.timer != None: self.startTimer() return def handleChoiceTimeout(self): self.sendUpdate('setAvatarChoice', [0, 0]) self.gameFSM.request('waitServerChoices') def putChoicesInScrollList(self): available = self.currentVotes[self.localAvId] if len(self.scrollList['items']) > 0: self.scrollList.removeAllItems() self.indexToVotes = {} index = 0 for vote in range(available)[::-1]: self.scrollList.addItem(str(-(vote + 1))) self.indexToVotes[index] = vote + 1 index += 1 self.scrollList.addItem(str(0)) self.indexToVotes[index] = 0 self.zeroVoteIndex = index index += 1 for vote in range(available): self.scrollList.addItem(str(vote + 1)) self.indexToVotes[index] = vote + 1 index += 1 self.scrollList.scrollTo(self.zeroVoteIndex) def getAbsVoteChoice(self): available = self.currentVotes[self.localAvId] retval = 0 if hasattr(self, 'scrollList'): selectedIndex = self.scrollList.getSelectedIndex() if self.indexToVotes.has_key(selectedIndex): retval = self.indexToVotes[selectedIndex] return retval def getAbsDirectionChoice(self): selectedIndex = self.scrollList.getSelectedIndex() if selectedIndex < self.zeroVoteIndex: retval = 0 elif selectedIndex == self.zeroVoteIndex: retval = 0 else: retval = 1 return retval def makeTextMatchChoice(self): self.votesPeriodLabel.hide() self.votesToGoLabel.hide() self.upLabel.hide() self.downLabel.hide() if not hasattr(self, 'scrollList') or not hasattr(self, 'zeroVoteIndex'): return selectedIndex = self.scrollList.getSelectedIndex() if selectedIndex < self.zeroVoteIndex: self.votesToGoLabel.show() self.upLabel.show() elif selectedIndex == self.zeroVoteIndex: self.votesPeriodLabel.show() else: self.votesToGoLabel.show() self.downLabel.show() def scrollChoiceChanged(self): choiceVotes = self.getAbsVoteChoice() if choiceVotes == 1: self.votesToGoLabel['text'] = TTLocalizer.TravelGameVoteToGo else: self.votesToGoLabel['text'] = TTLocalizer.TravelGameVotesToGo available = self.currentVotes[self.localAvId] self.localVotesRemaining['text'] = str(available - choiceVotes) self.makeTextMatchChoice() def setAvatarChose(self, avId): if not self.hasLocalToon: return self.notify.debug('setAvatarChose: avatar: ' + str(avId) + ' choose a number') def handleInputChoice(self): numVotes = self.getAbsVoteChoice() direction = self.getAbsDirectionChoice() self.sendUpdate('setAvatarChoice', [numVotes, direction]) self.gameFSM.request('waitServerChoices') def setServerChoices(self, votes, directions, directionToGo, directionReason): if not self.hasLocalToon: return self.notify.debug('requesting displayVotes, curState=%s' % self.gameFSM.getCurrentState().getName()) self.gameFSM.request('displayVotes', [votes, directions, directionToGo, directionReason]) def __cleanupDialog(self, value): if self.dialog: self.dialog.cleanup() self.dialog = None return def displayVotesTimeoutTask(self, task): self.notify.debug('Done waiting for display votes') self.gameFSM.request('moveTrolley') return Task.done def updateCurrentVotes(self): for index in range(len(self.resultVotes)): avId = self.avIdList[index] oldCurrentVotes = self.currentVotes[avId] self.currentVotes[avId] -= self.resultVotes[index] self.putChoicesInScrollList() self.makeTextMatchChoice() def isLeaf(self, switchIndex): retval = False links = TravelGameGlobals.BoardLayouts[self.boardIndex][switchIndex]['links'] if len(links) == 0: retval = True return retval def __cleanupWinDialog(self, value): if hasattr(self, 'winDialog') and self.winDialog: self.winDialog.cleanup() self.winDialog = None return def gameOverCallback(self, task): self.__cleanupWinDialog(0) self.gameOver() return Task.done def setMinigames(self, switches, minigames): if not self.hasLocalToon: return self.switchToMinigameDict = {} for index in range(len(switches)): switch = switches[index] minigame = minigames[index] self.switchToMinigameDict[switch] = minigame self.notify.debug('minigameDict = %s' % self.switchToMinigameDict) self.loadMinigameIcons() def loadMinigameIcons(self): self.mg_icons = loader.loadModel('phase_4/models/minigames/mg_icons') for switch in self.switchToMinigameDict.keys(): minigame = self.switchToMinigameDict[switch] switchPos = self.trainSwitches[switch].getPos() labelPos = map3dToAspect2d(render, switchPos) useText = True iconName = None if minigame in IconDict.keys(): iconName = IconDict[minigame] icon = None if self.mg_icons: icon = self.mg_icons.find('**/%s' % iconName) if not icon.isEmpty(): useText = False if labelPos: if useText: labelPos.setZ(labelPos.getZ() - 0.1) label = DirectLabel(text=self.idToNames[minigame], relief=None, scale=0.1, pos=labelPos, text_fg=(1.0, 1.0, 1.0, 1.0)) label.hide() self.minigameLabels.append(label) else: placeHolder = DirectButton(image=icon, relief=None, text=('', '', self.idToNames[minigame], ''), text_scale=0.3, text_pos=(0, -0.7, 0), text_fg=(1, 1, 1, 1), clickSound=None, pressEffect=0) placeHolder.setPos(labelPos) placeHolder.setScale(0.2) placeHolder.hide() self.minigameIcons.append(placeHolder) tunnel = self.tunnels[switch] sign = tunnel.attachNewNode('sign') icon.copyTo(sign) sign.setH(-90) sign.setZ(26) sign.setScale(10) return def showMinigamesAndBonuses(self): for label in self.minigameLabels: label.show() for label in self.bonusLabels: label.show() for icon in self.minigameIcons: icon.show() def hideMinigamesAndBonuses(self): for label in self.minigameLabels: label.hide() for label in self.bonusLabels: label.hide() for icon in self.minigameIcons: icon.hide() def loadBonuses(self): self.switchToBonusLabelDict = {} for avId in self.avIdBonuses.keys(): if avId == self.localAvId: switch = self.avIdBonuses[avId][0] beans = self.avIdBonuses[avId][1] switchPos = self.trainSwitches[switch].getPos() labelPos = map3dToAspect2d(render, switchPos) if labelPos: labelPos.setX(labelPos.getX() + 0.1) labelPos.setZ(labelPos.getZ() - 0.02) bonusStr = TTLocalizer.TravelGameBonusBeans % {'numBeans': beans} label = DirectLabel(text=bonusStr, relief=None, scale=0.1, pos=labelPos, text_fg=(1.0, 1.0, 1.0, 1.0), text_align=TextNode.ALeft) label.hide() self.bonusLabels.append(label) self.switchToBonusLabelDict[switch] = label break return def setBonuses(self, switches, beans): if not self.hasLocalToon: return self.avIdBonuses = {} for index in range(len(self.avIdList)): avId = self.avIdList[index] switch = switches[index] bean = beans[index] self.avIdBonuses[avId] = (switch, bean) self.notify.debug('self.avIdBonuses = %s' % self.avIdBonuses) self.loadBonuses() def handleDisabledAvatar(self, avId): self.notify.warning('DistrbutedTravelGame: handleDisabledAvatar: disabled avId: ' + str(avId)) self.disconnectedAvIds.append(avId) def setBoardIndex(self, boardIndex): self.boardIndex = boardIndex def getIntroMovie(self): rootInfo = TravelGameGlobals.BoardLayouts[self.boardIndex][0] rootX, rootY, rootZ = rootInfo['pos'] startX = rootX - TravelGameGlobals.xInc heading = 90 moveTrolley = Sequence() moveTrolley.append(Func(self.trolleyCar.setH, 90)) moveTrolley.append(LerpPosInterval(self.trolleyCar, 3, Vec3(rootX, rootY, 0), startPos=Vec3(startX, rootY, 0))) moveTrolley.append(LerpHprInterval(self.trolleyCar, 1, Vec3(heading, 0, 0))) soundTrack = Sequence() trolleyExitAwayInterval = SoundInterval(self.trolleyAwaySfx, duration=3) trolleyExitBellInterval = SoundInterval(self.trolleyBellSfx, duration=1) soundTrack.append(trolleyExitAwayInterval) soundTrack.append(trolleyExitBellInterval) retval = Parallel(moveTrolley, soundTrack) return retval def animateTrolley(self, t, keyAngle, wheelAngle): for i in range(self.numKeys): key = self.keys[i] ref = self.keyRef[i] key.setH(ref, t * keyAngle) for i in range(self.numFrontWheels): frontWheel = self.frontWheels[i] ref = self.frontWheelRef[i] frontWheel.setH(ref, t * wheelAngle) for i in range(self.numBackWheels): backWheel = self.backWheels[i] ref = self.backWheelRef[i] backWheel.setH(ref, t * wheelAngle) def resetAnimation(self): for i in range(self.numKeys): self.keys[i].setTransform(self.keyInit[i]) for i in range(self.numFrontWheels): self.frontWheels[i].setTransform(self.frontWheelInit[i]) for i in range(self.numBackWheels): self.backWheels[i].setTransform(self.backWheelInit[i])