def startCustomEffects(self):
     self.stopCustomEffects()
     self.envEffects = EnvironmentEffects(self.geom, self.modelPath)
    def startCustomEffects(self, interior=True, loadIslandMusic=False):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        if self.environment == 'Swamp':
            self.envEffects = SwampEffects.SwampEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            base.musicMgr.request(SoundGlobals.MUSIC_SWAMP,
                                  priority=1,
                                  volume=0.6)
        elif self.environment == 'Jungle':
            self.envEffects = ForestEffects.ForestEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            base.musicMgr.request(SoundGlobals.MUSIC_JUNGLE,
                                  priority=1,
                                  volume=0.6)
        elif self.environment == 'Cave':
            self.envEffects = CaveEffects.CaveEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            if self.uniqueId == LocationIds.RAVENS_COVE_MINE:
                base.musicMgr.request(SoundGlobals.getMainMusic(self.uniqueId),
                                      priority=1,
                                      volume=0.6)
            else:
                base.musicMgr.request(SoundGlobals.MUSIC_CAVE,
                                      priority=1,
                                      volume=0.6)
        elif self.uniqueId in ('1189479168.0sdnaik0', '1150922126.8akelts'):
            r = Reflection.getGlobalReflection()
            water = SeaPatch(self, reflection=r)
            water.loadSeaPatchFile('out.spf')
            self.water = water
            self.initializeIslandWaterParameters(self.geom)
        else:
            self.envEffects = EnvironmentEffects(self, self.modelPath)
            if interior:
                pass
        if loadIslandMusic:
            if not base.localAvatar.isInInvasion():
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA)
                base.musicMgr.requestFadeOut(
                    SoundGlobals.MUSIC_TORMENTA_COMBAT)

            def getCurrentIslandMusic():
                priZeros = []
                for music in base.musicMgr.playlist:
                    if music.priority == 0:
                        priZeros.append(music)

                return priZeros

            def changeMusic(music, pri):
                for priZero in getCurrentIslandMusic():
                    base.musicMgr.requestFadeOut(priZero.name,
                                                 removeFromPlaylist=True)

                base.musicMgr.request(music, priority=0, volume=0.6)

            mainMusic = SoundGlobals.getMainMusic(self.uniqueId)
            altMusic = SoundGlobals.getAltMusic(self.uniqueId)
            if mainMusic and altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                todMgr = base.cr.timeOfDayManager
                todMgr.addTimeOfDayToggle('Day-Night Area Music', 6.0, 20.0,
                                          changeMusic, [mainMusic, 0],
                                          changeMusic, [altMusic, 0])
            elif mainMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                base.musicMgr.request(mainMusic, volume=0.6)
            elif altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                base.musicMgr.request(altMusic, volume=0.6)
        self.builder.initEffects()
        return
class DistributedTunnel(DistributedNode, StagedObject):
    __module__ = __name__
    L_WORLD_STACK = 0
    L_AREA_UID = 1
    L_AREA_NODE = 2
    L_LINK_NODE = 3
    notify = directNotify.newCategory('DistributedTunnel')

    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'DistributedTunnel')
        StagedObject.__init__(self, StagedObject.OFF)
        self.uniqueId = ''
        self.fakeZoneId = PiratesGlobals.FakeZoneId
        self.GridLOD = {}
        self.visNodes = {}
        self.geom = None
        self.envEffects = None
        self._links = {}
        self.areaWorldZone = [None, None]
        self.areaNode = [None, None]
        self.__loadedArea = None
        self.areaIndexLoading = None
        self.pendingAreaUnload = False
        self.pendingArea = None
        self.minimapObj = None
        self.builder = GridAreaBuilder.GridAreaBuilder(self)
        self.connectorNodes = ['portal_connector_1', 'portal_connector_2']
        self.connectorNodePosHpr = []
        self.ambientNames = [None, None]
        self.avatarZoneContext = None
        self.floorIndex = -1
        self._inTransition = False
        self.ownHandles = []
        return

    def announceGenerate(self):
        DistributedNode.announceGenerate(self)
        if self.cr.activeWorld == None or self.cr.activeWorld.getType(
        ) != PiratesGlobals.INSTANCE_PVP:
            self.setupCollisions()
        self.geom.hide(OTPRender.MainCameraBitmask)
        self.geom.showThrough(OTPRender.EnviroCameraBitmask)
        return

    def delete(self):
        self.goOffStage()
        self.fadeoutAllAmbient()
        self.destroyMinimapObject()
        self.cr.relatedObjectMgr.abortRequest(self.pendingArea)
        self.pendingArea = None
        self.setLoadedArea(None)
        for node in self.visNodes.values():
            node.detachNode()

        self.visNodes = {}
        if self.fakeZoneId != None:
            for node in self.GridLOD.values():
                node.cleanup()

            del self.GridLOD
        del self.fakeZoneId
        self.removeNode()
        self.ignoreAll()
        self.builder.delete()
        DistributedNode.delete(self)
        return

    def setLoadedArea(self, area):
        if self.__loadedArea and self.__loadedArea.isGenerated():
            self.__loadedArea.builder.removeLargeObj(
                self.visNodes[self.__loadedArea.getUniqueId()], self.uniqueId)
        if area:
            self.__loadedArea = area
            self.__loadedArea.builder.addLargeObj(
                self.visNodes[self.__loadedArea.getUniqueId()], self.uniqueId)

    def getLoadedArea(self):
        return self.__loadedArea

    def setLinks(self, links):
        for link in links:
            sideIndex = self.connectorNodes.index(link[self.L_LINK_NODE])
            self._links[sideIndex] = link
            self.visNodes.setdefault(
                link[self.L_AREA_UID],
                NodePath('vis-%s-%s' % (self.uniqueId, link[self.L_AREA_UID])))

        self.calcAmbientNames()
        self.setupConnectorNodes()

    def calcAmbientNames(self):
        self.ambientNames = [
            self.calcOneAmbientName(self._links[index][self.L_AREA_NODE])
            for index in (0, 1)
        ]

    @report(types=['deltaStamp', 'args'], dConfigParam='connector')
    def calcOneAmbientName(self, area):
        return SoundGlobals.getAmbientFromStr(
            area.split('_')[-1]) or SoundGlobals.getAmbientFromStr(
                self.modelPath.split('_')[1])

    def fadeInAmbient(self, index):
        if self.ambientNames[index]:
            base.ambientMgr.requestChangeVolume(
                self.ambientNames[index],
                duration=0.1,
                finalVolume=PiratesGlobals.DEFAULT_AMBIENT_VOLUME_NEAR)

    def fadeOutAmbient(self, index):
        if self.ambientNames[index]:
            base.ambientMgr.requestFadeOut(self.ambientNames[index],
                                           duration=0.01)
        if self.ambientNames[1 - index]:
            base.ambientMgr.requestChangeVolume(self.ambientNames[1 - index],
                                                duration=0,
                                                finalVolume=0)

    def fadeoutAllAmbient(self):
        for ambientName in self.ambientNames:
            if ambientName:
                base.ambientMgr.requestFadeOut(ambientName)

    @report(types=['args'], dConfigParam='connector')
    def setupConnectorNodes(self):
        locatorNodes = [
            self.find('**/' + locator) for locator in self.connectorNodes
        ]
        self.connectorNodePosHpr = [[self.getPos(node),
                                     self.getHpr(node)]
                                    for node in locatorNodes]

    def setupCollisions(self):
        floorNames = [
            'collision_floor_1', 'collision_floor_2', 'collision_floor_middle'
        ]
        for x, floorName in enumerate(floorNames):
            floor = self.find('**/' + floorName)
            floor.setName(self.uniqueName(floorName))
            floorNames[x] = floor.getName()
            self.accept('enterFloor' + floor.getName(),
                        self.__handleOnFloor,
                        extraArgs=[x])

    @report(types=['deltaStamp', 'args'], dConfigParam='connector')
    def __handleOnFloor(self, areaIndex, collEntry):
        if not self._inTransition:
            self.floorIndex = 1 - areaIndex
            self._inTransition = True
            area = self.getLoadedArea()
            entranceNode = self.getEntranceNode(area)
            if collEntry:
                self.acceptOnce('EnterTunnelFinished',
                                self.transitionToArea,
                                extraArgs=[self.floorIndex])
                localAvatar.b_setGameState('EnterTunnel', [entranceNode])
            else:
                self.transitionToArea(self.floorIndex)

    @report(types=['deltaStamp', 'args'], dConfigParam='connector')
    def transitionToArea(self, areaIndex):
        areaUid = self._links[areaIndex][self.L_AREA_UID]
        self.cr.loadingScreen.showTarget(areaUid)
        self.cr.loadingScreen.showHint(areaUid)
        localAvatar.b_setLocation(self.cr.distributedDistrict.getDoId(),
                                  PiratesGlobals.QuietZone)
        localAvatar.detachNode()
        self.currTransParent, self.currTransZone = self.getLocation()

        def continueTransition():
            self.acceptOnce('activeTunnel-%s-complete' % self.getDoId(),
                            continueTransition)
            currParentObj = self.cr.doId2do.get(self.currTransParent)
            if currParentObj:
                self.currTransParent, self.currTransZone = currParentObj.getLocation(
                )
                self.ownHandles.append(
                    self.cr.addTaggedInterest(
                        self.currTransParent,
                        self.currTransZone,
                        self.cr.ITAG_GAME,
                        'activeTunnelParent-%s' % self.getDoId(),
                        event='activeTunnel-%s-complete' % self.getDoId()))
            else:
                self.cr.activeWorld.goOffStage([self.getLoadedArea()])
                self.d_requestArea(areaIndex)
                localAvatar.refreshActiveQuestStep(forceClear=True)
                localAvatar.lastConnectorId = self.doId

        self.acceptOnce('activeTunnel-%s-complete' % self.getDoId(),
                        continueTransition)
        self.ownHandles.append(
            self.cr.addTaggedInterest(self.currTransParent,
                                      self.currTransZone,
                                      self.cr.ITAG_GAME,
                                      'activeTunnel-%s' % self.getDoId(),
                                      event='activeTunnel-%s-complete' %
                                      self.getDoId()))

    @report(types=['frameCount'], dConfigParam='connector')
    def handleOnStage(self):
        StagedObject.handleOnStage(self)
        self.startCustomEffects()

    @report(types=['frameCount'], dConfigParam='connector')
    def handleOffStage(self):
        self.stopCustomEffects()
        StagedObject.handleOffStage(self)

    def setUniqueId(self, uid):
        if self.uniqueId:
            self.cr.uidMgr.removeUid(self.uniqueId)
        self.uniqueId = uid
        self.cr.uidMgr.addUid(self.uniqueId, self.getDoId())

    def getUniqueId(self):
        return self.uniqueId

    @report(types=['frameCount', 'args'], dConfigParam='connector')
    def reparentConnectorToArea(self, area):
        self.notify.debug('%s reparentConnectorToArea %s' % (self.doId, area))
        entranceNode = self.getEntranceNode(area)
        entranceNode.setScale(1)
        entranceNode.setP(0)
        entranceNode.setR(0)
        rootNode = self.visNodes[area.uniqueId]
        rootNode.reparentTo(area)
        rootNode.setTransform(entranceNode.getTransform(area))
        self.reparentTo(entranceNode)
        pos, hpr = self.connectorNodePosHpr[self.getAreaIndex(area)]
        self.setPos(pos)
        self.setHpr(hpr[0], 0, 0)
        self.wrtReparentTo(rootNode)
        self.setLoadedArea(area)
        if area.showTunnelOnMinimap(self.getUniqueId()):
            obj = self.getMinimapObject(entranceNode)
            area.addMinimapObject(obj)
            obj.updateWorldNode(entranceNode)

    def setModelPath(self, modelPath):
        self.notify.debug('setModelPath %s' % modelPath)
        self.modelPath = modelPath
        self.loadModel()

    def loadModel(self):
        if not self.geom:
            self.loadWholeModel()
            self.geom.flattenStrong()
            self.geom.reparentTo(self)

    def loadWholeModel(self):
        modelBaseName = self.modelPath
        self.geom = loader.loadModel(modelBaseName)

    def getAreaIndex(self, area):
        areaUid = area.getUniqueId()
        for x in (0, 1):
            if areaUid == self._links[x][self.L_AREA_UID]:
                return x

        return

    def getAreaObject(self, index):
        areaUid = self._links[index][self.L_AREA_UID]
        areaDoId = self.cr.uidMgr.getDoId(areaUid)
        return self.cr.doId2do.get(areaDoId)

    def getConnectorNodePosHpr(self, index):
        if index < len(self.connectorNodePosHpr):
            return self.connectorNodePosHpr[index]
        return (Point3(0), Vec3(0))

    def getAreaNodeNameFromAreaUid(self, areaUid):
        for link in self._links.itervalues():
            if areaUid == link[self.L_AREA_UID]:
                return link[self.L_AREA_NODE]

        return

    def getEntranceNode(self, area):
        areaIndex = self.getAreaIndex(area)
        areaNode = self._links[areaIndex][self.L_AREA_NODE]
        return area.find('**/' + areaNode + '*')

    @report(types=['frameCount', 'args'], dConfigParam='connector')
    def d_requestArea(self, linkIndex):
        self.sendUpdate('requestArea',
                        [self._links[linkIndex][self.L_LINK_NODE]])

    @report(types=['frameCount', 'args'], dConfigParam='connector')
    def setArea(self, worldStack, areaDoId, autoFadeIn=True):
        self.cr.setWorldStack(worldStack, event='WorldOpen')

        @report(types=['frameCount', 'args'], dConfigParam='connector')
        def areaFinishedCallback(area):
            self.pendingArea = None
            self.loadAreaFinished(area, autoFadeIn)
            return

        self.cr.relatedObjectMgr.abortRequest(self.pendingArea)
        self.pendingArea = self.cr.relatedObjectMgr.requestObjects(
            [areaDoId], eachCallback=areaFinishedCallback)

    @report(types=['deltaStamp', 'args'], dConfigParam='connector')
    def loadAreaFinished(self, area, autoFadeIn=True):
        def handleFinished():
            for currHandle in self.ownHandles:
                self.cr.removeTaggedInterest(currHandle)

            self.ownHandles = []

        self.acceptOnce('EnterTunnelFinished', handleFinished)

        @report(types=['deltaStamp', 'args'], dConfigParam='connector')
        def leaveTunnel():
            if autoFadeIn:

                def leaveTunnelFinished():
                    self._inTransition = False
                    area.forceManagePass(localAvatar)
                    localAvatar.sendCurrentPosition()

                self.acceptOnce('LeaveTunnelFinished', leaveTunnelFinished)
                localAvatar.b_setGameState('LeaveTunnel',
                                           [self, area, not autoFadeIn])
            else:

                def leaveTunnelFinished():
                    self.sendUpdate('sendLeaveTunnelDone')
                    area.forceManagePass(localAvatar)
                    localAvatar.sendCurrentPosition()

                localAvatar.b_setGameState('LeaveTunnel',
                                           [self, area, not autoFadeIn])
                self.cr.setAllInterestsCompleteCallback(leaveTunnelFinished)
            area.handleEnterGameArea()
            self.fadeInAmbient(self.floorIndex)

        world = area.getParentObj()
        world.goOnStage()
        area.goOnStage()
        self.cr.setAllInterestsCompleteCallback(leaveTunnel)

    def startCustomEffects(self):
        self.stopCustomEffects()
        self.envEffects = EnvironmentEffects(self.geom, self.modelPath)

    def stopCustomEffects(self):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        return

    def getMinimapObject(self, worldNode):
        if not self.minimapObj and not self.isDisabled():
            self.minimapObj = MinimapTunnel(worldNode)
        return self.minimapObj

    def destroyMinimapObject(self):
        if self.minimapObj:
            self.minimapObj.removeFromMap()
            self.minimapObj = None
        return

    def quickLoadOtherSide(self):
        self.cr.loadingScreen.show(waitForLocation=True)
        if self.floorIndex != -1:
            self._inTransition = False
            self.__handleOnFloor(self.floorIndex, None)
        return
class DistributedGameArea(DistributedNode, MappableArea, StagedObject):
    notify = directNotify.newCategory('DistributedGameArea')

    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'GameArea')
        MappableArea.__init__(self)
        StagedObject.__init__(self, StagedObject.OFF)
        self.uniqueId = ''
        self.geom = None
        self.funnelDisplayName = None
        self.previousDisplayName = None
        self.gameFSM = None
        self.links = []
        self.pendingSetupConnector = {}
        self.connectors = {}
        self.connectorInterests = set()
        self.envEffects = None
        self.spawnTriggers = []
        self.blockerColls = []
        self.islandWaterParameters = None
        self.swamp_water = None
        self.entryTime = [None, 0]
        self.timeCheck = 0
        self.minimap = None
        self.footprintNode = None
        self.popupDialog = None
        self.minimapArea = 0
        self.laMinimapObj = None
        self.footstepSound = None
        self.environment = None
        self.connectorsHereCallback = None
        return

    def __repr__(self):
        return '%s (%s)' % (DistributedNode.__repr__(self), self.getName()
                            or self.uniqueId)

    def __str__(self):
        return '%s (%s)' % (DistributedNode.__repr__(self), self.getName()
                            or self.uniqueId)

    def disable(self):
        taskMgr.remove('showEnterMessage')
        DistributedNode.disable(self)
        if self.geom:
            self.geom.removeNode()
        self.unloadConnectors()
        for request in self.pendingSetupConnector.itervalues():
            self.cr.relatedObjectMgr.abortRequest(request)

        self.pendingSetupConnector = {}
        self.builder.delete()
        self.builder = None
        return

    def delete(self):
        if base.zoneLODTarget == self:
            base.disableZoneLODs()
        for trigger in self.spawnTriggers:
            trigger.removeNode()

        del self.spawnTriggers
        del self.connectors
        del self.links
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        DistributedNode.delete(self)
        if self.islandWaterParameters:
            del self.islandWaterParameters
        if self.swamp_water:
            self.swamp_water.delete()
            del self.swamp_water
        if self.popupDialog:
            self.popupDialog.destroy()
        del self.popupDialog
        self.connectorsHereCallback = None
        return

    def setLocation(self, parentId, zoneId):
        DistributedNode.setLocation(self, parentId, zoneId)
        if parentId:
            parent = self.getParentObj()
            self.reparentTo(parent)

    def setName(self, name):
        self.name = name

    def setModelPath(self, modelPath):
        self.modelPath = modelPath

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def handleChildArrive(self, childObj, zoneId):
        DistributedNode.handleChildArrive(self, childObj, zoneId)
        if childObj.isLocal():
            base.loadingScreen.endStep('enterArea')
            base.enableZoneLODs(self)
            childObj.refreshActiveQuestStep()
            localAvatar.guiMgr.setMinimap(self.minimap)
            localAvatar.setAreaFootstep(self.footstepSound)
            localAvatar.guiMgr.radarGui.showLocation(self.uniqueId)
            envName = base.worldCreator.environmentTable.get(self.uniqueId)
            if envName:
                environmentID = TODGlobals.ENVIRONMENT_NAMES_TO_ID.get(
                    envName, TODGlobals.ENV_DEFAULT)
                envData = {}
                envSettings = base.worldCreator.uidEnvSettings.get(
                    self.uniqueId)
                if envSettings != None:
                    envData = envSettings
                base.cr.timeOfDayManager.setEnvironment(environmentID, envData)
            else:
                envData = None
                envSettings = base.worldCreator.uidEnvSettings.get(
                    self.uniqueId)
                if envSettings != None:
                    envData = envSettings
                base.cr.timeOfDayManager.setEnvironment(
                    TODGlobals.ENV_INTERIOR, envData)
            self.builder.arrived()
        self.accept('transferMinimapObjects', self.transferMinimapObject)
        if self.minimap and hasattr(childObj, 'getMinimapObject'):
            if childObj.getMinimapObject():
                self.laMinimapObj = childObj.getMinimapObject()
                self.minimap.addObject(childObj.getMinimapObject())
        return

    def transferMinimapObject(self, guiMgr):
        if self.laMinimapObj:
            guiMgr.transferMinimapObject(self.laMinimapObj)

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def handleChildLeave(self, childObj, zoneId):
        if childObj.isLocal():
            base.disableZoneLODs()
            localAvatar.guiMgr.clearMinimap(self.minimap)
            self.builder.localAvLeaving()
            self.builder.left()
        self.ignore('transferMinimapObjects')
        self.laMinimapObj = None
        if self.minimap and hasattr(childObj, 'getMinimapObject'):
            if childObj.getMinimapObject():
                self.minimap.removeObject(childObj.getMinimapObject())
        DistributedNode.handleChildLeave(self, childObj, zoneId)
        return

    def setUniqueId(self, uid):
        if self.uniqueId != '':
            self.cr.uidMgr.removeUid(self.uniqueId)
        self.uniqueId = uid
        self.cr.uidMgr.addUid(self.uniqueId, self.getDoId())

    def getUniqueId(self):
        return self.uniqueId

    def loadModel(self):
        pass

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail'])
    def setLinks(self, links):
        for link in links:
            areaNode, connId, areaUid, connParent, connZone, connNode, connWorld, connWorldZone = link
            newLink = [connId, connParent, connZone, connWorld, connWorldZone]
            if newLink in self.links:
                continue
            self.links.append(newLink)

            def setupConnector(connector):
                self.connectors[connector.doId] = connector
                request = self.pendingSetupConnector.pop(connector.doId, None)
                if not request:
                    pass
                return

            connector = self.cr.doId2do.get(connId)
            if connector:
                self.pendingSetupConnector[connId] = None
                setupConnector(connector)
            elif connId:
                if connId in self.pendingSetupConnector:
                    request = self.pendingSetupConnector.pop(connId)
                    self.cr.relatedObjectMgr.abortRequest(request)
                request = self.cr.relatedObjectMgr.requestObjects(
                    [connId], eachCallback=setupConnector)
                self.pendingSetupConnector[connId] = request

        return

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail', 'teleport'])
    def loadConnectors(self):
        for link in self.links:
            if link:
                connectorId = link[0]
                if connectorId not in self.connectorInterests or not self.cr.doId2do.has_key(
                        connectorId):
                    if connectorId not in self.connectorInterests:
                        self.connectorInterests.add(connectorId)
                    parentId = link[1]
                    zoneId = link[2]
                    linkParentId = link[3]
                    linkParentZoneId = link[4]

                    def connectorParentHere(connectorId, parentId, zoneId):
                        connectorEvent = 'connector-%s' % connectorId
                        self.acceptOnce(connectorEvent,
                                        self.reparentConnector,
                                        extraArgs=[connectorId])
                        self.cr.addTaggedInterest(
                            parentId,
                            zoneId,
                            self.cr.ITAG_GAME,
                            'Connectors-%s' % self.doId,
                            event=connectorEvent,
                            otherTags=['Connectors-%s' % self.doId])

                    connectorEvent = 'connector-%s' % connectorId
                    self.acceptOnce(connectorEvent,
                                    connectorParentHere,
                                    extraArgs=[connectorId, parentId, zoneId])
                    self.cr.addTaggedInterest(
                        linkParentId,
                        linkParentZoneId,
                        self.cr.ITAG_GAME,
                        'ConnectorsParent-%s' % self.doId,
                        event=connectorEvent,
                        otherTags=['ConnectorsParent-%s' % self.doId])
                else:
                    self.reparentConnector(connectorId)

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail', 'teleport'])
    def unloadConnectors(self):
        for connectorId, connector in self.connectors.iteritems():
            if connector:
                connector.setLoadedArea(None)
                connector.goOffStage()

        self.connectors = {}
        self.cr.removeInterestTag('Connectors-%s' % self.doId)
        self.cr.removeInterestTag('ConnectorsParent-%s' % self.doId)
        self.connectorInterests = set()
        return

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail', 'teleport'])
    def reparentConnector(self, connectorId):
        connector = self.cr.doId2do.get(connectorId)
        if connector:
            self.connectors[connectorId] = connector
            connector.reparentConnectorToArea(self)
            if self.isOnStage():
                connector.goOnStage()
            else:
                connector.goOffStage()
            if self.connectorsHereCallback and len(self.connectors) == len(
                    self.links):
                self.connectorsHereCallback()
                self.connectorsHereCallback = None
        return

    def setConnectorsHereCallback(self, callback):
        self.connectorsHereCallback = callback

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail', 'teleport'])
    def handleEnterGameArea(self, collEntry=None):
        inventory = localAvatar.getInventory()
        if localAvatar.style.getTutorial(
        ) == PiratesGlobals.TUT_GOT_SEACHEST and self.uniqueId == LocationIds.RAMBLESHACK_ISLAND and len(
                inventory.getWeapons()) < 1 and base.localAvatar.showQuest:
            base.localAvatar.resetQuestShow()
            popupDialogText = ['showBlacksmith', 'closeShowBlacksmith']
            self.popupDialog = NewTutorialPanel(popupDialogText)

            def closeTutorialWindow():
                messenger.send(self.popupDialog.closeMessage)

            self.popupDialog.setYesCommand(closeTutorialWindow)
            self.acceptOnce('closeTutorialWindow', closeTutorialWindow)
            self.popupDialog.activate()
        taskMgr.doMethodLater(1, self.showEnterMessage, 'showEnterMessage')
        UserFunnel.logSubmit(0, 'ENTERING_' + str(self.funnelDisplayName))
        UserFunnel.logSubmit(1, 'ENTERING_' + str(self.funnelDisplayName))
        self.storeLocationTime(self.funnelDisplayName, time.time())
        displayName = PLocalizer.LocationNames.get(self.uniqueId)
        base.setLocationCode(displayName)
        self.builder.initEffects()

    def storeLocationTime(self, loc, time):
        if loc == self.entryTime[0]:
            if self.entryTime[1] == 0:
                self.entryTime[1] = time
            return
        else:
            self.entryTime = [loc, time]

    def readLocationTime(self):
        return self.entryTime[1]

    def showEnterMessage(self, task):
        displayName = PLocalizer.LocationNames.get(self.uniqueId)
        self.displayGameAreaName(displayName)

    @report(types=['args', 'deltaStamp'], dConfigParam=['jail', 'teleport'])
    def handleExitGameArea(self, collEntry=None):
        UserFunnel.logSubmit(0, 'EXITING_' + str(self.funnelDisplayName))
        UserFunnel.logSubmit(1, 'EXITING_' + str(self.funnelDisplayName))
        self.stopCustomEffects()
        self.previousDisplayName = None
        displayName = str(self.funnelDisplayName)
        timeSpent = int(time.time()) - int(self.readLocationTime())
        if int(self.timeCheck) + 1 == int(timeSpent) or int(
                self.timeCheck) - 1 == int(timeSpent) or int(
                    self.timeCheck) == int(timeSpent):
            pass
        else:
            base.cr.centralLogger.writeClientEvent('EXITING_AREA|%s|%d' %
                                                   (displayName, timeSpent))
            self.timeCheck = timeSpent
        return

    def displayGameAreaName(self, displayName):
        self.funnelDisplayName = displayName
        if self.previousDisplayName != displayName:
            self.previousDisplayName = displayName
            base.localAvatar.guiMgr.createTitle(displayName,
                                                PiratesGuiGlobals.TextFG2)

    def setPlayerBarrier(self, isOn):
        pass

    def setupCannonballLandColl(self, collNode, mask, index):
        if collNode and not collNode.isEmpty():
            collNode.node().setCollideMask(mask)
            collNode.setTag('objType', str(PiratesGlobals.COLL_LAND))
            collNode.setTag('groundCode', str(index))
            collNode.setTag('groundId', str(self.doId))

    def projectileWeaponHit(self,
                            skillId,
                            ammoSkillId,
                            skillResult,
                            targetEffects,
                            pos,
                            normal,
                            codes,
                            attacker,
                            itemEffects=[]):
        pass

    def startCustomEffects(self, interior=True, loadIslandMusic=False):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        if self.environment == 'Swamp':
            self.envEffects = SwampEffects.SwampEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            base.musicMgr.request(SoundGlobals.MUSIC_SWAMP,
                                  priority=1,
                                  volume=0.6)
        elif self.environment == 'Jungle':
            self.envEffects = ForestEffects.ForestEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            base.musicMgr.request(SoundGlobals.MUSIC_JUNGLE,
                                  priority=1,
                                  volume=0.6)
        elif self.environment == 'Cave':
            self.envEffects = CaveEffects.CaveEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=False)
            if self.uniqueId == LocationIds.RAVENS_COVE_MINE:
                base.musicMgr.request(SoundGlobals.getMainMusic(self.uniqueId),
                                      priority=1,
                                      volume=0.6)
            else:
                base.musicMgr.request(SoundGlobals.MUSIC_CAVE,
                                      priority=1,
                                      volume=0.6)
        elif self.uniqueId in ('1189479168.0sdnaik0', '1150922126.8akelts'):
            r = Reflection.getGlobalReflection()
            water = SeaPatch(self, reflection=r)
            water.loadSeaPatchFile('out.spf')
            self.water = water
            self.initializeIslandWaterParameters(self.geom)
        else:
            self.envEffects = EnvironmentEffects(self, self.modelPath)
            if interior:
                pass
        if loadIslandMusic:
            if not base.localAvatar.isInInvasion():
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA)
                base.musicMgr.requestFadeOut(
                    SoundGlobals.MUSIC_TORMENTA_COMBAT)

            def getCurrentIslandMusic():
                priZeros = []
                for music in base.musicMgr.playlist:
                    if music.priority == 0:
                        priZeros.append(music)

                return priZeros

            def changeMusic(music, pri):
                for priZero in getCurrentIslandMusic():
                    base.musicMgr.requestFadeOut(priZero.name,
                                                 removeFromPlaylist=True)

                base.musicMgr.request(music, priority=0, volume=0.6)

            mainMusic = SoundGlobals.getMainMusic(self.uniqueId)
            altMusic = SoundGlobals.getAltMusic(self.uniqueId)
            if mainMusic and altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                todMgr = base.cr.timeOfDayManager
                todMgr.addTimeOfDayToggle('Day-Night Area Music', 6.0, 20.0,
                                          changeMusic, [mainMusic, 0],
                                          changeMusic, [altMusic, 0])
            elif mainMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                base.musicMgr.request(mainMusic, volume=0.6)
            elif altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist=True)
                base.musicMgr.request(altMusic, volume=0.6)
        self.builder.initEffects()
        return

    def stopCustomEffects(self):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        if 'swamp' in self.modelPath:
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_SWAMP,
                                         removeFromPlaylist=True)
        elif 'jungle' in self.modelPath:
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_JUNGLE,
                                         removeFromPlaylist=True)
        elif self.uniqueId in getLocationList(LocationIds.ANY_CAVE):
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_CAVE,
                                         removeFromPlaylist=True)
            base.musicMgr.requestFadeOut(SoundGlobals.getMainMusic(
                self.uniqueId),
                                         removeFromPlaylist=True)
        elif self.uniqueId == '1189479168.0sdnaik0':
            self.water.delete()
            self.water = None
        if base.cr.timeOfDayManager:
            base.cr.timeOfDayManager.removeTimeOfDayToggle(
                'Day-Night Area Music')
        return

    def updateAvReturnLocation(self, av, uniqueId):
        pass

    @report(types=['frameCount', 'args'], dConfigParam=['jail', 'teleport'])
    def quickLoadOtherSide(self):
        connector = self.connectors.get(localAvatar.lastConnectorId)
        if connector:
            connector.quickLoadOtherSide()

    def addSpawnTriggers(self, triggerSpheres):
        for x, y, z, triggerRadius, spawnPtId in triggerSpheres:
            objectSphere = CollisionSphere(x, y, z, triggerRadius)
            objectName = uniqueName('spawnTriggerSphere')
            objectSphere.setTangible(0)
            objectSphereNode = CollisionNode(objectName)
            objectSphereNode.addSolid(objectSphere)
            objectSphereNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
            objectSphereNodePath = self.builder.collisions.attachNewNode(
                objectSphereNode)
            self.accept('enter' + objectName,
                        self.handleEnterSphere,
                        extraArgs=[spawnPtId])
            self.spawnTriggers.append(objectSphereNodePath)

    def handleEnterSphere(self, spawnPtId, entry):
        if base.localAvatar:
            if hasattr(base.localAvatar, 'getDoId'):
                doId = base.localAvatar.getDoId()
                self.sendUpdate('spawnNPC', [spawnPtId, doId])

    def initBlockers(self, geom):
        self.disableBlockers = False
        if base.config.GetBool('disable-blockers', 0):
            self.disableBlockers = True
        blockerColls = geom.findAllMatches('**/blocker_*;+s')
        interior = False
        if not blockerColls.isEmpty():
            if blockerColls[0].getName().find('_i') != -1:
                interior = True
            for i in range(0, blockerColls.getNumPaths()):
                self.blockerColls.append(blockerColls[i])
                if self.disableBlockers:
                    blockerColls[i].stash()

        if interior:
            self.accept('enterblocker_1_i',
                        self.handleInteriorBlockerCollision)
        else:
            self.accept('enterblocker_1', self.handleBlockerCollision)
            self.accept('enterblocker_0', self.handleBlockerCollision)

    def stashSpecificBlocker(self, name):
        self.ignore('enter' + name)
        for blocker in self.blockerColls:
            if blocker.getName() == name:
                blocker.stash()

    def stashAllBlockers(self):
        self.ignore('enterblocker_1_i')
        self.ignore('enterblocker_1')
        self.ignore('enterblocker_0')
        for blocker in self.blockerColls:
            blocker.stash()

    def handleInteriorBlockerCollision(self, entry):
        questId = localAvatar.activeQuestId
        if base.localAvatar.style.getTutorial(
        ) < PiratesGlobals.TUT_GOT_CUTLASS:
            questId = 'c2_visit_will_turner'
            localAvatar.guiMgr.messageStack.addTextMessage(
                PLocalizer.QuestStrings[questId]['blockerMessage'])
        else:
            self.stashAllBlockers()

    def handleBlockerCollision(self, entry):
        if base.localAvatar.style.getTutorial(
        ) < PiratesGlobals.TUT_KILLED_1_SKELETON:
            questId = 'c2.2defeatSkeletons'
            localAvatar.guiMgr.messageStack.addTextMessage(
                PLocalizer.QuestStrings[questId]['blockerMessage'])
        elif base.localAvatar.style.getTutorial(
        ) < PiratesGlobals.TUT_GOT_COMPASS:
            questId = 'c2_visit_tia_dalma'
            self.stashSpecificBlocker('blocker_1')
            if entry.getIntoNodePath().getName() != 'blocker_1':
                localAvatar.guiMgr.messageStack.addTextMessage(
                    PLocalizer.QuestStrings[questId]['blockerMessage'])
        else:
            self.stashAllBlockers()

    @report(types=['frameCount'], dConfigParam='connector')
    def handleOnStage(self):
        StagedObject.handleOnStage(self)
        for id, connector in self.connectors.iteritems():
            if connector:
                connector.goOnStage()

        self.builder.addCutsceneOriginNode()

    @report(types=['frameCount'], dConfigParam='connector')
    def handleOffStage(self):
        for id, connector in self.connectors.iteritems():
            if connector:
                connector.goOffStage()

        StagedObject.handleOffStage(self)

    def getTeleportDestPosH(self, index=0):
        pt = self._getTunnelSpawnPos(index)
        if not pt:
            self.notify.warning('could not find tunnel location %s' % self)
            return (0, 0, 0, 0)
        return (pt[0], pt[1], pt[2], 0)

    @report(types=['args'], dConfigParam='teleport')
    def _getTunnelSpawnPos(self, index=0):
        connectorNodes = self.findAllMatches(
            '**/portal_exterior*') + self.findAllMatches('**/portal_interior*')
        if not connectorNodes:
            return None
        return self.getRelativePoint(
            connectorNodes[index % len(connectorNodes)], Point3(40, 0, 0))

    def initializeIslandWaterParameters(self, reference):
        debug = False
        island_water_parameters = IslandWaterParameters()
        world_position = self.getPos(render)
        world_x_offset = world_position[0]
        world_y_offset = world_position[1]
        world_z_offset = world_position[2]
        if debug:
            print self, '=', self.getName()
            print 'GAME AREA X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
        self.swampAreaNode = reference.find('**/ocean')
        model = reference.find('**/water_color')
        if model:
            if debug:
                print 'WATER COLOR X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
            model.hide()
            min_point = Point3(0)
            max_point = Point3(0)
            model.calcTightBounds(min_point, max_point)
            size = max_point - min_point
            if self.getH() == 180 or self.getH() == -180:
                x = -min_point[0] + world_x_offset
                y = -min_point[1] + world_y_offset
                x_size = -size[0]
                y_size = -size[1]
            else:
                x = min_point[0] + world_x_offset
                y = min_point[1] + world_y_offset
                x_size = size[0]
                y_size = size[1]
            island_water_parameters.map_x_origin = x
            island_water_parameters.map_y_origin = y
            island_water_parameters.map_x_scale = x_size
            island_water_parameters.map_y_scale = y_size
            if debug:
                print 'X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[
                    1], x_size, y_size
            texture = model.findTexture('*')
            if texture:
                island_water_parameters.water_color_texture = texture
                if debug:
                    print 'WATER COLOR TEXTURE', texture
        elif debug:
            print '*** water_color NODE NOT FOUND'
        model = reference.find('**/water_alpha')
        if model:
            if debug:
                print 'WATER ALPHA X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
            model.hide()
            min_point = Point3(0)
            max_point = Point3(0)
            model.calcTightBounds(min_point, max_point)
            size = max_point - min_point
            if self.getH() == 180 or self.getH() == -180:
                x = -min_point[0] + world_x_offset
                y = -min_point[1] + world_y_offset
                x_size = -size[0]
                y_size = -size[1]
            else:
                x = min_point[0] + world_x_offset
                y = min_point[1] + world_y_offset
                x_size = size[0]
                y_size = size[1]
            island_water_parameters.alpha_map_x_origin = x
            island_water_parameters.alpha_map_y_origin = y
            island_water_parameters.alpha_map_x_scale = x_size
            island_water_parameters.alpha_map_y_scale = y_size
            if debug:
                print 'ALPHA X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[
                    1], x_size, y_size
            texture = model.findTexture('*')
            if texture:
                island_water_parameters.water_alpha_texture = texture
                if debug:
                    print 'WATER ALPHA TEXTURE', texture
        elif debug:
            print '*** water_alpha NODE NOT FOUND'
        use_shader = False
        if base.config.GetBool(
                'want-shaders',
                1) and base.win and base.win.getGsg() and base.win.getGsg(
                ).getShaderModel() >= GraphicsStateGuardian.SM20:
            use_shader = True
        model_ns = reference.find('**/water_swamp_ns')
        if model_ns:
            if use_shader:
                model_ns.hide()
            else:
                model_ns.show()
                model = model_ns
                model.setBin('water', 1)
                parent = model.getParent()
                model.detachNode()
                stencil_one_node_path = NodePath('stencil_one')
                stencil_one_node_path.reparentTo(parent)
                model.instanceTo(stencil_one_node_path)
                mask = 4294967295L
                stencil_one = StencilAttrib.make(1, StencilAttrib.SCFEqual,
                                                 StencilAttrib.SOKeep,
                                                 StencilAttrib.SOKeep,
                                                 StencilAttrib.SOKeep, 1, mask,
                                                 mask)
                stencil_one_node_path.setAttrib(stencil_one, 100)
                stencil_one_node_path.setDepthTest(0)
                if not base.useStencils:
                    stencil_one_node_path.hide()
        model_alpha_texture = None
        model_alpha = reference.find('**/water_alpha_swamp')
        if model_alpha:
            model_alpha_texture = model_alpha.findTexture('*')
            model_alpha.hide()
            if debug:
                print 'model_alpha_texture', model_alpha_texture
            if False:
                texture = model_alpha_texture
                card_x_size = 0.5
                card_y_size = 0.5
                card = CardMaker('test_texture_card')
                card.setFrame(-card_x_size, card_x_size, -card_y_size,
                              card_y_size)
                card_node_path = NodePath(card.generate())
                card_node_path.setTexture(texture, 1)
                card_node_path.node().setBounds(OmniBoundingVolume())
                card_node_path.node().setFinal(1)
                card_node_path.reparentTo(render2d)
        else:
            model_alpha = None
        model = reference.find('**/water_color_swamp')
        if model:
            if use_shader:
                model.show()
                model_texture = model.findTexture('*')
                if debug:
                    print 'WATER COLOR SWAMP X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
                parent = model.getParent()
                model.detachNode()
                stencil_one_node_path = NodePath('stencil_one')
                stencil_one_node_path.reparentTo(parent)
                model.instanceTo(stencil_one_node_path)
                mask = 4294967295L
                stencil_one = StencilAttrib.make(1, StencilAttrib.SCFEqual,
                                                 StencilAttrib.SOKeep,
                                                 StencilAttrib.SOKeep,
                                                 StencilAttrib.SOKeep, 1, mask,
                                                 mask)
                stencil_one_node_path.setAttrib(stencil_one, 100)
                stencil_one_node_path.setDepthTest(0)
                if not base.useStencils:
                    stencil_one_node_path.hide()
                min_point = Point3(0)
                max_point = Point3(0)
                model.calcTightBounds(min_point, max_point)
                size = max_point - min_point
                if self.getH() == 180 or self.getH() == -180:
                    x = -min_point[0] + world_x_offset
                    y = -min_point[1] + world_y_offset
                    x_size = -size[0]
                    y_size = -size[1]
                else:
                    x = min_point[0] + world_x_offset
                    y = min_point[1] + world_y_offset
                    x_size = size[0]
                    y_size = size[1]
                if debug:
                    print 'min_point', min_point
                    print 'max_point', max_point
                    print 'size', size
                    print 'x y', x, y
                island_water_parameters.swamp_map_x_origin = x
                island_water_parameters.swamp_map_y_origin = y
                island_water_parameters.swamp_map_x_scale = x_size
                island_water_parameters.swamp_map_y_scale = y_size
                if debug:
                    print 'X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[
                        1], x_size, y_size
                texture = model.findTexture('*')
                if texture:
                    island_water_parameters.swamp_water_color_texture = texture
                    if debug:
                        print 'SWAMP WATER COLOR TEXTURE', texture
                water_color_file_path = island_water_parameters.default_water_color_file_path
                alpha_texture_file_path = island_water_parameters.default_water_alpha_file_path
                opacity_texture_file_path = None
                shader_file_path = 'models/swamps/cuba_swamp001_2X.cg'
                reflection = Reflection.getGlobalReflection()
                self.swamp_water = Swamp(None, None, reflection, model,
                                         shader_file_path)
                island_water_parameters.swamp_water = self.swamp_water
                unload_previous_texture = True
                self.swamp_water.set_water_color_texture(
                    water_color_file_path, unload_previous_texture,
                    model_texture)
                self.swamp_water.set_water_alpha_texture(
                    alpha_texture_file_path, unload_previous_texture,
                    model_alpha_texture)
                self.swamp_water.set_wrap_or_clamp(True)
                r = 37.0
                g = 62.0
                b = 40.0
                self.swamp_water.water_r = r
                self.swamp_water.water_g = g
                self.swamp_water.water_b = b
                island_water_parameters.swamp_color_r = r
                island_water_parameters.swamp_color_g = g
                island_water_parameters.swamp_color_b = b
                x = 0.0
                y = 1.0
                speed = 3.2
                island_water_parameters.swamp_direction_x = x
                island_water_parameters.swamp_direction_y = y
                island_water_parameters.swamp_speed = speed
                self.swamp_water.update_water_direction_and_speed(x, y, speed)
            else:
                model.hide()
        elif debug:
            print '*** water_color_swamp NODE NOT FOUND'
        self.islandWaterParameters = island_water_parameters
        return

    def getLevel(self):
        return 1

    def announceGenerate(self):
        base.loadingScreen.tick()
        DistributedNode.announceGenerate(self)
        base.worldCreator.registerSpecialNodes(self, self.uniqueId)
        self.areaType = base.worldCreator.getFieldFromUid(
            self.uniqueId, 'Visibility')
        self.envSettings = base.worldCreator.getEnvSettingsByUid(self.uniqueId)
        self.builder = base.worldCreator.getBuilder(self, self.areaType)

    def retrieveFootprintNode(self):
        footprintCache = self.getFootprintCache()
        if footprintCache.hasData() and base.config.GetBool(
                'want-disk-cache', 0):
            data = footprintCache.getData()
            newData = data.copySubgraph()
            footprintNode = NodePath(newData)
        else:
            footprintNode = self.buildFootprintNode()
        return footprintNode

    def getFootprintCache(self):
        return base.bamCache.lookup(
            Filename('/%s_footprint_%s.bam' %
                     (self.uniqueId, base.gridDetail)), 'bam')

    def buildFootprintNode(self):
        footprintCache = self.getFootprintCache()
        footprintNode = self.builder.buildFootprintNode()
        footprintCache.setData(footprintNode.node(), 0)
        base.bamCache.store(footprintCache)
        return footprintNode

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def hideMapNodes(self):
        mapNodes = self.geom.findAllMatches('**/minimap_*')
        mapNodes.hide()

    def setFootstepSound(self, footstepSound):
        self.footstepSound = footstepSound
        if self.footstepSound and base.localAvatar:
            base.localAvatar.setAreaFootstep(self.footstepSound)
            base.localAvatar.setSurfaceIndexFromLevelDefault()

    def setEnvironment(self, environment):
        self.environment = environment

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def setMinimapPrefix(self, prefix):
        minimaps = self.geom.findAllMatches('**/minimap_*;+s')
        for map in minimaps:
            if prefix not in map.getName():
                map.detachNode()

        minimaps = sorted(self.geom.findAllMatches('**/minimap_*;+s'))
        for x, map in enumerate(minimaps):
            map.setName('minimap_%d' % x)

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def getMapNode(self):
        mapNode = self.geom.find('**/minimap_%s' % (self.minimapArea, ))
        if not mapNode:
            minSide = 1500.0
            a, b = self.geom.getTightBounds()
            diff = b - a
            sideScale = 1
            if diff[0] > diff[1]:
                if diff[0] < minSide:
                    sideScale = minSide / diff[0]
            elif diff[1] < minSide:
                sideScale = minSide / diff[1]
            cm = CardMaker('minimap-card')
            cm.setFrame(VBase4(a[0], b[0], a[1], b[1]) * sideScale)
            modelNode = ModelNode('minimap_0')
            modelNode.setPreserveTransform(1)
            mapNode = self.geom.attachNewNode(modelNode)
            mapGeom = mapNode.attachNewNode(cm.generate())
            mapGeom.setP(-90)
            mapGeom.hide()
        return mapNode

    def getMapName(self):
        return 'map-' + self.getUniqueId()

    def getFootprintNode(self):
        if not self.footprintNode:
            self.footprintNode = self.retrieveFootprintNode()
        return self.footprintNode.find('footprint_%s' %
                                       (self.minimapArea, )) or NodePath(
                                           'footprint_%s' %
                                           (self.minimapArea, ))

    def getShopNodes(self):
        shopNodes = self.builder.getMinimapShopNodes()
        mapNodes = NodePathCollection()
        for node in shopNodes:
            minimapArea = int(node.getTag('MinimapArea') or '0')
            if minimapArea == self.minimapArea:
                mapNodes.addPath(node)

        return mapNodes

    def getCapturePointNodes(self, holidayName):
        capturePoints = self.builder.getMinimapCapturePointNodes(holidayName)
        mapNodes = NodePathCollection()
        for node in capturePoints:
            minimapArea = int(node.getTag('MinimapArea') or '0')
            if minimapArea == self.minimapArea:
                mapNodes.addPath(node)

        return mapNodes

    def getZoomLevels(self):
        return ((150, 200, 300), 1)

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def addMinimapObject(self, obj):
        if self.minimap:
            self.minimap.addObject(obj)

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def removeMinimapObject(self, obj):
        if self.minimap:
            self.minimap.removeObject(obj)

    def ensureLoaded(self):
        pass

    @report(types=['args'], dConfigParam='minimap')
    def setMinimapArea(self, areaId):
        if areaId != self.minimapArea:
            self.minimapArea = areaId
            self.destroyMinimap()
            self.setupMinimap()
            self.minimap.addObject(localAvatar.getMinimapObject())
            self.loadConnectors()
            localAvatar.guiMgr.setMinimap(self.minimap)

    @report(types=['frameCount', 'args'], dConfigParam='minimap')
    def showTunnelOnMinimap(self, tunnelUid):
        return self.builder.getTunnelMinimap(tunnelUid) == self.minimapArea

    def getConnectorNodeNamed(self, name):
        return self.find('**/' + name + '*')

    @report(types=['args'], dConfigParam='minimap')
    def handleHolidayStarted(self, holiday):
        if self.minimap:
            self.minimap.handleHolidayStarted(self, holiday)

    @report(types=['args'], dConfigParam='minimap')
    def handleHolidayEnded(self, holiday):
        if self.minimap:
            self.minimap.handleHolidayEnded(self, holiday)
示例#5
0
 def startCustomEffects(self):
     self.stopCustomEffects()
     self.envEffects = EnvironmentEffects(self.geom, self.modelPath)
示例#6
0
class DistributedTunnel(DistributedNode, StagedObject):
    L_WORLD_STACK = 0
    L_AREA_UID = 1
    L_AREA_NODE = 2
    L_LINK_NODE = 3
    notify = directNotify.newCategory('DistributedTunnel')
    
    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'DistributedTunnel')
        StagedObject.__init__(self, StagedObject.OFF)
        self.uniqueId = ''
        self.fakeZoneId = PiratesGlobals.FakeZoneId
        self.GridLOD = { }
        self.visNodes = { }
        self.geom = None
        self.envEffects = None
        self._links = { }
        self.areaWorldZone = [
            None,
            None]
        self.areaNode = [
            None,
            None]
        self._DistributedTunnel__loadedArea = None
        self.areaIndexLoading = None
        self.pendingAreaUnload = False
        self.pendingArea = None
        self.minimapObj = None
        self.builder = GridAreaBuilder.GridAreaBuilder(self)
        self.connectorNodes = [
            'portal_connector_1',
            'portal_connector_2']
        self.connectorNodePosHpr = []
        self.ambientNames = [
            None,
            None]
        self.avatarZoneContext = None
        self.floorIndex = -1
        self._inTransition = False
        self.ownHandles = []

    
    def announceGenerate(self):
        DistributedNode.announceGenerate(self)
        if self.cr.activeWorld == None or self.cr.activeWorld.getType() != PiratesGlobals.INSTANCE_PVP:
            self.setupCollisions()
        
        self.geom.hide(OTPRender.MainCameraBitmask)
        self.geom.showThrough(OTPRender.EnviroCameraBitmask)

    
    def delete(self):
        self.goOffStage()
        self.fadeoutAllAmbient()
        self.destroyMinimapObject()
        self.cr.relatedObjectMgr.abortRequest(self.pendingArea)
        self.pendingArea = None
        self.setLoadedArea(None)
        for node in self.visNodes.values():
            node.detachNode()
        
        self.visNodes = { }
        if self.fakeZoneId != None:
            for node in self.GridLOD.values():
                node.cleanup()
            
            del self.GridLOD
        
        del self.fakeZoneId
        self.removeNode()
        self.ignoreAll()
        self.builder.delete()
        DistributedNode.delete(self)

    
    def setLoadedArea(self, area):
        if self._DistributedTunnel__loadedArea and self._DistributedTunnel__loadedArea.isGenerated():
            self._DistributedTunnel__loadedArea.builder.removeLargeObj(self.visNodes[self._DistributedTunnel__loadedArea.getUniqueId()], self.uniqueId)
        
        if area:
            self._DistributedTunnel__loadedArea = area
            self._DistributedTunnel__loadedArea.builder.addLargeObj(self.visNodes[self._DistributedTunnel__loadedArea.getUniqueId()], self.uniqueId)
        

    
    def getLoadedArea(self):
        return self._DistributedTunnel__loadedArea

    
    def setLinks(self, links):
        for link in links:
            sideIndex = self.connectorNodes.index(link[self.L_LINK_NODE])
            self._links[sideIndex] = link
            self.visNodes.setdefault(link[self.L_AREA_UID], NodePath('vis-%s-%s' % (self.uniqueId, link[self.L_AREA_UID])))
        
        self.calcAmbientNames()
        self.setupConnectorNodes()

    
    def calcAmbientNames(self):
        
        self.ambientNames = [ self.calcOneAmbientName(self._links[index][self.L_AREA_NODE]) for index in (0, 1) ]

    
    def calcOneAmbientName(self, area):
        if not SoundGlobals.getAmbientFromStr(area.split('_')[-1]):
            pass
        return SoundGlobals.getAmbientFromStr(self.modelPath.split('_')[1])

    calcOneAmbientName = report(types = [
        'deltaStamp',
        'args'], dConfigParam = 'connector')(calcOneAmbientName)
    
    def fadeInAmbient(self, index):
        if self.ambientNames[index]:
            base.ambientMgr.requestChangeVolume(self.ambientNames[index], duration = 0.10000000000000001, finalVolume = PiratesGlobals.DEFAULT_AMBIENT_VOLUME_NEAR)
        

    
    def fadeOutAmbient(self, index):
        if self.ambientNames[index]:
            base.ambientMgr.requestFadeOut(self.ambientNames[index], duration = 0.01)
        
        if self.ambientNames[1 - index]:
            base.ambientMgr.requestChangeVolume(self.ambientNames[1 - index], duration = 0, finalVolume = 0)
        

    
    def fadeoutAllAmbient(self):
        for ambientName in self.ambientNames:
            if ambientName:
                base.ambientMgr.requestFadeOut(ambientName)
                
        

    
    def setupConnectorNodes(self):
        
        locatorNodes = [ self.find('**/' + locator) for locator in self.connectorNodes ]
        
        self.connectorNodePosHpr = [ [
            self.getPos(node),
            self.getHpr(node)] for node in locatorNodes ]

    setupConnectorNodes = report(types = [
        'args'], dConfigParam = 'connector')(setupConnectorNodes)
    
    def setupCollisions(self):
        floorNames = [
            'collision_floor_1',
            'collision_floor_2',
            'collision_floor_middle']
        for (x, floorName) in enumerate(floorNames):
            floor = self.find('**/' + floorName)
            floor.setName(self.uniqueName(floorName))
            floorNames[x] = floor.getName()
            self.accept('enterFloor' + floor.getName(), self._DistributedTunnel__handleOnFloor, extraArgs = [
                x])
        

    
    def __handleOnFloor(self, areaIndex, collEntry):
        if not self._inTransition:
            self.floorIndex = 1 - areaIndex
            self._inTransition = True
            area = self.getLoadedArea()
            entranceNode = self.getEntranceNode(area)
            if collEntry:
                self.acceptOnce('EnterTunnelFinished', self.transitionToArea, extraArgs = [
                    self.floorIndex])
                localAvatar.b_setGameState('EnterTunnel', [
                    entranceNode])
            else:
                self.transitionToArea(self.floorIndex)
        

    _DistributedTunnel__handleOnFloor = report(types = [
        'deltaStamp',
        'args'], dConfigParam = 'connector')(__handleOnFloor)
    
    def transitionToArea(self, areaIndex):
        areaUid = self._links[areaIndex][self.L_AREA_UID]
        self.cr.loadingScreen.showTarget(areaUid)
        self.cr.loadingScreen.showHint(areaUid)
        localAvatar.b_setLocation(self.cr.distributedDistrict.getDoId(), PiratesGlobals.QuietZone)
        localAvatar.detachNode()
        (self.currTransParent, self.currTransZone) = self.getLocation()
        
        def Transition():
            self.acceptOnce('activeTunnel-%s-complete' % self.getDoId(), Transition)
            currParentObj = self.cr.doId2do.get(self.currTransParent)
            if currParentObj:
                (self.currTransParent, self.currTransZone) = currParentObj.getLocation()
                self.ownHandles.append(self.cr.addTaggedInterest(self.currTransParent, self.currTransZone, self.cr.ITAG_GAME, 'activeTunnelParent-%s' % self.getDoId(), event = 'activeTunnel-%s-complete' % self.getDoId()))
            else:
                self.cr.activeWorld.goOffStage([
                    self.getLoadedArea()])
                self.d_requestArea(areaIndex)
                localAvatar.refreshActiveQuestStep(forceClear = True)
                localAvatar.lastConnectorId = self.doId

        self.acceptOnce('activeTunnel-%s-complete' % self.getDoId(), Transition)
        self.ownHandles.append(self.cr.addTaggedInterest(self.currTransParent, self.currTransZone, self.cr.ITAG_GAME, 'activeTunnel-%s' % self.getDoId(), event = 'activeTunnel-%s-complete' % self.getDoId()))

    transitionToArea = report(types = [
        'deltaStamp',
        'args'], dConfigParam = 'connector')(transitionToArea)
    
    def handleOnStage(self):
        StagedObject.handleOnStage(self)
        self.startCustomEffects()

    handleOnStage = report(types = [
        'frameCount'], dConfigParam = 'connector')(handleOnStage)
    
    def handleOffStage(self):
        self.stopCustomEffects()
        StagedObject.handleOffStage(self)

    handleOffStage = report(types = [
        'frameCount'], dConfigParam = 'connector')(handleOffStage)
    
    def setUniqueId(self, uid):
        if self.uniqueId:
            self.cr.uidMgr.removeUid(self.uniqueId)
        
        self.uniqueId = uid
        self.cr.uidMgr.addUid(self.uniqueId, self.getDoId())

    
    def getUniqueId(self):
        return self.uniqueId

    
    def reparentConnectorToArea(self, area):
        self.notify.debug('%s reparentConnectorToArea %s' % (self.doId, area))
        entranceNode = self.getEntranceNode(area)
        entranceNode.setScale(1)
        entranceNode.setP(0)
        entranceNode.setR(0)
        rootNode = self.visNodes[area.uniqueId]
        rootNode.reparentTo(area)
        rootNode.setTransform(entranceNode.getTransform(area))
        self.reparentTo(entranceNode)
        (pos, hpr) = self.connectorNodePosHpr[self.getAreaIndex(area)]
        self.setPos(pos)
        self.setHpr(hpr[0], 0, 0)
        self.wrtReparentTo(rootNode)
        self.setLoadedArea(area)
        if area.showTunnelOnMinimap(self.getUniqueId()):
            obj = self.getMinimapObject(entranceNode)
            area.addMinimapObject(obj)
            obj.updateWorldNode(entranceNode)
        

    reparentConnectorToArea = report(types = [
        'frameCount',
        'args'], dConfigParam = 'connector')(reparentConnectorToArea)
    
    def setModelPath(self, modelPath):
        self.notify.debug('setModelPath %s' % modelPath)
        self.modelPath = modelPath
        self.loadModel()

    
    def loadModel(self):
        if not self.geom:
            self.loadWholeModel()
            self.geom.flattenStrong()
            self.geom.reparentTo(self)
        

    
    def loadWholeModel(self):
        modelBaseName = self.modelPath
        self.geom = loader.loadModel(modelBaseName)

    
    def getAreaIndex(self, area):
        areaUid = area.getUniqueId()
        for x in (0, 1):
            if areaUid == self._links[x][self.L_AREA_UID]:
                return x
                
        

    
    def getAreaObject(self, index):
        areaUid = self._links[index][self.L_AREA_UID]
        areaDoId = self.cr.uidMgr.getDoId(areaUid)
        return self.cr.doId2do.get(areaDoId)

    
    def getConnectorNodePosHpr(self, index):
        if index < len(self.connectorNodePosHpr):
            return self.connectorNodePosHpr[index]
        
        return (Point3(0), Vec3(0))

    
    def getAreaNodeNameFromAreaUid(self, areaUid):
        for link in self._links.itervalues():
            if areaUid == link[self.L_AREA_UID]:
                return link[self.L_AREA_NODE]
                
        

    
    def getEntranceNode(self, area):
        areaIndex = self.getAreaIndex(area)
        areaNode = self._links[areaIndex][self.L_AREA_NODE]
        return area.find('**/' + areaNode + '*')

    
    def d_requestArea(self, linkIndex):
        self.sendUpdate('requestArea', [
            self._links[linkIndex][self.L_LINK_NODE]])

    d_requestArea = report(types = [
        'frameCount',
        'args'], dConfigParam = 'connector')(d_requestArea)
    
    def setArea(self, worldStack, areaDoId, autoFadeIn = True):
        self.cr.setWorldStack(worldStack, event = 'WorldOpen')
        
        def areaFinishedCallback(area):
            self.pendingArea = None
            self.loadAreaFinished(area, autoFadeIn)

        areaFinishedCallback = report(types = [
            'frameCount',
            'args'], dConfigParam = 'connector')(areaFinishedCallback)
        self.cr.relatedObjectMgr.abortRequest(self.pendingArea)
        self.pendingArea = self.cr.relatedObjectMgr.requestObjects([
            areaDoId], eachCallback = areaFinishedCallback)

    setArea = report(types = [
        'frameCount',
        'args'], dConfigParam = 'connector')(setArea)
    
    def loadAreaFinished(self, area, autoFadeIn = True):
        
        def handleFinished():
            for currHandle in self.ownHandles:
                self.cr.removeTaggedInterest(currHandle)
            
            self.ownHandles = []

        self.acceptOnce('EnterTunnelFinished', handleFinished)
        
        def leaveTunnel():
            if autoFadeIn:
                
                def leaveTunnelFinished():
                    self._inTransition = False
                    area.forceManagePass(localAvatar)
                    localAvatar.sendCurrentPosition()

                self.acceptOnce('LeaveTunnelFinished', leaveTunnelFinished)
                localAvatar.b_setGameState('LeaveTunnel', [
                    self,
                    area,
                    not autoFadeIn])
            else:
                
                def leaveTunnelFinished():
                    self.sendUpdate('sendLeaveTunnelDone')
                    area.forceManagePass(localAvatar)
                    localAvatar.sendCurrentPosition()

                localAvatar.b_setGameState('LeaveTunnel', [
                    self,
                    area,
                    not autoFadeIn])
                self.cr.setAllInterestsCompleteCallback(leaveTunnelFinished)
            area.handleEnterGameArea()
            self.fadeInAmbient(self.floorIndex)

        leaveTunnel = report(types = [
            'deltaStamp',
            'args'], dConfigParam = 'connector')(leaveTunnel)
        world = area.getParentObj()
        world.goOnStage()
        area.goOnStage()
        self.cr.setAllInterestsCompleteCallback(leaveTunnel)

    loadAreaFinished = report(types = [
        'deltaStamp',
        'args'], dConfigParam = 'connector')(loadAreaFinished)
    
    def startCustomEffects(self):
        self.stopCustomEffects()
        self.envEffects = EnvironmentEffects(self.geom, self.modelPath)

    
    def stopCustomEffects(self):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        

    
    def getMinimapObject(self, worldNode):
        if not (self.minimapObj) and not self.isDisabled():
            self.minimapObj = MinimapTunnel(worldNode)
        
        return self.minimapObj

    
    def destroyMinimapObject(self):
        if self.minimapObj:
            self.minimapObj.removeFromMap()
            self.minimapObj = None
        

    
    def quickLoadOtherSide(self):
        self.cr.loadingScreen.show(waitForLocation = True)
        if self.floorIndex != -1:
            self._inTransition = False
            self._DistributedTunnel__handleOnFloor(self.floorIndex, None)
