class DistributedStartingBlock(DistributedObject.DistributedObject, FSM): """ Purpose: MUST ADD COMMENTS HERE. """ ###################################################################### # Class Variables ###################################################################### notify = DirectNotifyGlobal.directNotify.newCategory( "DistributedStartingBlock") sphereRadius = 1.5 id = 0 cameraPos = Point3(0, -23, 10) cameraHpr = Point3(0, -10, 0) SFX_BaseDir = "phase_6/audio/sfx/" SFX_KartAppear = SFX_BaseDir + "KART_Appear.mp3" defaultTransitions = { 'Off': ['EnterMovie'], 'EnterMovie': ['Off', 'Waiting', 'ExitMovie'], 'Waiting': ['ExitMovie', 'Off'], 'ExitMovie': ['Off', 'ExitMovie'] } def __init__(self, cr): """ comment """ # Initialize the Super Class DistributedObject.DistributedObject.__init__(self, cr) FSM.__init__(self, "staringBlock_%s_FSM" % (DistributedStartingBlock.id)) # Initialize Instance Variables self.avId = 0 self.av = None self.lastAvId = 0 self.avatar = None self.kartPad = None self.collNode = None self.movieNode = None self.movieTrack = None self.collSphere = None self.collNodePath = None self.localToonKarting = 0 self.kartNode = None self.kart = None self.holeActor = None self.exitRequested = False if (__debug__): # FOR LOD TESTING - should really move this to a config_variable. self.testLOD = False self.id = DistributedStartingBlock.id DistributedStartingBlock.id += 1 def disable(self): """ Comment """ FSM.cleanup(self) #self.notify.debugStateCall( self ) self.ignore(self.uniqueName('enterStartingBlockSphere')) self.ignore("stoppedAsleep") self.setOccupied(0) self.avId = 0 self.nodePath.detachNode() self.kartPad = None if self.holeActor: self.holeActor.cleanup() self.holeActor = None # Call Super Class Disable Routine DistributedObject.DistributedObject.disable(self) def delete(self): """ comment """ #self.notify.debugStateCall( self ) #if( __debug__ ): #self.smiley.remove() #self.smiley2.remove() if (hasattr(self, 'dialog')): if (not self.dialog.removed()): self.dialog.ignoreAll() if (not self.dialog.isEmpty()): self.dialog.cleanup() del self.dialog self.finishMovie() if (hasattr(self, 'cancelButton')): self.cancelButton.destroy() del self.cancelButton del self.kartPad if (self.nodePath): self.nodePath.removeNode() del self.nodePath # Call Super Class Delete Method DistributedObject.DistributedObject.delete(self) def generateInit(self): """ comment """ self.notify.debugStateCall(self) DistributedObject.DistributedObject.generateInit(self) # Create a NodePath to represent the spot itself. It gets # repositioned according to setPosHpr. self.nodePath = NodePath(self.uniqueName('StartingBlock')) # Make a collision sphere to detect when an avatar enters the # kart block. self.collSphere = CollisionSphere(0, 0, 0, self.sphereRadius) # Make sure the sphere is intangible initially. self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) #self.collNodePath.show() def announceGenerate(self): """ Comment """ self.notify.debugStateCall(self) DistributedObject.DistributedObject.announceGenerate(self) # The posHpr has been set at this point, thus reparent to render # and accept the collision sphere event. #if( __debug__ ): # self.smiley = loader.loadModel( "models/misc/smiley" ) # self.smiley.setScale( 0.25 ) # self.smiley.setColorScale( 1, 0, 0, 1 ) # self.smiley.reparentTo( self.nodePath ) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadDoId(self, padDoId): """ comment """ self.notify.debugStateCall(self) # Create Reference to Pad and add the block to the # Pad's references as well. self.kartPad = base.cr.doId2do.get(padDoId) self.kartPad.addStartingBlock(self) def setPosHpr(self, x, y, z, h, p, r): """ """ self.notify.debugStateCall(self) self.nodePath.setPosHpr(x, y, z, h + 180, 0, 0) def setPadLocationId(self, padLocationId): """ """ self.notify.debugStateCall(self) # Generate a new node on the nodepath. self.movieNode = self.nodePath.attachNewNode( self.uniqueName('MovieNode')) self.exitMovieNode = self.movieNode if (padLocationId % 2): # padLocation is on the right-side, thus the view node should # be placed on the right-side. self.movieNode.setPosHpr(3.0, 0, 0, 90.0, 0, 0) else: # otherwise its on the left-side. self.movieNode.setPosHpr(-3.0, 0, 0, -90.0, 0, 0) #if( __debug__ ): # self.smiley2 = loader.loadModel( "models/misc/smiley" ) # self.smiley2.setScale( 0.2 ) # self.smiley2.setColorScale( 0, 1, 0, 1 ) # self.smiley2.reparentTo( self.movieNode ) def setActive(self, isTangible): """ Comment: """ self.collSphere.setTangible(isTangible) def __handleEnterSphere(self, collEntry): """ comment """ assert self.notify.debug("__handleEnterSphere") # Protect against the same toon from re-entering the sphere # immediately after exiting. It is most likely a mistake on the # toon's part. if( base.localAvatar.doId == self.lastAvId and \ globalClock.getFrameCount() <= self.lastFrame + 1 ): self.notify.debug("Ignoring duplicate entry for avatar.") return # Only toons with hp > 0 and own a kart may enter the sphere. if ((base.localAvatar.hp > 0)): def handleEnterRequest(self=self): self.ignore("stoppedAsleep") if hasattr(self.dialog, 'doneStatus') and (self.dialog.doneStatus == 'ok'): self.d_requestEnter(base.cr.isPaid()) else: if self.cr and not self.isDisabled(): self.cr.playGame.getPlace().setState("walk") else: self.notify.warning( "Warning! Object has already been disabled.") self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog # take the localToon out of walk mode self.cr.playGame.getPlace().fsm.request('stopped') # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleEnterRequest) # A dialog box should prompt the toon for action, to either # enter a race or ignore it. doneEvent = 'enterRequest|dialog' if (self.kartPad.isPractice()): msg = TTLocalizer.StartingBlock_EnterPractice else: raceName = TTLocalizer.KartRace_RaceNames[ self.kartPad.trackType] numTickets = RaceGlobals.getEntryFee(self.kartPad.trackId, self.kartPad.trackType) msg = TTLocalizer.StartingBlock_EnterNonPractice % (raceName, numTickets) self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) #self.d_requestEnter() ###################################################################### # Distributed Methods ###################################################################### def d_movieFinished(self): """ """ self.notify.debugStateCall(self) self.sendUpdate("movieFinished", []) def d_requestEnter(self, paid): """ """ self.notify.debugStateCall(self) self.sendUpdate("requestEnter", [paid]) def d_requestExit(self): """ """ self.notify.debugStateCall(self) self.exitRequested = True self.hideGui() self.sendUpdate("requestExit", []) def rejectEnter(self, errCode): """ """ self.notify.debugStateCall(self) def handleTicketError(self=self): self.ignore("stoppedAsleep") self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().setState("walk") doneEvent = 'errorCode|dialog' if (errCode == KartGlobals.ERROR_CODE.eTickets): msg = TTLocalizer.StartingBlock_NotEnoughTickets self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleTicketError) elif (errCode == KartGlobals.ERROR_CODE.eBoardOver): msg = TTLocalizer.StartingBlock_NoBoard self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleTicketError) elif (errCode == KartGlobals.ERROR_CODE.eNoKart): msg = TTLocalizer.StartingBlock_NoKart self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleTicketError) elif (errCode == KartGlobals.ERROR_CODE.eOccupied): msg = TTLocalizer.StartingBlock_Occupied self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleTicketError) elif (errCode == KartGlobals.ERROR_CODE.eTrackClosed): msg = TTLocalizer.StartingBlock_TrackClosed self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleTicketError) elif (errCode == KartGlobals.ERROR_CODE.eUnpaid): self.dialog = TeaserPanel(pageName="karting", doneFunc=handleTicketError) else: self.cr.playGame.getPlace().setState("walk") def finishMovie(self): if self.movieTrack: self.movieTrack.finish() self.movieTrack = None def setOccupied(self, avId): """ """ self.notify.debug("%d setOccupied: %d" % (self.doId, avId)) # Check if there is a current avatar in the spot. if (self.av != None): # make sure any movies playing are done self.finishMovie() if (not self.av.isEmpty() and not self.av.isDisabled()): self.av.loop('neutral') self.av.setParent(ToontownGlobals.SPRender) self.av.startSmooth() # make sure any movies playing are done self.finishMovie() if self.kart: self.kart.delete() self.kart = None # remove the kart node if self.kartNode: self.kartNode.removeNode() self.kartNode = None self.placedAvatar = 0 self.ignore(self.av.uniqueName("disable")) self.av = None assert self.kart == None # Store avatar and frame information wasLocalToon = self.localToonKarting self.lastAvId = self.avId self.lastFrame = globalClock.getFrameCount() # Update new information self.avId = avId self.localToonKarting = 0 if (self.avId == 0): # The Kart Block is now available. self.collSphere.setTangible(0) self.request("Off") else: # The Kart block is now occupied; no one else may be here. self.collSphere.setTangible(1) av = self.cr.doId2do.get(self.avId) self.placedAvatar = 0 if (self.avId == base.localAvatar.doId): self.localToonKarting = 1 if (av != None): self.av = av self.av.stopSmooth() self.placedAvatar = 0 self.acceptOnce(self.av.uniqueName("disable"), self.__avatarGone) # Create a kart node self.kartNode = render.attachNewNode( self.av.uniqueName('KartNode')) self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) # Create the kart assert self.kart == None self.kart = Kart() self.kart.baseScale = 1.6 self.kart.setDNA(self.av.getKartDNA()) # Generate the actual kart. self.kart.generateKart() self.kart.resetGeomPos() # Parent the Avatar to the kart block. self.av.wrtReparentTo(self.nodePath) self.av.setAnimState('neutral', 1.0) if not self.localToonKarting: av.stopSmooth() self.__placeAvatar() self.avParent = av.getParent() else: self.notify.warning("Unknown avatar %d in kart block %d " % (self.avId, self.doId)) # make sure we don't try to play any movies here, but # let the next setOccupied (to 0 hopefully) reset # the starting block self.avId = 0 # If the local toon was involved but is no longer, restore # walk mode. We do this down here, after we have twiddled # with the tangible flag, so that the toon must walk out and # walk back in again in order to generate the enter event # again. if wasLocalToon and not self.localToonKarting: # Reset to walk mode, but not if we're exiting all the way # out (and our place is already gone). place = base.cr.playGame.getPlace() if place: # check to see if the toon requested the exit, or was booted if self.exitRequested: place.setState('walk') else: # the toon was booted off the block def handleDialogOK(self=self): self.ignore("stoppedAsleep") place.setState("walk") self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog doneEvent = 'kickedOutDialog' msg = TTLocalizer.StartingBlock_KickSoloRacer self.dialog = TTGlobalDialog(msg, doneEvent, style=1) self.dialog.accept(doneEvent, handleDialogOK) # make dialog go away if they fall asleep while stopped self.accept("stoppedAsleep", handleDialogOK) def __avatarGone(self): self.notify.debugStateCall(self) # Called when the avatar in the kart block vanishes. The AI will # call setOccupied( 0 ) as well, but the client calls it first # just to be on the safe side, so that it doesn't try to access a # non-existent avatar. self.setOccupied(0) def __placeAvatar(self): self.notify.debugStateCall(self) # Places the avatar at the Kart Block, mainly for the # benefit of those who did not observe the EnterMovie. if (not self.placedAvatar): self.placedAvatar = 1 self.av.setPosHpr(0, 0, 0, 0, 0, 0) def setMovie(self, mode): """ """ self.notify.debugStateCall(self) if (self.avId == 0): return # make sure to finish any currently playing movie self.finishMovie() if (mode == 0): pass elif (mode == KartGlobals.ENTER_MOVIE): self.request("EnterMovie") elif (mode == KartGlobals.EXIT_MOVIE): self.request("ExitMovie") else: pass def makeGui(self): self.notify.debugStateCall(self) # Check if the timer exists, if so then the gui has been # made. if (hasattr(self, 'cancelButton')): return fishGui = loader.loadModel("phase_4/models/gui/fishingGui") self.cancelButton = DirectGui.DirectButton( relief=None, scale=(0.67), pos=(-0.133, 0.0, 0.13), #pos = (0,0,0), text=("", TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), textMayChange=0, text_scale=0.1, image=(fishGui.find("**/exit_buttonUp"), fishGui.find("**/exit_buttonDown"), fishGui.find("**/exit_buttonRollover")), text_font=ToontownGlobals.getInterfaceFont(), command=self.d_requestExit, parent=base.a2dBottomRight #pressEffect = False, ) self.cancelButton.hide() def showGui(self): """ """ self.notify.debugStateCall(self) # hack to make sure we don't show the exit button # during the 'WaitBoarding' state on race starting blocks if hasattr(self.kartPad, 'state'): if not self.kartPad.state == 'WaitCountdown': return self.cancelButton.show() def hideGui(self): self.notify.debugStateCall(self) if (not hasattr(self, 'cancelButton')): return self.cancelButton.hide() def generateToonMoveTrack(self): """ """ hpr = self.movieNode.getHpr(render) heading = PythonUtil.fitDestAngle2Src(self.av.getH(render), hpr[0]) hpr.setX(heading) self.av.setAnimState('run', 1.0) toonTrack = Sequence( Wait(0.5), Parallel( LerpPosInterval( self.av, 1., Point3(self.movieNode.getX(self.avParent), self.movieNode.getY(self.avParent), 0)), #other = self.nodePath ), LerpHprInterval(self.av, 1., hpr=hpr, other=render)), Func(self.av.loop, 'neutral'), ) return toonTrack def generateKartAppearTrack(self): """ """ if (not self.av): # Obtain the toon's kart if not self.kartNode: self.kartNode = render.attachNewNode(str(self) + 'kartNode') self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) self.kart.setScale(0.85) self.kart.reparentTo(self.kartNode) return Parallel() self.kart.setScale(0.1) kartTrack = Parallel( Sequence(ActorInterval(self.av, "feedPet"), Func(self.av.loop, 'neutral')), Sequence( Func(self.kart.setActiveShadow, False), Func(self.kart.reparentTo, self.av.rightHand), #Func( self.kart.setPos, .1, 0, .2 ), Wait(2.1), Func(self.kart.wrtReparentTo, render), Func(self.kart.setShear, 0, 0, 0), Parallel( LerpHprInterval(self.kart, hpr=self.kartNode.getHpr(render), duration=1.2), ProjectileInterval(self.kart, endPos=self.kartNode.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Func(self.kart.setActiveShadow, True), # Must be a cleaner way to do this. Sequence( LerpScaleInterval(self.kart, scale=Point3(1.1, 1.1, .1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(.9, .9, .1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1., 1., .1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1., 1., 1.1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(1., 1., .9), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1., 1., 1.), duration=0.1), Func(self.kart.wrtReparentTo, self.kartNode)))) return kartTrack def generateToonJumpTrack(self): """ """ # Maintain a reference to Parent and Scale of avatar in case they # exit from the kart. base.sb = self def getToonJumpTrack(av, kart): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=kart.toonNode[0]): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av=av, node=kart.toonNode[0]): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=.9), ProjectileInterval(av, endPos=getJumpDest, duration=.9)), )) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(self.av, self.kart) toonSitTrack = getToonSitTrack(self.av) jumpTrack = Sequence( Parallel( toonJumpTrack, Sequence( Wait(1), toonSitTrack, ), ), #Func( self.av.setPosHpr, 0, 0, 0, 0, 0, 0 ), Func(self.av.setPosHpr, 0, .45, -.25, 0, 0, 0), Func(self.av.reparentTo, self.kart.toonSeat), #Func( self.av.setScale, self.kart.accGeomScale/self.kart.baseScale ), #toonSitTrack, #Func( self.av.wrtReparentTo, self.kart.rotateNode ) ) return jumpTrack def generateToonReverseJumpTrack(self): """ """ def getToonJumpTrack(av, destNode): # using a local func allows the ProjectileInterval to # calculate this pos at run-time def getJumpDest(av=av, node=destNode): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av=av, node=destNode): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.1), #43 ), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=.9), ProjectileInterval(av, endPos=getJumpDest, duration=.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(self.av, self.exitMovieNode) jumpTrack = Sequence( toonJumpTrack, Func(self.av.loop, 'neutral'), Func(self.av.reparentTo, render), Func(self.av.setPosHpr, self.exitMovieNode, 0, 0, 0, 0, 0, 0), ) return jumpTrack def generateCameraMoveTrack(self): """ """ self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, self.cameraPos, self.cameraHpr) return cameraTrack def generateCameraReturnMoveTrack(self): cameraTrack = Sequence( Func(camera.wrtReparentTo, self.av), LerpPosHprInterval(camera, 1.5, self.cPos, self.cHpr)) return cameraTrack def generateKartDisappearTrack(self): def getHoleTrack(hole, holeParent): holeTrack = Sequence( Wait(.2), Func(hole.setBin, 'shadow', 0), Func(hole.setDepthTest, 0), Func(hole.setDepthWrite, 0), Func(hole.reparentTo, holeParent), Func(hole.setPos, holeParent, Point3(0, 0.0, -.6)), ActorInterval(hole, 'hole', startTime=3.4, endTime=3.1), Wait(0.4), ActorInterval(hole, 'hole', startTime=3.1, endTime=3.4)) return holeTrack def getKartShrinkTrack(kart): pos = kart.getPos() pos.addZ(-1.) kartTrack = Sequence( LerpScaleInterval(kart, scale=Point3(1., 1., .9), duration=0.1), LerpScaleInterval(kart, scale=Point3(1., 1., 1.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1., 1., .1), duration=0.2), LerpScaleInterval(kart, scale=Point3(.9, .9, .1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.1, 1.1, .1), duration=0.1), LerpScaleInterval(kart, scale=Point3(.1, .1, .1), duration=0.2), Wait(0.2), LerpPosInterval(kart, pos=pos, duration=0.2), Func(kart.hide), ) return kartTrack if not self.holeActor: self.holeActor = Actor.Actor( 'phase_3.5/models/props/portal-mod', {'hole': 'phase_3.5/models/props/portal-chan'}) holeTrack = getHoleTrack(self.holeActor, self.kartNode) shrinkTrack = getKartShrinkTrack(self.kart) kartTrack = Parallel(shrinkTrack, holeTrack) return kartTrack ###################################################################### # State Transitions ###################################################################### def enterOff(self): """ """ self.notify.debug("%d enterOff: Entering the Off State." % self.doId) self.hideGui() def exitOff(self): """ """ self.notify.debug("%d exitOff: Exiting the Off State." % self.doId) def enterEnterMovie(self): """ """ #pdb.set_trace() self.notify.debug( "%d enterEnterMovie: Entering the Enter Movie State." % self.doId) if ConfigVariableBool('want-qa-regression', 0).getValue(): raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) # Obtain the Enter Movie Tracks toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName("EnterRaceTrack") if ((self.av is not None) and (self.localToonKarting)): kartAppearSfx = base.loader.loadSfx(self.SFX_KartAppear) cameraTrack = self.generateCameraMoveTrack() engineStartTrack = self.kart.generateEngineStartTrack() self.finishMovie() self.movieTrack = Sequence(Parallel( cameraTrack, toonTrack, ), Parallel( SoundInterval(kartAppearSfx), Sequence( kartTrack, jumpTrack, engineStartTrack, Func(self.makeGui), Func(self.showGui), Func(self.request, "Waiting"), Func(self.d_movieFinished)), ), name=name, autoFinish=1) self.exitRequested = False else: self.finishMovie() self.movieTrack = Sequence( toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1, ) self.movieTrack.start() def exitEnterMovie(self): """ """ self.notify.debug("%d exitEnterMovie: Exiting the Enter Movie State." % self.doId) def enterWaiting(self): """ """ self.notify.debug("%d enterWaiting: Entering the Waiting State." % self.doId) def exitWaiting(self): """ """ self.notify.debug("%d exitWaiting: Exiting the Waiting State." % self.doId) def enterExitMovie(self): """ """ self.notify.debug("%d enterExitMovie: Entering the Exit Movie State." % self.doId) # this should be hidden by now... but just in case. self.hideGui() jumpTrack = self.generateToonReverseJumpTrack() kartTrack = self.generateKartDisappearTrack() self.finishMovie() self.movieTrack = Sequence(Func(self.kart.kartLoopSfx.stop), jumpTrack, kartTrack, name=self.av.uniqueName("ExitRaceTrack"), autoFinish=1) if ((self.av is not None) and (self.localToonKarting)): cameraTrack = self.generateCameraReturnMoveTrack() self.movieTrack.append(cameraTrack) self.movieTrack.append(Func(self.d_movieFinished)) self.movieTrack.start() def exitExitMovie(self): """ """ self.notify.debug("%d exitExitMovie: Exiting the Exit Movie State." % self.doId) #Moved up to SetOccupied #CHECK: IS THIS OKAY? #self.kartNode.removeNode() #del self.kartNode def doExitToRaceTrack(self): self.hideGui() self.finishMovie() # obtain old block position and the new position to move to. oldBlockPos = self.kartNode.getPos(render) self.kartNode.setPos(self.kartNode, 0, 40, 0) newBlockPos = self.kartNode.getPos(render) oldBlockScale = self.kartNode.getScale() # up kart lod self.kart.LODnode.setSwitch(0, 60, 0) # Set the old pos back self.kartNode.setPos(render, oldBlockPos) blockLerpIval = LerpPosInterval(self.kartNode, pos=newBlockPos, duration=2.0) scaleLerpIval = LerpScaleInterval(self.kartNode, scale=oldBlockScale * .2, duration=2.0) engineStopTrack = self.kart.generateEngineStopTrack(2) self.finishMovie() self.movieTrack = Parallel() if (self.av == base.localAvatar): # If we are the local avatar, then iris out. self.movieTrack.insert(0, Func(base.transitions.irisOut, 1.5, 0)) self.movieTrack.append(engineStopTrack), taskMgr.doMethodLater(1.6, self.bulkLoad, "loadIt", extraArgs=[]) self.movieTrack.append( Sequence( Parallel( blockLerpIval, scaleLerpIval, ), Func(self.kartNode.hide), Func(self.kartNode.setPos, render, oldBlockPos), Func(self.kartNode.setScale, oldBlockScale), )) self.movieTrack.start() def bulkLoad(self): base.loader.beginBulkLoad("atRace", TTLocalizer.StartingBlock_Loading, 60, 1, TTLocalizer.TIP_KARTING)
class DistributedStartingBlock(DistributedObject.DistributedObject, FSM): notify = DirectNotifyGlobal.directNotify.newCategory( 'DistributedStartingBlock') sphereRadius = 1.5 id = 0 cameraPos = Point3(0, -23, 10) cameraHpr = Point3(0, -10, 0) SFX_BaseDir = 'phase_6/audio/sfx/' SFX_KartAppear = SFX_BaseDir + 'KART_Appear.ogg' defaultTransitions = { 'Off': ['EnterMovie'], 'EnterMovie': ['Off', 'Waiting', 'ExitMovie'], 'Waiting': ['ExitMovie', 'Off'], 'ExitMovie': ['Off', 'ExitMovie'] } def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) FSM.__init__(self, 'staringBlock_%s_FSM' % DistributedStartingBlock.id) self.avId = 0 self.av = None self.lastAvId = 0 self.avatar = None self.kartPad = None self.collNode = None self.movieNode = None self.movieTrack = None self.collSphere = None self.collNodePath = None self.localToonKarting = 0 self.kartNode = None self.kart = None self.holeActor = None self.exitRequested = False if (__debug__): self.testLOD = False self.id = DistributedStartingBlock.id DistributedStartingBlock.id += 1 return def disable(self): FSM.cleanup(self) self.ignore(self.uniqueName('enterStartingBlockSphere')) self.ignore('stoppedAsleep') self.setOccupied(0) self.avId = 0 self.nodePath.detachNode() self.kartPad = None if self.holeActor: self.holeActor.cleanup() self.holeActor = None DistributedObject.DistributedObject.disable(self) return def delete(self): if hasattr(self, 'dialog'): if not self.dialog.removed(): self.dialog.ignoreAll() if not self.dialog.isEmpty(): self.dialog.cleanup() del self.dialog self.finishMovie() if hasattr(self, 'cancelButton'): self.cancelButton.destroy() del self.cancelButton del self.kartPad if self.nodePath: self.nodePath.removeNode() del self.nodePath DistributedObject.DistributedObject.delete(self) def generateInit(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('StartingBlock')) self.collSphere = CollisionSphere(0, 0, 0, self.sphereRadius) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) def announceGenerate(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.announceGenerate(self) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadDoId(self, padDoId): self.notify.debugStateCall(self) self.kartPad = base.cr.doId2do.get(padDoId) self.kartPad.addStartingBlock(self) def setPosHpr(self, x, y, z, h, p, r): self.notify.debugStateCall(self) self.nodePath.setPosHpr(x, y, z, h + 180, 0, 0) def setPadLocationId(self, padLocationId): self.notify.debugStateCall(self) self.movieNode = self.nodePath.attachNewNode( self.uniqueName('MovieNode')) self.exitMovieNode = self.movieNode if padLocationId % 2: self.movieNode.setPosHpr(3.0, 0, 0, 90.0, 0, 0) else: self.movieNode.setPosHpr(-3.0, 0, 0, -90.0, 0, 0) def setActive(self, isTangible): self.collSphere.setTangible(isTangible) def __handleEnterSphere(self, collEntry): if base.localAvatar.doId == self.lastAvId and globalClock.getFrameCount( ) <= self.lastFrame + 1: self.notify.debug('Ignoring duplicate entry for avatar.') return if base.localAvatar.hp > 0: def handleEnterRequest(self=self): self.ignore('stoppedAsleep') if hasattr(self.dialog, 'doneStatus') and self.dialog.doneStatus == 'ok': self.d_requestEnter() elif self.cr and not self.isDisabled(): self.cr.playGame.getPlace().setState('walk') else: self.notify.warning( 'Warning! Object has already been disabled.') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().fsm.request('stopped') self.accept('stoppedAsleep', handleEnterRequest) doneEvent = 'enterRequest|dialog' if self.kartPad.isPractice(): msg = TTLocalizer.StartingBlock_EnterPractice else: raceName = TTLocalizer.KartRace_RaceNames[ self.kartPad.trackType] numTickets = RaceGlobals.getEntryFee(self.kartPad.trackId, self.kartPad.trackType) msg = TTLocalizer.StartingBlock_EnterNonPractice % (raceName, numTickets) self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) def d_movieFinished(self): self.notify.debugStateCall(self) self.sendUpdate('movieFinished', []) def d_requestEnter(self): self.notify.debugStateCall(self) self.sendUpdate('requestEnter', []) def d_requestExit(self): self.notify.debugStateCall(self) self.exitRequested = True self.hideGui() self.sendUpdate('requestExit', []) def rejectEnter(self, errCode): self.notify.debugStateCall(self) def handleTicketError(self=self): self.ignore('stoppedAsleep') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().setState('walk') doneEvent = 'errorCode|dialog' if errCode == KartGlobals.ERROR_CODE.eTickets: msg = TTLocalizer.StartingBlock_NotEnoughTickets self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eBoardOver: msg = TTLocalizer.StartingBlock_NoBoard self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eNoKart: msg = TTLocalizer.StartingBlock_NoKart self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eOccupied: msg = TTLocalizer.StartingBlock_Occupied self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eTrackClosed: msg = TTLocalizer.StartingBlock_TrackClosed self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) else: self.cr.playGame.getPlace().setState('walk') def finishMovie(self): if self.movieTrack: self.movieTrack.finish() self.movieTrack = None return def setOccupied(self, avId): self.notify.debug('%d setOccupied: %d' % (self.doId, avId)) if self.av != None: self.finishMovie() if not self.av.isEmpty() and not self.av.isDisabled(): self.av.loop('neutral') self.av.setParent(ToontownGlobals.SPRender) self.av.startSmooth() self.finishMovie() if self.kart: self.kart.delete() self.kart = None if self.kartNode: self.kartNode.removeNode() self.kartNode = None self.placedAvatar = 0 self.ignore(self.av.uniqueName('disable')) self.av = None wasLocalToon = self.localToonKarting self.lastAvId = self.avId self.lastFrame = globalClock.getFrameCount() self.avId = avId self.localToonKarting = 0 if self.avId == 0: self.collSphere.setTangible(0) self.request('Off') else: self.collSphere.setTangible(1) av = self.cr.doId2do.get(self.avId) self.placedAvatar = 0 if self.avId == base.localAvatar.doId: self.localToonKarting = 1 if av != None: self.av = av self.av.stopSmooth() self.placedAvatar = 0 self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.kartNode = render.attachNewNode( self.av.uniqueName('KartNode')) self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) self.kart = Kart() self.kart.baseScale = 1.6 self.kart.setDNA(self.av.getKartDNA()) self.kart.generateKart() self.kart.resetGeomPos() self.av.wrtReparentTo(self.nodePath) self.av.setAnimState('neutral', 1.0) if not self.localToonKarting: av.stopSmooth() self.__placeAvatar() self.avParent = av.getParent() else: self.notify.warning('Unknown avatar %d in kart block %d ' % (self.avId, self.doId)) self.avId = 0 if wasLocalToon and not self.localToonKarting: place = base.cr.playGame.getPlace() if place: if self.exitRequested: place.setState('walk') else: def handleDialogOK(self=self): self.ignore('stoppedAsleep') place.setState('walk') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog doneEvent = 'kickedOutDialog' msg = TTLocalizer.StartingBlock_KickSoloRacer self.dialog = TTGlobalDialog(msg, doneEvent, style=1) self.dialog.accept(doneEvent, handleDialogOK) self.accept('stoppedAsleep', handleDialogOK) return def __avatarGone(self): self.notify.debugStateCall(self) self.setOccupied(0) def __placeAvatar(self): self.notify.debugStateCall(self) if not self.placedAvatar: self.placedAvatar = 1 self.av.setPosHpr(0, 0, 0, 0, 0, 0) def setMovie(self, mode): self.notify.debugStateCall(self) if self.avId == 0: return self.finishMovie() if mode == 0: pass elif mode == KartGlobals.ENTER_MOVIE: self.request('EnterMovie') elif mode == KartGlobals.EXIT_MOVIE: self.request('ExitMovie') def makeGui(self): self.notify.debugStateCall(self) if hasattr(self, 'cancelButton'): return fishGui = loader.loadModel('phase_4/models/gui/fishingGui') self.cancelButton = DirectGui.DirectButton( relief=None, scale=0.67, parent=base.a2dBottomRight, pos=(-0.173333, 0, 0.1), text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), textMayChange=0, text_scale=0.1, image=(fishGui.find('**/exit_buttonUp'), fishGui.find('**/exit_buttonDown'), fishGui.find('**/exit_buttonRollover')), text_font=ToontownGlobals.getInterfaceFont(), command=self.d_requestExit) self.cancelButton.hide() return def showGui(self): self.notify.debugStateCall(self) if hasattr(self.kartPad, 'state'): if not self.kartPad.state == 'WaitCountdown': return self.cancelButton.show() def hideGui(self): self.notify.debugStateCall(self) if not hasattr(self, 'cancelButton'): return self.cancelButton.hide() def generateToonMoveTrack(self): hpr = self.movieNode.getHpr(render) heading = PythonUtil.fitDestAngle2Src(self.av.getH(render), hpr[0]) hpr.setX(heading) self.av.setAnimState('run', 1.0) toonTrack = Sequence( Wait(0.5), Parallel( LerpPosInterval( self.av, 1.0, Point3(self.movieNode.getX(self.avParent), self.movieNode.getY(self.avParent), 0)), LerpHprInterval(self.av, 1.0, hpr=hpr, other=render)), Func(self.av.loop, 'neutral')) return toonTrack def generateKartAppearTrack(self): if not self.av: if not self.kartNode: self.kartNode = render.attachNewNode(str(self) + 'kartNode') self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) self.kart.setScale(0.85) self.kart.reparentTo(self.kartNode) return Parallel() self.kart.setScale(0.1) kartTrack = Parallel( Sequence(ActorInterval(self.av, 'feedPet'), Func(self.av.loop, 'neutral')), Sequence( Func(self.kart.setActiveShadow, False), Func(self.kart.reparentTo, self.av.rightHand), Wait(2.1), Func(self.kart.wrtReparentTo, render), Func(self.kart.setShear, 0, 0, 0), Parallel( LerpHprInterval(self.kart, hpr=self.kartNode.getHpr(render), duration=1.2), ProjectileInterval(self.kart, endPos=self.kartNode.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Func(self.kart.setActiveShadow, True), Sequence( LerpScaleInterval(self.kart, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 0.1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 1.1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 1.0), duration=0.1), Func(self.kart.wrtReparentTo, self.kartNode)))) return kartTrack def generateToonJumpTrack(self): base.sb = self def getToonJumpTrack(av, kart): def getJumpDest(av=av, node=kart.toonNode[0]): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av=av, node=kart.toonNode[0]): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(self.av, self.kart) toonSitTrack = getToonSitTrack(self.av) jumpTrack = Sequence( Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)), Func(self.av.setPosHpr, 0, 0.45, -.25, 0, 0, 0), Func(self.av.reparentTo, self.kart.toonSeat)) return jumpTrack def generateToonReverseJumpTrack(self): def getToonJumpTrack(av, destNode): def getJumpDest(av=av, node=destNode): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av=av, node=destNode): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence( Wait(0.1), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(self.av, self.exitMovieNode) jumpTrack = Sequence( toonJumpTrack, Func(self.av.loop, 'neutral'), Func(self.av.reparentTo, render), Func(self.av.setPosHpr, self.exitMovieNode, 0, 0, 0, 0, 0, 0)) return jumpTrack def generateCameraMoveTrack(self): self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, self.cameraPos, self.cameraHpr) return cameraTrack def generateCameraReturnMoveTrack(self): cameraTrack = Sequence( Func(camera.wrtReparentTo, self.av), LerpPosHprInterval(camera, 1.5, self.cPos, self.cHpr)) return cameraTrack def generateKartDisappearTrack(self): def getHoleTrack(hole, holeParent): holeTrack = Sequence( Wait(0.2), Func(hole.setBin, 'shadow', 0), Func(hole.setDepthTest, 0), Func(hole.setDepthWrite, 0), Func(hole.reparentTo, holeParent), Func(hole.setPos, holeParent, Point3(0, 0.0, -.6)), ActorInterval(hole, 'hole', startTime=3.4, endTime=3.1), Wait(0.4), ActorInterval(hole, 'hole', startTime=3.1, endTime=3.4)) return holeTrack def getKartShrinkTrack(kart): pos = kart.getPos() pos.addZ(-1.0) kartTrack = Sequence( LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 1.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 0.1), duration=0.2), LerpScaleInterval(kart, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.1, 1.1, 0.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(0.1, 0.1, 0.1), duration=0.2), Wait(0.2), LerpPosInterval(kart, pos=pos, duration=0.2), Func(kart.hide)) return kartTrack if not self.holeActor: self.holeActor = Actor.Actor( 'phase_3.5/models/props/portal-mod', {'hole': 'phase_3.5/models/props/portal-chan'}) holeTrack = getHoleTrack(self.holeActor, self.kartNode) shrinkTrack = getKartShrinkTrack(self.kart) kartTrack = Parallel(shrinkTrack, holeTrack) return kartTrack def enterOff(self): self.notify.debug('%d enterOff: Entering the Off State.' % self.doId) self.hideGui() def exitOff(self): self.notify.debug('%d exitOff: Exiting the Off State.' % self.doId) def enterEnterMovie(self): self.notify.debug( '%d enterEnterMovie: Entering the Enter Movie State.' % self.doId) if base.config.GetBool('want-qa-regression', 0): raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName('EnterRaceTrack') if self.av is not None and self.localToonKarting: kartAppearSfx = base.loader.loadSfx(self.SFX_KartAppear) cameraTrack = self.generateCameraMoveTrack() engineStartTrack = self.kart.generateEngineStartTrack() self.finishMovie() self.movieTrack = Sequence(Parallel(cameraTrack, toonTrack), Parallel( SoundInterval(kartAppearSfx), Sequence( kartTrack, jumpTrack, engineStartTrack, Func(self.makeGui), Func(self.showGui), Func(self.request, 'Waiting'), Func(self.d_movieFinished))), name=name, autoFinish=1) self.exitRequested = False else: self.finishMovie() self.movieTrack = Sequence(toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1) self.movieTrack.start() return def exitEnterMovie(self): self.notify.debug('%d exitEnterMovie: Exiting the Enter Movie State.' % self.doId) def enterWaiting(self): self.notify.debug('%d enterWaiting: Entering the Waiting State.' % self.doId) def exitWaiting(self): self.notify.debug('%d exitWaiting: Exiting the Waiting State.' % self.doId) def enterExitMovie(self): self.notify.debug('%d enterExitMovie: Entering the Exit Movie State.' % self.doId) self.hideGui() jumpTrack = self.generateToonReverseJumpTrack() kartTrack = self.generateKartDisappearTrack() self.finishMovie() self.movieTrack = Sequence(Func(self.kart.kartLoopSfx.stop), jumpTrack, kartTrack, name=self.av.uniqueName('ExitRaceTrack'), autoFinish=1) if self.av is not None and self.localToonKarting: cameraTrack = self.generateCameraReturnMoveTrack() self.movieTrack.append(cameraTrack) self.movieTrack.append(Func(self.d_movieFinished)) self.movieTrack.start() return def exitExitMovie(self): self.notify.debug('%d exitExitMovie: Exiting the Exit Movie State.' % self.doId) def doExitToRaceTrack(self): self.hideGui() self.finishMovie() oldBlockPos = self.kartNode.getPos(render) self.kartNode.setPos(self.kartNode, 0, 40, 0) newBlockPos = self.kartNode.getPos(render) oldBlockScale = self.kartNode.getScale() self.kart.LODnode.setSwitch(0, 60, 0) self.kartNode.setPos(render, oldBlockPos) blockLerpIval = LerpPosInterval(self.kartNode, pos=newBlockPos, duration=2.0) scaleLerpIval = LerpScaleInterval(self.kartNode, scale=oldBlockScale * 0.2, duration=2.0) engineStopTrack = self.kart.generateEngineStopTrack(2) self.finishMovie() self.movieTrack = Parallel() if self.av == base.localAvatar: self.movieTrack.insert(0, Func(base.transitions.irisOut, 1.5, 0)) (self.movieTrack.append(engineStopTrack), ) taskMgr.doMethodLater(1.6, self.bulkLoad, 'loadIt', extraArgs=[]) self.movieTrack.append( Sequence(Parallel(blockLerpIval, scaleLerpIval), Func(self.kartNode.hide), Func(self.kartNode.setPos, render, oldBlockPos), Func(self.kartNode.setScale, oldBlockScale))) self.movieTrack.start() def bulkLoad(self): base.loader.beginBulkLoad('atRace', TTLocalizer.StartingBlock_Loading, 60, 1, TTLocalizer.TIP_KARTING)
class DistributedStartingBlock(DistributedObject.DistributedObject, FSM): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedStartingBlock') sphereRadius = 1.5 id = 0 cameraPos = Point3(0, -23, 10) cameraHpr = Point3(0, -10, 0) SFX_BaseDir = 'phase_6/audio/sfx/' SFX_KartAppear = SFX_BaseDir + 'KART_Appear.ogg' defaultTransitions = {'Off': ['EnterMovie'], 'EnterMovie': ['Off', 'Waiting', 'ExitMovie'], 'Waiting': ['ExitMovie', 'Off'], 'ExitMovie': ['Off', 'ExitMovie']} def __init__(self, cr): DistributedObject.DistributedObject.__init__(self, cr) FSM.__init__(self, 'staringBlock_%s_FSM' % DistributedStartingBlock.id) self.avId = 0 self.av = None self.lastAvId = 0 self.avatar = None self.kartPad = None self.collNode = None self.movieNode = None self.movieTrack = None self.collSphere = None self.collNodePath = None self.localToonKarting = 0 self.kartNode = None self.kart = None self.holeActor = None self.exitRequested = False if (__debug__): self.testLOD = False self.id = DistributedStartingBlock.id DistributedStartingBlock.id += 1 return def disable(self): FSM.cleanup(self) self.ignore(self.uniqueName('enterStartingBlockSphere')) self.ignore('stoppedAsleep') self.setOccupied(0) self.avId = 0 self.nodePath.detachNode() self.kartPad = None if self.holeActor: self.holeActor.cleanup() self.holeActor = None DistributedObject.DistributedObject.disable(self) return def delete(self): if hasattr(self, 'dialog'): if not self.dialog.removed(): self.dialog.ignoreAll() if not self.dialog.isEmpty(): self.dialog.cleanup() del self.dialog self.finishMovie() if hasattr(self, 'cancelButton'): self.cancelButton.destroy() del self.cancelButton del self.kartPad if self.nodePath: self.nodePath.removeNode() del self.nodePath DistributedObject.DistributedObject.delete(self) def generateInit(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.generateInit(self) self.nodePath = NodePath(self.uniqueName('StartingBlock')) self.collSphere = CollisionSphere(0, 0, 0, self.sphereRadius) self.collSphere.setTangible(0) self.collNode = CollisionNode(self.uniqueName('StartingBlockSphere')) self.collNode.setCollideMask(ToontownGlobals.WallBitmask) self.collNode.addSolid(self.collSphere) self.collNodePath = self.nodePath.attachNewNode(self.collNode) def announceGenerate(self): self.notify.debugStateCall(self) DistributedObject.DistributedObject.announceGenerate(self) self.nodePath.reparentTo(render) self.accept(self.uniqueName('enterStartingBlockSphere'), self.__handleEnterSphere) if (__debug__): if self.testLOD: self.__generateKartAppearTrack() def setPadDoId(self, padDoId): if padDoId in self.cr.doId2do: self.setPad(self.cr.doId2do[padDoId]) else: self.acceptOnce('generate-%d' % padDoId, self.setPad) def setPad(self, pad): self.kartPad = pad self.kartPad.addStartingBlock(self) def setPosHpr(self, x, y, z, h, p, r): self.notify.debugStateCall(self) self.nodePath.setPosHpr(x, y, z, h + 180, 0, 0) def setPadLocationId(self, padLocationId): self.notify.debugStateCall(self) self.movieNode = self.nodePath.attachNewNode(self.uniqueName('MovieNode')) self.exitMovieNode = self.movieNode if padLocationId % 2: self.movieNode.setPosHpr(3.0, 0, 0, 90.0, 0, 0) else: self.movieNode.setPosHpr(-3.0, 0, 0, -90.0, 0, 0) def setActive(self, isTangible): self.collSphere.setTangible(isTangible) def __handleEnterSphere(self, collEntry): if base.localAvatar.doId == self.lastAvId and globalClock.getFrameCount() <= self.lastFrame + 1: self.notify.debug('Ignoring duplicate entry for avatar.') return if base.localAvatar.hp > 0: def handleEnterRequest(self = self): self.ignore('stoppedAsleep') if hasattr(self.dialog, 'doneStatus') and self.dialog.doneStatus == 'ok': self.d_requestEnter(base.cr.isPaid()) elif self.cr and not self.isDisabled(): self.cr.playGame.getPlace().setState('walk') else: self.notify.warning('Warning! Object has already been disabled.') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().fsm.request('stopped') self.accept('stoppedAsleep', handleEnterRequest) doneEvent = 'enterRequest|dialog' if self.kartPad.isPractice(): msg = TTLocalizer.StartingBlock_EnterPractice else: raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] numTickets = RaceGlobals.getEntryFee(self.kartPad.trackId, self.kartPad.trackType) msg = TTLocalizer.StartingBlock_EnterNonPractice % (raceName, numTickets) self.dialog = TTGlobalDialog(msg, doneEvent, 4) self.dialog.accept(doneEvent, handleEnterRequest) def d_movieFinished(self): self.notify.debugStateCall(self) self.sendUpdate('movieFinished', []) def d_requestEnter(self, paid): self.notify.debugStateCall(self) self.sendUpdate('requestEnter', [paid]) def d_requestExit(self): self.notify.debugStateCall(self) self.exitRequested = True self.hideGui() self.sendUpdate('requestExit', []) def rejectEnter(self, errCode): self.notify.debugStateCall(self) def handleTicketError(self = self): self.ignore('stoppedAsleep') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog self.cr.playGame.getPlace().setState('walk') doneEvent = 'errorCode|dialog' if errCode == KartGlobals.ERROR_CODE.eTickets: msg = TTLocalizer.StartingBlock_NotEnoughTickets self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eBoardOver: msg = TTLocalizer.StartingBlock_NoBoard self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eNoKart: msg = TTLocalizer.StartingBlock_NoKart self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eOccupied: msg = TTLocalizer.StartingBlock_Occupied self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eTrackClosed: msg = TTLocalizer.StartingBlock_TrackClosed self.dialog = TTGlobalDialog(msg, doneEvent, 2) self.dialog.accept(doneEvent, handleTicketError) self.accept('stoppedAsleep', handleTicketError) elif errCode == KartGlobals.ERROR_CODE.eUnpaid: self.dialog = TeaserPanel(pageName='karting', doneFunc=handleTicketError) else: self.cr.playGame.getPlace().setState('walk') def finishMovie(self): if self.movieTrack: self.movieTrack.finish() self.movieTrack = None return def setOccupied(self, avId): self.notify.debug('%d setOccupied: %d' % (self.doId, avId)) if self.av != None: self.finishMovie() if not self.av.isEmpty() and not self.av.isDisabled(): self.av.loop('neutral') self.av.setParent(ToontownGlobals.SPRender) self.av.startSmooth() self.finishMovie() if self.kart: self.kart.delete() self.kart = None if self.kartNode: self.kartNode.removeNode() self.kartNode = None self.placedAvatar = 0 self.ignore(self.av.uniqueName('disable')) self.av = None wasLocalToon = self.localToonKarting self.lastAvId = self.avId self.lastFrame = globalClock.getFrameCount() self.avId = avId self.localToonKarting = 0 if self.avId == 0: self.collSphere.setTangible(0) self.request('Off') else: self.collSphere.setTangible(1) av = self.cr.doId2do.get(self.avId) self.placedAvatar = 0 if self.avId == base.localAvatar.doId: self.localToonKarting = 1 if av != None: self.av = av self.av.stopSmooth() self.placedAvatar = 0 self.acceptOnce(self.av.uniqueName('disable'), self.__avatarGone) self.kartNode = render.attachNewNode(self.av.uniqueName('KartNode')) self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) self.kart = Kart() self.kart.baseScale = 1.6 self.kart.setDNA(self.av.getKartDNA()) self.kart.generateKart() self.kart.resetGeomPos() self.av.wrtReparentTo(self.nodePath) self.av.setAnimState('neutral', 1.0) if not self.localToonKarting: av.stopSmooth() self.__placeAvatar() self.avParent = av.getParent() else: self.notify.warning('Unknown avatar %d in kart block %d ' % (self.avId, self.doId)) self.avId = 0 if wasLocalToon and not self.localToonKarting: place = base.cr.playGame.getPlace() if place: if self.exitRequested: place.setState('walk') else: def handleDialogOK(self = self): self.ignore('stoppedAsleep') place.setState('walk') self.dialog.ignoreAll() self.dialog.cleanup() del self.dialog doneEvent = 'kickedOutDialog' msg = TTLocalizer.StartingBlock_KickSoloRacer self.dialog = TTGlobalDialog(msg, doneEvent, style=1) self.dialog.accept(doneEvent, handleDialogOK) self.accept('stoppedAsleep', handleDialogOK) return def __avatarGone(self): self.notify.debugStateCall(self) self.setOccupied(0) def __placeAvatar(self): self.notify.debugStateCall(self) if not self.placedAvatar: self.placedAvatar = 1 self.av.setPosHpr(0, 0, 0, 0, 0, 0) def setMovie(self, mode): self.notify.debugStateCall(self) if self.avId == 0: return self.finishMovie() if mode == 0: pass elif mode == KartGlobals.ENTER_MOVIE: self.request('EnterMovie') elif mode == KartGlobals.EXIT_MOVIE: self.request('ExitMovie') def makeGui(self): self.notify.debugStateCall(self) if hasattr(self, 'cancelButton'): return fishGui = loader.loadModel('phase_4/models/gui/fishingGui') self.cancelButton = DirectGui.DirectButton(relief=None, scale=0.67, pos=(1.16, 0, -0.9), text=('', TTLocalizer.FishingExit, TTLocalizer.FishingExit), text_align=TextNode.ACenter, text_fg=Vec4(1, 1, 1, 1), text_shadow=Vec4(0, 0, 0, 1), text_pos=(0.0, -0.12), textMayChange=0, text_scale=0.1, image=(fishGui.find('**/exit_buttonUp'), fishGui.find('**/exit_buttonDown'), fishGui.find('**/exit_buttonRollover')), text_font=ToontownGlobals.getInterfaceFont(), command=self.d_requestExit) self.cancelButton.hide() return def showGui(self): self.notify.debugStateCall(self) if hasattr(self.kartPad, 'state'): if not self.kartPad.state == 'WaitCountdown': return self.cancelButton.show() def hideGui(self): self.notify.debugStateCall(self) if not hasattr(self, 'cancelButton'): return self.cancelButton.hide() def generateToonMoveTrack(self): hpr = self.movieNode.getHpr(render) heading = PythonUtil.fitDestAngle2Src(self.av.getH(render), hpr[0]) hpr.setX(heading) self.av.setAnimState('run', 1.0) toonTrack = Sequence(Wait(0.5), Parallel(LerpPosInterval(self.av, 1.0, Point3(self.movieNode.getX(self.avParent), self.movieNode.getY(self.avParent), 0)), LerpHprInterval(self.av, 1.0, hpr=hpr, other=render)), Func(self.av.loop, 'neutral')) return toonTrack def generateKartAppearTrack(self): if not self.av: if not self.kartNode: self.kartNode = render.attachNewNode(str(self) + 'kartNode') self.kartNode.setPosHpr(self.nodePath.getPos(render), self.nodePath.getHpr(render)) self.kart.setScale(0.85) self.kart.reparentTo(self.kartNode) return Parallel() self.kart.setScale(0.1) kartTrack = Parallel( Sequence( ActorInterval(self.av, 'feedPet'), Func(self.av.loop, 'neutral')), Sequence( Func(self.kart.setActiveShadow, False), Func(self.kart.reparentTo, self.av.rightHand), Wait(2.1), Func(self.kart.wrtReparentTo, render), Func(self.kart.setShear, 0, 0, 0), Parallel( LerpHprInterval(self.kart, hpr=self.kartNode.getHpr(render), duration=1.2), ProjectileInterval(self.kart, endPos=self.kartNode.getPos(render), duration=1.2, gravityMult=0.45)), Wait(0.2), Func(self.kart.setActiveShadow, True), Sequence( LerpScaleInterval(self.kart, scale=Point3(1.1, 1.1, 0.1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 0.1), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 1.1), duration=0.2), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(self.kart, scale=Point3(1.0, 1.0, 1.0), duration=0.1), Func(self.kart.wrtReparentTo, self.kartNode)))) return kartTrack def generateToonJumpTrack(self): base.sb = self def getToonJumpTrack(av, kart): def getJumpDest(av = av, node = kart.toonNode[0]): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av = av, node = kart.toonNode[0]): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel( ActorInterval(av, 'jump'), Sequence(Wait(0.43), Parallel( LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack def getToonSitTrack(av): toonSitTrack = Sequence(ActorInterval(av, 'sit-start'), Func(av.loop, 'sit')) return toonSitTrack toonJumpTrack = getToonJumpTrack(self.av, self.kart) toonSitTrack = getToonSitTrack(self.av) jumpTrack = Sequence( Parallel( toonJumpTrack, Sequence( Wait(1), toonSitTrack)), Func(self.av.setPosHpr, 0, 0.45, -.25, 0, 0, 0), Func(self.av.reparentTo, self.kart.toonSeat)) return jumpTrack def generateToonReverseJumpTrack(self): def getToonJumpTrack(av, destNode): def getJumpDest(av = av, node = destNode): dest = node.getPos(av.getParent()) return dest def getJumpHpr(av = av, node = destNode): hpr = node.getHpr(av.getParent()) return hpr toonJumpTrack = Parallel(ActorInterval(av, 'jump'), Sequence(Wait(0.1), Parallel(LerpHprInterval(av, hpr=getJumpHpr, duration=0.9), ProjectileInterval(av, endPos=getJumpDest, duration=0.9)))) return toonJumpTrack toonJumpTrack = getToonJumpTrack(self.av, self.exitMovieNode) jumpTrack = Sequence(toonJumpTrack, Func(self.av.loop, 'neutral'), Func(self.av.reparentTo, render), Func(self.av.setPosHpr, self.exitMovieNode, 0, 0, 0, 0, 0, 0)) return jumpTrack def generateCameraMoveTrack(self): self.cPos = camera.getPos(self.av) self.cHpr = camera.getHpr(self.av) camera.wrtReparentTo(self.nodePath) cameraTrack = LerpPosHprInterval(camera, 1.5, self.cameraPos, self.cameraHpr) return cameraTrack def generateCameraReturnMoveTrack(self): cameraTrack = Sequence(Func(camera.wrtReparentTo, self.av), LerpPosHprInterval(camera, 1.5, self.cPos, self.cHpr)) return cameraTrack def generateKartDisappearTrack(self): def getHoleTrack(hole, holeParent): holeTrack = Sequence( Wait(0.2), Func(hole.setBin, 'shadow', 0), Func(hole.setDepthTest, 0), Func(hole.setDepthWrite, 0), Func(hole.reparentTo, holeParent), Func(hole.setPos, holeParent, Point3(0, 0.0, -.6)), ActorInterval(hole, 'hole', startTime=3.4, endTime=3.1), Wait(0.4), ActorInterval(hole, 'hole', startTime=3.1, endTime=3.4)) return holeTrack def getKartShrinkTrack(kart): pos = kart.getPos() pos.addZ(-1.0) kartTrack = Sequence(LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 0.9), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 1.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.0, 1.0, 0.1), duration=0.2), LerpScaleInterval(kart, scale=Point3(0.9, 0.9, 0.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(1.1, 1.1, 0.1), duration=0.1), LerpScaleInterval(kart, scale=Point3(0.1, 0.1, 0.1), duration=0.2), Wait(0.2), LerpPosInterval(kart, pos=pos, duration=0.2), Func(kart.hide)) return kartTrack if not self.holeActor: self.holeActor = Actor.Actor('phase_3.5/models/props/portal-mod', {'hole': 'phase_3.5/models/props/portal-chan'}) holeTrack = getHoleTrack(self.holeActor, self.kartNode) shrinkTrack = getKartShrinkTrack(self.kart) kartTrack = Parallel(shrinkTrack, holeTrack) return kartTrack def enterOff(self): self.notify.debug('%d enterOff: Entering the Off State.' % self.doId) self.hideGui() def exitOff(self): self.notify.debug('%d exitOff: Exiting the Off State.' % self.doId) def enterEnterMovie(self): self.notify.debug('%d enterEnterMovie: Entering the Enter Movie State.' % self.doId) if base.config.GetBool('want-qa-regression', 0): raceName = TTLocalizer.KartRace_RaceNames[self.kartPad.trackType] self.notify.info('QA-REGRESSION: KARTING: %s' % raceName) toonTrack = self.generateToonMoveTrack() kartTrack = self.generateKartAppearTrack() jumpTrack = self.generateToonJumpTrack() name = self.av.uniqueName('EnterRaceTrack') if self.av is not None and self.localToonKarting: kartAppearSfx = base.loadSfx(self.SFX_KartAppear) cameraTrack = self.generateCameraMoveTrack() engineStartTrack = self.kart.generateEngineStartTrack() self.finishMovie() self.movieTrack = Sequence(Parallel(cameraTrack, toonTrack), Parallel(SoundInterval(kartAppearSfx), Sequence(kartTrack, jumpTrack, engineStartTrack, Func(self.makeGui), Func(self.showGui), Func(self.request, 'Waiting'), Func(self.d_movieFinished))), name=name, autoFinish=1) self.exitRequested = False else: self.finishMovie() self.movieTrack = Sequence(toonTrack, kartTrack, jumpTrack, name=name, autoFinish=1) self.movieTrack.start() return def exitEnterMovie(self): self.notify.debug('%d exitEnterMovie: Exiting the Enter Movie State.' % self.doId) def enterWaiting(self): self.notify.debug('%d enterWaiting: Entering the Waiting State.' % self.doId) def exitWaiting(self): self.notify.debug('%d exitWaiting: Exiting the Waiting State.' % self.doId) def enterExitMovie(self): self.notify.debug('%d enterExitMovie: Entering the Exit Movie State.' % self.doId) self.hideGui() jumpTrack = self.generateToonReverseJumpTrack() kartTrack = self.generateKartDisappearTrack() self.finishMovie() self.movieTrack = Sequence(Func(self.kart.kartLoopSfx.stop), jumpTrack, kartTrack, name=self.av.uniqueName('ExitRaceTrack'), autoFinish=1) if self.av is not None and self.localToonKarting: cameraTrack = self.generateCameraReturnMoveTrack() self.movieTrack.append(cameraTrack) self.movieTrack.append(Func(self.d_movieFinished)) self.movieTrack.start() return def exitExitMovie(self): self.notify.debug('%d exitExitMovie: Exiting the Exit Movie State.' % self.doId) def doExitToRaceTrack(self): self.hideGui() self.finishMovie() oldBlockPos = self.kartNode.getPos(render) self.kartNode.setPos(self.kartNode, 0, 40, 0) newBlockPos = self.kartNode.getPos(render) oldBlockScale = self.kartNode.getScale() self.kart.LODnode.setSwitch(0, 60, 0) self.kartNode.setPos(render, oldBlockPos) blockLerpIval = LerpPosInterval(self.kartNode, pos=newBlockPos, duration=2.0) scaleLerpIval = LerpScaleInterval(self.kartNode, scale=oldBlockScale * 0.2, duration=2.0) engineStopTrack = self.kart.generateEngineStopTrack(2) self.finishMovie() self.movieTrack = Parallel() if self.av == base.localAvatar: self.movieTrack.insert(0, Func(base.transitions.irisOut, 1.5, 0)) (self.movieTrack.append(engineStopTrack),) taskMgr.doMethodLater(1.6, self.bulkLoad, 'loadIt', extraArgs=[]) self.movieTrack.append(Sequence(Parallel(blockLerpIval, scaleLerpIval), Func(self.kartNode.hide), Func(self.kartNode.setPos, render, oldBlockPos), Func(self.kartNode.setScale, oldBlockScale))) self.movieTrack.start() def bulkLoad(self): base.loader.beginBulkLoad('atRace', TTLocalizer.StartingBlock_Loading, 60, 1, TTLocalizer.TIP_KARTING)