示例#1
0
 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
示例#2
0
 def createFireworkShow(self):
     if not self.fireworkShow:
         self.fireworkShow = FireworkShow(self.eventId)
示例#3
0
class FireworkShowMixin:
    notify = DirectNotifyGlobal.directNotify.newCategory('FireworkShowMixin')
    
    def __init__(self, restorePlaygroundMusic = True, startDelay = 0.0):
        self.currentShow = None
        self.restorePlaygroundMusic = restorePlaygroundMusic
        self.startDelay = startDelay
        self.timestamp = None
        self.fireworkShow = None
        self.eventId = JULY4_FIREWORKS
        self.accept('MusicEnabled', self.startMusic)

    
    def disable(self):
        if self.currentShow:
            self.currentShow.pause()
            self.currentShow = None
            if base.cr.config.GetBool('want-old-fireworks', 0):
                ivalMgr.finishIntervalsMatching('shootFirework*')
            else:
                self.destroyFireworkShow()
        
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1)
        
        self.restoreCameraLens()
        if hasattr(self.getHood(), 'loader'):
            self.getGeom().clearColorScale()
        
        if hasattr(self.getHood(), 'sky'):
            self.getSky().show()
            self.getSky().clearColorScale()
        
        if hasattr(base, 'localAvatar') and base.localAvatar:
            base.localAvatar.clearColorScale()
        
        base.setBackgroundColor(DefaultBackgroundColor)
        self.ignoreAll()

    
    def startMusic(self):
        if self.timestamp:
            self.getLoader().music.stop()
            t = globalClockDelta.localElapsedTime(self.timestamp) - self.startDelay
            base.playMusic(self.showMusic, 0, 1, 0.80000000000000004, max(0, t))
        

    
    def shootFirework(self, x, y, z, style, color1, color2):
        amp = 5
        Fireworks.shootFirework(style, x, y, z, color1, color2, amp)

    
    def startShow(self, eventId, style, timestamp, root = render):
        t = globalClockDelta.localElapsedTime(timestamp) - self.startDelay
        self.timestamp = timestamp
        self.showMusic = None
        self.eventId = eventId
        if base.config.GetBool('want-old-fireworks', 0):
            self.currentShow = self.getFireworkShowIval(eventId, style, t)
            if self.currentShow:
                self.currentShow.start(t)
            
        else:
            self.createFireworkShow()
            if t > self.fireworkShow.getShowDuration():
                return None
            
            preShow = self.preShow(eventId, t)
            postShow = self.postShow(eventId)
            beginFireworkShow = Func(self.beginFireworkShow, max(0, t), root)
            self.currentShow = Sequence(preShow, beginFireworkShow, Wait(max(0, self.fireworkShow.getShowDuration() - max(0, t))), postShow)
            self.currentShow.start()

    
    def preShow(self, eventId, startT):
        if eventId == JULY4_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksJuly4Beginning
            endMessage = TTLocalizer.FireworksJuly4Ending
            musicFile = 'phase_4/audio/bgm/tt_party2.mid'
        elif eventId == NEWYEARS_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksNewYearsEveBeginning
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
            musicFile = 'phase_4/audio/bgm/tt_s_ara_gen_fireworks_auldLangSyne.mid'
        elif eventId == PartyGlobals.FireworkShows.Summer:
            instructionMessage = TTLocalizer.FireworksActivityInstructions
            startMessage = TTLocalizer.FireworksActivityBeginning
            endMessage = TTLocalizer.FireworksActivityEnding
            musicFile = 'phase_4/audio/bgm/tt_summer.mid'
        elif eventId == COMBO_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksComboBeginning
            endMessage = TTLocalizer.FireworksComboEnding
            musicFile = 'phase_4/audio/bgm/tt_party2.mid'
        else:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None
        self.showMusic = loader.loadMusic(musicFile)
        self.showMusic.setVolume(1)
        
        def __lightDecorationOn__():
            place = base.cr.playGame.getPlace()
            if place is None:
                return None
            
            if hasattr(place, 'halloweenLights'):
                if not self._FireworkShowMixin__checkStreetValidity():
                    return None
                else:
                    place.halloweenLights = base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*light*').asList()
                    place.halloweenLights.extend(base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*lamp*').asList())
                    for light in place.halloweenLights:
                        light.setColorScaleOff(0)
                    
            elif not self._FireworkShowMixin__checkHoodValidity():
                return None
            else:
                place.loader.hood.halloweenLights = base.cr.playGame.hood.loader.geom.findAllMatches('**/*light*').asList()
                place.loader.hood.halloweenLights.extend(base.cr.playGame.hood.loader.geom.findAllMatches('**/*lamp*').asList())
                for light in base.cr.playGame.hood.halloweenLights:
                    light.setColorScaleOff(0)
                
            if self.fireworkShow and not self.fireworkShow.isEmpty():
                self.fireworkShow.setColorScaleOff(0)
            

        if self._FireworkShowMixin__checkHoodValidity() and hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            preShow = Sequence(Func(base.localAvatar.setSystemMessage, 0, startMessage), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(0.0, 0.0, 0.0, 1.0)), LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(0.25, 0.25, 0.34999999999999998, 1)), LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(0.84999999999999998, 0.84999999999999998, 0.84999999999999998, 1)), Func(__lightDecorationOn__)), Func(base.setBackgroundColor, Vec4(0, 0, 0, 1)), Func(self._FireworkShowMixin__checkDDFog), Func(base.camLens.setFar, 1000.0), Func(base.cr.playGame.hood.sky.hide), Func(base.localAvatar.setSystemMessage, 0, instructionMessage), Func(self.getLoader().music.stop), Wait(2.0), Func(base.playMusic, self.showMusic, 0, 1, 0.80000000000000004, max(0, startT)))
            return preShow
        

    
    def restoreCameraLens(self):
        hood = self.getHood()
        from toontown.hood import *
        if isinstance(hood, OZHood.OZHood):
            base.camLens.setFar(SpeedwayCameraFar)
        elif isinstance(hood, GSHood.GSHood):
            base.camLens.setFar(SpeedwayCameraFar)
        else:
            base.camLens.setFar(DefaultCameraFar)

    
    def postShow(self, eventId):
        if eventId == JULY4_FIREWORKS:
            endMessage = TTLocalizer.FireworksJuly4Ending
        elif eventId == NEWYEARS_FIREWORKS:
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
        elif eventId == PartyGlobals.FireworkShows.Summer:
            endMessage = TTLocalizer.FireworksActivityEnding
        elif eventId == COMBO_FIREWORKS:
            endMessage = TTLocalizer.FireworksComboEnding
        else:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None
        if self._FireworkShowMixin__checkHoodValidity() and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            postShow = Sequence(Func(base.cr.playGame.hood.sky.show), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(1, 1, 1, 1))), Func(self._FireworkShowMixin__restoreDDFog), Func(self.restoreCameraLens), Func(base.setBackgroundColor, DefaultBackgroundColor), Func(self.showMusic.stop), Func(base.localAvatar.setSystemMessage, 0, endMessage))
        
        if self.restorePlaygroundMusic:
            postShow.append(Wait(2.0))
            postShow.append(Func(base.playMusic, self.getLoader().music, 1, 1, 0.80000000000000004))
        
        return postShow

    
    def createFireworkShow(self):
        if not self.fireworkShow:
            self.fireworkShow = FireworkShow(self.eventId)
        

    
    def destroyFireworkShow(self):
        if self.fireworkShow:
            self.fireworkShow.cleanupShow()
            self.fireworkShow = None
        

    
    def beginFireworkShow(self, timeStamp, root):
        if self.fireworkShow and not self.fireworkShow.isPlaying():
            self.fireworkShow.begin(timeStamp)
            self.fireworkShow.reparentTo(root)
            hood = self.getHood()
            from toontown.hood import *
            if isinstance(hood, TTHood.TTHood):
                self.fireworkShow.setPos(150, 0, 80)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, BRHood.BRHood):
                self.fireworkShow.setPos(-200, -60, 50)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, MMHood.MMHood):
                self.fireworkShow.setPos(150, -25, 40)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, DGHood.DGHood):
                self.fireworkShow.setPos(-80, -50, 60)
                self.fireworkShow.setHpr(0, 0, 0)
            elif isinstance(hood, DLHood.DLHood):
                self.fireworkShow.setPos(-160, 0, 80)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, GSHood.GSHood):
                self.fireworkShow.setPos(60, -350, 80)
                self.fireworkShow.setHpr(20, 0, 0)
            elif isinstance(hood, DDHood.DDHood):
                self.fireworkShow.setPos(150, 0, 50)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, OZHood.OZHood):
                self.fireworkShow.setPos(-450, -80, 140)
                self.fireworkShow.setHpr(300, 0, 0)
            elif isinstance(hood, PartyHood.PartyHood):
                self.fireworkShow.setPos(0, -400, 120)
                self.fireworkShow.lookAt(0, 0, 0)
                self.fireworkShow.setScale(1.8)
            
        

    
    def getFireworkShowIval(self, eventId, index, startT):
        show = FireworkShows.getShow(eventId, index)
        if show is None:
            FireworkShowMixin.notify.warning('could not find firework show: index: %s' % index)
            return None
        
        preShow = self.preShow(eventId, startT)
        mainShow = Sequence()
        currentT = skyTransitionDuration + preShowPauseDuration
        for effect in show:
            (waitTime, style, colorIndex1, colorIndex2, amp, x, y, z) = effect
            if waitTime > 0:
                currentT += waitTime
                mainShow.append(Wait(waitTime))
            
            if currentT >= startT:
                mainShow.append(Func(Fireworks.shootFirework, style, x, y, z, colorIndex1, colorIndex2, amp))
                continue
        
        postShow = self.postShow(eventId)
        return Sequence(preShow, mainShow, postShow)

    
    def clearMyColorScales(self):
        if self.getGeom() and not self.getGeom().isEmpty():
            self.getGeom().clearColorScale()
        
        if self.getSky() and not self.getSky().isEmpty():
            self.getSky().clearColorScale()
        

    
    def getLoader(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood.loader
        

    
    def getHood(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood
        

    
    def getGeom(self):
        loader = self.getLoader()
        if loader:
            return loader.geom
        

    
    def getSky(self):
        hood = self.getHood()
        if hood:
            return hood.sky
        

    
    def _FireworkShowMixin__checkDDFog(self):
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()
                
            
        

    
    def _FireworkShowMixin__restoreDDFog(self):
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()
                
            
        

    
    def _FireworkShowMixin__checkStreetValidity(self):
        if hasattr(base.cr.playGame, 'getPlace') and base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'loader') and base.cr.playGame.getPlace().loader and hasattr(base.cr.playGame.getPlace().loader, 'geom') and base.cr.playGame.getPlace().loader.geom:
            return True
        else:
            return False

    
    def _FireworkShowMixin__checkHoodValidity(self):
        if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom:
            return True
        else:
            return False
 def createFireworkShow(self):
     if not self.fireworkShow:
         self.fireworkShow = FireworkShow(self.eventId)
class FireworkShowMixin:
    notify = DirectNotifyGlobal.directNotify.newCategory('FireworkShowMixin')
    
    def __init__(self, restorePlaygroundMusic = True, startDelay = 0.0):
        self.currentShow = None
        self.restorePlaygroundMusic = restorePlaygroundMusic
        self.startDelay = startDelay
        self.timestamp = None
        self.fireworkShow = None
        self.eventId = JULY4_FIREWORKS
        self.accept('MusicEnabled', self.startMusic)

    
    def disable(self):
        if self.currentShow:
            self.currentShow.pause()
            self.currentShow = None
            if base.cr.config.GetBool('want-old-fireworks', 0):
                ivalMgr.finishIntervalsMatching('shootFirework*')
            else:
                self.destroyFireworkShow()
        
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1)
        
        self.restoreCameraLens()
        if hasattr(self.getHood(), 'loader'):
            self.getGeom().clearColorScale()
        
        if hasattr(self.getHood(), 'sky'):
            self.getSky().show()
            self.getSky().clearColorScale()
        
        if hasattr(base, 'localAvatar') and base.localAvatar:
            base.localAvatar.clearColorScale()
        
        base.setBackgroundColor(DefaultBackgroundColor)
        self.ignoreAll()

    
    def startMusic(self):
        if self.timestamp:
            self.getLoader().music.stop()
            t = globalClockDelta.localElapsedTime(self.timestamp) - self.startDelay
            base.playMusic(self.showMusic, 0, 1, 0.80000000000000004, max(0, t))
        

    
    def shootFirework(self, x, y, z, style, color1, color2):
        amp = 5
        Fireworks.shootFirework(style, x, y, z, color1, color2, amp)

    
    def startShow(self, eventId, style, timestamp, root = render):
        t = globalClockDelta.localElapsedTime(timestamp) - self.startDelay
        self.timestamp = timestamp
        self.showMusic = None
        self.eventId = eventId
        if base.config.GetBool('want-old-fireworks', 0):
            self.currentShow = self.getFireworkShowIval(eventId, style, t)
            if self.currentShow:
                self.currentShow.start(t)
            
        else:
            self.createFireworkShow()
            if t > self.fireworkShow.getShowDuration():
                return None
            
            preShow = self.preShow(eventId, t)
            postShow = self.postShow(eventId)
            beginFireworkShow = Func(self.beginFireworkShow, max(0, t), root)
            self.currentShow = Sequence(preShow, beginFireworkShow, Wait(max(0, self.fireworkShow.getShowDuration() - max(0, t))), postShow)
            self.currentShow.start()

    
    def preShow(self, eventId, startT):
        if eventId == JULY4_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksJuly4Beginning
            endMessage = TTLocalizer.FireworksJuly4Ending
            musicFile = 'phase_4/audio/bgm/tt_party2.mid'
        elif eventId == NEWYEARS_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksNewYearsEveBeginning
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
            musicFile = 'phase_4/audio/bgm/tt_s_ara_gen_fireworks_auldLangSyne.mid'
        elif eventId == PartyGlobals.FireworkShows.Summer:
            instructionMessage = TTLocalizer.FireworksActivityInstructions
            startMessage = TTLocalizer.FireworksActivityBeginning
            endMessage = TTLocalizer.FireworksActivityEnding
            musicFile = 'phase_4/audio/bgm/tt_summer.ogg'
        elif eventId == COMBO_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksComboBeginning
            endMessage = TTLocalizer.FireworksComboEnding
            musicFile = 'phase_4/audio/bgm/tt_party2.ogg'
        else:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None
        self.showMusic = loader.loadMusic(musicFile)
        self.showMusic.setVolume(1)
        
        def __lightDecorationOn__():
            place = base.cr.playGame.getPlace()
            if place is None:
                return None
            
            if hasattr(place, 'halloweenLights'):
                if not self._FireworkShowMixin__checkStreetValidity():
                    return None
                else:
                    place.halloweenLights = base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*light*').asList()
                    place.halloweenLights.extend(base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*lamp*').asList())
                    for light in place.halloweenLights:
                        light.setColorScaleOff(0)
                    
            elif not self._FireworkShowMixin__checkHoodValidity():
                return None
            else:
                place.loader.hood.halloweenLights = base.cr.playGame.hood.loader.geom.findAllMatches('**/*light*').asList()
                place.loader.hood.halloweenLights.extend(base.cr.playGame.hood.loader.geom.findAllMatches('**/*lamp*').asList())
                for light in base.cr.playGame.hood.halloweenLights:
                    light.setColorScaleOff(0)
                
            if self.fireworkShow and not self.fireworkShow.isEmpty():
                self.fireworkShow.setColorScaleOff(0)
            

        if self._FireworkShowMixin__checkHoodValidity() and hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            preShow = Sequence(Func(base.localAvatar.setSystemMessage, 0, startMessage), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(0.0, 0.0, 0.0, 1.0)), LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(0.25, 0.25, 0.34999999999999998, 1)), LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(0.84999999999999998, 0.84999999999999998, 0.84999999999999998, 1)), Func(__lightDecorationOn__)), Func(base.setBackgroundColor, Vec4(0, 0, 0, 1)), Func(self._FireworkShowMixin__checkDDFog), Func(base.camLens.setFar, 1000.0), Func(base.cr.playGame.hood.sky.hide), Func(base.localAvatar.setSystemMessage, 0, instructionMessage), Func(self.getLoader().music.stop), Wait(2.0), Func(base.playMusic, self.showMusic, 0, 1, 0.80000000000000004, max(0, startT)))
            return preShow
        

    
    def restoreCameraLens(self):
        hood = self.getHood()
        from toontown.hood import *
        if isinstance(hood, OZHood.OZHood):
            base.camLens.setFar(SpeedwayCameraFar)
        elif isinstance(hood, GSHood.GSHood):
            base.camLens.setFar(SpeedwayCameraFar)
        else:
            base.camLens.setFar(DefaultCameraFar)

    
    def postShow(self, eventId):
        if eventId == JULY4_FIREWORKS:
            endMessage = TTLocalizer.FireworksJuly4Ending
        elif eventId == NEWYEARS_FIREWORKS:
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
        elif eventId == PartyGlobals.FireworkShows.Summer:
            endMessage = TTLocalizer.FireworksActivityEnding
        elif eventId == COMBO_FIREWORKS:
            endMessage = TTLocalizer.FireworksComboEnding
        else:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None
        if self._FireworkShowMixin__checkHoodValidity() and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            postShow = Sequence(Func(base.cr.playGame.hood.sky.show), Parallel(LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(1, 1, 1, 1)), LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(1, 1, 1, 1))), Func(self._FireworkShowMixin__restoreDDFog), Func(self.restoreCameraLens), Func(base.setBackgroundColor, DefaultBackgroundColor), Func(self.showMusic.stop), Func(base.localAvatar.setSystemMessage, 0, endMessage))
        
        if self.restorePlaygroundMusic:
            postShow.append(Wait(2.0))
            postShow.append(Func(base.playMusic, self.getLoader().music, 1, 1, 0.80000000000000004))
        
        return postShow

    
    def createFireworkShow(self):
        if not self.fireworkShow:
            self.fireworkShow = FireworkShow(self.eventId)
        

    
    def destroyFireworkShow(self):
        if self.fireworkShow:
            self.fireworkShow.cleanupShow()
            self.fireworkShow = None
        

    
    def beginFireworkShow(self, timeStamp, root):
        if self.fireworkShow and not self.fireworkShow.isPlaying():
            self.fireworkShow.begin(timeStamp)
            self.fireworkShow.reparentTo(root)
            hood = self.getHood()
            from toontown.hood import *
            if isinstance(hood, TTHood.TTHood):
                self.fireworkShow.setPos(150, 0, 80)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, BRHood.BRHood):
                self.fireworkShow.setPos(-200, -60, 50)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, MMHood.MMHood):
                self.fireworkShow.setPos(150, -25, 40)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, DGHood.DGHood):
                self.fireworkShow.setPos(-80, -50, 60)
                self.fireworkShow.setHpr(0, 0, 0)
            elif isinstance(hood, DLHood.DLHood):
                self.fireworkShow.setPos(-160, 0, 80)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, GSHood.GSHood):
                self.fireworkShow.setPos(60, -350, 80)
                self.fireworkShow.setHpr(20, 0, 0)
            elif isinstance(hood, DDHood.DDHood):
                self.fireworkShow.setPos(150, 0, 50)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, OZHood.OZHood):
                self.fireworkShow.setPos(-450, -80, 140)
                self.fireworkShow.setHpr(300, 0, 0)
            elif isinstance(hood, PartyHood.PartyHood):
                self.fireworkShow.setPos(0, -400, 120)
                self.fireworkShow.lookAt(0, 0, 0)
                self.fireworkShow.setScale(1.8)
            
        

    
    def getFireworkShowIval(self, eventId, index, startT):
        show = FireworkShows.getShow(eventId, index)
        if show is None:
            FireworkShowMixin.notify.warning('could not find firework show: index: %s' % index)
            return None
        
        preShow = self.preShow(eventId, startT)
        mainShow = Sequence()
        currentT = skyTransitionDuration + preShowPauseDuration
        for effect in show:
            (waitTime, style, colorIndex1, colorIndex2, amp, x, y, z) = effect
            if waitTime > 0:
                currentT += waitTime
                mainShow.append(Wait(waitTime))
            
            if currentT >= startT:
                mainShow.append(Func(Fireworks.shootFirework, style, x, y, z, colorIndex1, colorIndex2, amp))
                continue
        
        postShow = self.postShow(eventId)
        return Sequence(preShow, mainShow, postShow)

    
    def clearMyColorScales(self):
        if self.getGeom() and not self.getGeom().isEmpty():
            self.getGeom().clearColorScale()
        
        if self.getSky() and not self.getSky().isEmpty():
            self.getSky().clearColorScale()
        

    
    def getLoader(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood.loader
        

    
    def getHood(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood
        

    
    def getGeom(self):
        loader = self.getLoader()
        if loader:
            return loader.geom
        

    
    def getSky(self):
        hood = self.getHood()
        if hood:
            return hood.sky
        

    
    def _FireworkShowMixin__checkDDFog(self):
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.20000000000000001, 0.20000000000000001, 0.20000000000000001, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()
                
            
        

    
    def _FireworkShowMixin__restoreDDFog(self):
        DDHood = DDHood
        import toontown.hood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.80000000000000004, 0.80000000000000004, 0.80000000000000004, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()
                
            
        

    
    def _FireworkShowMixin__checkStreetValidity(self):
        if hasattr(base.cr.playGame, 'getPlace') and base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'loader') and base.cr.playGame.getPlace().loader and hasattr(base.cr.playGame.getPlace().loader, 'geom') and base.cr.playGame.getPlace().loader.geom:
            return True
        else:
            return False

    
    def _FireworkShowMixin__checkHoodValidity(self):
        if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom:
            return True
        else:
            return False
示例#6
0
class FireworkShowMixin:

    notify = DirectNotifyGlobal.directNotify.newCategory("FireworkShowMixin")

    def __init__(self, restorePlaygroundMusic=True, startDelay=0.0):
        assert (FireworkShowMixin.notify.debug("__init__"))
        self.currentShow = None
        self.restorePlaygroundMusic = restorePlaygroundMusic
        self.startDelay = startDelay
        self.timestamp = None
        self.fireworkShow = None  # Reference to the new show
        self.eventId = JULY4_FIREWORKS  # Defines type of show enabled
        self.accept('MusicEnabled', self.startMusic)

    def disable(self):
        assert (FireworkShowMixin.notify.debug("disable"))
        if self.currentShow:
            self.currentShow.pause()
            self.currentShow = None
            # Finish the actual intervals that are shooting individual
            # fireworks in case we exited during the show
            if base.cr.config.GetBool('want-old-fireworks', 0):
                ivalMgr.finishIntervalsMatching("shootFirework*")
            else:
                self.destroyFireworkShow()

        from toontown.hood import DDHood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)

        self.restoreCameraLens()
        # If this firework show is deleted after the hood, then
        # we will not be able to clear these color scales
        if hasattr(self.getHood(), "loader"):
            self.getGeom().clearColorScale()
        if hasattr(self.getHood(), "sky"):
            self.getSky().show()
            self.getSky().clearColorScale()
        if hasattr(base, "localAvatar") and base.localAvatar:
            base.localAvatar.clearColorScale()

        base.setBackgroundColor(DefaultBackgroundColor)

        # cleanup messenger hooks
        self.ignoreAll()

    def startMusic(self):
        """
        Start the music for the firework show
        so that it correctly syncs up
        """

        if self.timestamp:
            self.getLoader().music.stop()
            t = globalClockDelta.localElapsedTime(
                self.timestamp) - self.startDelay
            base.playMusic(self.showMusic, 0, 1, 0.8, max(0, t))

    def shootFirework(self, x, y, z, style, color1, color2):
        assert (FireworkShowMixin.notify.debug("shootFirework: style: %s" %
                                               style))
        amp = 5
        Fireworks.shootFirework(style, x, y, z, color1, color2, amp)

    def startShow(self, eventId, style, timestamp, root=render):
        t = globalClockDelta.localElapsedTime(timestamp) - self.startDelay

        self.timestamp = timestamp
        self.showMusic = None
        self.eventId = eventId

        if base.config.GetBool('want-old-fireworks', 0):
            self.currentShow = self.getFireworkShowIval(eventId, style, t)
            if self.currentShow:
                self.currentShow.start(t)
        else:
            self.createFireworkShow()
            if t > self.fireworkShow.getShowDuration():
                return
            preShow = self.preShow(eventId, t)
            postShow = self.postShow(eventId)
            beginFireworkShow = Func(self.beginFireworkShow, max(0, t), root)
            self.currentShow = Sequence(
                preShow, beginFireworkShow,
                Wait(max(0,
                         self.fireworkShow.getShowDuration() - max(0, t))),
                postShow)
            self.currentShow.start()

            assert( FireworkShowMixin.notify.debug("startShow: event: %s, networkTime: %s, elapsedTime: %s, showDuration: %s" \
                        % (eventId, timestamp,t, self.fireworkShow.getShowDuration()) ) )

    def preShow(self, eventId, startT):
        # Is this a valid ID?  If so get appropriate message and music
        if eventId == JULY4_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksJuly4Beginning
            endMessage = TTLocalizer.FireworksJuly4Ending
            musicFile = "phase_4/audio/bgm/tt_party2.mid"
        elif eventId == NEWYEARS_FIREWORKS:
            instructionMessage = TTLocalizer.FireworksInstructions
            startMessage = TTLocalizer.FireworksNewYearsEveBeginning
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
            musicFile = "phase_4/audio/bgm/tt_s_ara_gen_fireworks_auldLangSyne.mid"
        elif eventId == PartyGlobals.FireworkShows.Summer:
            instructionMessage = TTLocalizer.FireworksActivityInstructions
            startMessage = TTLocalizer.FireworksActivityBeginning
            endMessage = TTLocalizer.FireworksActivityEnding
            musicFile = "phase_4/audio/bgm/tt_summer.mid"
        else:
            FireworkShowMixin.notify.warning("Invalid fireworks event ID: %d" %
                                             (eventId))
            return None
        self.showMusic = loader.loadMusic(musicFile)
        self.showMusic.setVolume(1)

        def __lightDecorationOn__():
            """ Switch the lights on """
            place = base.cr.playGame.getPlace()
            if hasattr(place, "halloweenLights"):
                if not self.__checkStreetValidity():
                    return
                else:
                    place.halloweenLights = base.cr.playGame.getPlace(
                    ).loader.geom.findAllMatches("**/*light*").asList()
                    place.halloweenLights.extend(
                        base.cr.playGame.getPlace().loader.geom.findAllMatches(
                            "**/*lamp*").asList())
                    for light in place.halloweenLights:
                        light.setColorScaleOff(0)
            else:
                if not self.__checkHoodValidity():
                    return
                else:
                    place.loader.hood.halloweenLights = base.cr.playGame.hood.loader.geom.findAllMatches(
                        "**/*light*").asList()
                    place.loader.hood.halloweenLights.extend(
                        base.cr.playGame.hood.loader.geom.findAllMatches(
                            "**/*lamp*").asList())
                    for light in base.cr.playGame.hood.halloweenLights:
                        light.setColorScaleOff(0)

            if self.fireworkShow and not self.fireworkShow.isEmpty():
                self.fireworkShow.setColorScaleOff(0)

        # Fixes transition related crashes

        if self.__checkHoodValidity() and hasattr(base.cr.playGame, "hood") \
        and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, "sky")\
        and base.cr.playGame.hood.sky:
            preShow = Sequence(
                Func(base.localAvatar.setSystemMessage, 0, startMessage),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5,
                                           Vec4(0.0, 0.0, 0.0, 1.0)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom,
                                           2.5, Vec4(0.25, 0.25, 0.35, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5,
                                           Vec4(0.85, 0.85, 0.85, 1)),
                    Func(__lightDecorationOn__),
                ),
                Func(base.setBackgroundColor, Vec4(0, 0, 0, 1)),
                Func(self.__checkDDFog),
                Func(base.camLens.setFar, 1000.0),
                Func(base.cr.playGame.hood.sky.hide),
                Func(base.localAvatar.setSystemMessage, 0, instructionMessage),
                Func(self.getLoader().music.stop),
                Wait(2.0),
                # Start music at right place when elapsed time is > 4 seconds
                Func(base.playMusic, self.showMusic, 0, 1, 0.8, max(0,
                                                                    startT)),
            )

            return preShow

    def restoreCameraLens(self):
        """ Restore the far clipping distance after fireworks """

        hood = self.getHood()

        from toontown.hood import *

        if isinstance(hood, OZHood.OZHood):
            base.camLens.setFar(SpeedwayCameraFar)
        elif isinstance(hood, GSHood.GSHood):
            base.camLens.setFar(SpeedwayCameraFar)
        else:
            base.camLens.setFar(DefaultCameraFar)

    def postShow(self, eventId):
        if eventId == JULY4_FIREWORKS:
            endMessage = TTLocalizer.FireworksJuly4Ending
        elif eventId == NEWYEARS_FIREWORKS:
            endMessage = TTLocalizer.FireworksNewYearsEveEnding
        elif eventId == PartyGlobals.FireworkShows.Summer:
            endMessage = TTLocalizer.FireworksActivityEnding
        else:
            FireworkShowMixin.notify.warning("Invalid fireworks event ID: %d" %
                                             (eventId))
            return None

        # Fixes transition related crashes
        if self.__checkHoodValidity() and hasattr(base.cr.playGame.hood, "sky") \
        and base.cr.playGame.hood.sky:
            postShow = Sequence(
                Func(base.cr.playGame.hood.sky.show),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5,
                                           Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom,
                                           2.5, Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5,
                                           Vec4(1, 1, 1, 1)),
                ), Func(self.__restoreDDFog), Func(self.restoreCameraLens),
                Func(base.setBackgroundColor, DefaultBackgroundColor),
                Func(self.showMusic.stop),
                Func(base.localAvatar.setSystemMessage, 0, endMessage))

        if self.restorePlaygroundMusic:
            # Start the playground music up again
            postShow.append(Wait(2.0))
            postShow.append(
                Func(base.playMusic,
                     self.getLoader().music, 1, 1, 0.8))

        return postShow

    def createFireworkShow(self):
        if not self.fireworkShow:
            self.fireworkShow = FireworkShow(self.eventId)

    def destroyFireworkShow(self):
        if self.fireworkShow:
            self.fireworkShow.cleanupShow()
            self.fireworkShow = None

    def beginFireworkShow(self, timeStamp, root):
        if self.fireworkShow and not self.fireworkShow.isPlaying():
            self.fireworkShow.begin(timeStamp)
            self.fireworkShow.reparentTo(root)

            hood = self.getHood()

            from toontown.hood import *

            if isinstance(hood, TTHood.TTHood):
                self.fireworkShow.setPos(150, 0, 80)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, BRHood.BRHood):
                self.fireworkShow.setPos(-200, -60, 50)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, MMHood.MMHood):
                self.fireworkShow.setPos(150, -25, 40)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, DGHood.DGHood):
                self.fireworkShow.setPos(-80, -50, 60)
                self.fireworkShow.setHpr(0, 0, 0)
            elif isinstance(hood, DLHood.DLHood):
                self.fireworkShow.setPos(-160, 0, 80)
                self.fireworkShow.setHpr(270, 0, 0)
            elif isinstance(hood, GSHood.GSHood):
                self.fireworkShow.setPos(60, -350, 80)
                self.fireworkShow.setHpr(20, 0, 0)
            elif isinstance(hood, DDHood.DDHood):
                self.fireworkShow.setPos(150, 0, 50)
                self.fireworkShow.setHpr(90, 0, 0)
            elif isinstance(hood, OZHood.OZHood):
                self.fireworkShow.setPos(-450, -80, 140)
                self.fireworkShow.setHpr(300, 0, 0)
            elif isinstance(hood, PartyHood.PartyHood):
                self.fireworkShow.setPos(0, -400, 120)
                self.fireworkShow.lookAt(0, 0, 0)
                self.fireworkShow.setScale(1.8)

    def getFireworkShowIval(self, eventId, index, startT):
        show = FireworkShows.getShow(eventId, index)
        if show is None:
            FireworkShowMixin.notify.warning(
                "could not find firework show: index: %s" % (index))
            return None

        # dark = 0.5
        # skyDark = 1
        # Show is beginning, turn off the lights
        # Stop the playground music
        # Start our music
        # preShow = Sequence(
        # Func(base.localAvatar.setSystemMessage, 0, startMessage),
        # Func(self.__checkDDFog),
        # Parallel(
        # LerpColorScaleInterval(
        # self.getGeom(),
        # skyTransitionDuration,
        # Vec4(dark, dark, dark, 1)
        # Vec4(0.33, 0.33, 0.52, 1)
        # ),
        # LerpColorScaleInterval(
        # self.getSky(),
        # skyTransitionDuration,
        # Vec4(skyDark,skyDark,skyDark,1)
        # Vec4(0.1, 0.1, 0.25, 1)
        # ),
        # ),
        # Func(base.localAvatar.setSystemMessage, 0, instructionMessage),
        # Wait(preShowPauseDuration),
        # Func(self.getLoader().music.stop),
        # Start music at right place when elapsed time is > 4 seconds
        # Func(base.playMusic, showMusic, 0, 1, 0.8, max(0, startT-(skyTransitionDuration + preShowPauseDuration))),
        # )

        preShow = self.preShow(eventId, startT)

        # Main show
        mainShow = Sequence()
        currentT = skyTransitionDuration + preShowPauseDuration
        for effect in show:
            waitTime, style, colorIndex1, colorIndex2, amp, x, y, z = effect
            if waitTime > 0:
                currentT += waitTime
                mainShow.append(Wait(waitTime))
            # Do not add the firework Ival if our start time is greater than
            # the current time since the Func Interval can not be skipped over
            # and all the skipped over fireworks will otherwise fire at once
            if currentT >= startT:
                mainShow.append(
                    Func(Fireworks.shootFirework, style, x, y, z, colorIndex1,
                         colorIndex2, amp))

        # Show is over, turn on the lights
        # postShow = Sequence(
        # Wait(postShowPauseDuration),
        # Func(self.__restoreDDFog),
        # Parallel(
        # LerpColorScaleInterval(
        # self.getGeom(),
        # skyTransitionDuration, Vec4(1, 1, 1, 1)
        # ),
        # LerpColorScaleInterval(
        # self.getSky(),
        # skyTransitionDuration, Vec4(1, 1, 1, 1)
        # ),
        # ),
        # Func(self.clearMyColorScales),
        # Func(showMusic.stop),
        # Func(base.localAvatar.setSystemMessage, 0, endMessage),
        # )
        # if self.restorePlaygroundMusic:
        # Start the playground music up again
        # postShow.append( Wait(preNormalMusicPauseDuration) )
        # postShow.append( Func(base.playMusic, self.getLoader().music, 1, 1, 0.8) )

        postShow = self.postShow(eventId)
        return Sequence(preShow, mainShow, postShow)

    # Utility functions to handle the difference between hoods and estates.
    # These functions might eventually want to move to PlayGame, but for now
    # Fireworks are the only things that really need it.  Also, the getHood
    # function is a bit misleading, since in case of estates it will return
    # the estateLoader.  The playGame.hood.loader hierarchy for hoods is compressed
    # into playGame.estateLoader for estates.  The getHood function is used by
    # fireworks to access the sky and the fog.  Sky/fog are stored under the
    # playGame.estateLoader for the estates, and the playGame.hood for hoods.
    def clearMyColorScales(self):
        if self.getGeom() and not (self.getGeom().isEmpty()):
            self.getGeom().clearColorScale()
        if self.getSky() and not (self.getSky().isEmpty()):
            self.getSky().clearColorScale()

    def getLoader(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood.loader

    def getHood(self):
        if base.cr.playGame.hood != None:
            return base.cr.playGame.hood

    def getGeom(self):
        loader = self.getLoader()
        if loader:
            return loader.geom
        return None

    def getSky(self):
        hood = self.getHood()
        if hood:
            return hood.sky
        return None

    #####################################################
    # Utility functions
    #####################################################

    def __checkDDFog(self):
        # Ok, Donald's Dock has fog that gets in the way of the fireworks
        # We need to color it darker so we can see the show
        from toontown.hood import DDHood

        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.2, 0.2, 0.2, 1)
            # If we are not submerged (swimming), then change the fog
            if hasattr(base.cr.playGame.getPlace(), "cameraSubmerged"):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __restoreDDFog(self):
        from toontown.hood import DDHood
        if isinstance(self.getHood(), DDHood.DDHood):
            self.getHood().whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)
            # If we are not submerged (swimming), then change the fog
            if hasattr(base.cr.playGame.getPlace(), "cameraSubmerged"):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __checkStreetValidity(self):
        """ Function that checks the validity of a street,
        it's loader and the geometry"""
        if hasattr(base.cr.playGame, "getPlace") and base.cr.playGame.getPlace() and \
        hasattr(base.cr.playGame.getPlace(), "loader") and base.cr.playGame.getPlace().loader \
        and hasattr(base.cr.playGame.getPlace().loader, "geom") and base.cr.playGame.getPlace().loader.geom:
            return True
        else:
            return False

    def __checkHoodValidity(self):
        """Function that checks the validity of a hood,
        it's loader and the geometry """
        if hasattr(base.cr.playGame, "hood") and base.cr.playGame.hood and \
        hasattr(base.cr.playGame.hood, "loader") and base.cr.playGame.hood.loader \
        and hasattr(base.cr.playGame.hood.loader, "geom") and base.cr.playGame.hood.loader.geom:
            return True
        else:
            return False
