Exemplo n.º 1
0
    def load(self):
        DistributedPartyFireworksActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.eventId = PartyGlobals.FireworkShows.Summer
        self.launchPadModel = loader.loadModel(
            'phase_13/models/parties/launchPad')
        self.launchPadModel.setH(90.0)
        self.launchPadModel.setPos(0.0, -18.0, 0.0)
        self.launchPadModel.reparentTo(self.root)
        railingsCollection = self.launchPadModel.findAllMatches(
            '**/launchPad_mesh/*railing*')
        for i in range(railingsCollection.getNumPaths()):
            railingsCollection[i].setAttrib(
                AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))

        leverLocator = self.launchPadModel.find('**/RocketLever_locator')
        self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
        self.lever.reparentTo(leverLocator)
        self.toonPullingLeverInterval = None
        self.sign.reparentTo(
            self.launchPadModel.find('**/launchPad_sign_locator'))
        self.rocketActor = Actor(
            'phase_13/models/parties/rocket_model',
            {'launch': 'phase_13/models/parties/rocket_launch'})
        rocketLocator = self.launchPadModel.find('**/rocket_locator')
        self.rocketActor.reparentTo(rocketLocator)
        self.rocketActor.node().setBound(OmniBoundingVolume())
        self.rocketActor.node().setFinal(True)
        effectsLocator = self.rocketActor.find('**/joint1')
        self.rocketExplosionEffect = RocketExplosion(effectsLocator,
                                                     rocketLocator)
        self.rocketParticleSeq = None
        self.launchSound = base.loadSfx('phase_13/audio/sfx/rocket_launch.mp3')
        self.activityFSM = FireworksActivityFSM(self)
        self.activityFSM.request('Idle')
 def __init__(self,
              air,
              partyDoId,
              x,
              y,
              h,
              eventId=PartyGlobals.FireworkShows.Summer,
              showStyle=0):
     """
     air: instance of ToontownAIRepository
     eventId: a PartyGlobals.FireworkShows value that tells us which show
              to run
     """
     DistributedPartyFireworksActivityAI.notify.debug("__init__")
     DistributedPartyActivityAI.__init__(
         self,
         air,
         partyDoId,
         x,
         y,
         h,
         PartyGlobals.ActivityIds.PartyFireworks,
         PartyGlobals.ActivityTypes.HostInitiated,
     )
     self.eventId = eventId
     self.showStyle = showStyle
     self.activityFSM = FireworksActivityFSM(self)
 def load(self):
     """
     Load the necessary assets
     """
     DistributedPartyFireworksActivity.notify.debug("load")
     DistributedPartyActivity.load(self)
     
     self.eventId = PartyGlobals.FireworkShows.Summer
     
     # load the rocket platform and place it in party space
     self.launchPadModel = loader.loadModel('phase_13/models/parties/launchPad')
     # Compensate for pivot of fireworks model and center it in 2x4 space
     self.launchPadModel.setH(90.0)
     self.launchPadModel.setPos(0.0, -18.0, 0.0)
     # reparent to root
     self.launchPadModel.reparentTo( self.root )
     # special case the depth testing on the railings to prevent
     # transparency oddness
     railingsCollection = self.launchPadModel.findAllMatches("**/launchPad_mesh/*railing*")
     for i in range( railingsCollection.getNumPaths() ):
         railingsCollection[i].setAttrib(AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))
             
     # place the lever on the platform
     leverLocator = self.launchPadModel.find("**/RocketLever_locator")
     self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
     self.lever.reparentTo(leverLocator)
     self.toonPullingLeverInterval = None
     
     # place the activity sign
     self.sign.reparentTo( self.launchPadModel.find("**/launchPad_sign_locator") )
     
     # load the rocket with animation and place it on the platform
     self.rocketActor = Actor(
         'phase_13/models/parties/rocket_model',
         {'launch':'phase_13/models/parties/rocket_launch'},
     )
     
     rocketLocator = self.launchPadModel.find("**/rocket_locator")
     self.rocketActor.reparentTo(rocketLocator)
     # ensure the rocket is never culled
     self.rocketActor.node().setBound( OmniBoundingVolume() )
     self.rocketActor.node().setFinal( True )
     
     effectsLocator = self.rocketActor.find("**/joint1")
     self.rocketExplosionEffect  = RocketExplosion(effectsLocator, rocketLocator)
     
     self.rocketParticleSeq = None
     
     self.launchSound = base.loadSfx("phase_13/audio/sfx/rocket_launch.mp3")
     
     # create state machine and set initial state
     self.activityFSM = FireworksActivityFSM( self )
     self.activityFSM.request("Idle")
    def load(self):
        DistributedPartyFireworksActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.eventId = PartyGlobals.FireworkShows.Summer
        self.launchPadModel = loader.loadModel('phase_13/models/parties/launchPad')
        self.launchPadModel.setH(90.0)
        self.launchPadModel.setPos(0.0, -18.0, 0.0)
        self.launchPadModel.reparentTo(self.root)
        railingsCollection = self.launchPadModel.findAllMatches('**/launchPad_mesh/*railing*')
        for i in xrange(railingsCollection.getNumPaths()):
            railingsCollection[i].setAttrib(AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))

        leverLocator = self.launchPadModel.find('**/RocketLever_locator')
        self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
        self.lever.reparentTo(leverLocator)
        self.toonPullingLeverInterval = None
        self.sign.reparentTo(self.launchPadModel.find('**/launchPad_sign_locator'))
        self.rocketActor = Actor('phase_13/models/parties/rocket_model', {'launch': 'phase_13/models/parties/rocket_launch'})
        rocketLocator = self.launchPadModel.find('**/rocket_locator')
        self.rocketActor.reparentTo(rocketLocator)
        self.rocketActor.node().setBound(OmniBoundingVolume())
        self.rocketActor.node().setFinal(True)
        effectsLocator = self.rocketActor.find('**/joint1')
        self.rocketExplosionEffect = RocketExplosion(effectsLocator, rocketLocator)
        self.rocketParticleSeq = None
        self.launchSound = base.loadSfx('phase_13/audio/sfx/rocket_launch.ogg')
        self.activityFSM = FireworksActivityFSM(self)
        self.activityFSM.request('Idle')
        return