示例#7
0
    def startCustomEffects(self, interior = True, loadIslandMusic = False):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        
        if self.environment == 'Swamp':
            self.envEffects = SwampEffects.SwampEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            base.musicMgr.request(SoundGlobals.MUSIC_SWAMP, priority = 1, volume = 0.59999999999999998)
        elif self.environment == 'Jungle':
            self.envEffects = ForestEffects.ForestEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            base.musicMgr.request(SoundGlobals.MUSIC_JUNGLE, priority = 1, volume = 0.59999999999999998)
        elif self.environment == 'Cave':
            self.envEffects = CaveEffects.CaveEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            if self.uniqueId == LocationIds.RAVENS_COVE_MINE:
                base.musicMgr.request(SoundGlobals.getMainMusic(self.uniqueId), priority = 1, volume = 0.59999999999999998)
            else:
                base.musicMgr.request(SoundGlobals.MUSIC_CAVE, priority = 1, volume = 0.59999999999999998)
        elif self.uniqueId in ('1189479168.0sdnaik0', '1150922126.8akelts'):
            r = Reflection.getGlobalReflection()
            water = SeaPatch(self, reflection = r)
            water.loadSeaPatchFile('out.spf')
            self.water = water
            self.initializeIslandWaterParameters(self.geom)
        else:
            self.envEffects = EnvironmentEffects(self, self.modelPath)
            if interior:
                pass
            
        if loadIslandMusic:
            if not base.localAvatar.isInInvasion():
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA)
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA_COMBAT)
            
            
            def getCurrentIslandMusic():
                priZeros = []
                for music in base.musicMgr.playlist:
                    if music.priority == 0:
                        priZeros.append(music)
                        continue
                
                return priZeros

            
            def changeMusic(music, pri):
                for priZero in getCurrentIslandMusic():
                    base.musicMgr.requestFadeOut(priZero.name, removeFromPlaylist = True)
                
                base.musicMgr.request(music, priority = 0, volume = 0.59999999999999998)

            mainMusic = SoundGlobals.getMainMusic(self.uniqueId)
            altMusic = SoundGlobals.getAltMusic(self.uniqueId)
            if mainMusic and altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                todMgr = base.cr.timeOfDayManager
                todMgr.addTimeOfDayToggle('Day-Night Area Music', 6.0, 20.0, changeMusic, [
                    mainMusic,
                    0], changeMusic, [
                    altMusic,
                    0])
            elif mainMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                base.musicMgr.request(mainMusic, volume = 0.59999999999999998)
            elif altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                base.musicMgr.request(altMusic, volume = 0.59999999999999998)
            
        
        self.builder.initEffects()