class FireworkShowMixin:
    notify = DirectNotifyGlobal.directNotify.newCategory('FireworkShowMixin')

    def __init__(self, restorePlaygroundMusic=True, startDelay=0.0):
        self.currentShow = None
        self.restorePlaygroundMusic = restorePlaygroundMusic
        self.startDelay = startDelay
        self.timestamp = None
        self.fireworkShow = None
        self.eventId = JULY4_FIREWORKS
        self.accept('MusicEnabled', self.startMusic)
        return

    def disable(self):
        if self.currentShow:
            self.currentShow.pause()
            self.currentShow = None
            if base.config.GetBool('want-old-fireworks', False):
                ivalMgr.finishIntervalsMatching('shootFirework*')
            else:
                self.destroyFireworkShow()
        hood = self.getHood()
        if hood is not None:
            if hood.id == DonaldsDock:
                hood.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)
        self.restoreCameraLens()
        if hood is not None:
            if hasattr(hood, 'loader'):
                self.getGeom().clearColorScale()
            if hasattr(hood, 'sky'):
                self.getSky().show()
                self.getSky().clearColorScale()
        if hasattr(base, 'localAvatar') and base.localAvatar:
            base.localAvatar.clearColorScale()
        base.setBackgroundColor(DefaultBackgroundColor)
        self.ignoreAll()

    def startMusic(self):
        if self.timestamp:
            self.getLoader().music.stop()
            t = globalClockDelta.localElapsedTime(
                self.timestamp) - self.startDelay
            base.playMusic(self.showMusic, 0, 1, 1, max(0, t))

    def shootFirework(self, x, y, z, style, color1, color2):
        amp = 5
        Fireworks.shootFirework(style, x, y, z, color1, color2, amp)

    def startShow(self, eventId, style, songId, timestamp, root=render):
        t = globalClockDelta.localElapsedTime(timestamp) - self.startDelay
        self.timestamp = timestamp
        self.showMusic = None
        self.eventId = eventId
        if base.config.GetBool('want-old-fireworks', 0):
            self.currentShow = self.getFireworkShowIval(
                eventId, style, songId, t)
            if self.currentShow:
                self.currentShow.start(t)
            return

        self.createFireworkShow()
        if t > self.fireworkShow.getShowDuration():
            return
        preShow = self.preShow(eventId, songId, t)
        postShow = self.postShow(eventId)
        beginFireworkShow = Func(self.beginFireworkShow, max(0, t), root)
        self.currentShow = Sequence(
            preShow, beginFireworkShow,
            Wait(max(0,
                     self.fireworkShow.getShowDuration() - max(0, t))),
            postShow)
        self.currentShow.start()
        return

    def preShow(self, eventId, songId, startT):
        if eventId not in PRESHOW_DICT:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' %
                                             eventId)
            return None

        instructionMessage, startMessage, endMessage, songs = PRESHOW_DICT[
            eventId]
        musicFile = 'phase_4/audio/bgm/%s.ogg' % songs[songId]

        self.showMusic = loader.loadMusic(musicFile)
        self.showMusic.setVolume(1)

        def __lightDecorationOn__():
            place = base.cr.playGame.getPlace()
            if place is None:
                return
            if hasattr(place, 'halloweenLights'):
                if not self.__checkStreetValidity():
                    return
                else:
                    place.halloweenLights = base.cr.playGame.getPlace(
                    ).loader.geom.findAllMatches('**/*light*')
                    place.halloweenLights.extend(
                        base.cr.playGame.getPlace().loader.geom.findAllMatches(
                            '**/*lamp*'))
                    for light in place.halloweenLights:
                        light.setColorScaleOff(0)

            elif not self.__checkHoodValidity():
                return
            else:
                place.loader.hood.halloweenLights = base.cr.playGame.hood.loader.geom.findAllMatches(
                    '**/*light*')
                place.loader.hood.halloweenLights.extend(
                    base.cr.playGame.hood.loader.geom.findAllMatches(
                        '**/*lamp*'))
                for light in base.cr.playGame.hood.halloweenLights:
                    light.setColorScaleOff(0)

            if self.fireworkShow and not self.fireworkShow.isEmpty():
                self.fireworkShow.setColorScaleOff(0)
            return

        if self.__checkHoodValidity() and hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood \
                and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            return Sequence(
                Func(base.localAvatar.setSystemMessage, 0, startMessage),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5,
                                           Vec4(0.0, 0.0, 0.0, 1.0)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom,
                                           2.5, Vec4(0.25, 0.25, 0.35, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5,
                                           Vec4(0.85, 0.85, 0.85, 1)),
                    Func(__lightDecorationOn__)),
                Func(base.setBackgroundColor, Vec4(0, 0, 0, 1)),
                Func(self.__checkDDFog), Func(base.camLens.setFar, 1000.0),
                Func(base.cr.playGame.hood.sky.hide),
                Func(base.localAvatar.setSystemMessage, 0, instructionMessage),
                Func(self.getLoader().music.stop), Wait(2.0),
                Func(base.playMusic, self.showMusic, 0, 1, 0.8, max(0,
                                                                    startT)))
        return None

    def restoreCameraLens(self):
        hood = self.getHood()
        if hood is not None:
            if hood.id == GoofySpeedway or hood.id == OutdoorZone:
                base.camLens.setFar(SpeedwayCameraFar)
            else:
                base.camLens.setFar(DefaultCameraFar)

    def postShow(self, eventId):
        endMessage = POSTSHOW_DICT.get(eventId)
        if endMessage is None:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' %
                                             eventId)
            return None

        if self.__checkHoodValidity() and hasattr(
                base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            postShow = Sequence(
                Func(base.cr.playGame.hood.sky.show),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5,
                                           Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom,
                                           2.5, Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5,
                                           Vec4(1, 1, 1, 1))),
                Func(self.__restoreDDFog), Func(self.restoreCameraLens),
                Func(base.setBackgroundColor, DefaultBackgroundColor),
                Func(self.showMusic.stop),
                Func(base.localAvatar.setSystemMessage, 0, endMessage))
        if self.restorePlaygroundMusic:
            postShow.append(Wait(2.0))
            postShow.append(
                Func(base.playMusic,
                     self.getLoader().music, 1, 1, 0.8))
        return postShow

    def createFireworkShow(self):
        if not self.fireworkShow:
            self.fireworkShow = FireworkShow(self.eventId)

    def destroyFireworkShow(self):
        if self.fireworkShow:
            self.fireworkShow.cleanupShow()
            self.fireworkShow = None
        return

    def beginFireworkShow(self, timeStamp, root):
        if self.fireworkShow and not self.fireworkShow.isPlaying():
            self.fireworkShow.begin(timeStamp)
            self.fireworkShow.reparentTo(root)
            hoodId = self.getHood().id
            if hoodId in FIREWORK_SHOW_LOCATION:
                self.fireworkShow.setPosHpr(*FIREWORK_SHOW_LOCATION[hoodId])
            if hoodId == PartyHood:
                self.fireworkShow.setScale(1.8)

    def getFireworkShowIval(self, eventId, index, songId, startT):
        show = FireworkShows.getShow(eventId, index)
        if show is None:
            FireworkShowMixin.notify.warning(
                'could not find firework show: index: %s' % index)
            return
        preShow = self.preShow(eventId, songId, startT)
        mainShow = Sequence()
        currentT = skyTransitionDuration + preShowPauseDuration
        for effect in show:
            waitTime, style, colorIndex1, colorIndex2, amp, x, y, z = effect
            if waitTime > 0:
                currentT += waitTime
                mainShow.append(Wait(waitTime))
            if currentT >= startT:
                mainShow.append(
                    Func(Fireworks.shootFirework, style, x, y, z, colorIndex1,
                         colorIndex2, amp))

        postShow = self.postShow(eventId)
        return Sequence(preShow, mainShow, postShow)

    def clearMyColorScales(self):
        if self.getGeom() and not self.getGeom().isEmpty():
            self.getGeom().clearColorScale()
        if self.getSky() and not self.getSky().isEmpty():
            self.getSky().clearColorScale()

    def getLoader(self):
        if base.cr.playGame.hood is not None:
            return base.cr.playGame.hood.loader
        return

    def getHood(self):
        if base.cr.playGame.hood is not None:
            return base.cr.playGame.hood
        return

    def getGeom(self):
        loader = self.getLoader()
        if loader:
            return loader.geom
        return None

    def getSky(self):
        hood = self.getHood()
        if hood:
            return hood.sky
        return None

    def __checkDDFog(self):
        if self.getHood().id == DonaldsDock:
            self.getHood().whiteFogColor = Vec4(0.2, 0.2, 0.2, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __restoreDDFog(self):
        if self.getHood().id == DonaldsDock:
            self.getHood().whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __checkStreetValidity(self):
        return hasattr(base.cr.playGame, 'getPlace') and base.cr.playGame.getPlace()\
            and hasattr(base.cr.playGame.getPlace(), 'loader') and base.cr.playGame.getPlace().loader\
            and hasattr(base.cr.playGame.getPlace().loader, 'geom') and base.cr.playGame.getPlace().loader.geom

    def __checkHoodValidity(self):
        return hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood\
            and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader\
            and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom
class FireworkShowMixin:
    notify = DirectNotifyGlobal.directNotify.newCategory('FireworkShowMixin')

    def __init__(self, restorePlaygroundMusic = True, startDelay = 0.0):
        self.currentShow = None
        self.restorePlaygroundMusic = restorePlaygroundMusic
        self.startDelay = startDelay
        self.timestamp = None
        self.fireworkShow = None
        self.eventId = JULY4_FIREWORKS
        self.accept('MusicEnabled', self.startMusic)
        return

    def disable(self):
        if self.currentShow:
            self.currentShow.pause()
            self.currentShow = None
            if base.config.GetBool('want-old-fireworks', False):
                ivalMgr.finishIntervalsMatching('shootFirework*')
            else:
                self.destroyFireworkShow()
        hood = self.getHood()
        if hood is not None:
            if hood.id == DonaldsDock:
                hood.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)
        self.restoreCameraLens()
        if hood is not None:
            if hasattr(hood, 'loader'):
                self.getGeom().clearColorScale()
            if hasattr(hood, 'sky'):
                self.getSky().show()
                self.getSky().clearColorScale()
        if hasattr(base, 'localAvatar') and base.localAvatar:
            base.localAvatar.clearColorScale()
        base.setBackgroundColor(DefaultBackgroundColor)
        self.ignoreAll()

    def startMusic(self):
        if self.timestamp:
            self.getLoader().music.stop()
            t = globalClockDelta.localElapsedTime(self.timestamp) - self.startDelay
            base.playMusic(self.showMusic, 0, 1, 1, max(0, t))

    def shootFirework(self, x, y, z, style, color1, color2):
        amp = 5
        Fireworks.shootFirework(style, x, y, z, color1, color2, amp)

    def startShow(self, eventId, style, songId, timestamp, root = render):
        t = globalClockDelta.localElapsedTime(timestamp) - self.startDelay
        self.timestamp = timestamp
        self.showMusic = None
        self.eventId = eventId
        if base.config.GetBool('want-old-fireworks', 0):
            self.currentShow = self.getFireworkShowIval(eventId, style, songId, t)
            if self.currentShow:
                self.currentShow.start(t)
            return

        self.createFireworkShow()
        if t > self.fireworkShow.getShowDuration():
            return
        preShow = self.preShow(eventId, songId, t)
        postShow = self.postShow(eventId)
        beginFireworkShow = Func(self.beginFireworkShow, max(0, t), root)
        self.currentShow = Sequence(
            preShow, beginFireworkShow, Wait(max(0, self.fireworkShow.getShowDuration() - max(0, t))), postShow
        )
        self.currentShow.start()
        return

    def preShow(self, eventId, songId, startT):
        if eventId not in PRESHOW_DICT:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None

        instructionMessage, startMessage, endMessage, songs = PRESHOW_DICT[eventId]
        musicFile = 'phase_4/audio/bgm/%s.ogg' % songs[songId]

        self.showMusic = loader.loadMusic(musicFile)
        self.showMusic.setVolume(1)

        def __lightDecorationOn__():
            place = base.cr.playGame.getPlace()
            if place is None:
                return
            if hasattr(place, 'halloweenLights'):
                if not self.__checkStreetValidity():
                    return
                else:
                    place.halloweenLights = base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*light*')
                    place.halloweenLights.extend(base.cr.playGame.getPlace().loader.geom.findAllMatches('**/*lamp*'))
                    for light in place.halloweenLights:
                        light.setColorScaleOff(0)

            elif not self.__checkHoodValidity():
                return
            else:
                place.loader.hood.halloweenLights = base.cr.playGame.hood.loader.geom.findAllMatches('**/*light*')
                place.loader.hood.halloweenLights.extend(base.cr.playGame.hood.loader.geom.findAllMatches('**/*lamp*'))
                for light in base.cr.playGame.hood.halloweenLights:
                    light.setColorScaleOff(0)

            if self.fireworkShow and not self.fireworkShow.isEmpty():
                self.fireworkShow.setColorScaleOff(0)
            return

        if self.__checkHoodValidity() and hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood \
                and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            return Sequence(
                Func(base.localAvatar.setSystemMessage, 0, startMessage),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(0.0, 0.0, 0.0, 1.0)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(0.25, 0.25, 0.35, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(0.85, 0.85, 0.85, 1)), Func(__lightDecorationOn__)
                ),
                Func(base.setBackgroundColor, Vec4(0, 0, 0, 1)),
                Func(self.__checkDDFog), Func(base.camLens.setFar, 1000.0),
                Func(base.cr.playGame.hood.sky.hide),
                Func(base.localAvatar.setSystemMessage, 0, instructionMessage),
                Func(self.getLoader().music.stop),
                Wait(2.0),
                Func(base.playMusic, self.showMusic, 0, 1, 0.8, max(0, startT))
            )
        return None

    def restoreCameraLens(self):
        hood = self.getHood()
        if hood is not None:
            if hood.id == GoofySpeedway or hood.id == OutdoorZone:
                base.camLens.setFar(SpeedwayCameraFar)
            else:
                base.camLens.setFar(DefaultCameraFar)

    def postShow(self, eventId):
        endMessage = POSTSHOW_DICT.get(eventId)
        if endMessage is None:
            FireworkShowMixin.notify.warning('Invalid fireworks event ID: %d' % eventId)
            return None

        if self.__checkHoodValidity() and hasattr(base.cr.playGame.hood, 'sky') and base.cr.playGame.hood.sky:
            postShow = Sequence(
                Func(base.cr.playGame.hood.sky.show),
                Parallel(
                    LerpColorScaleInterval(base.cr.playGame.hood.sky, 2.5, Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 2.5, Vec4(1, 1, 1, 1)),
                    LerpColorScaleInterval(base.localAvatar, 2.5, Vec4(1, 1, 1, 1))
                ),
                Func(self.__restoreDDFog),
                Func(self.restoreCameraLens),
                Func(base.setBackgroundColor, DefaultBackgroundColor),
                Func(self.showMusic.stop),
                Func(base.localAvatar.setSystemMessage, 0, endMessage)
            )
        if self.restorePlaygroundMusic:
            postShow.append(Wait(2.0))
            postShow.append(Func(base.playMusic, self.getLoader().music, 1, 1, 0.8))
        return postShow

    def createFireworkShow(self):
        if not self.fireworkShow:
            self.fireworkShow = FireworkShow(self.eventId)

    def destroyFireworkShow(self):
        if self.fireworkShow:
            self.fireworkShow.cleanupShow()
            self.fireworkShow = None
        return

    def beginFireworkShow(self, timeStamp, root):
        if self.fireworkShow and not self.fireworkShow.isPlaying():
            self.fireworkShow.begin(timeStamp)
            self.fireworkShow.reparentTo(root)
            hoodId = self.getHood().id
            if hoodId in FIREWORK_SHOW_LOCATION:
                self.fireworkShow.setPosHpr(*FIREWORK_SHOW_LOCATION[hoodId])
            if hoodId == PartyHood:
                self.fireworkShow.setScale(1.8)

    def getFireworkShowIval(self, eventId, index, songId, startT):
        show = FireworkShows.getShow(eventId, index)
        if show is None:
            FireworkShowMixin.notify.warning('could not find firework show: index: %s' % index)
            return
        preShow = self.preShow(eventId, songId, startT)
        mainShow = Sequence()
        currentT = skyTransitionDuration + preShowPauseDuration
        for effect in show:
            waitTime, style, colorIndex1, colorIndex2, amp, x, y, z = effect
            if waitTime > 0:
                currentT += waitTime
                mainShow.append(Wait(waitTime))
            if currentT >= startT:
                mainShow.append(Func(Fireworks.shootFirework, style, x, y, z, colorIndex1, colorIndex2, amp))

        postShow = self.postShow(eventId)
        return Sequence(preShow, mainShow, postShow)

    def clearMyColorScales(self):
        if self.getGeom() and not self.getGeom().isEmpty():
            self.getGeom().clearColorScale()
        if self.getSky() and not self.getSky().isEmpty():
            self.getSky().clearColorScale()

    def getLoader(self):
        if base.cr.playGame.hood is not None:
            return base.cr.playGame.hood.loader
        return

    def getHood(self):
        if base.cr.playGame.hood is not None:
            return base.cr.playGame.hood
        return

    def getGeom(self):
        loader = self.getLoader()
        if loader:
            return loader.geom
        return None

    def getSky(self):
        hood = self.getHood()
        if hood:
            return hood.sky
        return None

    def __checkDDFog(self):
        if self.getHood().id == DonaldsDock:
            self.getHood().whiteFogColor = Vec4(0.2, 0.2, 0.2, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __restoreDDFog(self):
        if self.getHood().id == DonaldsDock:
            self.getHood().whiteFogColor = Vec4(0.8, 0.8, 0.8, 1)
            if hasattr(base.cr.playGame.getPlace(), 'cameraSubmerged'):
                if not base.cr.playGame.getPlace().cameraSubmerged:
                    self.getHood().setWhiteFog()

    def __checkStreetValidity(self):
        return hasattr(base.cr.playGame, 'getPlace') and base.cr.playGame.getPlace()\
            and hasattr(base.cr.playGame.getPlace(), 'loader') and base.cr.playGame.getPlace().loader\
            and hasattr(base.cr.playGame.getPlace().loader, 'geom') and base.cr.playGame.getPlace().loader.geom

    def __checkHoodValidity(self):
        return hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood\
            and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader\
            and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom