from panda3d.core import * from direct.directnotify import DirectNotifyGlobal from direct.task.Task import Task from direct.distributed.ClockDelta import * from direct.fsm.FSM import FSM from direct.interval.IntervalGlobal import * from toontown.racing.DistributedKartPad import DistributedKartPad from toontown.racing import RaceGlobals from toontown.toonbase.ToontownTimer import ToontownTimer from toontown.toonbase import TTLocalizer from toontown.toonbase import ToontownGlobals from toontown.racing.KartShopGlobals import KartGlobals class DistributedRacePad(DistributedKartPad, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedRacePad') defaultTransitions = {'Off': ['WaitEmpty'], 'WaitEmpty': ['WaitCountdown', 'Off'], 'WaitCountdown': ['WaitEmpty', 'WaitBoarding', 'Off', 'AllAboard'], 'WaitBoarding': ['AllAboard', 'WaitEmpty', 'Off'], 'AllAboard': ['Off', 'WaitEmpty', 'WaitCountdown']} id = 0 def __init__(self, cr): self.cr = cr DistributedKartPad.__init__(self, cr) FSM.__init__(self, 'RacePad_%s_FSM' % self.id) self.id = DistributedRacePad.id DistributedRacePad.id += 1 self.trackId = None self.trackType = None self.timeStamp = None self.clockNodepath = None self.timerTask = None self.tunnelSign = None self.trackNameNode = None self.tunnelSignInterval = None return def disable(self): self.notify.debug('Disable') self.ignore('enterPlayground') self.request('Off') if self.tunnelSignInterval: self.tunnelSignInterval = None DistributedKartPad.disable(self) return def enableStartingBlocks(self): self.notify.debug('Enabling starting blocks') for block in self.startingBlocks: block.setActive(0) def disableStartingBlocks(self): for block in self.startingBlocks: self.notify.debug('Disabling kart block: %s' % block.getDoId()) block.setActive(1) def isPractice(self): return self.trackType == RaceGlobals.Practice def setState(self, state, timestamp): self.request(state, [timestamp]) def setRaceZone(self, zoneId): for block in self.startingBlocks: if block.avId == base.localAvatar.getDoId(): hoodId = self.cr.playGame.hood.hoodId self.cr.playGame.getPlace().doneStatus = {'loader': 'racetrack', 'where': 'racetrack', 'zoneId': zoneId, 'trackId': self.trackId, 'hoodId': hoodId} messenger.send(base.cr.playGame.getPlace().doneEvent) def setTrackInfo(self, trackInfo): if self.isDisabled(): return self.trackId, self.trackType = trackInfo self.notify.debugStateCall(self) self.setTunnelSignText() self.ignore('enterPlayground') self.acceptOnce('enterPlayground', self.setTunnelSignText) def enterOff(self): self.notify.debug('enterOff: Entering Off State for RacePad %s' % self.id) if self.tunnelSignInterval: self.tunnelSignInterval.finish() self.cleanupTunnelText() def exitOff(self): self.notify.debug('exitOff: Exiting Off state for RacePad %s' % self.id) def enterWaitEmpty(self, args): self.notify.debug('enterWaitEmpty: Entering WaitEmpty State for RacePad %s' % self.id) if self.tunnelSignInterval: self.tunnelSignInterval.finish() def exitWaitEmpty(self): self.notify.debug('exitWaitEmpty: Exiting WaitEmpty State for RacePad %s' % self.id) def enterWaitCountdown(self, args): self.notify.debug('enterWaitCountdown: Entering WaitCountdown State for RacePad %s' % self.id) self.timeStamp = args[0] self.startCountdown() def exitWaitCountdown(self): self.notify.debug('exitWaitCountdown: Exiting WaitCountdown State for RacePad %s' % self.id) self.stopCountdown() def enterWaitBoarding(self, args): self.notify.debug('enterWaitBoarding: Entering WaitBoarding State for RacePad %s' % self.id) self.timeStamp = args[0] for block in self.startingBlocks: block.hideGui() def exitWaitBoarding(self): self.notify.debug('exitWaitBoarding: Exiting WaitBording State for RacePad %s' % self.id) def enterAllAboard(self, args): self.notify.debug('enterAllAboard: Entering AllAboard State for RacePad %s' % self.id) for block in self.startingBlocks: block.request('Off') if block.av and block.kartNode: self.notify.debug('enterAllAboard: Avatar %s is in the race.' % block.av.doId) block.doExitToRaceTrack() def exitAllAboard(self): self.notify.debug('enterAllAboard: Exiting AllAboard State for RacePad %s' % self.id) def getTimestamp(self, avId = None): error = 'DistributedRacePad::getTimeStamp - timestamp not yet set!' return self.timeStamp def stopCountdown(self): if self.timerTask: taskMgr.remove(self.timerTask) self.clockNodepath.removeNode() self.clockNodepath = None self.clockNode = None self.timerTask = None return def updateTimerTask(self, task): countdownTime = int(task.duration - task.time) timeStr = str(countdownTime) if self.clockNode.getText() != timeStr: self.clockNode.setText(timeStr) if task.time >= task.duration: return Task.done else: return Task.cont def startCountdown(self): if not self.timerTask and self.startingBlocks: self.makeClockGui() duration = KartGlobals.COUNTDOWN_TIME - globalClockDelta.localElapsedTime(self.getTimestamp()) countdownTask = Task(self.updateTimerTask) countdownTask.duration = duration self.timerTask = taskMgr.add(countdownTask, self.uniqueName('racePadTimerTask')) def addStartingBlock(self, block): DistributedKartPad.addStartingBlock(self, block) if self.state == 'WaitCountdown': self.startCountdown() def makeClockGui(self): self.notify.debugStateCall(self) if self.clockNodepath is not None: return self.clockNode, self.clockNodepath = self.getSignTextNodes('racePadClock') self.clockNodepath.setPos(0, 0.125, -3.0) self.clockNodepath.setScale(2.5) self.clockNodepath.flattenLight() return def getTunnelSign(self): cPadId = RaceGlobals.RaceInfo2RacePadId(self.trackId, self.trackType) genreId = RaceGlobals.getTrackGenre(self.trackId) tunnelName = RaceGlobals.getTunnelSignName(genreId, cPadId) self.tunnelSign = self.cr.playGame.hood.loader.geom.find('**/' + tunnelName) def getSignTextNodes(self, nodeName, font = ToontownGlobals.getSignFont()): signTextNode = TextNode(nodeName) signTextNode.setFont(font) signTextNode.setAlign(TextNode.ACenter) signTextNode.setTextColor(0.5, 0.5, 0.5, 1) signTextNodepath = self.tunnelSign.attachNewNode(signTextNode) signTextNodepath.setPos(0, 0.25, 0) signTextNodepath.setH(165.0) signTextNodepath.setDepthWrite(0) return (signTextNode, signTextNodepath) def setTunnelSignText(self): self.notify.debugStateCall(self) self.getTunnelSign() if not self.tunnelSign or self.tunnelSign.isEmpty(): return if not self.trackNameNode: self.makeTextNodes() if self.tunnelSignInterval: self.tunnelSignInterval.finish() self.tunnelSignInterval = Sequence(Func(self.hideTunnelSignText), Wait(0.2), Func(self.showTunnelSignText), Wait(0.2), Func(self.hideTunnelSignText), Wait(0.2), Func(self.showTunnelSignText), Wait(0.2), Func(self.hideTunnelSignText), Wait(0.2), Func(self.updateTunnelSignText), Func(self.showTunnelSignText)) self.tunnelSignInterval.start() def hideTunnelSignText(self): if self.tunnelSign: textNodePaths = self.tunnelSign.findAllMatches('**/+TextNode') numTextNodePaths = textNodePaths.getNumPaths() for i in range(numTextNodePaths): textNodePath = textNodePaths.getPath(i) textNodePath.hide() def showTunnelSignText(self): if self.tunnelSign: textNodePaths = self.tunnelSign.findAllMatches('**/+TextNode') numTextNodePaths = textNodePaths.getNumPaths() for i in range(numTextNodePaths): textNodePath = textNodePaths.getPath(i) textNodePath.show() def updateTunnelSignText(self): self.notify.debugStateCall(self) trackNameString = TTLocalizer.KartRace_TrackNames[self.trackId] if not self.trackNameNode: self.notify.warning('invalid trackNameNode, just returning') return self.trackNameNode.setText(trackNameString) trackTypeString = TTLocalizer.KartRace_RaceNames[self.trackType] self.trackTypeNode.setText(trackTypeString) deposit = 0 if self.trackType: deposit = RaceGlobals.getEntryFee(self.trackId, self.trackType) depositString = TTLocalizer.KartRace_DepositPhrase + str(deposit) self.depositNode.setText(depositString) time = RaceGlobals.TrackDict[self.trackId][1] secs, hundredths = divmod(time, 1) min, sec = divmod(secs, 60) timeText = '%02d:%02d:%02d' % (min, sec, hundredths * 100) qualifyString = TTLocalizer.KartRace_QualifyPhrase + timeText self.qualifyNode.setText(qualifyString) def makeTextNodes(self): self.notify.debugStateCall(self) self.trackNameNode, trackNameNodePath = self.getSignTextNodes('trackNameNode') trackNameNodePath.setZ(0.7) trackNameNodePath.setScale(0.875) trackNameNodePath.flattenLight() self.trackTypeNode, trackTypeNodePath = self.getSignTextNodes('trackTypeNode') trackTypeNodePath.setZ(-0.35) trackTypeNodePath.setScale(0.875) trackTypeNodePath.flattenLight() self.depositNode, depositNodePath = self.getSignTextNodes('depositNode', ToontownGlobals.getToonFont()) self.depositNode.setTextColor(0, 0, 0, 1) depositNodePath.setPos(4.0, -1.0, -2.0) depositNodePath.setScale(0.75) depositNodePath.flattenLight() self.qualifyNode, qualifyNodePath = self.getSignTextNodes('qualifyNode', ToontownGlobals.getToonFont()) self.qualifyNode.setTextColor(0, 0, 0, 1) qualifyNodePath.setPos(-4.0, 1.2, -2.0) qualifyNodePath.setScale(0.75) qualifyNodePath.flattenLight() def cleanupTunnelText(self): self.notify.debugStateCall(self) if self.tunnelSign: textNodePaths = self.tunnelSign.findAllMatches('**/+TextNode') numTextNodePaths = textNodePaths.getNumPaths() for i in range(numTextNodePaths): textNodePath = textNodePaths.getPath(i) textNodePath.removeNode() textNodePath = None self.tunnelSign = None self.trackNameNode = None return