示例#8
0
class DistributedGameArea(DistributedNode, MappableArea, StagedObject):
    notify = directNotify.newCategory('DistributedGameArea')
    
    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'GameArea')
        MappableArea.__init__(self)
        StagedObject.__init__(self, StagedObject.OFF)
        self.uniqueId = ''
        self.geom = None
        self.funnelDisplayName = None
        self.previousDisplayName = None
        self.gameFSM = None
        self.links = []
        self.pendingSetupConnector = { }
        self.connectors = { }
        self.connectorInterests = set()
        self.envEffects = None
        self.spawnTriggers = []
        self.blockerColls = []
        self.islandWaterParameters = None
        self.swamp_water = None
        self.entryTime = [
            None,
            0]
        self.timeCheck = 0
        self.minimap = None
        self.footprintNode = None
        self.popupDialog = None
        self.minimapArea = 0
        self.laMinimapObj = None
        self.footstepSound = None
        self.environment = None
        self.connectorsHereCallback = None

    
    def __repr__(self):
        if not self.getName():
            pass
        return '%s (%s)' % (DistributedNode.__repr__(self), self.uniqueId)

    
    def __str__(self):
        if not self.getName():
            pass
        return '%s (%s)' % (DistributedNode.__repr__(self), self.uniqueId)

    
    def disable(self):
        taskMgr.remove('showEnterMessage')
        DistributedNode.disable(self)
        if self.geom:
            self.geom.removeNode()
        
        self.unloadConnectors()
        for request in self.pendingSetupConnector.itervalues():
            self.cr.relatedObjectMgr.abortRequest(request)
        
        self.pendingSetupConnector = { }
        self.builder.delete()
        self.builder = None

    
    def delete(self):
        if base.zoneLODTarget == self:
            base.disableZoneLODs()
        
        for trigger in self.spawnTriggers:
            trigger.removeNode()
        
        del self.spawnTriggers
        del self.connectors
        del self.links
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        
        DistributedNode.delete(self)
        if self.islandWaterParameters:
            del self.islandWaterParameters
        
        if self.swamp_water:
            self.swamp_water.delete()
            del self.swamp_water
        
        if self.popupDialog:
            self.popupDialog.destroy()
        
        del self.popupDialog
        self.connectorsHereCallback = None

    
    def setLocation(self, parentId, zoneId):
        DistributedNode.setLocation(self, parentId, zoneId)
        if parentId:
            parent = self.getParentObj()
            self.reparentTo(parent)
        

    
    def setName(self, name):
        self.name = name

    
    def setModelPath(self, modelPath):
        self.modelPath = modelPath

    
    def handleChildArrive(self, childObj, zoneId):
        DistributedNode.handleChildArrive(self, childObj, zoneId)
        if childObj.isLocal():
            base.loadingScreen.endStep('enterArea')
            base.enableZoneLODs(self)
            childObj.refreshActiveQuestStep()
            localAvatar.guiMgr.setMinimap(self.minimap)
            localAvatar.setAreaFootstep(self.footstepSound)
            localAvatar.guiMgr.radarGui.showLocation(self.uniqueId)
            envName = base.worldCreator.environmentTable.get(self.uniqueId)
            if envName:
                environmentID = TODGlobals.ENVIRONMENT_NAMES_TO_ID.get(envName, TODGlobals.ENV_DEFAULT)
                envData = { }
                envSettings = base.worldCreator.uidEnvSettings.get(self.uniqueId)
                if envSettings != None:
                    envData = envSettings
                
                base.cr.timeOfDayManager.setEnvironment(environmentID, envData)
            else:
                envData = None
                envSettings = base.worldCreator.uidEnvSettings.get(self.uniqueId)
                if envSettings != None:
                    envData = envSettings
                
                base.cr.timeOfDayManager.setEnvironment(TODGlobals.ENV_INTERIOR, envData)
            self.builder.arrived()
        
        self.accept('transferMinimapObjects', self.transferMinimapObject)
        if self.minimap and hasattr(childObj, 'getMinimapObject'):
            if childObj.getMinimapObject():
                self.laMinimapObj = childObj.getMinimapObject()
                self.minimap.addObject(childObj.getMinimapObject())
            
        

    handleChildArrive = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(handleChildArrive)
    
    def transferMinimapObject(self, guiMgr):
        if self.laMinimapObj:
            guiMgr.transferMinimapObject(self.laMinimapObj)
        

    
    def handleChildLeave(self, childObj, zoneId):
        if childObj.isLocal():
            base.disableZoneLODs()
            localAvatar.guiMgr.clearMinimap(self.minimap)
            self.builder.localAvLeaving()
            self.builder.left()
        
        self.ignore('transferMinimapObjects')
        self.laMinimapObj = None
        if self.minimap and hasattr(childObj, 'getMinimapObject'):
            if childObj.getMinimapObject():
                self.minimap.removeObject(childObj.getMinimapObject())
            
        
        DistributedNode.handleChildLeave(self, childObj, zoneId)

    handleChildLeave = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(handleChildLeave)
    
    def setUniqueId(self, uid):
        if self.uniqueId != '':
            self.cr.uidMgr.removeUid(self.uniqueId)
        
        self.uniqueId = uid
        self.cr.uidMgr.addUid(self.uniqueId, self.getDoId())

    
    def getUniqueId(self):
        return self.uniqueId

    
    def loadModel(self):
        pass

    
    def setLinks(self, links):
        for link in links:
            (areaNode, connId, areaUid, connParent, connZone, connNode, connWorld, connWorldZone) = link
            newLink = [
                connId,
                connParent,
                connZone,
                connWorld,
                connWorldZone]
            if newLink in self.links:
                continue
            
            self.links.append(newLink)
            
            def setupConnector(connector):
                self.connectors[connector.doId] = connector
                request = self.pendingSetupConnector.pop(connector.doId, None)
                if not request:
                    pass

            connector = self.cr.doId2do.get(connId)
            if connector:
                self.pendingSetupConnector[connId] = None
                setupConnector(connector)
                continue
            if connId:
                if connId in self.pendingSetupConnector:
                    request = self.pendingSetupConnector.pop(connId)
                    self.cr.relatedObjectMgr.abortRequest(request)
                
                request = self.cr.relatedObjectMgr.requestObjects([
                    connId], eachCallback = setupConnector)
                self.pendingSetupConnector[connId] = request
                continue
        

    setLinks = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail'])(setLinks)
    
    def loadConnectors(self):
        for link in self.links:
            if link:
                connectorId = link[0]
                if connectorId not in self.connectorInterests or not self.cr.doId2do.has_key(connectorId):
                    if connectorId not in self.connectorInterests:
                        self.connectorInterests.add(connectorId)
                    
                    parentId = link[1]
                    zoneId = link[2]
                    linkParentId = link[3]
                    linkParentZoneId = link[4]
                    
                    def connectorParentHere(connectorId, parentId, zoneId):
                        connectorEvent = 'connector-%s' % connectorId
                        self.acceptOnce(connectorEvent, self.reparentConnector, extraArgs = [
                            connectorId])
                        self.cr.addTaggedInterest(parentId, zoneId, self.cr.ITAG_GAME, 'Connectors-%s' % self.doId, event = connectorEvent, otherTags = [
                            'Connectors-%s' % self.doId])

                    connectorEvent = 'connector-%s' % connectorId
                    self.acceptOnce(connectorEvent, connectorParentHere, extraArgs = [
                        connectorId,
                        parentId,
                        zoneId])
                    self.cr.addTaggedInterest(linkParentId, linkParentZoneId, self.cr.ITAG_GAME, 'ConnectorsParent-%s' % self.doId, event = connectorEvent, otherTags = [
                        'ConnectorsParent-%s' % self.doId])
                else:
                    self.reparentConnector(connectorId)
            not self.cr.doId2do.has_key(connectorId)
        

    loadConnectors = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail',
        'teleport'])(loadConnectors)
    
    def unloadConnectors(self):
        for (connectorId, connector) in self.connectors.iteritems():
            if connector:
                connector.setLoadedArea(None)
                connector.goOffStage()
                continue
        
        self.connectors = { }
        self.cr.removeInterestTag('Connectors-%s' % self.doId)
        self.cr.removeInterestTag('ConnectorsParent-%s' % self.doId)
        self.connectorInterests = set()

    unloadConnectors = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail',
        'teleport'])(unloadConnectors)
    
    def reparentConnector(self, connectorId):
        connector = self.cr.doId2do.get(connectorId)
        if connector:
            self.connectors[connectorId] = connector
            connector.reparentConnectorToArea(self)
            if self.isOnStage():
                connector.goOnStage()
            else:
                connector.goOffStage()
            if self.connectorsHereCallback and len(self.connectors) == len(self.links):
                self.connectorsHereCallback()
                self.connectorsHereCallback = None
            
        

    reparentConnector = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail',
        'teleport'])(reparentConnector)
    
    def setConnectorsHereCallback(self, callback):
        self.connectorsHereCallback = callback

    
    def handleEnterGameArea(self, collEntry = None):
        inventory = localAvatar.getInventory()
        if localAvatar.style.getTutorial() == PiratesGlobals.TUT_GOT_SEACHEST and self.uniqueId == LocationIds.RAMBLESHACK_ISLAND and len(inventory.getWeapons()) < 1 and base.localAvatar.showQuest:
            base.localAvatar.resetQuestShow()
            popupDialogText = [
                'showBlacksmith',
                'closeShowBlacksmith']
            self.popupDialog = NewTutorialPanel(popupDialogText)
            
            def closeTutorialWindow():
                messenger.send(self.popupDialog.closeMessage)

            self.popupDialog.setYesCommand(closeTutorialWindow)
            self.acceptOnce('closeTutorialWindow', closeTutorialWindow)
            self.popupDialog.activate()
        
        taskMgr.doMethodLater(1, self.showEnterMessage, 'showEnterMessage')
        UserFunnel.logSubmit(0, 'ENTERING_' + str(self.funnelDisplayName))
        UserFunnel.logSubmit(1, 'ENTERING_' + str(self.funnelDisplayName))
        self.storeLocationTime(self.funnelDisplayName, time.time())
        displayName = PLocalizer.LocationNames.get(self.uniqueId)
        base.setLocationCode(displayName)
        self.builder.initEffects()

    handleEnterGameArea = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail',
        'teleport'])(handleEnterGameArea)
    
    def storeLocationTime(self, loc, time):
        if loc == self.entryTime[0]:
            if self.entryTime[1] == 0:
                self.entryTime[1] = time
            
            return None
        else:
            self.entryTime = [
                loc,
                time]

    
    def readLocationTime(self):
        return self.entryTime[1]

    
    def showEnterMessage(self, task):
        displayName = PLocalizer.LocationNames.get(self.uniqueId)
        self.displayGameAreaName(displayName)

    
    def handleExitGameArea(self, collEntry = None):
        UserFunnel.logSubmit(0, 'EXITING_' + str(self.funnelDisplayName))
        UserFunnel.logSubmit(1, 'EXITING_' + str(self.funnelDisplayName))
        self.stopCustomEffects()
        self.previousDisplayName = None
        displayName = str(self.funnelDisplayName)
        timeSpent = int(time.time()) - int(self.readLocationTime())
        if int(self.timeCheck) + 1 == int(timeSpent) and int(self.timeCheck) - 1 == int(timeSpent) or int(self.timeCheck) == int(timeSpent):
            pass
        1
        base.cr.centralLogger.writeClientEvent('EXITING_AREA|%s|%d' % (displayName, timeSpent))
        self.timeCheck = timeSpent

    handleExitGameArea = report(types = [
        'args',
        'deltaStamp'], dConfigParam = [
        'jail',
        'teleport'])(handleExitGameArea)
    
    def displayGameAreaName(self, displayName):
        self.funnelDisplayName = displayName
        if self.previousDisplayName != displayName:
            self.previousDisplayName = displayName
            base.localAvatar.guiMgr.createTitle(displayName, PiratesGuiGlobals.TextFG2)
        

    
    def setPlayerBarrier(self, isOn):
        pass

    
    def setupCannonballLandColl(self, collNode, mask, index):
        if collNode and not collNode.isEmpty():
            collNode.node().setCollideMask(mask)
            collNode.setTag('objType', str(PiratesGlobals.COLL_LAND))
            collNode.setTag('groundCode', str(index))
            collNode.setTag('groundId', str(self.doId))
        

    
    def projectileWeaponHit(self, skillId, ammoSkillId, skillResult, targetEffects, pos, normal, codes, attacker, itemEffects = []):
        pass

    
    def startCustomEffects(self, interior = True, loadIslandMusic = False):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        
        if self.environment == 'Swamp':
            self.envEffects = SwampEffects.SwampEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            base.musicMgr.request(SoundGlobals.MUSIC_SWAMP, priority = 1, volume = 0.59999999999999998)
        elif self.environment == 'Jungle':
            self.envEffects = ForestEffects.ForestEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            base.musicMgr.request(SoundGlobals.MUSIC_JUNGLE, priority = 1, volume = 0.59999999999999998)
        elif self.environment == 'Cave':
            self.envEffects = CaveEffects.CaveEffects(self, self.modelPath)
            base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = False)
            if self.uniqueId == LocationIds.RAVENS_COVE_MINE:
                base.musicMgr.request(SoundGlobals.getMainMusic(self.uniqueId), priority = 1, volume = 0.59999999999999998)
            else:
                base.musicMgr.request(SoundGlobals.MUSIC_CAVE, priority = 1, volume = 0.59999999999999998)
        elif self.uniqueId in ('1189479168.0sdnaik0', '1150922126.8akelts'):
            r = Reflection.getGlobalReflection()
            water = SeaPatch(self, reflection = r)
            water.loadSeaPatchFile('out.spf')
            self.water = water
            self.initializeIslandWaterParameters(self.geom)
        else:
            self.envEffects = EnvironmentEffects(self, self.modelPath)
            if interior:
                pass
            
        if loadIslandMusic:
            if not base.localAvatar.isInInvasion():
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA)
                base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_TORMENTA_COMBAT)
            
            
            def getCurrentIslandMusic():
                priZeros = []
                for music in base.musicMgr.playlist:
                    if music.priority == 0:
                        priZeros.append(music)
                        continue
                
                return priZeros

            
            def changeMusic(music, pri):
                for priZero in getCurrentIslandMusic():
                    base.musicMgr.requestFadeOut(priZero.name, removeFromPlaylist = True)
                
                base.musicMgr.request(music, priority = 0, volume = 0.59999999999999998)

            mainMusic = SoundGlobals.getMainMusic(self.uniqueId)
            altMusic = SoundGlobals.getAltMusic(self.uniqueId)
            if mainMusic and altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                todMgr = base.cr.timeOfDayManager
                todMgr.addTimeOfDayToggle('Day-Night Area Music', 6.0, 20.0, changeMusic, [
                    mainMusic,
                    0], changeMusic, [
                    altMusic,
                    0])
            elif mainMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                base.musicMgr.request(mainMusic, volume = 0.59999999999999998)
            elif altMusic:
                base.musicMgr.requestCurMusicFadeOut(removeFromPlaylist = True)
                base.musicMgr.request(altMusic, volume = 0.59999999999999998)
            
        
        self.builder.initEffects()

    
    def stopCustomEffects(self):
        if self.envEffects:
            self.envEffects.delete()
            self.envEffects = None
        
        if 'swamp' in self.modelPath:
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_SWAMP, removeFromPlaylist = True)
        elif 'jungle' in self.modelPath:
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_JUNGLE, removeFromPlaylist = True)
        elif self.uniqueId in getLocationList(LocationIds.ANY_CAVE):
            base.musicMgr.requestFadeOut(SoundGlobals.MUSIC_CAVE, removeFromPlaylist = True)
            base.musicMgr.requestFadeOut(SoundGlobals.getMainMusic(self.uniqueId), removeFromPlaylist = True)
        elif self.uniqueId == '1189479168.0sdnaik0':
            self.water.delete()
            self.water = None
        
        if base.cr.timeOfDayManager:
            base.cr.timeOfDayManager.removeTimeOfDayToggle('Day-Night Area Music')
        

    
    def updateAvReturnLocation(self, av, uniqueId):
        pass

    
    def quickLoadOtherSide(self):
        connector = self.connectors.get(localAvatar.lastConnectorId)
        if connector:
            connector.quickLoadOtherSide()
        

    quickLoadOtherSide = report(types = [
        'frameCount',
        'args'], dConfigParam = [
        'jail',
        'teleport'])(quickLoadOtherSide)
    
    def addSpawnTriggers(self, triggerSpheres):
        for (x, y, z, triggerRadius, spawnPtId) in triggerSpheres:
            objectSphere = CollisionSphere(x, y, z, triggerRadius)
            objectName = uniqueName('spawnTriggerSphere')
            objectSphere.setTangible(0)
            objectSphereNode = CollisionNode(objectName)
            objectSphereNode.addSolid(objectSphere)
            objectSphereNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
            objectSphereNodePath = self.builder.collisions.attachNewNode(objectSphereNode)
            self.accept('enter' + objectName, self.handleEnterSphere, extraArgs = [
                spawnPtId])
            self.spawnTriggers.append(objectSphereNodePath)
        

    
    def handleEnterSphere(self, spawnPtId, entry):
        if base.localAvatar:
            if hasattr(base.localAvatar, 'getDoId'):
                doId = base.localAvatar.getDoId()
                self.sendUpdate('spawnNPC', [
                    spawnPtId,
                    doId])
            
        

    
    def initBlockers(self, geom):
        self.disableBlockers = False
        if base.config.GetBool('disable-blockers', 0):
            self.disableBlockers = True
        
        blockerColls = geom.findAllMatches('**/blocker_*;+s')
        interior = False
        if not blockerColls.isEmpty():
            if blockerColls[0].getName().find('_i') != -1:
                interior = True
            
            for i in range(0, blockerColls.getNumPaths()):
                self.blockerColls.append(blockerColls[i])
                if self.disableBlockers:
                    blockerColls[i].stash()
                    continue
            
        
        if interior:
            self.accept('enterblocker_1_i', self.handleInteriorBlockerCollision)
        else:
            self.accept('enterblocker_1', self.handleBlockerCollision)
            self.accept('enterblocker_0', self.handleBlockerCollision)

    
    def stashSpecificBlocker(self, name):
        self.ignore('enter' + name)
        for blocker in self.blockerColls:
            if blocker.getName() == name:
                blocker.stash()
                continue
        

    
    def stashAllBlockers(self):
        self.ignore('enterblocker_1_i')
        self.ignore('enterblocker_1')
        self.ignore('enterblocker_0')
        for blocker in self.blockerColls:
            blocker.stash()
        

    
    def handleInteriorBlockerCollision(self, entry):
        questId = localAvatar.activeQuestId
        if base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_GOT_CUTLASS:
            questId = 'c2_visit_will_turner'
            localAvatar.guiMgr.messageStack.addTextMessage(PLocalizer.QuestStrings[questId]['blockerMessage'])
        else:
            self.stashAllBlockers()

    
    def handleBlockerCollision(self, entry):
        if base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_KILLED_1_SKELETON:
            questId = 'c2.2defeatSkeletons'
            localAvatar.guiMgr.messageStack.addTextMessage(PLocalizer.QuestStrings[questId]['blockerMessage'])
        elif base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_GOT_COMPASS:
            questId = 'c2_visit_tia_dalma'
            self.stashSpecificBlocker('blocker_1')
            if entry.getIntoNodePath().getName() != 'blocker_1':
                localAvatar.guiMgr.messageStack.addTextMessage(PLocalizer.QuestStrings[questId]['blockerMessage'])
            
        else:
            self.stashAllBlockers()

    
    def handleOnStage(self):
        StagedObject.handleOnStage(self)
        for (id, connector) in self.connectors.iteritems():
            if connector:
                connector.goOnStage()
                continue
        
        self.builder.addCutsceneOriginNode()

    handleOnStage = report(types = [
        'frameCount'], dConfigParam = 'connector')(handleOnStage)
    
    def handleOffStage(self):
        for (id, connector) in self.connectors.iteritems():
            if connector:
                connector.goOffStage()
                continue
        
        StagedObject.handleOffStage(self)

    handleOffStage = report(types = [
        'frameCount'], dConfigParam = 'connector')(handleOffStage)
    
    def getTeleportDestPosH(self, index = 0):
        pt = self._getTunnelSpawnPos(index)
        if not pt:
            self.notify.warning('could not find tunnel location %s' % self)
            return (0, 0, 0, 0)
        
        return (pt[0], pt[1], pt[2], 0)

    
    def _getTunnelSpawnPos(self, index = 0):
        connectorNodes = self.findAllMatches('**/portal_exterior*') + self.findAllMatches('**/portal_interior*')
        if not connectorNodes:
            return None
        
        return self.getRelativePoint(connectorNodes[index % len(connectorNodes)], Point3(40, 0, 0))

    _getTunnelSpawnPos = report(types = [
        'args'], dConfigParam = 'teleport')(_getTunnelSpawnPos)
    
    def initializeIslandWaterParameters(self, reference):
        debug = False
        island_water_parameters = IslandWaterParameters()
        world_position = self.getPos(render)
        world_x_offset = world_position[0]
        world_y_offset = world_position[1]
        world_z_offset = world_position[2]
        if debug:
            print self, '=', self.getName()
            print 'GAME AREA X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
        
        self.swampAreaNode = reference.find('**/ocean')
        model = reference.find('**/water_color')
        if model:
            if debug:
                print 'WATER COLOR X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
            
            model.hide()
            min_point = Point3(0)
            max_point = Point3(0)
            model.calcTightBounds(min_point, max_point)
            size = max_point - min_point
            if self.getH() == 180 or self.getH() == -180:
                x = -min_point[0] + world_x_offset
                y = -min_point[1] + world_y_offset
                x_size = -size[0]
                y_size = -size[1]
            else:
                x = min_point[0] + world_x_offset
                y = min_point[1] + world_y_offset
                x_size = size[0]
                y_size = size[1]
            island_water_parameters.map_x_origin = x
            island_water_parameters.map_y_origin = y
            island_water_parameters.map_x_scale = x_size
            island_water_parameters.map_y_scale = y_size
            if debug:
                print 'X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[1], x_size, y_size
            
            texture = model.findTexture('*')
            if texture:
                island_water_parameters.water_color_texture = texture
                if debug:
                    print 'WATER COLOR TEXTURE', texture
                
            
        elif debug:
            print '*** water_color NODE NOT FOUND'
        
        model = reference.find('**/water_alpha')
        if model:
            if debug:
                print 'WATER ALPHA X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
            
            model.hide()
            min_point = Point3(0)
            max_point = Point3(0)
            model.calcTightBounds(min_point, max_point)
            size = max_point - min_point
            if self.getH() == 180 or self.getH() == -180:
                x = -min_point[0] + world_x_offset
                y = -min_point[1] + world_y_offset
                x_size = -size[0]
                y_size = -size[1]
            else:
                x = min_point[0] + world_x_offset
                y = min_point[1] + world_y_offset
                x_size = size[0]
                y_size = size[1]
            island_water_parameters.alpha_map_x_origin = x
            island_water_parameters.alpha_map_y_origin = y
            island_water_parameters.alpha_map_x_scale = x_size
            island_water_parameters.alpha_map_y_scale = y_size
            if debug:
                print 'ALPHA X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[1], x_size, y_size
            
            texture = model.findTexture('*')
            if texture:
                island_water_parameters.water_alpha_texture = texture
                if debug:
                    print 'WATER ALPHA TEXTURE', texture
                
            
        elif debug:
            print '*** water_alpha NODE NOT FOUND'
        
        use_shader = False
        if base.config.GetBool('want-shaders', 1) and base.win and base.win.getGsg() and base.win.getGsg().getShaderModel() >= GraphicsStateGuardian.SM20:
            use_shader = True
        
        model_ns = reference.find('**/water_swamp_ns')
        if model_ns:
            if use_shader:
                model_ns.hide()
            else:
                model_ns.show()
                model = model_ns
                model.setBin('water', 1)
                parent = model.getParent()
                model.detachNode()
                stencil_one_node_path = NodePath('stencil_one')
                stencil_one_node_path.reparentTo(parent)
                model.instanceTo(stencil_one_node_path)
                mask = 0xFFFFFFFFL
                stencil_one = StencilAttrib.make(1, StencilAttrib.SCFEqual, StencilAttrib.SOKeep, StencilAttrib.SOKeep, StencilAttrib.SOKeep, 1, mask, mask)
                stencil_one_node_path.setAttrib(stencil_one, 100)
                stencil_one_node_path.setDepthTest(0)
                if not base.useStencils:
                    stencil_one_node_path.hide()
                
        
        model_alpha_texture = None
        model_alpha = reference.find('**/water_alpha_swamp')
        if model_alpha:
            model_alpha_texture = model_alpha.findTexture('*')
            model_alpha.hide()
            if debug:
                print 'model_alpha_texture', model_alpha_texture
            
            if False:
                texture = model_alpha_texture
                card_x_size = 0.5
                card_y_size = 0.5
                card = CardMaker('test_texture_card')
                card.setFrame(-card_x_size, card_x_size, -card_y_size, card_y_size)
                card_node_path = NodePath(card.generate())
                card_node_path.setTexture(texture, 1)
                card_node_path.node().setBounds(OmniBoundingVolume())
                card_node_path.node().setFinal(1)
                card_node_path.reparentTo(render2d)
            
        else:
            model_alpha = None
        model = reference.find('**/water_color_swamp')
        if model:
            if use_shader:
                model.show()
                model_texture = model.findTexture('*')
                if debug:
                    print 'WATER COLOR SWAMP X OFF, Y OFF, Z OFF = ', world_x_offset, world_y_offset, world_z_offset
                
                parent = model.getParent()
                model.detachNode()
                stencil_one_node_path = NodePath('stencil_one')
                stencil_one_node_path.reparentTo(parent)
                model.instanceTo(stencil_one_node_path)
                mask = 0xFFFFFFFFL
                stencil_one = StencilAttrib.make(1, StencilAttrib.SCFEqual, StencilAttrib.SOKeep, StencilAttrib.SOKeep, StencilAttrib.SOKeep, 1, mask, mask)
                stencil_one_node_path.setAttrib(stencil_one, 100)
                stencil_one_node_path.setDepthTest(0)
                if not base.useStencils:
                    stencil_one_node_path.hide()
                
                min_point = Point3(0)
                max_point = Point3(0)
                model.calcTightBounds(min_point, max_point)
                size = max_point - min_point
                if self.getH() == 180 or self.getH() == -180:
                    x = -min_point[0] + world_x_offset
                    y = -min_point[1] + world_y_offset
                    x_size = -size[0]
                    y_size = -size[1]
                else:
                    x = min_point[0] + world_x_offset
                    y = min_point[1] + world_y_offset
                    x_size = size[0]
                    y_size = size[1]
                if debug:
                    print 'min_point', min_point
                    print 'max_point', max_point
                    print 'size', size
                    print 'x y', x, y
                
                island_water_parameters.swamp_map_x_origin = x
                island_water_parameters.swamp_map_y_origin = y
                island_water_parameters.swamp_map_x_scale = x_size
                island_water_parameters.swamp_map_y_scale = y_size
                if debug:
                    print 'X, Y, X SIZE, Y SIZE = ', min_point[0], min_point[1], x_size, y_size
                
                texture = model.findTexture('*')
                if texture:
                    island_water_parameters.swamp_water_color_texture = texture
                    if debug:
                        print 'SWAMP WATER COLOR TEXTURE', texture
                    
                
                water_color_file_path = island_water_parameters.default_water_color_file_path
                alpha_texture_file_path = island_water_parameters.default_water_alpha_file_path
                opacity_texture_file_path = None
                shader_file_path = 'models/swamps/cuba_swamp001_2X.cg'
                reflection = Reflection.getGlobalReflection()
                self.swamp_water = Swamp(None, None, reflection, model, shader_file_path)
                island_water_parameters.swamp_water = self.swamp_water
                unload_previous_texture = True
                self.swamp_water.set_water_color_texture(water_color_file_path, unload_previous_texture, model_texture)
                self.swamp_water.set_water_alpha_texture(alpha_texture_file_path, unload_previous_texture, model_alpha_texture)
                self.swamp_water.set_wrap_or_clamp(True)
                r = 37.0
                g = 62.0
                b = 40.0
                self.swamp_water.water_r = r
                self.swamp_water.water_g = g
                self.swamp_water.water_b = b
                island_water_parameters.swamp_color_r = r
                island_water_parameters.swamp_color_g = g
                island_water_parameters.swamp_color_b = b
                x = 0.0
                y = 1.0
                speed = 3.2000000000000002
                island_water_parameters.swamp_direction_x = x
                island_water_parameters.swamp_direction_y = y
                island_water_parameters.swamp_speed = speed
                self.swamp_water.update_water_direction_and_speed(x, y, speed)
            else:
                model.hide()
        elif debug:
            print '*** water_color_swamp NODE NOT FOUND'
        
        self.islandWaterParameters = island_water_parameters

    
    def getLevel(self):
        return 1

    
    def announceGenerate(self):
        base.loadingScreen.tick()
        DistributedNode.announceGenerate(self)
        base.worldCreator.registerSpecialNodes(self, self.uniqueId)
        self.areaType = base.worldCreator.getFieldFromUid(self.uniqueId, 'Visibility')
        self.envSettings = base.worldCreator.getEnvSettingsByUid(self.uniqueId)
        self.builder = base.worldCreator.getBuilder(self, self.areaType)

    
    def retrieveFootprintNode(self):
        footprintCache = self.getFootprintCache()
        if footprintCache.hasData() and base.config.GetBool('want-disk-cache', 0):
            data = footprintCache.getData()
            newData = data.copySubgraph()
            footprintNode = NodePath(newData)
        else:
            footprintNode = self.buildFootprintNode()
        return footprintNode

    
    def getFootprintCache(self):
        return base.bamCache.lookup(Filename('/%s_footprint_%s.bam' % (self.uniqueId, base.gridDetail)), 'bam')

    
    def buildFootprintNode(self):
        footprintCache = self.getFootprintCache()
        footprintNode = self.builder.buildFootprintNode()
        footprintCache.setData(footprintNode.node(), 0)
        base.bamCache.store(footprintCache)
        return footprintNode

    
    def hideMapNodes(self):
        mapNodes = self.geom.findAllMatches('**/minimap_*')
        mapNodes.hide()

    hideMapNodes = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(hideMapNodes)
    
    def setFootstepSound(self, footstepSound):
        self.footstepSound = footstepSound
        if self.footstepSound and base.localAvatar:
            base.localAvatar.setAreaFootstep(self.footstepSound)
            base.localAvatar.setSurfaceIndexFromLevelDefault()
        

    
    def setEnvironment(self, environment):
        self.environment = environment

    
    def setMinimapPrefix(self, prefix):
        minimaps = self.geom.findAllMatches('**/minimap_*;+s')
        for map in minimaps:
            if prefix not in map.getName():
                map.detachNode()
                continue
        
        minimaps = sorted(self.geom.findAllMatches('**/minimap_*;+s'))
        for (x, map) in enumerate(minimaps):
            map.setName('minimap_%d' % x)
        

    setMinimapPrefix = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(setMinimapPrefix)
    
    def getMapNode(self):
        mapNode = self.geom.find('**/minimap_%s' % (self.minimapArea,))
        if not mapNode:
            minSide = 1500.0
            (a, b) = self.geom.getTightBounds()
            diff = b - a
            sideScale = 1
            if diff[0] > diff[1]:
                if diff[0] < minSide:
                    sideScale = minSide / diff[0]
                
            elif diff[1] < minSide:
                sideScale = minSide / diff[1]
            
            cm = CardMaker('minimap-card')
            cm.setFrame(VBase4(a[0], b[0], a[1], b[1]) * sideScale)
            modelNode = ModelNode('minimap_0')
            modelNode.setPreserveTransform(1)
            mapNode = self.geom.attachNewNode(modelNode)
            mapGeom = mapNode.attachNewNode(cm.generate())
            mapGeom.setP(-90)
            mapGeom.hide()
        
        return mapNode

    getMapNode = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(getMapNode)
    
    def getMapName(self):
        return 'map-' + self.getUniqueId()

    
    def getFootprintNode(self):
        if not self.footprintNode:
            self.footprintNode = self.retrieveFootprintNode()
        
        if not self.footprintNode.find('footprint_%s' % (self.minimapArea,)):
            pass
        return NodePath('footprint_%s' % (self.minimapArea,))

    
    def getShopNodes(self):
        shopNodes = self.builder.getMinimapShopNodes()
        mapNodes = NodePathCollection()
        for node in shopNodes:
            if not node.getTag('MinimapArea'):
                pass
            minimapArea = int('0')
            if minimapArea == self.minimapArea:
                mapNodes.addPath(node)
                continue
        
        return mapNodes

    
    def getCapturePointNodes(self, holidayName):
        capturePoints = self.builder.getMinimapCapturePointNodes(holidayName)
        mapNodes = NodePathCollection()
        for node in capturePoints:
            if not node.getTag('MinimapArea'):
                pass
            minimapArea = int('0')
            if minimapArea == self.minimapArea:
                mapNodes.addPath(node)
                continue
        
        return mapNodes

    
    def getZoomLevels(self):
        return ((150, 200, 300), 1)

    
    def addMinimapObject(self, obj):
        if self.minimap:
            self.minimap.addObject(obj)
        

    addMinimapObject = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(addMinimapObject)
    
    def removeMinimapObject(self, obj):
        if self.minimap:
            self.minimap.removeObject(obj)
        

    removeMinimapObject = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(removeMinimapObject)
    
    def ensureLoaded(self):
        pass

    
    def setMinimapArea(self, areaId):
        if areaId != self.minimapArea:
            self.minimapArea = areaId
            self.destroyMinimap()
            self.setupMinimap()
            self.minimap.addObject(localAvatar.getMinimapObject())
            self.loadConnectors()
            localAvatar.guiMgr.setMinimap(self.minimap)
        

    setMinimapArea = report(types = [
        'args'], dConfigParam = 'minimap')(setMinimapArea)
    
    def showTunnelOnMinimap(self, tunnelUid):
        return self.builder.getTunnelMinimap(tunnelUid) == self.minimapArea

    showTunnelOnMinimap = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(showTunnelOnMinimap)
    
    def getConnectorNodeNamed(self, name):
        return self.find('**/' + name + '*')

    
    def handleHolidayStarted(self, holiday):
        if self.minimap:
            self.minimap.handleHolidayStarted(self, holiday)
        

    handleHolidayStarted = report(types = [
        'args'], dConfigParam = 'minimap')(handleHolidayStarted)
    
    def handleHolidayEnded(self, holiday):
        if self.minimap:
            self.minimap.handleHolidayEnded(self, holiday)
        

    handleHolidayEnded = report(types = [
        'args'], dConfigParam = 'minimap')(handleHolidayEnded)