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 value not in index: 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.loadSfx('phase_4/audio/sfx/SZ_trolley_away.ogg') self.trolleyBellSfx = base.loadSfx('phase_4/audio/sfx/SZ_trolley_bell.ogg') self.turntableRotateSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_turntble_rotate_2.ogg') self.wonGameSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_bonus.ogg') self.lostGameSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_no_bonus_2.ogg') self.noWinnerSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_no_bonus.ogg') 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 xrange(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 xrange(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 xrange(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 depthOffset = 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, depthOffset) trainTrack.reparentTo(hidden) self.trainTracks[linkKey] = trainTrack depthOffset += 3 switchModel.setDepthOffset(depthOffset) rootInfo = TravelGameGlobals.BoardLayouts[self.boardIndex][0] rootX, rootY, rootZ = rootInfo['pos'] startX = rootX - TravelGameGlobals.xInc tempModel = loader.loadModel('phase_4/models/minigames/trolley_game_turntable') self.entryTunnel = tempModel.find('**/tunnel1') self.entryTunnel.reparentTo(render) self.entryTunnel.setH(180) self.entryTunnel.setPos(startX, rootY, rootZ) tempModel.removeNode() 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 self.clipPlane = render.attachNewNode(PlaneNode('clipPlane')) self.clipPlane.setR(-90) self.clipPlane.setX(tunnelX) self.trolleyCar.setClipPlane(self.clipPlane) turnTable.removeNode() self.loadGui() self.introMovie = self.getIntroMovie() self.music = base.loadMusic('phase_4/audio/bgm/MG_Travel.ogg') self.flashWinningBeansTrack = None return def loadTrainTrack(self, x1, y1, x2, y2, depthOffset = 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) trainTrack.setDepthOffset(depthOffset) 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.clipPlane.removeNode() del self.clipPlane self.entryTunnel.removeNode() del self.entryTunnel 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.setForceOnscreenChat(True) 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.setForceOnscreenChat(False) 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 xrange(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.setForceOnscreenChat(True) 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.setForceOnscreenChat(False) 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 xrange(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 xrange(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 xrange(len(self.avIdList)): avId = self.avIdList[index] self.startingVotes[avId] = startingVotesArray[index] if avId not in self.currentVotes: 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 xrange(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 xrange(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 selectedIndex in self.indexToVotes: 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 setAvatarVotes(self, avId, votes): if not self.hasLocalToon: return self.currentVotes[avId] = votes 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 xrange(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 xrange(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 xrange(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 xrange(self.numKeys): key = self.keys[i] ref = self.keyRef[i] key.setH(ref, t * keyAngle) for i in xrange(self.numFrontWheels): frontWheel = self.frontWheels[i] ref = self.frontWheelRef[i] frontWheel.setH(ref, t * wheelAngle) for i in xrange(self.numBackWheels): backWheel = self.backWheels[i] ref = self.backWheelRef[i] backWheel.setH(ref, t * wheelAngle) def resetAnimation(self): for i in xrange(self.numKeys): self.keys[i].setTransform(self.keyInit[i]) for i in xrange(self.numFrontWheels): self.frontWheels[i].setTransform(self.frontWheelInit[i]) for i in xrange(self.numBackWheels): self.backWheels[i].setTransform(self.backWheelInit[i])