Exemplo n.º 5
0
class DistributedPartyFireworksActivity(DistributedPartyActivity,
                                        FireworkShowMixin):
    notify = directNotify.newCategory('DistributedPartyFireworksActivity')

    def __init__(self, cr):
        DistributedPartyFireworksActivity.notify.debug('__init__')
        DistributedPartyActivity.__init__(self,
                                          cr,
                                          ActivityIds.PartyFireworks,
                                          ActivityTypes.HostInitiated,
                                          wantLever=True)
        FireworkShowMixin.__init__(self,
                                   restorePlaygroundMusic=True,
                                   startDelay=FireworksPostLaunchDelay)

    def setEventId(self, eventId):
        DistributedPartyFireworksActivity.notify.debug(
            'setEventId( %s )' % FireworkShows.getString(eventId))
        self.eventId = eventId

    def setShowStyle(self, showStyle):
        DistributedPartyFireworksActivity.notify.debug('setShowStyle( %d )' %
                                                       showStyle)
        self.showStyle = showStyle

    def setSongId(self, songId):
        self.songId = songId

    def load(self):
        DistributedPartyFireworksActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.eventId = PartyGlobals.FireworkShows.Summer
        self.launchPadModel = loader.loadModel(
            'phase_13/models/parties/launchPad')
        self.launchPadModel.setH(90.0)
        self.launchPadModel.setPos(0.0, -18.0, 0.0)
        self.launchPadModel.reparentTo(self.root)
        railingsCollection = self.launchPadModel.findAllMatches(
            '**/launchPad_mesh/*railing*')
        for i in xrange(railingsCollection.getNumPaths()):
            railingsCollection[i].setAttrib(
                AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))

        leverLocator = self.launchPadModel.find('**/RocketLever_locator')
        self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
        self.lever.reparentTo(leverLocator)
        self.toonPullingLeverInterval = None
        self.sign.reparentTo(
            self.launchPadModel.find('**/launchPad_sign_locator'))
        self.rocketActor = Actor(
            'phase_13/models/parties/rocket_model',
            {'launch': 'phase_13/models/parties/rocket_launch'})
        rocketLocator = self.launchPadModel.find('**/rocket_locator')
        self.rocketActor.reparentTo(rocketLocator)
        self.rocketActor.node().setBound(OmniBoundingVolume())
        self.rocketActor.node().setFinal(True)
        effectsLocator = self.rocketActor.find('**/joint1')
        self.rocketExplosionEffect = RocketExplosion(effectsLocator,
                                                     rocketLocator)
        self.rocketParticleSeq = None
        self.launchSound = base.loader.loadSfx(
            'phase_13/audio/sfx/rocket_launch.ogg')
        self.activityFSM = FireworksActivityFSM(self)
        self.activityFSM.request('Idle')
        return

    def unload(self):
        DistributedPartyFireworksActivity.notify.debug('unload')
        taskMgr.remove(self.taskName('delayedStartShow'))
        if self.rocketParticleSeq:
            self.rocketParticleSeq.pause()
            self.rocketParticleSeq = None
        self.launchPadModel.removeNode()
        del self.launchPadModel
        del self.toonPullingLeverInterval
        self.rocketActor.delete()
        self.rocketExplosionEffect.destroy()
        self.activityFSM.request('Disabled')
        del self.rocketActor
        del self.launchSound
        del self.activityFSM
        del self.eventId
        del self.showStyle
        DistributedPartyActivity.unload(self)
        return

    def _leverPulled(self, collEntry):
        DistributedPartyFireworksActivity.notify.debug('_leverPulled')
        hostPulledLever = DistributedPartyActivity._leverPulled(
            self, collEntry)
        if self.activityFSM.getCurrentOrNextState() == 'Active':
            self.showMessage(TTLocalizer.PartyFireworksAlreadyActive)
        elif self.activityFSM.getCurrentOrNextState() == 'Disabled':
            self.showMessage(TTLocalizer.PartyFireworksAlreadyDone)
        elif self.activityFSM.getCurrentOrNextState() == 'Idle':
            if hostPulledLever:
                base.cr.playGame.getPlace().fsm.request('activity')
                self.toonPullingLeverInterval = self.getToonPullingLeverInterval(
                    base.localAvatar)
                self.toonPullingLeverInterval.append(
                    Func(self.d_toonJoinRequest))
                self.toonPullingLeverInterval.append(
                    Func(base.cr.playGame.getPlace().fsm.request, 'walk'))
                self.toonPullingLeverInterval.start()
            else:
                self.showMessage(TTLocalizer.PartyOnlyHostLeverPull)

    def setState(self, newState, timestamp):
        DistributedPartyFireworksActivity.notify.debug(
            'setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        if newState == 'Active':
            self.activityFSM.request(newState, timestamp)
        else:
            self.activityFSM.request(newState)

    def startIdle(self):
        DistributedPartyFireworksActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyFireworksActivity.notify.debug('finishIdle')

    def startActive(self, showStartTimestamp):
        DistributedPartyFireworksActivity.notify.debug('startActive')
        messenger.send(FireworksStartedEvent)
        timeSinceStart = globalClockDelta.localElapsedTime(showStartTimestamp)
        if timeSinceStart > self.rocketActor.getDuration('launch'):
            self.rocketActor.hide()
            if timeSinceStart < 60:
                self.startShow(self.eventId, self.showStyle, self.songId,
                               showStartTimestamp)
        else:
            self.rocketActor.play('launch')
            self.rocketParticleSeq = Sequence(
                Wait(RocketSoundDelay), Func(base.playSfx, self.launchSound),
                Func(self.rocketExplosionEffect.start),
                Wait(RocketDirectionDelay),
                LerpHprInterval(self.rocketActor, 4.0, Vec3(0, 0, -60)),
                Func(self.rocketExplosionEffect.end),
                Func(self.rocketActor.hide))
            self.rocketParticleSeq.start()
            taskMgr.doMethodLater(FireworksPostLaunchDelay,
                                  self.startShow,
                                  self.taskName('delayedStartShow'),
                                  extraArgs=[
                                      self.eventId, self.showStyle,
                                      self.songId, showStartTimestamp,
                                      self.root
                                  ])

    def finishActive(self):
        self.rocketParticleSeq = None
        DistributedPartyFireworksActivity.notify.debug('finishActive')
        messenger.send(FireworksFinishedEvent)
        taskMgr.remove(self.taskName('delayedStartShow'))
        FireworkShowMixin.disable(self)
        return

    def startDisabled(self):
        DistributedPartyFireworksActivity.notify.debug('startDisabled')
        if not self.rocketActor.isEmpty():
            self.rocketActor.hide()

    def finishDisabled(self):
        DistributedPartyFireworksActivity.notify.debug('finishDisabled')

    def handleToonDisabled(self, toonId):
        self.notify.warning('handleToonDisabled no implementation yet')
class DistributedPartyFireworksActivity(DistributedPartyActivity, FireworkShowMixin):
    notify = directNotify.newCategory('DistributedPartyFireworksActivity')

    def __init__(self, cr):
        DistributedPartyFireworksActivity.notify.debug('__init__')
        DistributedPartyActivity.__init__(self, cr, ActivityIds.PartyFireworks, ActivityTypes.HostInitiated, wantLever=True)
        FireworkShowMixin.__init__(self, restorePlaygroundMusic=True, startDelay=FireworksPostLaunchDelay)

    def setEventId(self, eventId):
        DistributedPartyFireworksActivity.notify.debug('setEventId( %s )' % FireworkShows.getString(eventId))
        self.eventId = eventId

    def setShowStyle(self, showStyle):
        DistributedPartyFireworksActivity.notify.debug('setShowStyle( %d )' % showStyle)
        self.showStyle = showStyle
    
    def setSongId(self, songId):
        self.songId = songId

    def load(self):
        DistributedPartyFireworksActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.eventId = PartyGlobals.FireworkShows.Summer
        self.launchPadModel = loader.loadModel('phase_13/models/parties/launchPad')
        self.launchPadModel.setH(90.0)
        self.launchPadModel.setPos(0.0, -18.0, 0.0)
        self.launchPadModel.reparentTo(self.root)
        railingsCollection = self.launchPadModel.findAllMatches('**/launchPad_mesh/*railing*')
        for i in xrange(railingsCollection.getNumPaths()):
            railingsCollection[i].setAttrib(AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))

        leverLocator = self.launchPadModel.find('**/RocketLever_locator')
        self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
        self.lever.reparentTo(leverLocator)
        self.toonPullingLeverInterval = None
        self.sign.reparentTo(self.launchPadModel.find('**/launchPad_sign_locator'))
        self.rocketActor = Actor('phase_13/models/parties/rocket_model', {'launch': 'phase_13/models/parties/rocket_launch'})
        rocketLocator = self.launchPadModel.find('**/rocket_locator')
        self.rocketActor.reparentTo(rocketLocator)
        self.rocketActor.node().setBound(OmniBoundingVolume())
        self.rocketActor.node().setFinal(True)
        effectsLocator = self.rocketActor.find('**/joint1')
        self.rocketExplosionEffect = RocketExplosion(effectsLocator, rocketLocator)
        self.rocketParticleSeq = None
        self.launchSound = base.loadSfx('phase_13/audio/sfx/rocket_launch.ogg')
        self.activityFSM = FireworksActivityFSM(self)
        self.activityFSM.request('Idle')
        return

    def unload(self):
        DistributedPartyFireworksActivity.notify.debug('unload')
        taskMgr.remove(self.taskName('delayedStartShow'))
        if self.rocketParticleSeq:
            self.rocketParticleSeq.pause()
            self.rocketParticleSeq = None
        self.launchPadModel.removeNode()
        del self.launchPadModel
        del self.toonPullingLeverInterval
        self.rocketActor.delete()
        self.rocketExplosionEffect.destroy()
        self.activityFSM.request('Disabled')
        del self.rocketActor
        del self.launchSound
        del self.activityFSM
        del self.eventId
        del self.showStyle
        DistributedPartyActivity.unload(self)
        return

    def _leverPulled(self, collEntry):
        DistributedPartyFireworksActivity.notify.debug('_leverPulled')
        hostPulledLever = DistributedPartyActivity._leverPulled(self, collEntry)
        if self.activityFSM.getCurrentOrNextState() == 'Active':
            self.showMessage(TTLocalizer.PartyFireworksAlreadyActive)
        elif self.activityFSM.getCurrentOrNextState() == 'Disabled':
            self.showMessage(TTLocalizer.PartyFireworksAlreadyDone)
        elif self.activityFSM.getCurrentOrNextState() == 'Idle':
            if hostPulledLever:
                base.cr.playGame.getPlace().fsm.request('activity')
                self.toonPullingLeverInterval = self.getToonPullingLeverInterval(base.localAvatar)
                self.toonPullingLeverInterval.append(Func(self.d_toonJoinRequest))
                self.toonPullingLeverInterval.append(Func(base.cr.playGame.getPlace().fsm.request, 'walk'))
                self.toonPullingLeverInterval.start()
            else:
                self.showMessage(TTLocalizer.PartyOnlyHostLeverPull)

    def setState(self, newState, timestamp):
        DistributedPartyFireworksActivity.notify.debug('setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        if newState == 'Active':
            self.activityFSM.request(newState, timestamp)
        else:
            self.activityFSM.request(newState)

    def startIdle(self):
        DistributedPartyFireworksActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyFireworksActivity.notify.debug('finishIdle')

    def startActive(self, showStartTimestamp):
        DistributedPartyFireworksActivity.notify.debug('startActive')
        messenger.send(FireworksStartedEvent)
        timeSinceStart = globalClockDelta.localElapsedTime(showStartTimestamp)
        if timeSinceStart > self.rocketActor.getDuration('launch'):
            self.rocketActor.hide()
            if timeSinceStart < 60:
                self.startShow(self.eventId, self.showStyle, self.songId, showStartTimestamp)
        else:
            self.rocketActor.play('launch')
            self.rocketParticleSeq = Sequence(Wait(RocketSoundDelay), Func(base.playSfx, self.launchSound), Func(self.rocketExplosionEffect.start), Wait(RocketDirectionDelay), LerpHprInterval(self.rocketActor, 4.0, Vec3(0, 0, -60)), Func(self.rocketExplosionEffect.end), Func(self.rocketActor.hide))
            self.rocketParticleSeq.start()
            taskMgr.doMethodLater(FireworksPostLaunchDelay, self.startShow, self.taskName('delayedStartShow'), extraArgs=[self.eventId,
             self.showStyle,
             self.songId,
             showStartTimestamp,
             self.root])

    def finishActive(self):
        self.rocketParticleSeq = None
        DistributedPartyFireworksActivity.notify.debug('finishActive')
        messenger.send(FireworksFinishedEvent)
        taskMgr.remove(self.taskName('delayedStartShow'))
        FireworkShowMixin.disable(self)
        return

    def startDisabled(self):
        DistributedPartyFireworksActivity.notify.debug('startDisabled')
        if not self.rocketActor.isEmpty():
            self.rocketActor.hide()

    def finishDisabled(self):
        DistributedPartyFireworksActivity.notify.debug('finishDisabled')

    def handleToonDisabled(self, toonId):
        self.notify.warning('handleToonDisabled no implementation yet')
class DistributedPartyFireworksActivityAI(DistributedPartyActivityAI):

    notify = directNotify.newCategory("DistributedPartyFireworksActivityAI")

    def __init__(self,
                 air,
                 partyDoId,
                 x,
                 y,
                 h,
                 eventId=PartyGlobals.FireworkShows.Summer,
                 showStyle=0):
        """
        air: instance of ToontownAIRepository
        eventId: a PartyGlobals.FireworkShows value that tells us which show
                 to run
        """
        DistributedPartyFireworksActivityAI.notify.debug("__init__")
        DistributedPartyActivityAI.__init__(
            self,
            air,
            partyDoId,
            x,
            y,
            h,
            PartyGlobals.ActivityIds.PartyFireworks,
            PartyGlobals.ActivityTypes.HostInitiated,
        )
        self.eventId = eventId
        self.showStyle = showStyle
        self.activityFSM = FireworksActivityFSM(self)

    def generate(self):
        DistributedPartyFireworksActivityAI.notify.debug("generate")
        self.activityFSM.request("Idle")

    def getEventId(self):
        DistributedPartyFireworksActivityAI.notify.debug("getEventId")
        return self.eventId

    def getShowStyle(self):
        DistributedPartyFireworksActivityAI.notify.debug("getShowStyle")
        return self.showStyle

    def toonJoinRequest(self):
        """
        The supposed host is requesting the fireworks to start.
        """
        # check that the host sent this message
        senderId = self.air.getAvatarIdFromSender()
        if senderId != self.party.partyInfo.hostId:
            self.air.writeServerEvent(
                'suspicious', senderId,
                'A non-host with avId=%d tried to start a host activated activity.'
                % senderId)
            return
        self.activityFSM.request("Active")

    def showComplete(self, task):
        DistributedPartyFireworksActivityAI.notify.debug("showComplete")
        self.activityFSM.request("Disabled")

        return Task.done

    def delete(self):
        DistributedPartyFireworksActivityAI.notify.debug("delete")
        if hasattr(self, 'activityFSM'):
            self.activityFSM.request('Disabled')
            del self.activityFSM
        DistributedPartyActivityAI.delete(self)

    # FSM transition methods
    def startIdle(self):
        DistributedPartyFireworksActivityAI.notify.debug("startIdle")

    def finishIdle(self):
        DistributedPartyFireworksActivityAI.notify.debug("finishIdle")

    def startActive(self):
        DistributedPartyFireworksActivityAI.notify.debug("startActive")
        messenger.send(PartyGlobals.FireworksStartedEvent)
        showStartTimestamp = ClockDelta.globalClockDelta.getRealNetworkTime()
        # put clients into this state
        self.sendUpdate(
            "setState",
            [
                "Active",  # new state
                showStartTimestamp  # when the show starts
            ])
        # setup to transition to Disabled after the show is over
        throwAwayShow = FireworkShow()
        showDuration = throwAwayShow.getShowDuration(self.eventId)
        showDuration += 20.0
        taskMgr.doMethodLater(
            PartyGlobals.FireworksPostLaunchDelay + showDuration +
            PartyGlobals.FireworksTransitionToDisabledDelay,
            self.showComplete,
            self.taskName("waitForShowComplete"),
        )
        del throwAwayShow

    def finishActive(self):
        DistributedPartyFireworksActivityAI.notify.debug("finishActive")
        messenger.send(PartyGlobals.FireworksFinishedEvent)
        # clean up doMethodLater
        taskMgr.removeTasksMatching(self.taskName("waitForShowComplete"))

    def startDisabled(self):
        DistributedPartyFireworksActivityAI.notify.debug("startDisabled")
        # put clients into this state
        self.sendUpdate(
            "setState",
            [
                "Disabled",  # new state
                0  # dummy timestamp
            ])

    def finishDisabled(self):
        DistributedPartyFireworksActivityAI.notify.debug("finishDisabled")
class DistributedPartyFireworksActivity(DistributedPartyActivity, FireworkShowMixin):

    notify = directNotify.newCategory("DistributedPartyFireworksActivity")
    
    def __init__(self, cr):
        """
        cr: instance of ClientRepository
        """
        DistributedPartyFireworksActivity.notify.debug("__init__")
        DistributedPartyActivity.__init__(self, cr, ActivityIds.PartyFireworks, ActivityTypes.HostInitiated, wantLever=True)
        FireworkShowMixin.__init__(self, restorePlaygroundMusic=True, startDelay=FireworksPostLaunchDelay)
    
    def setEventId(self, eventId):
        DistributedPartyFireworksActivity.notify.debug("setEventId( %s )" % FireworkShows.getString(eventId) )
        self.eventId = eventId
    
    def setShowStyle(self, showStyle):
        DistributedPartyFireworksActivity.notify.debug("setShowStyle( %d )" % showStyle)
        self.showStyle = showStyle
    
    def load(self):
        """
        Load the necessary assets
        """
        DistributedPartyFireworksActivity.notify.debug("load")
        DistributedPartyActivity.load(self)
        
        self.eventId = PartyGlobals.FireworkShows.Summer
        
        # load the rocket platform and place it in party space
        self.launchPadModel = loader.loadModel('phase_13/models/parties/launchPad')
        # Compensate for pivot of fireworks model and center it in 2x4 space
        self.launchPadModel.setH(90.0)
        self.launchPadModel.setPos(0.0, -18.0, 0.0)
        # reparent to root
        self.launchPadModel.reparentTo( self.root )
        # special case the depth testing on the railings to prevent
        # transparency oddness
        railingsCollection = self.launchPadModel.findAllMatches("**/launchPad_mesh/*railing*")
        for i in range( railingsCollection.getNumPaths() ):
            railingsCollection[i].setAttrib(AlphaTestAttrib.make(RenderAttrib.MGreater, 0.75))
                
        # place the lever on the platform
        leverLocator = self.launchPadModel.find("**/RocketLever_locator")
        self.lever.setPosHpr(Vec3.zero(), Vec3.zero())
        self.lever.reparentTo(leverLocator)
        self.toonPullingLeverInterval = None
        
        # place the activity sign
        self.sign.reparentTo( self.launchPadModel.find("**/launchPad_sign_locator") )
        
        # load the rocket with animation and place it on the platform
        self.rocketActor = Actor(
            'phase_13/models/parties/rocket_model',
            {'launch':'phase_13/models/parties/rocket_launch'},
        )
        
        rocketLocator = self.launchPadModel.find("**/rocket_locator")
        self.rocketActor.reparentTo(rocketLocator)
        # ensure the rocket is never culled
        self.rocketActor.node().setBound( OmniBoundingVolume() )
        self.rocketActor.node().setFinal( True )
        
        effectsLocator = self.rocketActor.find("**/joint1")
        self.rocketExplosionEffect  = RocketExplosion(effectsLocator, rocketLocator)
        
        self.rocketParticleSeq = None
        
        self.launchSound = base.loadSfx("phase_13/audio/sfx/rocket_launch.mp3")
        
        # create state machine and set initial state
        self.activityFSM = FireworksActivityFSM( self )
        self.activityFSM.request("Idle")
    
    def unload(self):
        DistributedPartyFireworksActivity.notify.debug("unload")
        taskMgr.remove( self.taskName( "delayedStartShow" ) )
        if self.rocketParticleSeq:
            self.rocketParticleSeq.pause()
            self.rocketParticleSeq = None
        self.launchPadModel.removeNode()
        del self.launchPadModel
        del self.toonPullingLeverInterval
        self.rocketActor.delete()
        self.rocketExplosionEffect.destroy()
        self.activityFSM.request("Disabled")
        del self.rocketActor
        del self.launchSound
        del self.activityFSM
        del self.eventId
        del self.showStyle
        DistributedPartyActivity.unload(self)
    
    def _leverPulled(self, collEntry):
        DistributedPartyFireworksActivity.notify.debug("_leverPulled")
        hostPulledLever = DistributedPartyActivity._leverPulled(self, collEntry)
        if self.activityFSM.getCurrentOrNextState() == "Active":
            self.showMessage(TTLocalizer.PartyFireworksAlreadyActive)
        elif self.activityFSM.getCurrentOrNextState() == "Disabled":
            self.showMessage(TTLocalizer.PartyFireworksAlreadyDone)
        elif self.activityFSM.getCurrentOrNextState() == "Idle":
            if hostPulledLever:
                base.cr.playGame.getPlace().fsm.request("activity") # prevent toon from moving
                self.toonPullingLeverInterval = self.getToonPullingLeverInterval(base.localAvatar)
                self.toonPullingLeverInterval.append(Func(self.d_toonJoinRequest))
                self.toonPullingLeverInterval.append(Func(base.cr.playGame.getPlace().fsm.request, 'walk'))
                self.toonPullingLeverInterval.start()
            else:
                self.showMessage(TTLocalizer.PartyOnlyHostLeverPull)
    
    # FSM utility methods
    def setState(self, newState, timestamp):
        DistributedPartyFireworksActivity.notify.debug( "setState( newState=%s, ... )" % newState )
        DistributedPartyActivity.setState( self, newState, timestamp )
        # pass additional parameters only to those states that need it
        if newState == "Active":
            self.activityFSM.request( newState, timestamp )
        else:
            self.activityFSM.request( newState )
    
    # FSM transition methods
    def startIdle(self):
        DistributedPartyFireworksActivity.notify.debug("startIdle")
    
    def finishIdle(self):
        DistributedPartyFireworksActivity.notify.debug("finishIdle")
        
    def startActive(self, showStartTimestamp):
        DistributedPartyFireworksActivity.notify.debug("startActive")
        messenger.send( FireworksStartedEvent )
        # if too much time has passed since the show started, don't bother
        # playing the rocket animation, just hide it
        timeSinceStart = globalClockDelta.localElapsedTime(showStartTimestamp)
        if timeSinceStart > self.rocketActor.getDuration("launch"):
            self.rocketActor.hide()
            self.startShow(self.eventId, self.showStyle, showStartTimestamp)
        else:
            self.rocketActor.play( "launch" )
            self.rocketParticleSeq = Sequence(Wait(RocketSoundDelay), \
                                                        Func(base.playSfx,self.launchSound), \
                                                        Func(self.rocketExplosionEffect.start), \
                                                        Wait(RocketDirectionDelay), \
                                                        LerpHprInterval(self.rocketActor, 4.0, Vec3(0, 0, -60)), \
                                                        Func(self.rocketExplosionEffect.end), \
                                                        Func(self.rocketActor.hide))
            self.rocketParticleSeq.start()
            
            # give rocket animation some time to play out before starting the show
            taskMgr.doMethodLater(
                FireworksPostLaunchDelay,
                self.startShow,
                self.taskName( "delayedStartShow" ),
                extraArgs=[self.eventId, self.showStyle, showStartTimestamp, self.root],
            )
        
    def finishActive(self):
        self.rocketParticleSeq = None
        DistributedPartyFireworksActivity.notify.debug("finishActive")
        messenger.send( FireworksFinishedEvent )
        taskMgr.remove( self.taskName( "delayedStartShow" ) )
        FireworkShowMixin.disable(self) # stop the fireworks show
        
    def startDisabled(self):
        DistributedPartyFireworksActivity.notify.debug("startDisabled")
        if not self.rocketActor.isEmpty():
            self.rocketActor.hide() # so late comers won't see the rocket
    
    def finishDisabled(self):
        DistributedPartyFireworksActivity.notify.debug("finishDisabled")

    def handleToonDisabled(self, toonId):
        """
        A toon dropped unexpectedly from the game. Handle it!
        """
        self.notify.warning("handleToonDisabled no implementation yet" )