コード例 #1
0
class CogdoFlyingLevelFog:
    def __init__(self, level, color=Globals.Level.FogColor):
        self._level = level
        self.color = color
        fogDistance = self._level.quadLengthUnits * max(
            1, self._level.quadVisibiltyAhead * 0.2)
        self.fog = Fog('RenderFog')
        self.fog.setColor(self.color)
        self.fog.setLinearRange(
            fogDistance * Globals.Level.RenderFogStartFactor, fogDistance)
        self._visible = False
        self._clearColor = Vec4(base.win.getClearColor())
        self._clearColor.setW(1.0)

    def destroy(self):
        self.setVisible(False)
        if hasattr(self, 'fog'):
            del self.fog

    def isVisible(self):
        return self._visible

    def setVisible(self, visible):
        self._visible = visible
        if self._visible:
            base.win.setClearColor(self.color)
            render.setFog(self.fog)
        else:
            base.win.setClearColor(self._clearColor)
            render.clearFog()
コード例 #2
0
ファイル: gamescene.py プロジェクト: drewp/blockstack
    def init(self):
        """setup calls that can be repeated on code reload"""
        self.resetNodes()

        self.base.setBackgroundColor(0, 0, 0)
        self.base.render.setShaderAuto() # pp shading
        self.base.render.setAttrib(
            AntialiasAttrib.make(AntialiasAttrib.MMultisample))
        
        if 1:
            cam = self.base.render.find("camera")
            # I don't know how to set cam position

            f = Fog("fog")
            f.setColor(0,0,0)
            f.setLinearRange(18, 25)
            self.base.render.setFog(f) 

            import videowall
            reload(videowall)
            self.videoWall = videowall.VideoWall(self.base.loader, self.base.render)

        self.cubes = self.base.render.attachNewNode(ModelNode("cubes"))
        self.cubes.setPos(-4.3, 18, -3)
        ground = self.makeGround(self.cubes)

        lights = self.base.render.attachNewNode("lights")
        self.makeLights(lights)

        self.centerMessageNode, self.cornerMessageNode = self.makeMessages()

        self.setLighting(self.currentLighting)
        self.base.render.ls()
コード例 #3
0
class CogdoFlyingLevelFog:

    def __init__(self, level, color = Globals.Level.FogColor):
        self._level = level
        self.color = color
        fogDistance = self._level.quadLengthUnits * max(1, self._level.quadVisibiltyAhead * 0.2)
        self.fog = Fog('RenderFog')
        self.fog.setColor(self.color)
        self.fog.setLinearRange(fogDistance * Globals.Level.RenderFogStartFactor, fogDistance)
        self._visible = False
        self._clearColor = Vec4(base.win.getClearColor())
        self._clearColor.setW(1.0)

    def destroy(self):
        self.setVisible(False)
        if hasattr(self, 'fog'):
            del self.fog

    def isVisible(self):
        return self._visible

    def setVisible(self, visible):
        self._visible = visible
        if self._visible:
            base.win.setClearColor(self.color)
            render.setFog(self.fog)
        else:
            base.win.setClearColor(self._clearColor)
            render.clearFog()
コード例 #4
0
    def init(self):
        """setup calls that can be repeated on code reload"""
        self.resetNodes()

        self.base.setBackgroundColor(0, 0, 0)
        self.base.render.setShaderAuto()  # pp shading
        self.base.render.setAttrib(
            AntialiasAttrib.make(AntialiasAttrib.MMultisample))

        if 1:
            cam = self.base.render.find("camera")
            # I don't know how to set cam position

            f = Fog("fog")
            f.setColor(0, 0, 0)
            f.setLinearRange(18, 25)
            self.base.render.setFog(f)

            import videowall
            reload(videowall)
            self.videoWall = videowall.VideoWall(self.base.loader,
                                                 self.base.render)

        self.cubes = self.base.render.attachNewNode(ModelNode("cubes"))
        self.cubes.setPos(-4.3, 18, -3)
        ground = self.makeGround(self.cubes)

        lights = self.base.render.attachNewNode("lights")
        self.makeLights(lights)

        self.centerMessageNode, self.cornerMessageNode = self.makeMessages()

        self.setLighting(self.currentLighting)
        self.base.render.ls()
コード例 #5
0
	def begin(self):
		base.setBackgroundColor( self.environment['colourBackground'] )

		alight = AmbientLight('AmbientLight')
		alight.setColor(self.environment['colourAmbient'] )
		alnp = self.sceneNode.attachNewNode(alight)
		self.sceneNode.setLight(alnp)

		if self.environment['fog']:
			fog = Fog( 'sceneName' )
			fog.setColor( self.environment['fog']['color'] )

			if self.environment['fog']['mode'] == "linear":
				fog.setLinearRange(self.environment['fog']['linearStart']*1000,self.environment['fog']['linearEnd']*1000)
			else:
				fog.setExpDensity( self.environment['fog']['expDensity'] )

			self.sceneNode.setFog(fog)

		[self.createNode(props) for props in self.nodes]
		[self.createLight(props) for props in self.lights]
		[self.createCamera(props) for props in self.cameras]
		[self.createEntity(props) for props in self.entities]
		# [self.createStaticGeoms(props) for props in self.staticGeoms]

		self.sceneNode.clearModelNodes()
		self.sceneNode.flattenStrong() 
		self.sceneNode.setShaderAuto()
コード例 #6
0
class Scene(NodePath):
    def __init__(self):
        super().__init__('scene')
        self.render = None
        self.world = None

        self.camera = None
        self.ui_camera = None

        self.entities = []
        self.hidden = NodePath('hidden')
        self.reflection_map = 'reflection_map_3'

    def set_up(self):
        from ursina.entity import Entity
        self.reparent_to(render)
        self.reflection_map = load_texture(self.reflection_map)

        self.fog = Fog('fog')
        self.setFog(self.fog)
        self.fog_color = color.light_gray
        self.fog_density = 0

    def clear(self):
        from ursina.ursinastuff import destroy
        to_destroy = [e for e in self.entities if not e.eternal]
        to_keep = [e for e in self.entities if e.eternal]

        for d in to_destroy:
            try:
                print('destroying:', d.name)
                destroy(d)
            except Exception as e:
                print('failed to destroy entity', e)

        self.entities = to_keep

        from ursina import application
        application.sequences.clear()

    @property
    def fog_color(self):
        return self.fog.getColor()

    @fog_color.setter
    def fog_color(self, value):
        self.fog.setColor(value)

    @property
    def fog_density(self):
        return self._fog_density

    @fog_density.setter  # set to a number for exponential density or (start, end) for linear.
    def fog_density(self, value):
        self._fog_density = value
        if isinstance(value, tuple):  # linear fog
            self.fog.setLinearRange(value[0], value[1])
        else:
            self.fog.setExpDensity(value)
コード例 #7
0
ファイル: robtest.py プロジェクト: dgou/gibson
    def __init__(self, *args, **kwargs):
        template.Panda.__init__(self, *args, **kwargs)
        print "Hurray!"

        self.cube = self.loader.loadModel("models/low-cube")
        self.cube.reparentTo(self.render)
        self.cube2 = self.loader.loadModel("models/low-cube")
        self.cube2.reparentTo(self.render)
        self.cube2.setPos(self.cube, 10,20,30)
        self.cube2.setHpr(175,3,45)

        self.taskMgr.add(self.update, "update")
        self.taskMgr.add(self.move, "move")
        self._dir = 1

        colour = (0.5,0.8,0.8)
        linfog = Fog("A linear-mode Fog node")
        linfog.setColor(*colour)
        linfog.setLinearRange(0,320)
        linfog.setLinearFallback(45,160,320)
        render.attachNewNode(linfog)
        render.setFog(linfog)
コード例 #8
0
def test2():
    startup = PandaStartup()
    PLight(color=(1, 1, 1, 1), position=vec3(3, -1, 4),
           size=0.1).apply(startup.render)
    PLight(color=(1, 1, 1, 1), position=vec3(0, -1, 4),
           size=0.1).apply(startup.render)

    fog = Fog('Fog')
    fog.setColor(0.2, 0.2, 0.2)
    fog.setLinearRange(0, 30)
    startup.render.setFog(fog)

    size = nar([7, 7, 0.01])
    ModelBox("floorBox", nar([-0.5, -2, -size[2]]), size, (0.4, 0.4, 0.4, 1),
             startup.render)

    models = world_model()
    for data in models:
        if 'box' in data['tag']:
            model = data['model']  # type: CollideBox
            ModelBox(data['id'], model.org, model.size, (0.7, 0.7, 0.7, 1),
                     startup.render)

    def spinCameraTask(task):
        self = startup
        angleDegrees = task.time * 30.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(40 * sin(angleRadians), -40.0 * cos(angleRadians),
                           3)
        self.camera.setHpr(angleDegrees, 0, 0)
        self.camera.look_at(0, 0, 3)
        # self.plight.setPos(10*sin(angleRadians), -10.0*cos(angleRadians), 3)
        time.sleep(1.0 / 80.0)
        return Task.cont

    # startup.task_mgr.add(spinCameraTask, 'spinCameraTask')
    startup.run()
コード例 #9
0
ファイル: Estate.py プロジェクト: DarthNihilus1/src
class Estate(Place.Place):
    notify = DirectNotifyGlobal.directNotify.newCategory('Estate')

    def __init__(self, loader, avId, zoneId, parentFSMState, doneEvent):
        Place.Place.__init__(self, None, doneEvent)
        self.id = MyEstate
        self.avId = avId
        self.zoneId = zoneId
        self.loader = loader
        self.cameraSubmerged = -1
        self.toonSubmerged = -1
        self.fsm = ClassicFSM.ClassicFSM('Estate', [
            State.State('init', self.enterInit, self.exitInit,
                        ['final', 'teleportIn', 'doorIn', 'walk']),
            State.State('petTutorial', self.enterPetTutorial,
                        self.exitPetTutorial, ['walk']),
            State.State('walk', self.enterWalk, self.exitWalk, [
                'final', 'sit', 'stickerBook', 'options', 'quest', 'fishing',
                'mailbox', 'stopped', 'DFA', 'trialerFA', 'doorOut', 'push',
                'pet', 'purchase'
            ]),
            State.State('stopped', self.enterStopped, self.exitStopped,
                        ['walk', 'teleportOut']),
            State.State('sit', self.enterSit, self.exitSit, ['walk']),
            State.State('push', self.enterPush, self.exitPush, ['walk']),
            State.State(
                'stickerBook', self.enterStickerBook, self.exitStickerBook, [
                    'walk', 'sit', 'quest', 'fishing', 'mailbox', 'stopped',
                    'doorOut', 'push', 'pet', 'DFA', 'trialerFA'
                ]),
            State.State('teleportIn', self.enterTeleportIn,
                        self.exitTeleportIn, ['walk', 'petTutorial']),
            State.State('teleportOut', self.enterTeleportOut,
                        self.exitTeleportOut, ['teleportIn', 'walk', 'final']),
            State.State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']),
            State.State('doorOut', self.enterDoorOut, self.exitDoorOut,
                        ['final', 'walk']),
            State.State('final', self.enterFinal, self.exitFinal,
                        ['teleportIn']),
            State.State('quest', self.enterQuest, self.exitQuest, ['walk']),
            State.State('fishing', self.enterFishing, self.exitFishing,
                        ['walk', 'stopped']),
            State.State('mailbox', self.enterMailbox, self.exitMailbox,
                        ['walk', 'stopped']),
            State.State('stopped', self.enterStopped, self.exitStopped,
                        ['walk']),
            State.State('pet', self.enterPet, self.exitPet,
                        ['walk', 'trialerFA']),
            State.State('trialerFA', self.enterTrialerFA, self.exitTrialerFA,
                        ['trialerFAReject', 'DFA']),
            State.State('trialerFAReject', self.enterTrialerFAReject,
                        self.exitTrialerFAReject, ['walk']),
            State.State('DFA', self.enterDFA, self.exitDFA,
                        ['DFAReject', 'teleportOut']),
            State.State('purchase', self.enterPurchase, self.exitPurchase,
                        ['walk']),
            State.State('DFAReject', self.enterDFAReject, self.exitDFAReject,
                        ['walk'])
        ], 'init', 'final')
        self.fsm.enterInitialState()
        self.doneEvent = doneEvent
        self.parentFSMState = parentFSMState
        return

    def delete(self):
        self.unload()

    def load(self):
        Place.Place.load(self)
        self.fog = Fog('EstateFog')
        taskMgr.add(self.__checkCameraUnderwater,
                    'estate-check-cam-underwater')
        path = self.loader.geom.find('**/Path')
        path.setBin('ground', 10, 1)
        self.parentFSMState.addChild(self.fsm)

    def unload(self):
        self.ignoreAll()
        self.notify.info(
            'remove estate-check-toon-underwater to TaskMgr in unload()')
        taskMgr.remove('estate-check-toon-underwater')
        taskMgr.remove('estate-check-cam-underwater')
        self.parentFSMState.removeChild(self.fsm)
        del self.fsm
        self.fog = None
        Place.Place.unload(self)
        return

    def enter(self, requestStatus):
        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        newsManager = base.cr.newsManager
        if config.GetBool('want-estate-telemetry-limiter', 1):
            limiter = TLGatherAllAvs('Estate', RotationLimitToH)
        else:
            limiter = TLNull()
        self._telemLimiter = limiter
        if newsManager:
            holidayIds = base.cr.newsManager.getDecorationHolidayId()
            if (ToontownGlobals.HALLOWEEN_COSTUMES in holidayIds
                    or ToontownGlobals.SPOOKY_COSTUMES
                    in holidayIds) and self.loader.hood.spookySkyFile:
                lightsOff = Sequence(
                    LerpColorScaleInterval(base.cr.playGame.hood.loader.geom,
                                           0.1, Vec4(0.55, 0.55, 0.65, 1)),
                    Func(self.loader.hood.startSpookySky))
                lightsOff.start()
            else:
                self.loader.hood.startSky()
                lightsOn = LerpColorScaleInterval(
                    base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
                lightsOn.start()
        else:
            self.loader.hood.startSky()
            lightsOn = LerpColorScaleInterval(
                base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
            lightsOn.start()
        self.loader.hood.sky.setFogOff()
        self.__setFaintFog()
        for i in self.loader.nodeList:
            self.loader.enterAnimatedProps(i)

        self.loader.geom.reparentTo(render)
        # The client April Toons Manager is currently broken, so we have to do this hacky thing instead. :(
        #if hasattr(base.cr, 'aprilToonsMgr'):
        #if self.isEventActive(AprilToonsGlobals.EventEstateGravity):
        #base.localAvatar.startAprilToonsControls()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.startAprilToonsControls()
        self.accept('doorDoneEvent', self.handleDoorDoneEvent)
        self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger)
        self.fsm.request(requestStatus['how'], [requestStatus])

    def exit(self):
        base.localAvatar.stopChat()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.stopAprilToonsControls()
        self._telemLimiter.destroy()
        del self._telemLimiter
        if hasattr(self, 'fsm'):
            self.fsm.requestFinalState()
        self.loader.geom.reparentTo(hidden)
        for i in self.loader.nodeList:
            self.loader.exitAnimatedProps(i)

        self.loader.hood.stopSky()
        render.setFogOff()
        base.cr.cache.flush()

    def __setZoneId(self, zoneId):
        self.zoneId = zoneId

    def detectedMailboxCollision(self):
        self.fsm.request('mailbox')

    def detectedGardenPlotUse(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('stopped')

    def detectedGardenPlotDone(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')

    def detectedFlowerSellUse(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('stopped')

    def detectedFlowerSellDone(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')

    def doRequestLeave(self, requestStatus):
        self.fsm.request('trialerFA', [requestStatus])

    def enterInit(self):
        pass

    def exitInit(self):
        pass

    def enterPurchase(self):
        Place.Place.enterPurchase(self)

    def exitPurchase(self):
        Place.Place.exitPurchase(self)

    def enterPetTutorial(self, bDummy=True):
        self.notify.info(
            'remove estate-check-toon-underwater to TaskMgr in enterPetTutorial()'
        )
        taskMgr.remove('estate-check-toon-underwater')
        self.petTutorialDoneEvent = 'PetTutorialDone'
        self.acceptOnce(self.petTutorialDoneEvent, self.petTutorialDone)
        self.petTutorial = PetTutorial.PetTutorial(self.petTutorialDoneEvent)

    def exitPetTutorial(self):
        self.notify.info(
            'add estate-check-toon-underwater to TaskMgr in exitPetTutorial()')
        if hasattr(self, 'fsm'):
            taskMgr.add(self.__checkToonUnderwater,
                        'estate-check-toon-underwater')
        if hasattr(self, 'petTutorial') and self.petTutorial is not None:
            self.petTutorial.destroy()
        return

    def petTutorialDone(self):
        self.ignore(self.petTutorialDoneEvent)
        self.petTutorial.destroy()
        self.petTutorial = None
        self.fsm.request('walk', [1])
        return

    def enterMailbox(self):
        Place.Place.enterPurchase(self)
        base.localAvatar.startSleepWatch(self.__handleFallingAsleepMailbox)
        self.enablePeriodTimer()

    def __handleFallingAsleepMailbox(self, arg):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')
        messenger.send('mailboxAsleep')
        base.localAvatar.forceGotoSleep()

    def exitMailbox(self):
        Place.Place.exitPurchase(self)
        base.localAvatar.stopSleepWatch()
        self.disablePeriodTimer()

    def enterTeleportIn(self, requestStatus):
        self._etiToken = self.addSetZoneCompleteCallback(
            Functor(self._teleportToHouse, requestStatus))
        Place.Place.enterTeleportIn(self, requestStatus)

    def _teleportToHouse(self, requestStatus):
        try:
            houseDo = base.cr.doId2do.get(base.localAvatar.houseId)
            house = houseDo.house
            pos = house.getPos(render)
            base.localAvatar.detachNode()
            base.localAvatar.setPosHpr(house, 17, 3, 0, 125, 0, 0)
        except:
            x, y, z, h, p, r = HouseGlobals.defaultEntryPoint
            base.localAvatar.detachNode()
            base.localAvatar.setPosHpr(render, x, y, z, h, p, r)

        base.localAvatar.setScale(1, 1, 1)
        self.toonSubmerged = -1
        self.notify.info(
            'remove estate-check-toon-underwater to TaskMgr in enterTeleportIn()'
        )
        taskMgr.remove('estate-check-toon-underwater')
        if base.wantPets:
            if base.localAvatar.hasPet(
            ) and not base.localAvatar.bPetTutorialDone:
                self.nextState = 'petTutorial'

    def teleportInDone(self):
        self.notify.debug('teleportInDone')
        self.toonSubmerged = -1
        if self.nextState is not 'petTutorial':
            self.notify.info(
                'add estate-check-toon-underwater to TaskMgr in teleportInDone()'
            )
            if hasattr(self, 'fsm'):
                taskMgr.add(self.__checkToonUnderwater,
                            'estate-check-toon-underwater')
        Place.Place.teleportInDone(self)

    def exitTeleportIn(self):
        self.removeSetZoneCompleteCallback(self._etiToken)
        Place.Place.exitTeleportIn(self)

    def enterTeleportOut(self, requestStatus):
        Place.Place.enterTeleportOut(self, requestStatus,
                                     self.__teleportOutDone)

    def __teleportOutDone(self, requestStatus):
        if hasattr(self, 'fsm'):
            self.fsm.requestFinalState()
        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        avId = requestStatus['avId']
        shardId = requestStatus['shardId']
        if hoodId == ToontownGlobals.MyEstate and zoneId == self.getZoneId(
        ) and shardId == None:
            self.fsm.request('teleportIn', [requestStatus])
        elif hoodId == ToontownGlobals.MyEstate and shardId == None:
            self.doneStatus = requestStatus
            self.getEstateZoneAndGoHome(requestStatus)
        else:
            self.doneStatus = requestStatus
            messenger.send(self.doneEvent, [self.doneStatus])
        return

    def goHomeFailed(self, task):
        self.notifyUserGoHomeFailed()
        self.ignore('setLocalEstateZone')
        self.doneStatus['avId'] = -1
        self.doneStatus['zoneId'] = self.getZoneId()
        self.fsm.request('teleportIn', [self.doneStatus])
        return Task.done

    def exitTeleportOut(self):
        Place.Place.exitTeleportOut(self)

    def exitDoorIn(self):
        self.toonSubmerged = -1
        self.notify.info(
            'add estate-check-toon-underwater to TaskMgr in exitDoorIn()')
        if hasattr(self, 'fsm'):
            taskMgr.add(self.__checkToonUnderwater,
                        'estate-check-toon-underwater')
        Place.Place.exitDoorIn(self)

    def getZoneId(self):
        if self.zoneId:
            return self.zoneId
        else:
            self.notify.warning('no zone id available')

    def __checkCameraUnderwater(self, task):
        if base.camera.getZ(render) < -1.2:
            self.__submergeCamera()
        else:
            self.__emergeCamera()
        return Task.cont

    def __checkToonUnderwater(self, task):
        if base.localAvatar.getZ() < -4.0:
            self.__submergeToon()
        else:
            self.__emergeToon()
        return Task.cont

    def __submergeCamera(self):
        if self.cameraSubmerged == 1:
            return
        self.__setUnderwaterFog()
        base.playSfx(self.loader.underwaterSound, looping=1, volume=0.8)
        self.cameraSubmerged = 1
        self.walkStateData.setSwimSoundAudible(1)

    def __emergeCamera(self):
        if self.cameraSubmerged == 0:
            return
        self.loader.underwaterSound.stop()
        self.loader.hood.sky.setFogOff()
        self.__setFaintFog()
        self.cameraSubmerged = 0
        self.walkStateData.setSwimSoundAudible(0)

    def forceUnderWater(self):
        self.toonSubmerged = 0
        self.__submergeToon()

    def __submergeToon(self):
        if self.toonSubmerged == 1:
            return
        self.notify.debug('continuing in __submergeToon')
        if hasattr(self, 'loader') and self.loader:
            base.playSfx(self.loader.submergeSound)
        if base.config.GetBool('disable-flying-glitch') == 0:
            self.fsm.request('walk')
        self.walkStateData.fsm.request('swimming', [self.loader.swimSound])
        pos = base.localAvatar.getPos(render)
        base.localAvatar.d_playSplashEffect(pos[0], pos[1], -2.3)
        self.toonSubmerged = 1

    def __emergeToon(self):
        if self.toonSubmerged == 0:
            return
        self.notify.debug('continuing in __emergeToon')
        if hasattr(self, 'walkStateData'):
            self.walkStateData.fsm.request('walking')
        self.toonSubmerged = 0
        # The client April Toons Manager is currently broken, so we have to do this hacky thing instead. :(
        #if hasattr(base.cr, 'aprilToonsMgr'):
        #if self.isEventActive(AprilToonsGlobals.EventEstateGravity):
        #base.localAvatar.startAprilToonsControls()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.startAprilToonsControls()

    def __setUnderwaterFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.0, 0.0, 0.6, 1.0))
            self.fog.setLinearRange(0.1, 100.0)
            render.setFog(self.fog)
            self.loader.hood.sky.setFog(self.fog)

    def __setWhiteFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
            self.fog.setLinearRange(0.0, 400.0)
            render.setFog(self.fog)
            self.loader.hood.sky.setFog(self.fog)

    def __setFaintFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
            self.fog.setLinearRange(0.0, 700.0)
            render.setFog(self.fog)
コード例 #10
0
class Estate(Place.Place):
    notify = DirectNotifyGlobal.directNotify.newCategory('Estate')

    def __init__(self, loader, avId, zoneId, parentFSMState, doneEvent):
        Place.Place.__init__(self, None, doneEvent)
        self.id = MyEstate
        self.avId = avId
        self.zoneId = zoneId
        self.loader = loader
        self.cameraSubmerged = -1
        self.toonSubmerged = -1
        self.fsm = ClassicFSM.ClassicFSM('Estate', [State.State('init', self.enterInit, self.exitInit, ['final',
          'teleportIn',
          'doorIn',
          'walk']),
         State.State('petTutorial', self.enterPetTutorial, self.exitPetTutorial, ['walk']),
         State.State('walk', self.enterWalk, self.exitWalk, ['final',
          'sit',
          'stickerBook',
          'options',
          'quest',
          'fishing',
          'mailbox',
          'stopped',
          'DFA',
          'trialerFA',
          'doorOut',
          'push',
          'pet',
          'purchase']),
         State.State('stopped', self.enterStopped, self.exitStopped, ['walk', 'teleportOut']),
         State.State('sit', self.enterSit, self.exitSit, ['walk']),
         State.State('push', self.enterPush, self.exitPush, ['walk']),
         State.State('stickerBook', self.enterStickerBook, self.exitStickerBook, ['walk',
          'sit',
          'quest',
          'fishing',
          'mailbox',
          'stopped',
          'doorOut',
          'push',
          'pet',
          'DFA',
          'trialerFA']),
         State.State('teleportIn', self.enterTeleportIn, self.exitTeleportIn, ['walk', 'petTutorial']),
         State.State('teleportOut', self.enterTeleportOut, self.exitTeleportOut, ['teleportIn', 'walk', 'final']),
         State.State('doorIn', self.enterDoorIn, self.exitDoorIn, ['walk']),
         State.State('doorOut', self.enterDoorOut, self.exitDoorOut, ['final', 'walk']),
         State.State('final', self.enterFinal, self.exitFinal, ['teleportIn']),
         State.State('quest', self.enterQuest, self.exitQuest, ['walk']),
         State.State('fishing', self.enterFishing, self.exitFishing, ['walk', 'stopped']),
         State.State('mailbox', self.enterMailbox, self.exitMailbox, ['walk', 'stopped']),
         State.State('stopped', self.enterStopped, self.exitStopped, ['walk']),
         State.State('pet', self.enterPet, self.exitPet, ['walk', 'trialerFA']),
         State.State('trialerFA', self.enterTrialerFA, self.exitTrialerFA, ['trialerFAReject', 'DFA']),
         State.State('trialerFAReject', self.enterTrialerFAReject, self.exitTrialerFAReject, ['walk']),
         State.State('DFA', self.enterDFA, self.exitDFA, ['DFAReject', 'teleportOut']),
         State.State('purchase', self.enterPurchase, self.exitPurchase, ['walk']),
         State.State('DFAReject', self.enterDFAReject, self.exitDFAReject, ['walk'])], 'init', 'final')
        self.fsm.enterInitialState()
        self.doneEvent = doneEvent
        self.parentFSMState = parentFSMState
        return

    def delete(self):
        self.unload()

    def load(self):
        Place.Place.load(self)
        self.fog = Fog('EstateFog')
        taskMgr.add(self.__checkCameraUnderwater, 'estate-check-cam-underwater')
        path = self.loader.geom.find('**/Path')
        path.setBin('ground', 10, 1)
        self.parentFSMState.addChild(self.fsm)

    def unload(self):
        self.ignoreAll()
        self.notify.info('remove estate-check-toon-underwater to TaskMgr in unload()')
        taskMgr.remove('estate-check-toon-underwater')
        taskMgr.remove('estate-check-cam-underwater')
        self.parentFSMState.removeChild(self.fsm)
        del self.fsm
        self.fog = None
        Place.Place.unload(self)
        return

    def enter(self, requestStatus):
        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        newsManager = base.cr.newsManager
        if config.GetBool('want-estate-telemetry-limiter', 1):
            limiter = TLGatherAllAvs('Estate', RotationLimitToH)
        else:
            limiter = TLNull()
        self._telemLimiter = limiter
        if newsManager:
            holidayIds = base.cr.newsManager.getDecorationHolidayId()
            if (ToontownGlobals.HALLOWEEN_COSTUMES in holidayIds or ToontownGlobals.SPOOKY_COSTUMES in holidayIds) and self.loader.hood.spookySkyFile:
                lightsOff = Sequence(LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(0.55, 0.55, 0.65, 1)), Func(self.loader.hood.startSpookySky))
                lightsOff.start()
            else:
                self.loader.hood.startSky()
                lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
                lightsOn.start()
        else:
            self.loader.hood.startSky()
            lightsOn = LerpColorScaleInterval(base.cr.playGame.hood.loader.geom, 0.1, Vec4(1, 1, 1, 1))
            lightsOn.start()
        self.loader.hood.sky.setFogOff()
        self.__setFaintFog()
        for i in self.loader.nodeList:
            self.loader.enterAnimatedProps(i)

        self.loader.geom.reparentTo(render)
        # The client April Toons Manager is currently broken, so we have to do this hacky thing instead. :(
        #if hasattr(base.cr, 'aprilToonsMgr'):
            #if self.isEventActive(AprilToonsGlobals.EventEstateGravity):
                #base.localAvatar.startAprilToonsControls()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.startAprilToonsControls()
        self.accept('doorDoneEvent', self.handleDoorDoneEvent)
        self.accept('DistributedDoor_doorTrigger', self.handleDoorTrigger)
        self.fsm.request(requestStatus['how'], [requestStatus])

    def exit(self):
        base.localAvatar.stopChat()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.stopAprilToonsControls()
        self._telemLimiter.destroy()
        del self._telemLimiter
        if hasattr(self, 'fsm'):
            self.fsm.requestFinalState()
        self.loader.geom.reparentTo(hidden)
        for i in self.loader.nodeList:
            self.loader.exitAnimatedProps(i)

        self.loader.hood.stopSky()
        render.setFogOff()
        base.cr.cache.flush()

    def __setZoneId(self, zoneId):
        self.zoneId = zoneId

    def detectedMailboxCollision(self):
        self.fsm.request('mailbox')

    def detectedGardenPlotUse(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('stopped')

    def detectedGardenPlotDone(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')

    def detectedFlowerSellUse(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('stopped')

    def detectedFlowerSellDone(self):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')

    def doRequestLeave(self, requestStatus):
        self.fsm.request('trialerFA', [requestStatus])

    def enterInit(self):
        pass

    def exitInit(self):
        pass

    def enterPurchase(self):
        Place.Place.enterPurchase(self)

    def exitPurchase(self):
        Place.Place.exitPurchase(self)

    def enterPetTutorial(self, bDummy = True):
        self.notify.info('remove estate-check-toon-underwater to TaskMgr in enterPetTutorial()')
        taskMgr.remove('estate-check-toon-underwater')
        self.petTutorialDoneEvent = 'PetTutorialDone'
        self.acceptOnce(self.petTutorialDoneEvent, self.petTutorialDone)
        self.petTutorial = PetTutorial.PetTutorial(self.petTutorialDoneEvent)

    def exitPetTutorial(self):
        self.notify.info('add estate-check-toon-underwater to TaskMgr in exitPetTutorial()')
        if hasattr(self, 'fsm'):
            taskMgr.add(self.__checkToonUnderwater, 'estate-check-toon-underwater')
        if hasattr(self, 'petTutorial') and self.petTutorial is not None:
            self.petTutorial.destroy()
        return

    def petTutorialDone(self):
        self.ignore(self.petTutorialDoneEvent)
        self.petTutorial.destroy()
        self.petTutorial = None
        self.fsm.request('walk', [1])
        return

    def enterMailbox(self):
        Place.Place.enterPurchase(self)
        base.localAvatar.startSleepWatch(self.__handleFallingAsleepMailbox)
        self.enablePeriodTimer()

    def __handleFallingAsleepMailbox(self, arg):
        if hasattr(self, 'fsm'):
            self.fsm.request('walk')
        messenger.send('mailboxAsleep')
        base.localAvatar.forceGotoSleep()

    def exitMailbox(self):
        Place.Place.exitPurchase(self)
        base.localAvatar.stopSleepWatch()
        self.disablePeriodTimer()

    def enterTeleportIn(self, requestStatus):
        self._etiToken = self.addSetZoneCompleteCallback(Functor(self._teleportToHouse, requestStatus))
        Place.Place.enterTeleportIn(self, requestStatus)

    def _teleportToHouse(self, requestStatus):
        try:
            houseDo = base.cr.doId2do.get(base.localAvatar.houseId)
            house = houseDo.house
            pos = house.getPos(render)
            base.localAvatar.detachNode()
            base.localAvatar.setPosHpr(house, 17, 3, 0, 125, 0, 0)
        except:
            x, y, z, h, p, r = HouseGlobals.defaultEntryPoint
            base.localAvatar.detachNode()
            base.localAvatar.setPosHpr(render, x, y, z, h, p, r)

        base.localAvatar.setScale(1, 1, 1)
        self.toonSubmerged = -1
        self.notify.info('remove estate-check-toon-underwater to TaskMgr in enterTeleportIn()')
        taskMgr.remove('estate-check-toon-underwater')
        if base.wantPets:
            if base.localAvatar.hasPet() and not base.localAvatar.bPetTutorialDone:
                self.nextState = 'petTutorial'

    def teleportInDone(self):
        self.notify.debug('teleportInDone')
        self.toonSubmerged = -1
        if self.nextState is not 'petTutorial':
            self.notify.info('add estate-check-toon-underwater to TaskMgr in teleportInDone()')
            if hasattr(self, 'fsm'):
                taskMgr.add(self.__checkToonUnderwater, 'estate-check-toon-underwater')
        Place.Place.teleportInDone(self)

    def exitTeleportIn(self):
        self.removeSetZoneCompleteCallback(self._etiToken)
        Place.Place.exitTeleportIn(self)

    def enterTeleportOut(self, requestStatus):
        Place.Place.enterTeleportOut(self, requestStatus, self.__teleportOutDone)

    def __teleportOutDone(self, requestStatus):
        if hasattr(self, 'fsm'):
            self.fsm.requestFinalState()
        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        avId = requestStatus['avId']
        shardId = requestStatus['shardId']
        if hoodId == ToontownGlobals.MyEstate and zoneId == self.getZoneId() and shardId == None:
            self.fsm.request('teleportIn', [requestStatus])
        elif hoodId == ToontownGlobals.MyEstate and shardId == None:
            self.doneStatus = requestStatus
            self.getEstateZoneAndGoHome(requestStatus)
        else:
            self.doneStatus = requestStatus
            messenger.send(self.doneEvent, [self.doneStatus])
        return

    def goHomeFailed(self, task):
        self.notifyUserGoHomeFailed()
        self.ignore('setLocalEstateZone')
        self.doneStatus['avId'] = -1
        self.doneStatus['zoneId'] = self.getZoneId()
        self.fsm.request('teleportIn', [self.doneStatus])
        return Task.done

    def exitTeleportOut(self):
        Place.Place.exitTeleportOut(self)

    def exitDoorIn(self):
        self.toonSubmerged = -1
        self.notify.info('add estate-check-toon-underwater to TaskMgr in exitDoorIn()')
        if hasattr(self, 'fsm'):
            taskMgr.add(self.__checkToonUnderwater, 'estate-check-toon-underwater')
        Place.Place.exitDoorIn(self)

    def getZoneId(self):
        if self.zoneId:
            return self.zoneId
        else:
            self.notify.warning('no zone id available')

    def __checkCameraUnderwater(self, task):
        if base.camera.getZ(render) < -1.2:
            self.__submergeCamera()
        else:
            self.__emergeCamera()
        return Task.cont

    def __checkToonUnderwater(self, task):
        if base.localAvatar.getZ() < -4.0:
            self.__submergeToon()
        else:
            self.__emergeToon()
        return Task.cont

    def __submergeCamera(self):
        if self.cameraSubmerged == 1:
            return
        self.__setUnderwaterFog()
        base.playSfx(self.loader.underwaterSound, looping=1, volume=0.8)
        self.cameraSubmerged = 1
        self.walkStateData.setSwimSoundAudible(1)

    def __emergeCamera(self):
        if self.cameraSubmerged == 0:
            return
        self.loader.underwaterSound.stop()
        self.loader.hood.sky.setFogOff()
        self.__setFaintFog()
        self.cameraSubmerged = 0
        self.walkStateData.setSwimSoundAudible(0)

    def forceUnderWater(self):
        self.toonSubmerged = 0
        self.__submergeToon()

    def __submergeToon(self):
        if self.toonSubmerged == 1:
            return
        self.notify.debug('continuing in __submergeToon')
        if hasattr(self, 'loader') and self.loader:
            base.playSfx(self.loader.submergeSound)
        if base.config.GetBool('disable-flying-glitch') == 0:
            self.fsm.request('walk')
        self.walkStateData.fsm.request('swimming', [self.loader.swimSound])
        pos = base.localAvatar.getPos(render)
        base.localAvatar.d_playSplashEffect(pos[0], pos[1], -2.3)
        self.toonSubmerged = 1

    def __emergeToon(self):
        if self.toonSubmerged == 0:
            return
        self.notify.debug('continuing in __emergeToon')
        if hasattr(self, 'walkStateData'):
            self.walkStateData.fsm.request('walking')
        self.toonSubmerged = 0
        # The client April Toons Manager is currently broken, so we have to do this hacky thing instead. :(
        #if hasattr(base.cr, 'aprilToonsMgr'):
            #if self.isEventActive(AprilToonsGlobals.EventEstateGravity):
                #base.localAvatar.startAprilToonsControls()
        if base.config.GetBool('want-april-toons'):
            base.localAvatar.startAprilToonsControls()

    def __setUnderwaterFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.0, 0.0, 0.6, 1.0))
            self.fog.setLinearRange(0.1, 100.0)
            render.setFog(self.fog)
            self.loader.hood.sky.setFog(self.fog)

    def __setWhiteFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
            self.fog.setLinearRange(0.0, 400.0)
            render.setFog(self.fog)
            self.loader.hood.sky.setFog(self.fog)

    def __setFaintFog(self):
        if base.wantFog:
            self.fog.setColor(Vec4(0.8, 0.8, 0.8, 1.0))
            self.fog.setLinearRange(0.0, 700.0)
            render.setFog(self.fog)
コード例 #11
0
ファイル: zonewalk.py プロジェクト: Cloudxtreme/spawn_tool
class World(DirectObject):

    def __init__(self):
        self.last_mousex = 0
        self.last_mousey = 0

        self.zone = None
        self.zone_reload_name = None
        
        self.winprops = WindowProperties( )

        # simple console output
        self.consoleNode = NodePath(PandaNode("console_root"))
        self.consoleNode.reparentTo(aspect2d)

        self.console_num_lines = 24
        self.console_cur_line = -1
        self.console_lines = []
        for i in range(0, self.console_num_lines):
            self.console_lines.append(OnscreenText(text='', style=1, fg=(1,1,1,1),
                        pos=(-1.3, .4-i*.05), align=TextNode.ALeft, scale = .035, parent = self.consoleNode))

        # Configuration
        self.consoleOut('zonewalk v.%s loading configuration' % VERSION)
        self.configurator = Configurator(self)
        cfg = self.configurator.config
        resaveRes = False
        if 'xres' in cfg:
            self.xres = int(cfg['xres'])
        else:
            self.xres = 1024
            resaveRes = True

        if 'yres' in cfg:
            self.yres = int(cfg['yres'])
        else:
            self.yres = 768
            resaveRes = True

        if resaveRes:
            self.saveDefaultRes()

        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.mouse_accum = MouseAccume( lambda: (self.xres_half,self.yres_half))

        self.eyeHeight = 7.0
        self.rSpeed = 80
        self.flyMode = 1

        # application window setup
        base.win.setClearColor(Vec4(0,0,0,1))
        self.winprops.setTitle( 'zonewalk')
        self.winprops.setSize(self.xres, self.yres) 
        
        base.win.requestProperties( self.winprops ) 
        base.disableMouse()

        # network test stuff
        self.login_client = None
        if 'testnet' in cfg:
            if cfg['testnet'] == '1':
                self.doLogin()
        
        # Post the instructions
        self.title = addTitle('zonewalk v.' + VERSION)
        self.inst0 = addInstructions(0.95, "[FLYMODE][1]")
        self.inst1 = addInstructions(-0.95, "Camera control with WSAD/mouselook. Press K for hotkey list, ESC to exit.")
        self.inst2 = addInstructions(0.9,  "Loc:")
        self.inst3 = addInstructions(0.85, "Hdg:")
        self.error_inst = addInstructions(0, '')
        self.kh = []
        
        self.campos = Point3(155.6, 41.2, 4.93)
        base.camera.setPos(self.campos)
        
        # Accept the application control keys: currently just esc to exit navgen       
        self.accept("escape", self.exitGame)
        self.accept("window-event", self.resizeGame)
        
        # Create some lighting
        ambient_level = .6
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(ambient_level, ambient_level, ambient_level, 1.0))
        render.setLight(render.attachNewNode(ambientLight))

        direct_level = 0.8
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0.0, 0.0, -1.0))
        directionalLight.setColor(Vec4(direct_level, direct_level, direct_level, 1))
        directionalLight.setSpecularColor(Vec4(direct_level, direct_level, direct_level, 1))
        render.setLight(render.attachNewNode(directionalLight))
        
        # create a point light that will follow our view point (the camera for now)
        # attenuation is set so that this point light has a torch like effect
        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        self.plight.setAttenuation(Point3(0.0, 0.0, 0.0002))
        
        self.plnp = base.camera.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 0)
        render.setLight(self.plnp)
        self.cam_light = 1
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, \
            "cam-right":0, "mouse3":0, "flymode":1 }

        # setup FOG
        self.fog_colour = (0.8,0.8,0.8,1.0)
        self.linfog = Fog("A linear-mode Fog node")
        self.linfog.setColor(self.fog_colour)
        self.linfog.setLinearRange(700, 980)         # onset, opaque distances as params
        # linfog.setLinearFallback(45,160,320)
        base.camera.attachNewNode(self.linfog)
        render.setFog(self.linfog)
        self.fog = 1
        
        # camera control
        self.campos = Point3(0, 0, 0)
        self.camHeading = 0.0
        self.camPitch = 0.0
        base.camLens.setFov(65.0)
        base.camLens.setFar(1200) 
        
        self.cam_speed = 0  # index into self.camp_speeds
        self.cam_speeds = [40.0, 80.0, 160.0, 320.0, 640.0]
        
        
        # Collision Detection for "WALKMODE"
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  The ray will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        
        self.cTrav = CollisionTraverser()
        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0.0, 0.0, 0.0)
        self.camGroundRay.setDirection(0,0,-1)      # straight down
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        # attach the col node to the camCollider dummy node
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)  
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)
        
        
        # Uncomment this line to see the collision rays
        # self.camGroundColNp.show()
       
        # Uncomment this line to show a visual representation of the 
        # collisions occuring
        # self.cTrav.showCollisions(render)
        
        # Add the spinCameraTask procedure to the task manager.
        # taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        taskMgr.add(self.camTask, "camTask")

        self.toggleControls(1)

        # need to step the task manager once to make our fake console work
        taskMgr.step()

    # CONSOLE ---------------------------------------------------------------------
    def consoleScroll(self):
        for i in range(0, self.console_num_lines-1):
            self.console_lines[i].setText(self.console_lines[i+1].getText())
            
    def consoleOut(self, text):
        print text  # output to stdout/log too

        if self.console_cur_line == self.console_num_lines-1:
            self.consoleScroll()
        elif self.console_cur_line < self.console_num_lines-1:
            self.console_cur_line += 1

        self.console_lines[self.console_cur_line].setText(text)

        taskMgr.step()
    
    def consoleOn(self):
        self.consoleNode.show()
        
    def consoleOff(self):
        self.consoleNode.hide()
        
    # User controls -----------------------------------------------------------
    def toggleControls(self, on):

        cfg = self.configurator.config

        if on == 1:
            self.accept("escape", self.exitGame)

            self.accept("1", self.setSpeed, ["speed", 0])
            self.accept("2", self.setSpeed, ["speed", 1])
            self.accept("3", self.setSpeed, ["speed", 2])
            self.accept("4", self.setSpeed, ["speed", 3])
            self.accept("5", self.setSpeed, ["speed", 4])

            self.accept("alt-f", self.fogToggle)

            self.accept(cfg['control_lighting'], self.camLightToggle)
            self.accept(cfg['control_help'], self.displayKeyHelp)
            self.accept(cfg['control_flymode'], self.toggleFlymode)
            self.accept(cfg['control_reload-zone'], self.reloadZone)
            # Deactivate this for now
            #self.accept("z", self.saveDefaultZone)
            self.accept(cfg['control_cam-left'], self.setKey, ["cam-left",1])
            self.accept(cfg['control_cam-right'], self.setKey, ["cam-right",1])
            self.accept(cfg['control_forward'], self.setKey, ["forward",1])
            # Mouse1 should be for clicking on objects
            #self.accept("mouse1", self.setKey, ["forward",1])
            self.accept("mouse3", self.setKey, ["mouse3",1])
            self.accept(cfg['control_backward'], self.setKey, ["backward",1])
        
            self.accept("k-up", self.hideKeyHelp)
            self.accept(cfg['control_cam-left']+"-up", self.setKey, ["cam-left",0])
            self.accept(cfg['control_cam-right']+"-up", self.setKey, ["cam-right",0])
            self.accept(cfg['control_forward']+"-up", self.setKey, ["forward",0])
            # Mouse1 should be for clicking on objects
            #self.accept("mouse1-up", self.setKey, ["forward",0])
            self.accept("mouse3-up", self.setKey, ["mouse3",0])
            self.accept(cfg['control_backward']+"-up", self.setKey, ["backward",0])
        else:
            messenger.clear()
            
    def setSpeed(self, key, value):
        self.cam_speed = value
        self.setFlymodeText()
        
    def fogToggle(self):
        if self.fog == 1:
            render.clearFog()
            base.camLens.setFar(100000) 
            self.fog = 0
        else:
            render.setFog(self.linfog)
            base.camLens.setFar(1200) 
            self.fog = 1
            
    def camLightToggle(self):
        if self.cam_light == 0:
            render.setLight(self.plnp)
            self.cam_light = 1
        else:
            render.clearLight(self.plnp)
            self.cam_light = 0
        
    def displayKeyHelp(self):
        self.kh = []
        msg = 'HOTKEYS:'
        pos = 0.75
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '------------------'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'W: camera fwd, S: camera bck, A: rotate view left, D: rotate view right'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '1-5: set camera movement speed'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'F: toggle Flymode/Walkmode'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'L: load a zone'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ALT-F: toggle FOG and FAR plane on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'T: toggle additional camera "torch" light on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'Z: set currently loaded zone as new startup default'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ESC: exit zonewalk'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
     
    def hideKeyHelp(self):
        for n in self.kh:
            n.removeNode()
                        
    def setFlymodeText(self):
        zname = ''
        if self.zone:
            zname = self.zone.name
            
        if self.flyMode == 0:
            self.inst0.setText("[WALKMODE][%i] %s" % (self.cam_speed+1, zname))
        else:
            self.inst0.setText("[FLYMODE][%i] %s " % (self.cam_speed+1, zname))
        
    def toggleFlymode(self):
        zname = ''
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.flyMode = 1
        else:
            self.flyMode = 0
            
        self.setFlymodeText()

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        base.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        base.camera.setHpr(angleDegrees, 0, 0)
        return task.cont


    def camTask(self, task):
        # query the mouse
        mouse_dx = 0
        mouse_dy = 0


        # if we have a mouse and the right button is depressed
        if base.mouseWatcherNode.hasMouse():
            if self.keyMap["mouse3"] != 0:
                self.mouse_accum.update()
            else:
                self.mouse_accum.reset()

        mouse_dx = self.mouse_accum.dx
        mouse_dy = self.mouse_accum.dy

        self.rXSpeed = fabs(self.mouse_accum.dx) * (self.cam_speed+1) * max(5 * 1000/self.xres,3)
        self.rYSpeed = fabs(self.mouse_accum.dy) * (self.cam_speed+1) * max(3 * 1000/self.yres,1)
            
        if (self.keyMap["cam-left"]!=0 or mouse_dx < 0):
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading += self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading += self.rSpeed * globalClock.getDt()

            if self.camHeading > 360.0:
                self.camHeading = self.camHeading - 360.0
        elif (self.keyMap["cam-right"]!=0 or mouse_dx > 0):
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading -= self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading -= self.rSpeed * globalClock.getDt()

            if self.camHeading < 0.0:
                self.camHeading = self.camHeading + 360.0
        else:
            self.rSpeed = 80

        if mouse_dy > 0:
            self.camPitch += self.rYSpeed * globalClock.getDt()
        elif mouse_dy < 0:
            self.camPitch -= self.rYSpeed * globalClock.getDt()
            
        # set camera heading and pitch
        base.camera.setHpr(self.camHeading, self.camPitch, 0)

        # viewer position (camera) movement control
        v = render.getRelativeVector(base.camera, Vec3.forward())
        if not self.flyMode:
            v.setZ(0.0)
        
        move_speed = self.cam_speeds[self.cam_speed]
        if self.keyMap["forward"] == 1:
            self.campos += v * move_speed * globalClock.getDt()
        if self.keyMap["backward"] == 1:
            self.campos -= v * move_speed * globalClock.getDt()            

        # actually move the camera
        lastPos = base.camera.getPos()
        base.camera.setPos(self.campos)
        # self.plnp.setPos(self.campos)      # move the point light with the viewer position

        # WALKMODE: simple collision detection
        # we simply check a ray from slightly below the "eye point" straight down
        # for geometry collisions and if there are any we detect the point of collision
        # and adjust the camera's Z accordingly
        if self.flyMode == 0:   
            # move the camera to where it would be if it made the move 
            # the colliderNode moves with it
            # base.camera.setPos(self.campos)
            # check for collissons
            self.cTrav.traverse(render)
            entries = []
            for i in range(self.camGroundHandler.getNumEntries()):
                entry = self.camGroundHandler.getEntry(i)
                entries.append(entry)
                # print 'collision'
            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))
                                     
            if (len(entries) > 0): # and (entries[0].getIntoNode().getName() == "terrain"):
                # print len(entries)
                self.campos.setZ(entries[0].getSurfacePoint(render).getZ()+self.eyeHeight)
            else:
                self.campos = lastPos
                base.camera.setPos(self.campos)
        
            #if (base.camera.getZ() < self.player.getZ() + 2.0):
            #    base.camera.setZ(self.player.getZ() + 2.0)


        # update loc and hpr display
        pos = base.camera.getPos()
        hpr = base.camera.getHpr()
        self.inst2.setText('Loc: %.2f, %.2f, %.2f' % (pos.getX(), pos.getY(), pos.getZ()))
        self.inst3.setText('Hdg: %.2f, %.2f, %.2f' % (hpr.getX(), hpr.getY(), hpr.getZ()))
        return task.cont

        
    def exitGame(self):           
        sys.exit(0)

    def resizeGame(self,win):
        props = base.win.getProperties() 
        self.xres = props.getXSize()
        self.yres = props.getYSize()
        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.saveDefaultRes()
                
    #Records the state of the arrow keys
    # this is used for camera control
    def setKey(self, key, value):
        self.keyMap[key] = value

    # -------------------------------------------------------------------------
    # this is the mythical MAIN LOOP :)
    def update(self):

        if self.zone_reload_name != None:
            self.doReload(self.zone_reload_name)
            self.zone_reload_name = None

        if self.zone != None:
            self.zone.update()

        taskMgr.step()
   
        if self.login_client != None:
            self.login_client.update()  
        
        
    # ZONE loading ------------------------------------------------------------
    
    # general zone loader driver
    # removes existing zone (if any) and load the new one 
    def loadZone(self, name, path):
        if path[len(path)-1] != '/':
            path += '/'

        if self.zone:
            self.zone.rootNode.removeNode()
            
        self.zone = Zone(self, name, path)
        error = self.zone.load()
        if error == 0:
            self.consoleOff()
            self.setFlymodeText()
            base.setBackgroundColor(self.fog_colour)
        
    def saveDefaultRes(self):
        cfg = self.configurator.config
        cfg['xres'] = str(self.xres)
        cfg['yres'] = str(self.yres)
        #self.configurator.saveConfig()

    # initial world load after bootup
    def load(self):       
        cfg = self.configurator.config
        
        if self.login_client != None:
            return
            
        zone_name = cfg['default_zone']
        basepath = cfg['basepath']
        self.loadZone(zone_name, basepath)
    

    # config save user interfacce
    def saveDefaultZone(self):
        if self.zone:
            cfg = self.configurator.config
            cfg['default_zone'] = self.zone.name
            #self.configurator.saveConfig()

    # zone reload user interface
    
    # this gets called from our update loop when it detects that zone_reload_name has been set
    # we do this in this convoluted fashion in order to keep the main loop taskMgr updates ticking
    # because otherwise our status console output at various stages during the zone load would not
    # be displayed. Yes, this is hacky.
    def doReload(self, name):
        cfg = self.configurator.config
        basepath = cfg['basepath']
        self.loadZone(name, basepath)

    # form dialog callback
    # this gets called from the form when the user has entered a something
    # (hopefully a correct zone short name)
    def reloadZoneDialogCB(self, name):
        self.frmDialog.end()
        self.zone_reload_name = name
        self.toggleControls(1)

    # this is called when the user presses "l"
    # it disables normal controls and fires up our query form dialog
    def reloadZone(self):
        base.setBackgroundColor((0,0,0))
        self.toggleControls(0)
        self.consoleOn()
        self.frmDialog = FileDialog(
            "Please enter the shortname of the zone you wish to load:", 
            "Examples: qrg, blackburrow, freportn, crushbone etc.",
            self.reloadZoneDialogCB) 
        
        self.frmDialog.activate()   # relies on the main update loop to run

    ###############################
    # EXPERIMENTAL         
    def doLogin(self):
        
        self.login_client = UDPClientStream('127.0.0.1', 5998)

    #####################################
    # Custom methods
    #####################################


    # What happens when a user clicks on a model
    def onModelClick():
        # Code adapted freely from http://www.panda3d.org/forums/viewtopic.php?t=12717
        global picker, selected_model
        namedNode, thePoint, rawNode = picker.pick()
        if namedNode:
            if "_mesh" not in namedNode.getName():  # rough test to avoid printing infos on global zone mesh (ie: "freporte_mesh")
                name = namedNode.getName()
                p = namedNode.getParent()
                pos = p.getPos()
                selected_model = namedNode
                print namedNode.getName()
                print "Collision Point: ", thePoint

                namedNode.ls()
            else:
                print "Clicked location point (y, x, z):", thePoint
                #selected_model.setPos(thePoint.getX(), thePoint.getY(), thePoint.getZ())

                m.setPos(thePoint.getX(), thePoint.getY(), thePoint.getZ())
                print "Moved !"

    # Handles populating the zone with spawn data from the EQEmu DB
    # also makes each spawner model pickable
    def PopulateSpawns(self, cursor, numrows):
        spawn_coords = list()
        globals.model_list = list()
        for x in range(0, numrows):
            row = cursor.fetchone()
            point = Point3(long(row["Spawn2Y"]), long(row["Spawn2X"]), long(row["Spawn2Z"]))
            if point not in spawn_coords:
                s = loader.loadModel("models/cube.egg")
                s.reparentTo(render)
                s.setPos(row["Spawn2Y"], row["Spawn2X"], row["Spawn2Z"])
                min,macks= s.getTightBounds()
                radius = max([macks.getY() - min.getY(), macks.getX() - min.getX()])/2
                cs = CollisionSphere(row["Spawn2X"], row["Spawn2Y"], row["Spawn2Z"], radius)
                csNode = s.attachNewNode(CollisionNode("modelCollide"))
                csNode.node().addSolid(cs)
                s.setTag("name", row["name"])
                picker.makePickable(s)
                globals.model_list.append(s)
                spawn_coords.append(point)

    # Establishes a connection to the EQEmu database
    def ConnectToDatabase(self):
        configurator = Configurator(world)
        cfg = configurator.config
        conn = MySQLdb.Connection(
            host=cfg['host'],
            user=cfg['user'],
            passwd=cfg['password'],
            db=cfg['db'])

        return conn

    # Queries the Database in order to get spawn data
    # (this should be refactored at some point)
    def GetDbSpawnData(self, connection):
        cursor = connection.cursor(MySQLdb.cursors.DictCursor)

        query = """SELECT nt.name, s2.zone, s2.x as Spawn2X, s2.y as Spawn2Y, s2.z as Spawn2Z, sg.name as spawngroup_name,sg.id as Spawngroup_id, sg.min_x as Spawngroup_minX, sg.max_x as Spawngroup_maxX, sg.min_y as Spawngroup_minY, sg.max_y as Spawngroup_maxY, sg.dist as Spawngroup_dist, sg.mindelay as Spawngroup_mindelay,
                sg.delay as Spawngroup_delay FROM spawn2 s2
                JOIN spawngroup sg ON sg.id = s2.spawngroupid
                JOIN spawnentry se
                ON se.spawngroupid = sg.id
                JOIN npc_types nt
                ON nt.id = se.npcid
                WHERE s2.zone = 'freporte'"""
        cursor.execute(query)
        return cursor

    # Initializes the camera position upon startup
    def InitCameraPosition(self):
        world.campos = Point3(-155.6, 41.2, 4.9 + world.eyeHeight)
        world.camHeading = 270.0

        base.camera.setPos(world.campos)

    def GetCamera(self):
        return base.camera
コード例 #12
0
class CogdoBarrelRoom:
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCogdoBarrelRoom')

    def __init__(self):
        self.timer = None
        self.model = None
        self._isLoaded = False
        self.dummyElevInNode = None
        self.cogdoBarrelsNode = None
        self.entranceNode = None
        self.nearBattleNode = None
        self.rewardUi = None
        self.rewardUiTaskName = 'CogdoBarrelRoom-RewardUI'
        self.rewardCameraTaskName = 'CogdoBarrelRoom-RewardCamera'
        self.fog = None
        self.defaultFar = None
        self.stomperSfx = None
        return

    def destroy(self):
        self.unload()

    def load(self):
        if self._isLoaded:
            return
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.stash()
        self.model = loader.loadModel(CogdoBarrelRoomConsts.BarrelRoomModel)
        self.model.setPos(*CogdoBarrelRoomConsts.BarrelRoomModelPos)
        self.model.reparentTo(render)
        self.model.stash()
        self.dummyElevInNode = self.model.attachNewNode('elevator-in')
        self.dummyElevInNode.hide()
        self.entranceNode = self.model.attachNewNode('door-entrance')
        self.entranceNode.setPos(0, -65, 0)
        self.nearBattleNode = self.model.attachNewNode('near-battle')
        self.nearBattleNode.setPos(0, -25, 0)
        self.rewardUi = CogdoBarrelRoomRewardPanel.CogdoBarrelRoomRewardPanel()
        self.hideRewardUi()
        self.stomperSfx = base.loadSfx(CogdoBarrelRoomConsts.StomperSound)
        self.fog = Fog('barrel-room-fog')
        self.fog.setColor(CogdoBarrelRoomConsts.BarrelRoomFogColor)
        self.fog.setLinearRange(*CogdoBarrelRoomConsts.BarrelRoomFogLinearRange)
        self._isLoaded = True

    def unload(self):
        if self.model:
            self.model.removeNode()
            self.model = None
        if self.timer:
            self.timer.destroy()
            self.timer = None
        if self.rewardUi:
            self.rewardUi.destroy()
            self.rewardUi = None
        if self.fog:
            render.setFogOff()
            del self.fog
        taskMgr.remove(self.rewardUiTaskName)
        taskMgr.remove(self.rewardCameraTaskName)
        self._isLoaded = False
        return

    def isLoaded(self):
        return self._isLoaded

    def show(self):
        if not self.cogdoBarrelsNode:
            self.cogdoBarrelsNode = render.find('**/@@CogdoBarrels')
            self.cogdoBarrelsNode.reparentTo(self.model)
            self.cogdoBarrelsNode.unstash()
        self.defaultFar = base.camLens.getFar()
        base.camLens.setFar(CogdoBarrelRoomConsts.BarrelRoomCameraFar)
        self.showBattleAreaLight(True)
        render.setFog(self.fog)
        self.model.unstash()

    def hide(self):
        self.model.stash()
        render.setFogOff()
        if self.defaultFar is not None:
            base.camLens.setFar(self.defaultFar)
        return

    def activate(self):
        self.notify.info('Activating barrel room: %d sec timer.' % CogdoBarrelRoomConsts.CollectionTime)
        self.timer.unstash()
        self.timer.posAboveShtikerBook()
        self.timer.countdown(CogdoBarrelRoomConsts.CollectionTime)
        base.cr.playGame.getPlace().fsm.request('walk')

    def deactivate(self):
        self.notify.info('Deactivating barrel room.')
        self.timer.stop()
        self.timer.stash()

    def placeToonsAtEntrance(self, toons):
        for i in xrange(len(toons)):
            toons[i].setPosHpr(self.entranceNode, *CogdoBarrelRoomConsts.BarrelRoomPlayerSpawnPoints[i])

    def placeToonsNearBattle(self, toons):
        for i in xrange(len(toons)):
            toons[i].setPosHpr(self.nearBattleNode, *CogdoBarrelRoomConsts.BarrelRoomPlayerSpawnPoints[i])

    def showBattleAreaLight(self, visible = True):
        lightConeNode = self.model.find('**/battleCone')
        if lightConeNode != None and not lightConeNode.isEmpty():
            if visible:
                lightConeNode.show()
            else:
                lightConeNode.hide()
        return

    def getIntroInterval(self):
        avatar = base.localAvatar
        trackName = '__introBarrelRoom-%d' % avatar.doId
        track = Parallel(name=trackName)
        track.append(self.__stomperIntervals())
        track.append(Sequence(Func(base.camera.reparentTo, render), Func(base.camera.setPosHpr, self.model, -20.0, -87.9, 12.0, -30, 0, 0), Func(base.transitions.irisIn, 0.5), Wait(1.0), LerpHprInterval(base.camera, duration=2.0, startHpr=Vec3(-30, 0, 0), hpr=Vec3(0, 0, 0), blendType='easeInOut'), Wait(2.5), LerpHprInterval(base.camera, duration=3.0, startHpr=Vec3(0, 0, 0), hpr=Vec3(-45, 0, 0), blendType='easeInOut'), Wait(2.5)))
        track.delayDelete = DelayDelete.DelayDelete(avatar, 'introBarrelRoomTrack')
        track.setDoneEvent(trackName)
        return (track, trackName)

    def __stomperIntervals(self):
        ivals = [SoundInterval(self.stomperSfx)]
        i = 0
        for stomperDef in CogdoBarrelRoomConsts.StomperProps:
            stomperNode = render.find(stomperDef['path'])
            if stomperNode:
                maxZ = random.uniform(10, 20)
                minZ = maxZ - 10
                if stomperDef['motion'] == 'up':
                    startZ, destZ = minZ, maxZ
                else:
                    startZ, destZ = maxZ, minZ
                stomperNode.setPos(Point3(0, 0, startZ))
                ivals.append(LerpPosInterval(stomperNode, CogdoBarrelRoomConsts.StomperHaltTime, Point3(0, 0, destZ), blendType='easeOut'))
            i += 1

        return Parallel(*tuple(ivals))

    def __rewardUiTimeout(self, callback):
        self.hideRewardUi()
        if callback is not None:
            callback()
        return

    def __rewardCamera(self):
        trackName = 'cogdoBarrelRoom-RewardCamera'
        track = Sequence(Func(base.camera.reparentTo, render), Func(base.camera.setPosHpr, self.model, 0, 0, 11.0, 0, -14, 0), Func(self.showBattleAreaLight, False), name=trackName)
        return (track, trackName)

    def showRewardUi(self, results, callback = None):
        track, trackName = self.__rewardCamera()
        if CogdoBarrelRoomConsts.ShowRewardUI:
            self.rewardUi.setRewards(results)
            self.rewardUi.unstash()
        taskMgr.doMethodLater(CogdoBarrelRoomConsts.RewardUiTime, self.__rewardUiTimeout, self.rewardUiTaskName, extraArgs=[callback])
        return (track, trackName)

    def setRewardResults(self, results):
        self.rewardUi.setRewards(results)

    def hideRewardUi(self):
        self.rewardUi.stash()
        taskMgr.remove(self.rewardUiTaskName)
コード例 #13
0
class VisualTest(ShowBase):
    def __init__(self):
        super().__init__(self)
        self.var1 = 0
        self.scene = loader.loadModel("models/world")
        playerTexture = loader.loadTexture("models/starfoxShip.jpg")
        self.player = self.scene.find("player")
        self.player.setTexture(playerTexture)

        base.setBackgroundColor(0.1, 0.1, 0.1, 1)
        enemyTexture = loader.loadTexture("models/enemyShip.jpg")
        self.enemy = self.scene.find("enemy1")
        self.enemy.setTexture(enemyTexture)

        self.basePlane = self.scene.find("basePlane")

        self.scene.reparentTo(self.render)
        self.player.setPos(50, 50, 3)
        self.enemy.setPos(50, 55, 0)

        self.ambient = AmbientLight("ambient")
        self.ambient.color = (0.1, 0.1, 0.1, 1)
        self.ambientPath = self.render.attachNewNode(self.ambient)
        render.setLight(self.ambientPath)

        self.dirLight = DirectionalLight("dir light")
        self.dirLight.color = (1, 1, 1, 1)
        self.dirLightPath = self.render.attachNewNode(self.dirLight)
        self.dirLightPath.setHpr(0, -90, 0)
        self.dirLight.setShadowCaster(True, 512, 512)
        render.setLight(self.dirLightPath)

        self.pointLight = PointLight("point light")
        self.pointLight.color = (1, 1, 1, 1)
        self.pointLightPath = self.render.attachNewNode(self.pointLight)
        self.pointLightPath.setPos(50, 52.5, 4)
        self.pointLight.attenuation = (.5, 0, 0)
        self.pointLight.setShadowCaster(True, 1024, 1024)
        self.render.setLight(self.pointLightPath)

        self.fog = Fog("fog")
        self.fog.setColor(0.1, 0.1, 0.1)
        self.fog.setExpDensity(.3)
        self.fog.setLinearRange(150, 300)
        self.fog.setLinearFallback(45, 160, 320)
        self.render.setFog(self.fog)

        self.render.setShaderAuto()
        self.render.setAntialias(AntialiasAttrib.MAuto)

        filters = CommonFilters(base.win, base.cam)
        filters.setBloom(size="large")
        filters.setAmbientOcclusion(strength=0.6, falloff=0.0005, radius=0.1)
        filters.setCartoonInk(separation=2, color=(0, 0, 0, 1))
        self.taskMgr.add(self.update, "update")

    def update(self, evt):
        self.var1 = self.var1 + 0.1
        #self.dirLight.color = (self.var1,0,1,1)
        #self.dirLightPath.setHpr(self.var1,-self.var1,0)
        self.camera.setPos(60 + self.var1, 60 + self.var1, 20)
        #self.pointLightPath.setPos(30+self.var1 ,52.5,4)
        self.camera.lookAt(self.player)

        return Task.cont
コード例 #14
0
class DistributedRace(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedRace')
    ReadyPost = 'RaceReady'
    WinEvent = 'RaceWinEvent'
    BGM_BaseDir = 'phase_6/audio/bgm/'
    SFX_BaseDir = 'phase_6/audio/sfx/'
    SFX_StartBoop = SFX_BaseDir + 'KART_raceStart1.ogg'
    SFX_StartBoop2 = SFX_BaseDir + 'KART_raceStart2.ogg'
    SFX_Applause = SFX_BaseDir + 'KART_Applause_%d.ogg'

    def __init__(self, cr):
        self.qbox = loader.loadModel('phase_6/models/karting/qbox')
        self.boostArrowTexture = loader.loadTexture('phase_6/maps/boost_arrow.jpg', 'phase_6/maps/boost_arrow_a.rgb')
        self.boostArrowTexture.setMinfilter(Texture.FTLinear)
        DistributedObject.DistributedObject.__init__(self, cr)
        self.kartMap = {}
        self.fsm = ClassicFSM.ClassicFSM('Race', [State.State('join', self.enterJoin, self.exitJoin, ['prep', 'leave']),
         State.State('prep', self.enterPrep, self.exitPrep, ['tutorial', 'leave']),
         State.State('tutorial', self.enterTutorial, self.exitTutorial, ['start', 'waiting', 'leave']),
         State.State('waiting', self.enterWaiting, self.exitWaiting, ['start', 'leave']),
         State.State('start', self.enterStart, self.exitStart, ['racing', 'leave']),
         State.State('racing', self.enterRacing, self.exitRacing, ['finished', 'leave']),
         State.State('finished', self.enterFinished, self.exitFinished, ['leave']),
         State.State('leave', self.enterLeave, self.exitLeave, [])], 'join', 'leave')
        self.gui = RaceGUI(self)
        base.race = self
        self.currT = 0
        self.currLapT = 0
        self.currGag = 0
        self.tdelay = 0
        self.finished = False
        self.thrownGags = []
        self.effectManager = EffectManager.EffectManager()
        self.piejectileManager = PiejectileManager.PiejectileManager()
        self.lastTimeUpdate = globalClock.getFrameTime()
        self.initGags()
        self.canShoot = True
        self.isUrbanTrack = False
        self.hasFog = False
        self.dummyNode = None
        self.fog = None
        self.bananaSound = base.loadSfx('phase_6/audio/sfx/KART_tossBanana.ogg')
        self.anvilFall = base.loadSfx('phase_6/audio/sfx/KART_Gag_Hit_Anvil.ogg')
        self.accept('leaveRace', self.leaveRace)
        self.toonsToLink = []
        self.curveTs = []
        self.curvePoints = []
        self.localKart = None
        self.musicTrack = None
        self.victory = None
        self.miscTaskNames = []
        self.boostDir = {}
        self.knownPlace = {}
        self.placeFixup = []
        self.curve = None
        self.barricadeSegments = 100.0
        self.outerBarricadeDict = {}
        self.innerBarricadeDict = {}
        self.maxLap = 0
        self.oldT = 0
        self.debugIt = 0
        self.startPos = None
        return

    def generate(self):
        self.notify.debug('generate: %s' % self.doId)
        DistributedObject.DistributedObject.generate(self)
        bboard.post('race', self)
        self.roomWatcher = None
        self.cutoff = 0.01
        self.startBoopSfx = base.loadSfx(self.SFX_StartBoop)
        self.startBoop2Sfx = base.loadSfx(self.SFX_StartBoop2)
        return

    def announceGenerate(self):
        self.notify.debug('announceGenerate: %s' % self.doId)
        DistributedObject.DistributedObject.announceGenerate(self)
        musicFile = self.BGM_BaseDir + RaceGlobals.TrackDict[self.trackId][7]
        self.raceMusic = base.loadMusic(musicFile)
        base.playMusic(self.raceMusic, looping=1, volume=0.8)
        base.camera.reparentTo(render)
        if self.trackId in (RaceGlobals.RT_Urban_1,
         RaceGlobals.RT_Urban_1_rev,
         RaceGlobals.RT_Urban_2,
         RaceGlobals.RT_Urban_2_rev):
            self.isUrbanTrack = True
        self.oldFarPlane = base.camLens.getFar()
        base.camLens.setFar(12000)
        localAvatar.startPosHprBroadcast()
        localAvatar.d_broadcastPositionNow()
        DistributedSmoothNode.activateSmoothing(1, 1)
        self.reversed = self.trackId / 2.0 > int(self.trackId / 2.0)
        for i in xrange(3):
            base.loader.tick()

        self.sky = loader.loadModel('phase_3.5/models/props/TT_sky')
        self.sky.setPos(0, 0, 0)
        self.sky.setScale(20.0)
        self.sky.setFogOff()
        if self.trackId in (RaceGlobals.RT_Urban_1,
         RaceGlobals.RT_Urban_1_rev,
         RaceGlobals.RT_Urban_2,
         RaceGlobals.RT_Urban_2_rev):
            self.loadFog()
        self.setupGeom()
        self.startSky()
        for i in xrange(5):
            base.loader.tick()

    def disable(self):
        self.notify.debug('disable %s' % self.doId)
        if self.musicTrack:
            self.musicTrack.finish()
        self.raceMusic.stop()
        self.stopSky()
        if self.sky is not None:
            self.sky.removeNode()
        if self.dummyNode:
            self.dummyNode.removeNode()
            self.dummyNode = None
        for taskName in self.miscTaskNames:
            taskMgr.remove(taskName)

        taskMgr.remove('raceWatcher')
        self.ignoreAll()
        DistributedSmoothNode.activateSmoothing(1, 0)
        if self.isUrbanTrack:
            self.unloadUrbanTrack()
        if self.fog:
            render.setFogOff()
            del self.fog
            self.fog = None
        if self.geom is not None:
            self.geom.hide()
        base.camLens.setFar(self.oldFarPlane)
        DistributedObject.DistributedObject.disable(self)
        return

    def delete(self):
        self.notify.debug('delete %s' % self.doId)
        if self.gui:
            self.gui.destroy()
            self.gui = None
        if self.geom is not None:
            self.geom.removeNode()
            self.geom = None
            for i in self.gags:
                i.delete()
                del i

        self.piejectileManager.delete()
        if self.curveTs:
            del self.curveTs
        if self.curvePoints:
            del self.curvePoints
        if self.curve:
            del self.curve
        if self.victory:
            del self.victory
        del self.fsm
        del self.anvilFall
        del self.bananaSound
        del self.localKart
        DistributedObject.DistributedObject.delete(self)
        taskMgr.remove(self.uniqueName('countdownTimerTask'))
        taskMgr.remove('raceWatcher')
        bboard.remove('race')
        self.ignoreAll()
        del base.race
        return

    def d_requestThrow(self, x, y, z):
        self.sendUpdate('requestThrow', [x, y, z])

    def d_requestKart(self):
        self.sendUpdate('requestKart', [])

    def waitingForJoin(self):
        self.notify.debug('I got the barrier')
        self.fsm.enterInitialState()

    def racerDisconnected(self, avId):
        self.notify.debug('lost racer: %s' % avId)
        if avId in self.kartMap:
            if avId in self.toonsToLink:
                self.toonsToLink.remove(avId)
            toon = base.cr.doId2do.get(avId, None)
            kart = base.cr.doId2do.get(self.kartMap.get(avId, None), None)
            self.avIds.remove(avId)
            del self.kartMap[avId]
            self.gui.racerLeft(avId, unexpected=True)
            if kart:
                kart.reparentTo(hidden)
            if toon:
                toon.reparentTo(hidden)
            if len(self.toonsToLink) == 0:
                self.doneBarrier('waitingForPrep')
        return

    def setPlace(self, avId, totalTime, place, entryFee, qualify, winnings, bonus, trophies, circuitPoints, circuitTime):
        if self.fsm.getCurrentState().getName() == 'leaving':
            return
        if avId == localAvatar.doId:
            cheerToPlay = place + (4 - self.numRacers)
            if cheerToPlay > 4:
                cheerToPlay = 4
            self.victory = base.loadSfx(self.SFX_Applause % cheerToPlay)
            self.victory.play()
        self.knownPlace[avId] = place
        kart = base.cr.doId2do.get(self.kartMap.get(avId, None), None)
        avatar = base.cr.doId2do.get(avId, None)
        if avatar:
            self.gui.racerFinished(avId, self.trackId, place, totalTime, entryFee, qualify, winnings, bonus, trophies, circuitPoints, circuitTime)
            taskName = 'hideAv: %s' % avId
            taskMgr.doMethodLater(6, avatar.reparentTo, taskName, extraArgs=[hidden])
            self.miscTaskNames.append(taskName)
        if kart:
            taskName = 'hideKart: %s' % self.localKart.doId
            taskMgr.doMethodLater(6, kart.reparentTo, taskName, extraArgs=[hidden])
            self.miscTaskNames.append(taskName)
        return

    def setCircuitPlace(self, avId, place, entryFee, winnings, bonus, trophies):
        print 'setting cicruit place'
        if self.fsm.getCurrentState().getName() == 'leaving':
            return
        if avId == localAvatar.doId:
            cheerToPlay = place + (4 - self.numRacers)
            self.victory = base.loadSfx(self.SFX_Applause % cheerToPlay)
            self.victory.play()
        oldPlace = 0
        if self.knownPlace.get(avId):
            oldPlace = self.knownPlace[avId]
            self.placeFixup.append([oldPlace - 1, place - 1])
        avatar = base.cr.doId2do.get(avId, None)
        if avatar:
            print 'circuit trophies %s' % trophies
            print 'winnings %s' % winnings
            self.gui.racerFinishedCircuit(avId, oldPlace, entryFee, winnings, bonus, trophies)
        return

    def endCircuitRace(self):
        print self.placeFixup
        self.gui.circuitFinished(self.placeFixup)

    def prepForRace(self):
        self.fsm.request('prep')

    def startRace(self, startTime = 0):
        self.baseTime = globalClockDelta.networkToLocalTime(startTime)
        self.fsm.request('start')

    def startTutorial(self):
        self.fsm.request('tutorial')

    def genGag(self, slot, number, type):
        self.notify.debug('making gag...')
        if not self.gags[slot].isActive():
            self.gags[slot].genGag(number, type)

    def dropAnvilOn(self, ownerId, avId, timeStamp):
        kart = base.cr.doId2do.get(self.kartMap.get(avId, None), None)
        if kart:
            if avId != ownerId:
                if avId == localAvatar.doId:
                    self.anvilFall.play()
                    kart.dropOnMe(timeStamp)
                else:
                    kart.dropOnHim(timeStamp)
        return

    def shootPiejectile(self, sourceId, targetId, type = 0):
        kart = base.cr.doId2do.get(self.kartMap.get(sourceId, None), None)
        if kart:
            self.piejectileManager.addPiejectile(sourceId, targetId, type)
        return

    def goToSpeedway(self, avIds, reason = RaceGlobals.Exit_UserReq):
        self.notify.debug('goToSpeedway %s %s' % (avIds, reason))
        if localAvatar.doId in avIds:
            base.loader.endBulkLoad('atRace')
            self.kartCleanup()
            self.doneBarrier('waitingForExit')
            self.sendUpdate('racerLeft', [localAvatar.doId])
            out = {'loader': 'safeZoneLoader',
             'where': 'playground',
             'how': 'teleportIn',
             'hoodId': localAvatar.lastHood,
             'zoneId': localAvatar.lastHood,
             'shardId': None,
             'avId': -1,
             'reason': reason}
            base.cr.playGame.fsm.request('quietZone', [out])
        return

    def kartCleanup(self):
        kart = self.localKart
        if kart:
            kart.setState('P', 0)
            for i in self.avIds:
                if i != localAvatar.doId:
                    toon = base.cr.doId2do.get(i, None)
                    if toon:
                        toon.stopSmooth()
                        toon.setScale(1)
                        toon.setShear(0, 0, 0)
                        toon.reparentTo(render)
                        kart.doHeadScale(toon, None)

        localAvatar.setPos(0, 14, 0)
        localAvatar.sendCurrentPosition()
        return

    def heresMyT(self, avId, avNumLaps, avTime, timestamp):
        self.gui.updateRacerInfo(avId, curvetime=avNumLaps + avTime)

    def setZoneId(self, zoneId):
        self.zoneId = zoneId

    def setRaceType(self, raceType):
        self.raceType = raceType

    def setCircuitLoop(self, circuitLoop):
        self.circuitLoop = circuitLoop

    def setTrackId(self, id):
        DistributedRace.notify.debug('setTrackId: %s' % id)
        self.trackId = id

    def setAvatars(self, avIds):
        ids = ''
        for i in avIds:
            ids += str(i) + ' '

        DistributedRace.notify.debug('setAvatars: %s' % ids)
        self.avIds = avIds
        self.avT = [0] * len(self.avIds)

    def setLapCount(self, lapCount):
        self.lapCount = lapCount

    def setStartingPlaces(self, startList):
        self.startingPlaces = startList

    def enterJoin(self):
        self.doneBarrier('waitingForJoin')
        self.notify.debug('entering Join')

    def exitJoin(self):
        pass

    def setEnteredRacers(self, avAndKarts):
        self.notify.debug('setEnteredRacers %s' % avAndKarts)
        avatarsGone = []
        avatarsLeft = []
        self.numRacers = len(avAndKarts)
        for i in avAndKarts:
            if i[0] in self.avIds:
                self.kartMap[i[0]] = i[1]
                avatarsLeft.append(i[0])

        for i in self.avIds:
            if i not in avatarsLeft:
                avatarsGone.append(i)

        base.loader.tick()
        for i in avatarsGone:
            self.avIds.remove(i)

        self.toonsToLink = list(self.avIds)
        for i in avAndKarts:
            self.cr.relatedObjectMgr.requestObjects(i, allCallback=self.__gotKartAvatarLink)

    def __gotKartAvatarLink(self, avAndKart):
        self.notify.debug('got a Link')
        toon = avAndKart[0]
        kart = avAndKart[1]
        base.loader.tick()
        if toon.doId in self.toonsToLink:
            self.toonsToLink.remove(toon.doId)
        if toon.doId == localAvatar.doId:
            self.localKart = kart
        if len(self.toonsToLink) == 0:
            self.doneBarrier('waitingForPrep')

    def enterPrep(self):
        self.d_requestKart()
        self.notify.debug('entering Prep State')
        if self.reversed:
            self.spin = Vec3(180, 0, 0)
        else:
            self.spin = Vec3(0, 0, 0)
        for i in xrange(4):
            base.loader.tick()

        self.gui.initRaceMode()
        self.gui.initResultMode()
        self.myPos = self.startingPos[self.startingPlaces[self.avIds.index(localAvatar.doId)]]
        self.localKart.setPosHpr(self.myPos[0], self.myPos[1] + self.spin)
        self.localKart.setupLapCollisions()
        if self.dummyNode:
            self.dummyNode.setPosHpr(self.myPos[0], self.myPos[1] + self.spin)
        self.currentPole = self.findSegmentStart()
        self.rabbitPoint = Vec3(0, 0, 0)
        self.doneBarrier('waitingForReady')

    def exitPrep(self):
        pass

    def enterTutorial(self):
        self.notify.debug('entering Tutorial State')
        base.loader.endBulkLoad('atRace')
        self.localKart.setPosHpr(self.myPos[0], self.myPos[1] + self.spin)
        base.transitions.irisIn()
        self.rulesDoneEvent = 'finishedRules'
        self.accept(self.rulesDoneEvent, self.handleRulesDone)
        self.rulesPanel = MinigameRulesPanel.MinigameRulesPanel('RacingRulesPanel', self.getTitle(), self.getInstructions(), self.rulesDoneEvent, 10)
        self.rulesPanel.load()
        self.rulesPanel.frame.setPos(0, 0, -0.6667)
        self.rulesPanel.enter()

    def exitTutorial(self):
        self.ignore(self.rulesDoneEvent)
        self.rulesPanel.exit()
        self.rulesPanel.unload()
        del self.rulesPanel

    def getTitle(self):
        return TTLocalizer.KartRace_TitleInfo

    def getInstructions(self):
        return TTLocalizer.KartRace_TrackInfo[self.trackId]

    def handleRulesDone(self):
        self.doneBarrier('readRules')
        self.fsm.request('waiting')

    def enterWaiting(self):
        self.waitingLabel = DirectLabel()
        self.waitingLabel['text'] = TTLocalizer.BuildingWaitingForVictors
        self.waitingLabel.setScale(TTLocalizer.DRenterWaiting)

    def exitWaiting(self):
        self.waitingLabel.removeNode()

    def enterStart(self):
        waitTime = self.baseTime - globalClock.getFrameTime()
        taskName = 'enableRaceModeLater'
        taskMgr.doMethodLater(1, self.gui.enableRaceMode, taskName, extraArgs=[])
        self.miscTaskNames.append(taskName)
        for i in self.avIds:
            self.gui.racerEntered(i)

        self.startCountdownClock(waitTime, 0)
        taskMgr.doMethodLater(waitTime, self.fsm.request, 'goToRacing', extraArgs=['racing'])

    def exitStart(self):
        pass

    def enterRacing(self):
        self.localKart.setInput(1)
        self.gui.setTimerEnabled(True)
        self.raceTask = taskMgr.add(self.raceWatcher, 'raceWatcher')

    def exitRacing(self):
        pass

    def raceWatcher(self, task):
        kart = base.cr.doId2do.get(self.kartMap.get(localAvatar.doId, None), None)
        if self.localKart.amIClampingPosition():
            self.notify.debug('teleporting kart %d back to main track' % localAvatar.doId)
            self.localKart.setPos(self.curvePoints[self.currentPole])
        kartPoint = self.localKart.getPos()
        direction = 0
        while True:
            currPoint = self.curvePoints[self.currentPole]
            nextPole = (self.currentPole + 1) % len(self.curvePoints)
            nextPoint = self.curvePoints[nextPole]
            segment = nextPoint - currPoint
            segment.setZ(0)
            segLength2 = segment.lengthSquared()
            kartVector = kartPoint - currPoint
            kartVector.setZ(0)
            project = segment * (segment.dot(kartVector) / segLength2)
            projLength2 = project.lengthSquared()
            if project.dot(segment) < 0:
                if direction == 1:
                    break
                prevPole = (self.currentPole - 1) % len(self.curvePoints)
                self.currentPole = prevPole
                direction = -1
            elif projLength2 > segLength2:
                if direction == -1:
                    break
                self.currentPole = nextPole
                direction = 1
            else:
                break

        if self.dummyNode:
            self.dummyNode.setPos(kartPoint[0], kartPoint[1], 0)
            self.dummyNode.setHpr(self.localKart.getH(), 0, 0)
        t = projLength2 / segLength2
        if self.debugIt:
            self.notify.debug('self.debugIt = %d' % self.debugIt)
            import pdb
            pdb.set_trace()
        if nextPole < self.currentPole:
            newT = self.curveTs[self.currentPole] * (1 - t) + self.curve.getMaxT() * t
        else:
            newT = self.curveTs[self.currentPole] * (1 - t) + self.curveTs[nextPole] * t
        kartDirection = self.localKart.forward.getPos(render) - self.localKart.getPos(render)
        kartDirection.normalize()
        project.normalize()
        globalDirection = kartDirection.dot(project)
        if globalDirection < 0:
            self.wrongWay = True
        elif globalDirection > 0.1:
            self.wrongWay = False
        newLapT = (newT - self.startT) / self.curve.getMaxT() % 1.0
        if newLapT - self.currLapT < -0.5:
            self.laps += 1
            self.changeMusicTempo(1 + self.laps * 0.5)
            self.notify.debug('crossed the start line: %s, %s, %s, %s' % (self.laps,
             self.startT,
             self.currT,
             newT))
        elif newLapT - self.currLapT > 0.5:
            self.laps -= 1
            self.changeMusicTempo(1 + self.laps * 0.5)
            self.notify.debug('crossed the start line - wrong way: %s, %s, %s, %s' % (self.laps,
             self.startT,
             self.currT,
             newT))
        self.currT = newT
        self.currLapT = newLapT
        if self.isUrbanTrack:
            self.showBuildings(self.currT)
        now = globalClock.getFrameTime()
        timestamp = globalClockDelta.localToNetworkTime(now)
        if self.laps == self.lapCount:
            self.sendUpdate('heresMyT', [localAvatar.doId,
             self.laps,
             self.currLapT,
             timestamp])
            self.fsm.request('finished')
        if self.laps > self.maxLap:
            self.maxLap = self.laps
            self.sendUpdate('heresMyT', [localAvatar.doId,
             self.laps,
             self.currLapT,
             timestamp])
        if now - self.lastTimeUpdate > 0.5:
            self.lastTimeUpdate = now
            self.sendUpdate('heresMyT', [localAvatar.doId,
             self.laps,
             self.currLapT,
             timestamp])
        self.gui.updateRacerInfo(localAvatar.doId, curvetime=self.currLapT + self.laps)
        self.gui.update(now)
        return Task.cont

    def enterFinished(self):
        taskMgr.remove('raceWatcher')
        self.fadeOutMusic()
        self.localKart.interruptTurbo()
        self.localKart.disableControls()
        taskName = 'parkIt'
        taskMgr.doMethodLater(2, self.stopDriving, taskName, extraArgs=[])
        self.miscTaskNames.append(taskName)
        self.finished = True
        base.camera.reparentTo(render)
        base.camera.setPos(self.localKart.getPos(render) + Vec3(0, 0, 10))
        base.camera.setH(self.localKart.getH(render) + 180)
        self.gui.disableRaceMode()
        self.gui.enableResultMode()
        localAvatar.reparentTo(hidden)
        self.localKart.reparentTo(hidden)

    def exitFinished(self):
        pass

    def stopDriving(self):
        kart = base.cr.doId2do.get(self.kartMap.get(localAvatar.doId, None), None)
        cpos = base.camera.getPos()
        chpr = base.camera.getHpr()
        localAvatar.reparentTo(hidden)
        self.localKart.reparentTo(hidden)
        self.localKart.stopSmooth()
        self.localKart.stopPosHprBroadcast()
        base.camera.setPos(cpos)
        base.camera.setHpr(chpr)
        return

    def enterLeave(self):
        kart = base.cr.doId2do.get(self.kartMap.get(localAvatar.doId, None), None)
        taskMgr.remove('raceWatcher')
        self.gui.disable()
        if self.localKart:
            self.localKart.disableControls()
        base.transitions.irisOut()
        if self.raceType == RaceGlobals.Circuit and not len(self.circuitLoop) == 0:
            self.sendUpdate('racerLeft', [localAvatar.doId])
        else:
            taskMgr.doMethodLater(1, self.goToSpeedway, 'leaveRace', extraArgs=[[localAvatar.doId], RaceGlobals.Exit_UserReq])
        if self.victory:
            self.victory.stop()
        self.bananaSound.stop()
        self.anvilFall.stop()
        return

    def exitLeave(self):
        pass

    def getCountdownColor(self, countdownTimeInt):
        clockNodeColors = [Vec4(0, 1, 0, 1),
         Vec4(1, 1, 0, 1),
         Vec4(1, 0.5, 0, 1),
         Vec4(1, 0, 0, 1)]
        i = max(min(countdownTimeInt, len(clockNodeColors) - 1), 0)
        return clockNodeColors[i]

    def startCountdownClock(self, countdownTime, ts):
        self.clockNode = TextNode('k')
        self.clockNode.setFont(ToontownGlobals.getSignFont())
        self.clockNode.setAlign(TextNode.ACenter)
        countdownInt = int(countdownTime)
        self.clockNode.setTextColor(self.getCountdownColor(countdownInt))
        self.clockNode.setText(str(countdownInt))
        self.clock = render2d.attachNewNode(self.clockNode)
        rs = TTLocalizer.DRrollScale
        self.clock.setPosHprScale(0, 0, 0, 0, 0, 0, rs, rs, rs)
        self.clock.hide()
        if ts < countdownTime:
            self.countdown(countdownTime - ts)

    def timerTask(self, task):
        countdownTime = int(task.duration - task.time)
        timeStr = str(countdownTime + 1)
        if self.clock.isHidden():
            if task.duration - task.time <= task.maxCount:
                self.clock.show()
        if self.clockNode.getText() != timeStr:
            self.startBoopSfx.play()
            self.clockNode.setText(timeStr)
            self.clockNode.setTextColor(self.getCountdownColor(countdownTime + 1))
        if task.time >= task.duration:
            self.startBoop2Sfx.play()
            self.clockNode.setText(TTLocalizer.KartRace_Go)
            self.clockNode.setTextColor(self.getCountdownColor(-1))
            taskMgr.doMethodLater(1, self.endGoSign, 'removeGoSign')
            return Task.done
        else:
            return Task.cont

    def endGoSign(self, t):
        self.clock.removeNode()

    def countdown(self, duration):
        countdownTask = Task(self.timerTask)
        countdownTask.duration = duration
        countdownTask.maxCount = RaceGlobals.RaceCountdown
        taskMgr.remove(self.uniqueName('countdownTimerTask'))
        return taskMgr.add(countdownTask, self.uniqueName('countdownTimerTask'))

    def initGags(self):
        self.banana = globalPropPool.getProp('banana')
        self.banana.setScale(2)
        self.pie = globalPropPool.getProp('creampie')
        self.pie.setScale(1)

    def makeCheckPoint(self, trigger, location, event):
        cs = CollisionSphere(0, 0, 0, 140)
        cs.setTangible(0)
        triggerEvent = 'imIn-' + trigger
        cn = CollisionNode(trigger)
        cn.addSolid(cs)
        cn.setIntoCollideMask(BitMask32(32768))
        cn.setFromCollideMask(BitMask32(32768))
        cnp = NodePath(cn)
        cnp.reparentTo(self.geom)
        cnp.setPos(location)
        self.accept(triggerEvent, event)

    def loadUrbanTrack(self):
        self.dnaStore = DNAStorage()
        files = ('phase_4/dna/storage.pdna', 'phase_5/dna/storage_town.pdna',
                 'phase_4/dna/storage_TT.pdna', 'phase_5/dna/storage_TT_town.pdna',
                 'phase_8/dna/storage_BR.pdna', 'phase_8/dna/storage_BR_town.pdna',
                 'phase_8/dna/storage_DL.pdna', 'phase_8/dna/storage_DL_town.pdna')
        dnaBulk = DNABulkLoader(self.dnaStore, files)
        dnaBulk.loadDNAFiles()
        dnaFile = 'phase_6/dna/urban_track_town.pdna'
        if self.trackId in (RaceGlobals.RT_Urban_2, RaceGlobals.RT_Urban_2_rev):
            dnaFile = 'phase_6/dna/urban_track_town_B.pdna'
        node = loader.loadDNAFile(self.dnaStore, dnaFile)
        self.townGeom = self.geom.attachNewNode(node)
        self.townGeom.findAllMatches('**/+CollisionNode').stash()
        self.buildingGroups = {}
        self.currBldgInd = {}
        self.currBldgGroups = {}
        bgGeom = self.geom.find('**/polySurface8')
        if self.dummyNode:
            bgGeom.reparentTo(self.dummyNode)
        else:
            bgGeom.reparentTo(localAvatar)
        bgGeom.setScale(0.1)
        ce = CompassEffect.make(NodePath(), CompassEffect.PRot)
        bgGeom.node().setEffect(ce)
        bgGeom.setDepthTest(0)
        bgGeom.setDepthWrite(0)
        bgGeom.setBin('background', 102)
        bgGeom.setZ(-1)
        self.bgGeom = bgGeom
        l = self.geom.findAllMatches('**/+ModelNode')
        for n in l:
            n.node().setPreserveTransform(0)
        self.geom.flattenLight()
        maxNum = 0
        for side in ['inner', 'outer']:
            self.buildingGroups[side] = []
            self.currBldgInd[side] = None
            self.currBldgGroups[side] = None
            i = 0
            while 1:
                bldgGroup = self.townGeom.find('**/Buildings_' + side + '-' + str(i))
                if bldgGroup.isEmpty():
                    break
                l = bldgGroup.findAllMatches('**/+ModelNode')
                for n in l:
                    n2 = n.getParent().attachNewNode(n.getName())
                    n.getChildren().reparentTo(n2)
                    n.removeNode()
                bldgGroup.flattenStrong()
                if not bldgGroup.getNode(0).getBounds().isEmpty():
                    self.buildingGroups[side].append(bldgGroup)
                i += 1
            if i > maxNum:
                maxNum = i
        for side in ['innersidest', 'outersidest']:
            self.buildingGroups[side] = []
            self.currBldgInd[side] = None
            self.currBldgGroups[side] = None
            for i in xrange(maxNum):
                for barricade in ('innerbarricade', 'outerbarricade'):
                    bldgGroup = self.townGeom.find('**/Buildings_' + side + '-' + barricade + '_' + str(i))
                    if bldgGroup.isEmpty():
                        continue
                    l = bldgGroup.findAllMatches('**/+ModelNode')
                    for n in l:
                        n2 = n.getParent().attachNewNode(n.getName())
                        n.getChildren().reparentTo(n2)
                        n.removeNode()
                    self.buildingGroups[side].append(bldgGroup)
        treeNodes = self.townGeom.findAllMatches('**/prop_tree_*')
        for tree in treeNodes:
            tree.flattenStrong()
        snowTreeNodes = self.townGeom.findAllMatches('**/prop_snow_tree_*')
        for snowTree in snowTreeNodes:
            snowTree.flattenStrong()
        for side in ['inner', 'outer', 'innersidest', 'outersidest']:
            for grp in self.buildingGroups[side]:
                grp.stash()
        self.showBuildings(0)

    def unloadUrbanTrack(self):
        del self.buildingGroups
        self.townGeom.removeNode()

    def loadFog(self):
        self.hasFog = True
        if self.isUrbanTrack:
            base.camLens.setFar(650)
        else:
            base.camLens.setFar(650)
        self.dummyNode = render.attachNewNode('dummyNode')
        if base.wantFog:
            self.fog = Fog('TrackFog')
            self.fog.setColor(Vec4(0.6, 0.7, 0.8, 1.0))
            if self.isUrbanTrack:
                self.fog.setLinearRange(200.0, 650.0)
            else:
                self.fog.setLinearRange(200.0, 800.0)
            render.setFog(self.fog)
        self.sky.setScale(1.725)
        self.sky.reparentTo(self.dummyNode)

    def showBuildings(self, t, forceRecompute = False):
        firstTimeCalled = 0
        if self.curve:
            t = t / self.curve.getMaxT()
        else:
            firstTimeCalled = 1
        if self.reversed:
            t = 1.0 - t
        numGroupsShown = 5
        for side in ['inner', 'outer']:
            numBldgGroups = len(self.buildingGroups[side])
            bldgInd = int(t * numBldgGroups)
            bldgInd = bldgInd % numBldgGroups
            if self.trackId in (RaceGlobals.RT_Urban_2, RaceGlobals.RT_Urban_2_rev):
                oldBldgInd = int(self.oldT * numBldgGroups)
                newBldgInd = int(t * numBldgGroups)
                kartPoint = self.startPos
                kart = base.cr.doId2do.get(self.kartMap.get(localAvatar.doId, None), None)
                if kart:
                    kartPoint = self.localKart.getPos()
                if not self.currBldgInd[side]:
                    self.currBldgInd[side] = 0
                curInd = self.currBldgInd[side]
                myCurGroup = self.buildingGroups[side][curInd]
                prevGrp = (curInd - 1) % numBldgGroups
                myPrevGroup = self.buildingGroups[side][prevGrp]
                nextGrp = (curInd + 1) % numBldgGroups
                myNextGroup = self.buildingGroups[side][nextGrp]
                curVector = myCurGroup.getNode(0).getBounds().getCenter() - kartPoint
                curDistance = curVector.lengthSquared()
                prevVector = myPrevGroup.getNode(0).getBounds().getCenter() - kartPoint
                prevDistance = prevVector.lengthSquared()
                nextVector = myNextGroup.getNode(0).getBounds().getCenter() - kartPoint
                nextDistance = nextVector.lengthSquared()
                if curDistance <= prevDistance and curDistance <= nextDistance:
                    bldgInd = self.currBldgInd[side]
                elif prevDistance <= curDistance and prevDistance <= nextDistance:
                    bldgInd = prevGrp
                elif nextDistance <= curDistance and nextDistance <= prevDistance:
                    bldgInd = nextGrp
                else:
                    self.notify.warning('unhandled case!!!!')
                    bldgInd = self.currBldgInd[side]
            if bldgInd != self.currBldgInd[side]:
                currBldgGroups = self.currBldgGroups[side]
                if currBldgGroups:
                    for i in currBldgGroups:
                        self.buildingGroups[side][i].stash()

                prevGrp2 = (bldgInd - 2) % numBldgGroups
                prevGrp = (bldgInd - 1) % numBldgGroups
                currGrp = bldgInd % numBldgGroups
                nextGrp = (bldgInd + 1) % numBldgGroups
                nextGrp2 = (bldgInd + 2) % numBldgGroups
                self.currBldgGroups[side] = [prevGrp2,
                 prevGrp,
                 currGrp,
                 nextGrp,
                 nextGrp2]
                for i in self.currBldgGroups[side]:
                    self.buildingGroups[side][i].unstash()

                self.currBldgInd[side] = bldgInd

        if self.currBldgGroups['inner'] != self.currBldgGroups['outer']:
            pass
        if t != self.oldT:
            self.oldT = t
        if self.trackId in (RaceGlobals.RT_Urban_2, RaceGlobals.RT_Urban_2_rev):
            if self.reversed:
                t = 1.0 - t
            for side in ['innersidest', 'outersidest']:
                segmentInd = int(t * self.barricadeSegments)
                seglmentInd = segmentInd % self.barricadeSegments
                if segmentInd != self.currBldgInd[side] or forceRecompute:
                    currBldgGroups = self.currBldgGroups[side]
                    if currBldgGroups:
                        for i in currBldgGroups:
                            self.buildingGroups[side][i].stash()

                    self.currBldgGroups[side] = []
                    if side == 'innersidest':
                        dict = self.innerBarricadeDict
                    elif side == 'outersidest':
                        dict = self.outerBarricadeDict
                    if segmentInd in dict:
                        self.currBldgGroups[side] = dict[segmentInd]
                    for i in self.currBldgGroups[side]:
                        self.buildingGroups[side][i].unstash()

                    self.currBldgInd[side] = segmentInd

        return

    def setupGeom(self):
        trackFilepath = RaceGlobals.TrackDict[self.trackId][0]
        self.geom = loader.loadModel(trackFilepath)
        for i in xrange(10):
            base.loader.tick()

        self.geom.reparentTo(render)
        if self.reversed:
            lapStartPos = self.geom.find('**/lap_start_rev').getPos()
        else:
            lapStartPos = self.geom.find('**/lap_start').getPos()
        self.startPos = lapStartPos
        lapMidPos = self.geom.find('**/lap_middle').getPos()
        for i in xrange(5):
            base.loader.tick()

        self.startingPos = []
        posLocators = self.geom.findAllMatches('**/start_pos*')
        for i in xrange(posLocators.getNumPaths()):
            base.loader.tick()
            self.startingPos.append([posLocators[i].getPos(), posLocators[i].getHpr()])

        self.notify.debug('self.startingPos: %s' % self.startingPos)
        self.wrongWay = False
        self.laps = 0
        if self.isUrbanTrack:
            self.loadUrbanTrack()
        self.genArrows()
        if self.reversed:
            self.curve = self.geom.find('**/curve_reverse').node()
        else:
            self.curve = self.geom.find('**/curve_forward').node()
        for i in xrange(4000):
            self.curvePoints.append(Point3(0, 0, 0))
            self.curve.getPoint(i / 4000.0 * (self.curve.getMaxT() - 1e-11), self.curvePoints[-1])
            self.curveTs.append(i / 4000.0 * (self.curve.getMaxT() - 1e-11))

        if self.trackId in (RaceGlobals.RT_Urban_2, RaceGlobals.RT_Urban_2_rev):
            self.precomputeSideStreets()
        for i in xrange(10):
            base.loader.tick()

        self.startT = self.getNearestT(lapStartPos)
        self.midT = self.getNearestT(lapMidPos)
        self.gags = []
        gagList = RaceGlobals.TrackDict[self.trackId][4]
        for i in xrange(len(gagList)):
            self.notify.debug('generating gag: %s' % i)
            self.gags.append(RaceGag(self, i, Vec3(*gagList[i]) + Vec3(0, 0, 3)))

        for i in xrange(5):
            base.loader.tick()

    def precomputeSideStreets(self):
        farDist = base.camLens.getFar() + 300
        farDistSquared = farDist * farDist
        for i in xrange(int(self.barricadeSegments)):
            testPoint = Point3(0, 0, 0)
            self.curve.getPoint(i / self.barricadeSegments * (self.curve.getMaxT() - 1e-11), testPoint)
            for side in ('innersidest', 'outersidest'):
                for bldgGroupIndex in xrange(len(self.buildingGroups[side])):
                    bldgGroup = self.buildingGroups[side][bldgGroupIndex]
                    if not bldgGroup.getNode(0).getBounds().isEmpty():
                        bldgPoint = bldgGroup.getNode(0).getBounds().getCenter()
                        vector = testPoint - bldgPoint
                        if vector.lengthSquared() < farDistSquared:
                            if side == 'innersidest':
                                dict = self.innerBarricadeDict
                            elif side == 'outersidest':
                                dict = self.outerBarricadeDict
                            else:
                                self.notify.error('unhandled side')
                            if i in dict:
                                if bldgGroupIndex not in dict[i]:
                                    dict[i].append(bldgGroupIndex)
                            else:
                                dict[i] = [bldgGroupIndex]
                    for childIndex in (0,):
                        if childIndex >= bldgGroup.getNumChildren():
                            continue
                        childNodePath = bldgGroup.getChild(childIndex)
                        bldgPoint = childNodePath.node().getBounds().getCenter()
                        vector = testPoint - bldgPoint
                        if vector.lengthSquared() < farDistSquared:
                            if side == 'innersidest':
                                dict = self.innerBarricadeDict
                            elif side == 'outersidest':
                                dict = self.outerBarricadeDict
                            else:
                                self.notify.error('unhandled side')
                            if i in dict:
                                if bldgGroupIndex not in dict[i]:
                                    dict[i].append(bldgGroupIndex)
                            else:
                                dict[i] = [bldgGroupIndex]

        for side in ('innersidest', 'outersidest'):
            for bldgGroup in self.buildingGroups[side]:
                bldgGroup.flattenStrong()

        if self.isUrbanTrack:
            self.showBuildings(0, forceRecompute=True)

    def findSegmentStart(self):
        kart = base.cr.doId2do.get(self.kartMap.get(localAvatar.doId, None), None)
        minLength2 = 1000000
        minIndex = -1
        currPoint = Point3(0, 0, 0)
        kartPoint = self.localKart.getPos()
        for i in xrange(len(self.curvePoints)):
            currPoint = self.curvePoints[i]
            currLength2 = (kartPoint - currPoint).lengthSquared()
            if currLength2 < minLength2:
                minLength2 = currLength2
                minIndex = i

        currPoint = self.curvePoints[minIndex]
        if minIndex + 1 == len(self.curvePoints):
            nextPoint = self.curvePoints[0]
        else:
            nextPoint = self.curvePoints[minIndex + 1]
        if minIndex - 1 < 0:
            prevIndex = len(self.curvePoints) - 1
        else:
            prevIndex = minIndex - 1
        forwardSegment = nextPoint - currPoint
        if (kartPoint - currPoint).dot(forwardSegment) > 0:
            return minIndex
        else:
            return prevIndex
        return

    def getNearestT(self, pos):
        minLength2 = 1000000
        minIndex = -1
        currPoint = Point3(0, 0, 0)
        for i in xrange(len(self.curvePoints)):
            currPoint = self.curvePoints[i]
            currLength2 = (pos - currPoint).lengthSquared()
            if currLength2 < minLength2:
                minLength2 = currLength2
                minIndex = i

        currPoint = self.curvePoints[minIndex]
        if minIndex + 1 == len(self.curvePoints):
            nextPoint = self.curvePoints[0]
        else:
            nextPoint = self.curvePoints[minIndex + 1]
        if minIndex - 1 < 0:
            prevIndex = len(self.curvePoints) - 1
        else:
            prevIndex = minIndex - 1
        forwardSegment = nextPoint - currPoint
        if (pos - currPoint).dot(forwardSegment) > 0:
            pole = minIndex
        else:
            pole = prevIndex
        currPoint = self.curvePoints[pole]
        nextPole = (pole + 1) % len(self.curvePoints)
        nextPoint = self.curvePoints[nextPole]
        segment = nextPoint - currPoint
        segment.setZ(0)
        segLength2 = segment.lengthSquared()
        posVector = pos - currPoint
        posVector.setZ(0)
        project = segment * (segment.dot(posVector) / segLength2)
        percent = project.lengthSquared() / segLength2
        if nextPole < pole:
            t = self.curveTs[pole] * (1 - percent) + self.curve.getMaxT() * percent
        else:
            t = self.curveTs[pole] * (1 - percent) + self.curveTs[nextPole] * percent
        return t

    def hasGag(self, slot, type, index):
        if self.gags[slot].isActive():
            self.gags[slot].disableGag()

    def leaveRace(self):
        self.fsm.request('leave')

    def racerLeft(self, avId):
        if avId != localAvatar.doId:
            self.gui.racerLeft(avId, unexpected=False)

    def skyTrack(self, task):
        return SkyUtil.cloudSkyTrack(task)

    def startSky(self):
        if self.hasFog:
            SkyUtil.startCloudSky(self, parent=self.dummyNode, effects=CompassEffect.PRot)
        else:
            SkyUtil.startCloudSky(self, parent=render)

    def stopSky(self):
        taskMgr.remove('skyTrack')

    def pickupGag(self, slot, index):
        self.canShoot = False
        standing = self.gui.racerDict[localAvatar.doId].place - 1
        self.currGag = RaceGlobals.GagFreq[standing][index]
        cycleTime = 2
        self.gui.waitingOnGag(cycleTime)
        taskMgr.doMethodLater(cycleTime, self.enableShoot, 'enableShoot')
        self.sendUpdate('hasGag', [slot, self.currGag, index])

    def shootGag(self):
        if self.canShoot:
            if self.currGag == 1:
                self.bananaSound.play()
                self.shootBanana()
            elif self.currGag == 2:
                self.d_requestThrow(0, 0, 0)
                self.localKart.startTurbo()
            elif self.currGag == 3:
                self.d_requestThrow(0, 0, 0)
            elif self.currGag == 4:
                self.bananaSound.play()
                self.shootPie()
            self.currGag = 0
            self.gui.updateGag(0)

    def enableShoot(self, t):
        self.canShoot = True
        if self.gui:
            self.gui.updateGag(self.currGag)

    def shootBanana(self):
        pos = self.localKart.getPos(render)
        banana = self.banana.copyTo(self.geom)
        banana.setPos(pos)
        self.thrownGags.append(banana)
        self.d_requestThrow(pos[0], pos[1], pos[2])

    def shootPie(self):
        pos = self.localKart.getPos(render)
        self.d_requestThrow(pos[0], pos[1], pos[2])

    def genArrows(self):
        base.arrows = []
        arrowId = 0
        for boost in RaceGlobals.TrackDict[self.trackId][5]:
            self.genArrow(boost[0], boost[1], arrowId)
            arrowId += 1

    def genArrow(self, pos, hpr, id):
        factory = CardMaker('factory')
        factory.setFrame(-.5, 0.5, -.5, 0.5)
        arrowNode = factory.generate()
        arrowRoot = NodePath('root')
        baseArrow = NodePath(arrowNode)
        baseArrow.setTransparency(1)
        baseArrow.setTexture(self.boostArrowTexture)
        baseArrow.reparentTo(arrowRoot)
        arrow2 = baseArrow.copyTo(baseArrow)
        arrow2.setPos(0, 0, 1)
        arrow3 = arrow2.copyTo(arrow2)
        arrowRoot.setPos(*pos)
        arrowRoot.setHpr(*hpr)
        baseArrow.setHpr(0, -90, 0)
        baseArrow.setScale(24)
        arrowRoot.reparentTo(self.geom)
        trigger = 'boostArrow' + str(id)
        cs = CollisionTube(Point3(0.6, -6, 0), Point3(0.6, 54, 0), 4.8)
        cs.setTangible(0)
        triggerEvent = 'imIn-' + trigger
        cn = CollisionNode(trigger)
        cn.addSolid(cs)
        cn.setIntoCollideMask(BitMask32(32768))
        cn.setFromCollideMask(BitMask32(32768))
        cnp = NodePath(cn)
        cnp.reparentTo(arrowRoot)
        self.accept(triggerEvent, self.hitBoostArrow)
        arrowVec = arrow2.getPos(self.geom) - baseArrow.getPos(self.geom)
        arrowVec.normalize()
        idStr = str(id)
        cnp.setTag('boostId', idStr)
        self.boostDir[idStr] = arrowVec
        base.arrows.append(arrowRoot)

    def hitBoostArrow(self, cevent):
        into = cevent.getIntoNodePath()
        idStr = into.getTag('boostId')
        arrowVec = self.boostDir.get(idStr)
        if arrowVec == None:
            print 'Unknown boost arrow %s' % idStr
            return
        fvec = self.localKart.forward.getPos(self.geom) - self.localKart.getPos(self.geom)
        fvec.normalize()
        dotP = arrowVec.dot(fvec)
        if dotP > 0.7:
            self.localKart.startTurbo()
        return

    def fadeOutMusic(self):
        if self.musicTrack:
            self.musicTrack.finish()
        curVol = self.raceMusic.getVolume()
        interval = LerpFunctionInterval(self.raceMusic.setVolume, fromData=curVol, toData=0, duration=3)
        self.musicTrack = Sequence(interval)
        self.musicTrack.start()

    def changeMusicTempo(self, newPR):
        return # TODO: Reenable when we have music change support.
        if self.musicTrack:
            self.musicTrack.finish()
        curPR = self.raceMusic.getPlayRate()
        interval = LerpFunctionInterval(self.raceMusic.setPlayRate, fromData=curPR, toData=newPR, duration=3)
        self.musicTrack = Sequence(interval)
        self.musicTrack.start()

    def setRaceZone(self, zoneId, trackId):
        hoodId = self.cr.playGame.hood.hoodId
        base.loader.endBulkLoad('atRace')
        self.kartCleanup()
        self.doneBarrier('waitingForExit')
        self.sendUpdate('racerLeft', [localAvatar.doId])
        out = {'loader': 'racetrack',
         'where': 'racetrack',
         'hoodId': hoodId,
         'zoneId': zoneId,
         'trackId': trackId,
         'shardId': None,
         'reason': RaceGlobals.Exit_UserReq}
        base.cr.playGame.hood.loader.fsm.request('quietZone', [out])
        return
コード例 #15
0
class ToontownFogManager:
    def __init__(self):
        self.fog = None
        self.fogMode = None
        print("Initialized Fog Manager")

        self.fog = Fog("ActiveFog")
        self.fog.setColor(1, 1, 1)

        self.fogTypes = {
            0: Fog.MExponential,
            1: Fog.MExponentialSquared,
            2: Fog.MLinear
        }

    def setFog(self, np):
        np.setFog(self.fog)

    def setColor(self, r, g, b):
        self.fog.setColor(r, g, b)

    def clearFog(self):
        return render.clearFog()

    def getFogMode(self):
        self.fogMode = self.fog.getMode()

    def setFogMode(self, id):
        mode = self.fog.setMode(self.fogTypes[id])
        self.fogMode = mode

    ## For Exponential Fog

    def setDensity(self, density):
        """
        Determines the density value used for exponential fog calculations.

        :param float density: A value between [0, 1]
        """
        self.fog.setExpDensity(density)

    ## For Linear Fog

    def setLinearRange(self, range, opacity):
        """
        Specifies the effects of the fog in linear distance units. This is only used if the mode is M_linear.

        This specifies a fog that begins at distance onset units from the origin, and becomes totally opaque at distance
        <opaque units> from the origin, along the forward axis (usually Y).

        This function also implicitly sets the mode the M_linear, if it is not already set.

        :param float opacity: [0, 1]
        """
        self.fog.setLinearRange(range, opacity)

    def setLinearFallback(self, angle, onset, opaque):
        """
        :param float angle: the minimum viewing angle (angle between the camera direction and fog direction) at which
         the fallback effect will be employed.
        :type onset: float
        :param float opaque: [0, 1]

        Defines how the fog should be rendered when the fog effect is diminished in this way.

        Onset and opaque specify camera-relative onset and opaque distances that will be fallen back on, overriding the
        Fog node's own onset and opaque distances.

        The linear fallback workaround will only look good in certain situations, for example when the fog is deep inside a dark cave.

        So in general, exponential mode fog is more useful than the default linear mode fog.
        """
        self.fog.setLinearFallback(angle, onset, opaque)
コード例 #16
0
class World(DirectObject):
    cfg = None
    def __init__(self):
        self.last_mousex = 0
        self.last_mousey = 0

        self.zone = None
        self.zone_reload_name = None
        
        self.winprops = WindowProperties( )

        # simple console output
        self.consoleNode = NodePath(PandaNode("console_root"))
        self.consoleNode.reparentTo(aspect2d)

        self.console_num_lines = 24
        self.console_cur_line = -1
        self.console_lines = []
        for i in range(0, self.console_num_lines):
            self.console_lines.append(OnscreenText(text='', style=1, fg=(1,1,1,1),
                        pos=(-1.3, .4-i*.05), align=TextNode.ALeft, scale = .035, parent = self.consoleNode))

        # Configuration
        self.consoleOut('World Forge v.%s loading configuration' % VERSION)
        self.configurator = Configurator(self)
        cfg = self.configurator.config
        resaveRes = False
        if 'xres' in cfg:
            self.xres = int(cfg['xres'])
        else:
            self.xres = 1024
            resaveRes = True

        if 'yres' in cfg:
            self.yres = int(cfg['yres'])
        else:
            self.yres = 768
            resaveRes = True

        if resaveRes:
            self.saveDefaultRes()

        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.mouse_accum = MouseAccume( lambda: (self.xres_half,self.yres_half))

        self.eyeHeight = 7.0
        self.rSpeed = 80
        self.flyMode = 1

        # application window setup
        base.win.setClearColor(Vec4(0,0,0,1))
        self.winprops.setTitle( 'World Forge')
        self.winprops.setSize(self.xres, self.yres) 
        
        base.win.requestProperties( self.winprops ) 
        base.disableMouse()
        
        # Post the instructions
        self.title = addTitle('World Forge v.' + VERSION)
        self.inst0 = addInstructions(0.95, "[FLYMODE][1]")
        self.inst1 = addInstructions(-0.95, "Camera control with WSAD/mouselook. Press K for hotkey list, ESC to exit.")
        self.inst2 = addInstructions(0.9,  "Loc:")
        self.inst3 = addInstructions(0.85, "Hdg:")
        self.error_inst = addInstructions(0, '')
        self.kh = []
        
        self.campos = Point3(155.6, 41.2, 4.93)
        base.camera.setPos(self.campos)
        
        # Accept the application control keys: currently just esc to exit navgen       
        self.accept("escape", self.exitGame)
        self.accept("window-event", self.resizeGame)
        
        # Create some lighting
        ambient_level = .6
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(ambient_level, ambient_level, ambient_level, 1.0))
        render.setLight(render.attachNewNode(ambientLight))

        direct_level = 0.8
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0.0, 0.0, -1.0))
        directionalLight.setColor(Vec4(direct_level, direct_level, direct_level, 1))
        directionalLight.setSpecularColor(Vec4(direct_level, direct_level, direct_level, 1))
        render.setLight(render.attachNewNode(directionalLight))
        
        # create a point light that will follow our view point (the camera for now)
        # attenuation is set so that this point light has a torch like effect
        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        self.plight.setAttenuation(Point3(0.0, 0.0, 0.0002))
        
        self.plnp = base.camera.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 0)
        render.setLight(self.plnp)
        self.cam_light = 1
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, \
            "cam-right":0, "mouse3":0, "flymode":1 }

        # setup FOG
        self.fog_colour = (0.8,0.8,0.8,1.0)
        self.linfog = Fog("A linear-mode Fog node")
        self.linfog.setColor(self.fog_colour)
        self.linfog.setLinearRange(700, 980)         # onset, opaque distances as params
        # linfog.setLinearFallback(45,160,320)
        base.camera.attachNewNode(self.linfog)
        render.setFog(self.linfog)
        self.fog = 1
        
        # camera control
        self.campos = Point3(0, 0, 0)
        self.camHeading = 0.0
        self.camPitch = 0.0
        base.camLens.setFov(65.0)
        base.camLens.setFar(1200) 
        
        self.cam_speed = 0  # index into self.camp_speeds
        self.cam_speeds = [40.0, 80.0, 160.0, 320.0, 640.0]
        
        
        # Collision Detection for "WALKMODE"
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  The ray will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        
        self.cTrav = CollisionTraverser()
        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0.0, 0.0, 0.0)
        self.camGroundRay.setDirection(0,0,-1)      # straight down
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        # attach the col node to the camCollider dummy node
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)  
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)
        
        
        # Uncomment this line to see the collision rays
        # self.camGroundColNp.show()
       
        # Uncomment this line to show a visual representation of the 
        # collisions occuring
        # self.cTrav.showCollisions(render)
        
        # Add the spinCameraTask procedure to the task manager.
        # taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        globals.hasClickedSpawn = False;
        globals.hasClickedGrid = False;
        taskMgr.add(self.camTask, "camTask")

        self.toggleControls(1)

        # need to step the task manager once to make our fake console work
        taskMgr.step()

    # CONSOLE ---------------------------------------------------------------------
    def consoleScroll(self):
        for i in range(0, self.console_num_lines-1):
            self.console_lines[i].setText(self.console_lines[i+1].getText())
            
    def consoleOut(self, text):
        print text  # output to stdout/log too

        if self.console_cur_line == self.console_num_lines-1:
            self.consoleScroll()
        elif self.console_cur_line < self.console_num_lines-1:
            self.console_cur_line += 1

        self.console_lines[self.console_cur_line].setText(text)

        taskMgr.step()
    
    def consoleOn(self):
        self.consoleNode.show()
        
    def consoleOff(self):
        self.consoleNode.hide()
        
    # User controls -----------------------------------------------------------
    def toggleControls(self, on):

        cfg = self.configurator.config

        if on == 1:
            self.accept("escape", self.exitGame)

            self.accept("1", self.setSpeed, ["speed", 0])
            self.accept("2", self.setSpeed, ["speed", 1])
            self.accept("3", self.setSpeed, ["speed", 2])
            self.accept("4", self.setSpeed, ["speed", 3])
            self.accept("5", self.setSpeed, ["speed", 4])

            self.accept("alt-f", self.fogToggle)

            self.accept(cfg['control_lighting'], self.camLightToggle)
            self.accept(cfg['control_help'], self.displayKeyHelp)
            self.accept(cfg['control_flymode'], self.toggleFlymode)
            self.accept(cfg['control_reload-zone'], self.reloadZone)
            self.accept(cfg['control_cam-left'], self.setKey, ["cam-left",1])
            self.accept(cfg['control_cam-right'], self.setKey, ["cam-right",1])
            self.accept(cfg['control_forward'], self.setKey, ["forward",1])
            self.accept("mouse3", self.setKey, ["mouse3",1])
            self.accept(cfg['control_backward'], self.setKey, ["backward",1])
        
            self.accept("k-up", self.hideKeyHelp)
            self.accept(cfg['control_cam-left']+"-up", self.setKey, ["cam-left",0])
            self.accept(cfg['control_cam-right']+"-up", self.setKey, ["cam-right",0])
            self.accept(cfg['control_forward']+"-up", self.setKey, ["forward",0])
            self.accept("mouse3-up", self.setKey, ["mouse3",0])
            self.accept(cfg['control_backward']+"-up", self.setKey, ["backward",0])
            self.accept(cfg['toggle_edit-mode'], self.toggleEditMode)
            self.accept(cfg['toggle_insert-mode'], self.toggleInsertMode)
            self.accept(cfg['toggle_explore-mode'], self.toggleExploreMode)
            self.accept(cfg['toggle_grid-mode'], self.toggleGridMode)
            # Accept both single-presses and long presses for rotating models
            self.accept(cfg['rotate-right'] + "-repeat", self.rotateModelRight)
            self.accept(cfg['rotate-left'] + "-repeat", self.rotateModelLeft)
            self.accept(cfg['rotate-right'], self.rotateModelRight)
            self.accept(cfg['rotate-left'], self.rotateModelLeft)
            self.accept(cfg['clear-selection'], self.clearSelection)
        else:
            messenger.clear()

    def rotateModelRight(self):
        if globals.editMode == True:
            if globals.selectedSpawn:
                cfg = self.configurator.config
                globals.selectedSpawn.model.setH(globals.selectedSpawn.model.getH() + int(cfg['rotation-amount']))
                # Really not sure about that...
                if globals.selectedSpawn.model.getH() > 360:
                    globals.selectedSpawn.model.setH(0)
                print globals.selectedSpawn.model.getH()
                globals.selectedSpawn.setheadingfromworld(globals.selectedSpawn.model.getH())
                globals.spawndialog.m_spawnEntryHeadingTextCtrl.SetValue(str(globals.selectedSpawn.spawnentry_heading))
                if globals.config['autosave_edit-mode'] == 'True':
                    globals.database.UpdateSpawn(globals.selectedSpawn)
                print globals.selectedSpawn.spawnentry_heading

    def rotateModelLeft(self):
        if globals.editMode == True:
            if globals.selectedSpawn:
                cfg = self.configurator.config
                globals.selectedSpawn.model.setH(globals.selectedSpawn.model.getH() - int(cfg['rotation-amount']))
                # Really not sure about that either...
                if globals.selectedSpawn.model.getH() < -360:
                    globals.selectedSpawn.model.setH(0)
                print globals.selectedSpawn.model.getH()
                globals.selectedSpawn.setheadingfromworld(globals.selectedSpawn.model.getH())
                globals.spawndialog.m_spawnEntryHeadingTextCtrl.SetValue(str(globals.selectedSpawn.spawnentry_heading))
                if globals.config['autosave_edit-mode'] == 'True':
                    globals.database.UpdateSpawn(globals.selectedSpawn)
                print globals.selectedSpawn.spawnentry_heading

    def clearSelection(self, eraseNpcId = True):
        globals.selectedspawn = None
        globals.selectedgrid = None
        globals.picker.lastSelectedObject = None
        if self.inst6:
            self.inst6.destroy()
        self.inst6 = addInstructions(0.7, "Current selection: None")
        npcid = globals.spawndialog.m_spawnEntryNpcIdTextCtrl.Value
        globals.spawndialog.Reset()
        # f*****g hacky shit man
        if eraseNpcId == False:
            globals.spawndialog.m_spawnEntryNpcIdTextCtrl.SetValue(npcid)
        gridmanager = GridpointManager()
        gridmanager.ResetGridList()
        print "Cleared all selections !"

    def toggleDefaultMode(self):
        globals.editMode = False
        globals.insertMode = False
        globals.exploreMode = True
        globals.gridMode = False
        print "STARTUP Explore mode ACTIVATED"
        print "STARTUP Grid mode DEACTIVATED"
        self.inst4 = addInstructions(0.8, "Explore mode ON")
        self.inst5 = addInstructions(0.75, "Grid mode OFF")
        self.inst6 = addInstructions(0.7, "Current selection: None")

    def toggleEditMode(self):
        globals.editMode = True
        globals.insertMode = False
        globals.exploreMode = False
        print "Edit mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Edit mode ON")

    def toggleInsertMode(self):
        globals.editMode = False
        globals.insertMode = True
        globals.exploreMode = False
        print "Insert mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Insert mode ON")

    def toggleExploreMode(self):
        globals.editMode = False
        globals.insertMode = False
        globals.exploreMode = True
        print "Explore mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Explore mode ON")

    def toggleGridMode(self):
        if globals.gridMode == False:
            globals.gridMode = True
            print "Grid mode ACTIVATED"
            if self.inst5:
                self.inst5.destroy()
            self.inst5 = addInstructions(0.75, "Grid mode ON")
        else:
            globals.gridMode = False
            print "Grid mode DEACTIVATED"
            if self.inst5:
                self.inst5.destroy()
            self.inst5 = addInstructions(0.75, "Grid mode OFF")

    def setSpeed(self, key, value):
        self.cam_speed = value
        self.setFlymodeText()
        
    def fogToggle(self):
        if self.fog == 1:
            render.clearFog()
            base.camLens.setFar(100000) 
            self.fog = 0
        else:
            render.setFog(self.linfog)
            base.camLens.setFar(1200) 
            self.fog = 1
            
    def camLightToggle(self):
        if self.cam_light == 0:
            render.setLight(self.plnp)
            self.cam_light = 1
        else:
            render.clearLight(self.plnp)
            self.cam_light = 0
        
    def displayKeyHelp(self):
        self.kh = []
        msg = 'HOTKEYS:'
        pos = 0.75
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '------------------'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'W: camera fwd, S: camera bck, A: rotate view left, D: rotate view right'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '1-5: set camera movement speed'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'F: toggle Flymode/Walkmode'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'L: load a zone'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ALT-F: toggle FOG and FAR plane on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'T: toggle additional camera "torch" light on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'Z: set currently loaded zone as new startup default'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ESC: exit World Forge'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
     
    def hideKeyHelp(self):
        for n in self.kh:
            n.removeNode()
                        
    def setFlymodeText(self):
        zname = ''
        if self.zone:
            zname = self.zone.name
            
        if self.flyMode == 0:
            self.inst0.setText("[WALKMODE][%i] %s" % (self.cam_speed+1, zname))
        else:
            self.inst0.setText("[FLYMODE][%i] %s " % (self.cam_speed+1, zname))
        
    def toggleFlymode(self):
        zname = ''
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.flyMode = 1
        else:
            self.flyMode = 0
            
        self.setFlymodeText()

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        base.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        base.camera.setHpr(angleDegrees, 0, 0)
        return task.cont


    def camTask(self, task):
        if globals.hasClickedSpawn:
           base.camera.setPos(globals.selectedSpawnPoint3D)
           self.campos = globals.selectedSpawnPoint3D
           globals.hasClickedSpawn = False
        elif globals.hasClickedGrid:
            base.camera.setPos(globals.selectedGridPoint3D)
            self.campos = globals.selectedGridPoint3D
            globals.hasClickedGrid = False
        else:
            # query the mouse
            mouse_dx = 0
            mouse_dy = 0


            # if we have a mouse and the right button is depressed
            if base.mouseWatcherNode.hasMouse():
                if self.keyMap["mouse3"] != 0:
                    self.mouse_accum.update()
                else:
                    self.mouse_accum.reset()

            mouse_dx = self.mouse_accum.dx
            mouse_dy = self.mouse_accum.dy

            self.rXSpeed = fabs(self.mouse_accum.dx) * (self.cam_speed+1) * max(5 * 1000/self.xres,3)
            self.rYSpeed = fabs(self.mouse_accum.dy) * (self.cam_speed+1) * max(3 * 1000/self.yres,1)
            
            if (self.keyMap["cam-left"]!=0 or mouse_dx < 0):
                if self.rSpeed < 160:
                    self.rSpeed += 80 * globalClock.getDt()

                if mouse_dx != 0:
                    self.camHeading += self.rXSpeed * globalClock.getDt()
                else:
                    self.camHeading += self.rSpeed * globalClock.getDt()

                if self.camHeading > 360.0:
                    self.camHeading = self.camHeading - 360.0
            elif (self.keyMap["cam-right"]!=0 or mouse_dx > 0):
                if self.rSpeed < 160:
                    self.rSpeed += 80 * globalClock.getDt()

                if mouse_dx != 0:
                    self.camHeading -= self.rXSpeed * globalClock.getDt()
                else:
                    self.camHeading -= self.rSpeed * globalClock.getDt()

                if self.camHeading < 0.0:
                    self.camHeading = self.camHeading + 360.0
            else:
                self.rSpeed = 80

            if mouse_dy > 0:
                self.camPitch += self.rYSpeed * globalClock.getDt()
            elif mouse_dy < 0:
                self.camPitch -= self.rYSpeed * globalClock.getDt()
            
            # set camera heading and pitch
            base.camera.setHpr(self.camHeading, self.camPitch, 0)

            # viewer position (camera) movement control
            v = render.getRelativeVector(base.camera, Vec3.forward())
            if not self.flyMode:
                v.setZ(0.0)
        
            move_speed = self.cam_speeds[self.cam_speed]
            if self.keyMap["forward"] == 1:
                self.campos += v * move_speed * globalClock.getDt()
            if self.keyMap["backward"] == 1:
                self.campos -= v * move_speed * globalClock.getDt()            

            # actually move the camera
            lastPos = base.camera.getPos()
            base.camera.setPos(self.campos)
            # self.plnp.setPos(self.campos)      # move the point light with the viewer position

            # WALKMODE: simple collision detection
            # we simply check a ray from slightly below the "eye point" straight down
            # for geometry collisions and if there are any we detect the point of collision
            # and adjust the camera's Z accordingly
            if self.flyMode == 0:   
                # move the camera to where it would be if it made the move 
                # the colliderNode moves with it
                # base.camera.setPos(self.campos)
                # check for collissons
                self.cTrav.traverse(render)
                entries = []
                for i in range(self.camGroundHandler.getNumEntries()):
                    entry = self.camGroundHandler.getEntry(i)
                    entries.append(entry)
                    # print 'collision'
                entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                             x.getSurfacePoint(render).getZ()))
                                     
                if (len(entries) > 0): # and (entries[0].getIntoNode().getName() == "terrain"):
                    # print len(entries)
                    self.campos.setZ(entries[0].getSurfacePoint(render).getZ()+self.eyeHeight)
                else:
                    self.campos = lastPos
                    base.camera.setPos(self.campos)
        
                #if (base.camera.getZ() < self.player.getZ() + 2.0):
                #    base.camera.setZ(self.player.getZ() + 2.0)


            # update loc and hpr display
            pos = base.camera.getPos()
            hpr = base.camera.getHpr()
            self.inst2.setText('Loc: %.2f, %.2f, %.2f' % (pos.getX(), pos.getY(), pos.getZ()))
            self.inst3.setText('Hdg: %.2f, %.2f, %.2f' % (hpr.getX(), hpr.getY(), hpr.getZ()))
        return task.cont

    def exitGame(self):
        globals.database.conn.close()
        print "DB connection closed !"
        sys.exit(0)

    def resizeGame(self,win):
        props = base.win.getProperties() 
        self.xres = props.getXSize()
        self.yres = props.getYSize()
        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.saveDefaultRes()
                
    #Records the state of the arrow keys
    # this is used for camera control
    def setKey(self, key, value):
        self.keyMap[key] = value

    # -------------------------------------------------------------------------
    # this is the mythical MAIN LOOP :)
    def update(self):

        if self.zone_reload_name != None:
            self.doReload(self.zone_reload_name)
            self.zone_reload_name = None

        if self.zone != None:
            self.zone.update()

        taskMgr.step()
        
        
    # ZONE loading ------------------------------------------------------------
    
    # general zone loader driver
    # removes existing zone (if any) and load the new one 
    def loadZone(self, name, path):
        if path[len(path)-1] != '/':
            path += '/'

        if self.zone:
            self.zone.rootNode.removeNode()
            
        self.zone = Zone(self, name, path)
        error = self.zone.load()
        if error == 0:
            self.consoleOff()
            self.setFlymodeText()
            base.setBackgroundColor(self.fog_colour)
        
    def saveDefaultRes(self):
        cfg = self.configurator.config
        cfg['xres'] = str(self.xres)
        cfg['yres'] = str(self.yres)

    # initial world load after bootup
    def load(self):       
        cfg = self.configurator.config
            
        zone_name = cfg['default_zone']
        globals.currentZone = zone_name
        basepath = cfg['basepath']
        self.loadZone(zone_name, basepath)

    # zone reload user interface
    
    # this gets called from our update loop when it detects that zone_reload_name has been set
    # we do this in this convoluted fashion in order to keep the main loop taskMgr updates ticking
    # because otherwise our status console output at various stages during the zone load would not
    # be displayed. Yes, this is hacky.
    def doReload(self, name):
        cfg = self.configurator.config
        basepath = cfg['basepath']
        self.loadZone(name, basepath)

    # form dialog callback
    # this gets called from the form when the user has entered a something
    # (hopefully a correct zone short name)
    def reloadZoneDialogCB(self, name):
        self.frmDialog.end()
        self.zone_reload_name = name
        self.toggleControls(1)

    # this is called when the user presses "l"
    # it disables normal controls and fires up our query form dialog
    def reloadZone(self):
        base.setBackgroundColor((0,0,0))
        self.toggleControls(0)
        self.consoleOn()
        self.frmDialog = FileDialog(
            "Please enter the shortname of the zone you wish to load:", 
            "Examples: qrg, blackburrow, freportn, crushbone etc.",
            self.reloadZoneDialogCB) 
        
        self.frmDialog.activate()   # relies on the main update loop to run

    #####################################
    # Custom methods
    #####################################


    # Handles populating the zone with spawn data from the EQEmu DB
    # also makes each spawner model pickable
    def PopulateSpawns(self, cursor, numrows):
        spawn_coords = list()
        globals.spawn_list = list()
        cfg = self.configurator.config
        for x in range(0, numrows):
            row = cursor.fetchone()
            point = Point3(long(row["Spawn2Y"]), long(row["Spawn2X"]), long(row["Spawn2Z"]))
            if cfg['ignore_duplicate_spawns'] == 'True':
                if point not in spawn_coords:
                    self.PlaceSpawnPointOn3dMap(row)
                    spawn_coords.append(point)
            else:
                self.PlaceSpawnPointOn3dMap(row)

    def PlaceSpawnPointOn3dMap(self, row):
        spawn = Spawn()
        self.InitSpawnData(spawn, row)
        spawn.model = loader.loadModel(spawn.modelname)
        spawn.initmodel()
        spawn.model.reparentTo(render)
        spawn.initheadingfromdb(row["Spawn2Heading"])
        spawn.placeintoworld(row["Spawn2Y"], row["Spawn2X"], row["Spawn2Z"])
        min, macks = spawn.model.getTightBounds()
        radius = max([macks.getY() - min.getY(), macks.getX() - min.getX()]) / 2
        cs = CollisionSphere(row["Spawn2X"], row["Spawn2Y"], row["Spawn2Z"], radius)
        csNode = spawn.model.attachNewNode(CollisionNode("modelCollide"))
        csNode.node().addSolid(cs)
        # TODO: ADD MORE TAGS??
        spawn.model.setTag("name", row["NpcName"])
        spawn.model.setTag("spawngroup_name", row["spawngroup_name"])
        spawn.model.setTag("spawn2id", str(row["Spawn2Id"]))
        spawn.model.setTag("type", "spawn")
        globals.picker.makePickable(spawn.model)
        globals.spawn_list.append(spawn)


    # Initializes a spawn object with database values
    def InitSpawnData(self, spawn, row):
        spawn.spawngroup_id = row["Spawngroup_id"]
        spawn.spawngroup_name = row["spawngroup_name"]
        spawn.spawngroup_minx = row["Spawngroup_minX"]
        spawn.spawngroup_maxx= row["Spawngroup_maxX"]
        spawn.spawngroup_miny = row["Spawngroup_minY"]
        spawn.spawngroup_maxy = row["Spawngroup_maxY"]
        spawn.spawngroup_dist = row["Spawngroup_dist"]
        spawn.spawngroup_mindelay = row["Spawngroup_mindelay"]
        spawn.spawngroup_delay = row["Spawngroup_delay"]
        spawn.spawngroup_despawn = row["Spawngroup_despawntimer"]
        spawn.spawngroup_despawntimer = row["Spawngroup_despawntimer"]
        spawn.spawngroup_spawnlimit = row["Spawngroup_spawnlimit"]


        spawn.spawnentry_id = row["Spawn2Id"]
        spawn.spawnentry_npcid = row["NpcId"]
        spawn.spawnentry_npcname = row["NpcName"]
        spawn.spawnentry_chance = row["Spawnentry_chance"]
        spawn.spawnentry_x = row["Spawn2X"]
        spawn.spawnentry_y = row["Spawn2Y"]
        spawn.spawnentry_z = row["Spawn2Z"]
        spawn.spawnentry_heading = row["Spawn2Heading"]
        spawn.spawnentry_respawn = row["Spawn2Respawn"]
        spawn.spawnentry_variance = row["Spawn2Variance"]
        spawn.spawnentry_pathgrid = row["Spawn2Grid"]
        spawn.spawnentry_condition = row["Spawn2Condition"]
        spawn.spawnentry_condvalue = row["Spawn2CondValue"]
        spawn.spawnentry_version = row["Spawn2Version"]
        spawn.spawnentry_enabled = row["Spawn2Enabled"]
        spawn.spawnentry_animation = row["Spawn2Animation"]
        spawn.spawnentry_zone = row["Spawn2Zone"]

        spawn.spawnentry_originalx = row["Spawn2X"]
        spawn.spawnentry_originaly = row["Spawn2Y"]
        spawn.spawnentry_originalz = row["Spawn2Z"]
        spawn.spawnentry_originalheading = row["Spawn2Heading"]


    # Initializes the camera position upon startup
    def InitCameraPosition(self):
        world.campos = Point3(-155.6, 41.2, 4.9 + world.eyeHeight)
        world.camHeading = 270.0

        base.camera.setPos(world.campos)

    def GetCamera(self):
        return base.camera
コード例 #17
0
class Starfox(ShowBase):
    def __init__(self):
        self.height = 500
        super().__init__(self)
        self.scene = self.loader.loadModel("./models/world.egg")
        playerTexture = loader.loadTexture("models/starfoxShip.jpg")
        enemyTexture = loader.loadTexture("models/enemyShip.jpg")
        bulletTexture = loader.loadTexture("models/shot.png")
        self.scene.reparentTo(self.render)

        base.setBackgroundColor(0.1, 0.1, 0.1, 1)

        self.player = self.scene.find("player")
        self.player.setPythonTag("ObjectController", Player(self.player))
        self.player.setTexture(playerTexture)

        self.building_enemy = self.scene.find("building_enemy")
        self.dynamic_enemy = self.scene.find("enemy1")
        self.dynamic_enemy.setTexture(enemyTexture)
        self.bullet = self.scene.find("bullet")
        self.bullet.setTexture(bulletTexture)

        base.cTrav = CollisionTraverser()
        self.CollisionHandlerEvent = CollisionHandlerEvent()
        base.enableParticles()
        self.CollisionHandlerEvent.addInPattern('into-%in')
        self.CollisionHandlerEvent.addOutPattern('out-%in')

        self.accept('into-collision_player', self.crash)
        self.accept('into-collision_plane', self.crash)
        self.accept('into-collision_enemy', self.crash)

        base.cTrav.addCollider(self.scene.find("player/collision**"),
                               self.CollisionHandlerEvent)
        base.cTrav.addCollider(self.scene.find("basePlane/collision**"),
                               self.CollisionHandlerEvent)

        self.player.find("**collision**").node().setFromCollideMask(0x3)
        self.player.find("**collision**").node().setIntoCollideMask(0x3)

        self.dynamic_enemy.find("**collision**").node().setFromCollideMask(0x5)
        self.dynamic_enemy.find("**collision**").node().setIntoCollideMask(0x5)

        self.building_enemy.find("**collision**").node().setFromCollideMask(
            0x5)
        self.building_enemy.find("**collision**").node().setIntoCollideMask(
            0x5)

        #base.cTrav.showCollisions(self.render)

        self.taskMgr.add(self.update, "update")
        InputManager.initWith(self, [
            InputManager.arrowUp, InputManager.arrowDown,
            InputManager.arrowLeft, InputManager.arrowRight,
            InputManager.space, InputManager.keyX, InputManager.keyV
        ])

        self.rails = self.scene.attachNewNode("rails")
        self.scene.find("basePlane").setHpr(70, 0, 0)
        self.rails.setPos(self.scene, 0, 0, 0)
        self.player.reparentTo(self.rails)
        self.player.setPos(self.rails, 0, 0, 0)
        self.rails_y = -50

        self.createStaticEnemy(self.building_enemy, 0, 50, 0)
        self.createStaticEnemy(self.building_enemy, -50, 50, 0)
        self.createStaticEnemy(self.building_enemy, -100, 50, 0)
        self.createStaticEnemy(self.building_enemy, -70, 130, 0)
        self.createStaticEnemy(self.building_enemy, -120, 80, 0)
        self.createStaticEnemy(self.building_enemy, -220, 130, 0)

        DynamicEnemy(self.dynamic_enemy,
                     self.scene,
                     Vec3(-230, 140, 10),
                     base.cTrav,
                     self.CollisionHandlerEvent,
                     type=ENEMY_TYPE.CHASER)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-240,160,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-250,200,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-270,160,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-250,200,10) ,  base.cTrav, self.CollisionHandlerEvent)

        self.building_enemy.hide()
        self.dynamic_enemy.hide()

        self.fog = Fog("fog")
        self.fog.setColor(0.1, 0.1, 0.1)
        self.fog.setExpDensity(.3)
        self.fog.setLinearRange(50, 150)
        self.fog.setLinearFallback(45, 160, 320)
        self.render.setFog(self.fog)

        self.dirLight = DirectionalLight("dir light")
        self.dirLight.color = (0.7, 0.7, 1, 1)
        self.dirLightPath = self.render.attachNewNode(self.dirLight)
        self.dirLightPath.setHpr(45, -45, 0)
        self.dirLight.setShadowCaster(True, 512, 512)
        render.setLight(self.dirLightPath)

        filters = CommonFilters(base.win, base.cam)
        filters.setBloom(size="large", mintrigger=0.2)

        self.render.setShaderAuto()

        self.initSounds()
        self.initUI()
        self.onGame = False

    def initUI(self):
        self.font = loader.loadFont('./fonts/Magenta.ttf')

        self.lifes = [
            OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(1.1, 0, 0.8),
                          scale=0.05),
            OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(1.2, 0, 0.8),
                          scale=0.05)
        ]

        self.lifes[0].setTransparency(True)
        self.lifes[1].setTransparency(True)

        self.dialogScreen = DirectDialog(frameSize=(-0.7, 0.7, -0.7, 0.7),
                                         relief=DGG.FLAT)

        s = OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(0, 0, -0.2),
                          scale=0.20,
                          parent=self.dialogScreen)
        s.setTransparency(True)

        self.titleUI = DirectLabel(text="Starfox Region 4",
                                   parent=self.dialogScreen,
                                   scale=0.1,
                                   pos=(0, 0, .2),
                                   text_font=self.font)

        self.btn = DirectButton(text="Start",
                                command=self.startGame,
                                pos=(0, 0, 0),
                                parent=self.dialogScreen,
                                scale=0.07)

    def startGame(self):
        self.dialogScreen.hide()
        self.flyingSound.play()
        self.onGame = True
        self.btn.hide()

    def initSounds(self):
        self.audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0],
                                                     self.camera)

        self.flyingSound = self.audio3d.loadSfx(
            "./sounds/great fox flying.mp3")
        self.flyingSound.setLoop(True)

        self.audio3d.attachSoundToObject(self.flyingSound, self.player)
        self.audio3d.setSoundVelocityAuto(self.flyingSound)
        self.audio3d.setListenerVelocityAuto()
        #self.audio3d.setDistanceFactor(100)
        self.audio3d.setDropOffFactor(0)

        self.fireSound = self.audio3d.loadSfx(
            "./sounds/arwing double laser one shot.mp3")
        self.crashSound = self.audio3d.loadSfx("./sounds/break.mp3")

    def createStaticEnemy(self, original, px, py, pz):
        be = original.copyTo(self.scene)
        be.setPos(px, py, pz)
        base.cTrav.addCollider(be.find("**collision**"),
                               self.CollisionHandlerEvent)
        """
        self.pointLight = PointLight("point light")
        self.pointLight.color = (1,1,1,1)
        self.pointLightPath = self.render.attachNewNode(self.pointLight)
        self.pointLightPath.setPos(px,py,pz)
        self.pointLight.attenuation = (1,0,0)
        #self.pointLight.setShadowCaster(True,1024,1024)
        self.render.setLight(self.pointLightPath)
        """

    def crash(self, evt):

        self.crashSound.play()
        objectInto = evt.getIntoNodePath().node().getParent(0).getPythonTag(
            "ObjectController")
        objectFrom = evt.getFromNodePath().node().getParent(0).getPythonTag(
            "ObjectController")

        if (objectInto != None):
            objectInto.crash(objectFrom)

        if (objectFrom != None):
            objectFrom.crash(objectInto)

        lifes = self.player.getPythonTag("ObjectController").getLifes()
        if (lifes <= 0):
            self.onGame = False
            self.dialogScreen.show()
            self.flyingSound.stop()

    def update(self, evt):
        #self.camera.setPos(0,-100,100)

        lifes = self.player.getPythonTag("ObjectController").getLifes()

        if (lifes > 2):
            self.lifes[0].show()
            self.lifes[1].show()
        elif (lifes > 1):
            self.lifes[0].show()
            self.lifes[1].hide()
        elif (lifes > 0):
            self.lifes[0].hide()
            self.lifes[1].hide()

        self.camera.lookAt(self.player)
        self.rails.setPos(self.scene, Path.getXOfY(self.rails_y), self.rails_y,
                          12.4)
        self.rails.setHpr(Path.getHeading(self.rails_y), 0, 0)
        self.dirLight.color = (self.rails_y / 600, 0.7, 1, 1)
        self.camera.setHpr(Path.getHeading(self.rails_y), 0, 0)

        if (self.onGame):
            self.rails_y = self.rails_y + globalClock.getDt() * 10
            #self.player.setPos(self.rails, 0, 0, sin(self.z/10.0)*40 )
            relX, relZ, isShooting = self.player.getPythonTag(
                "ObjectController").update(self.rails, globalClock.getDt())
            self.camera.setPos(self.rails, relX, -30, relZ)
            if (isShooting):
                self.fireSound.play()
                b = Bullet(
                    self.bullet, self.scene, self.player.getPos(self.scene),
                    base.cTrav, self.CollisionHandlerEvent,
                    self.scene.getRelativeVector(self.player,
                                                 Vec3(0, 1, 0)), 40, 0x4)
            enemies = self.scene.findAllMatches("dynamicEnemy")
            for e in enemies:
                enemy = e.getPythonTag("ObjectController")
                enemy.update(self.scene, globalClock.getDt(), self.player,
                             self.bullet)

            bullets = self.scene.findAllMatches("bulletC")
            for b in bullets:
                bullet = b.getPythonTag("ObjectController")
                bullet.update(self.scene, globalClock.getDt(), self.player)

        return Task.cont
コード例 #18
0
class CogdoBarrelRoom:
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedCogdoBarrelRoom')

    def __init__(self):
        self.timer = None
        self.model = None
        self._isLoaded = False
        self.dummyElevInNode = None
        self.cogdoBarrelsNode = None
        self.entranceNode = None
        self.nearBattleNode = None
        self.rewardUi = None
        self.rewardUiTaskName = 'CogdoBarrelRoom-RewardUI'
        self.rewardCameraTaskName = 'CogdoBarrelRoom-RewardCamera'
        self.fog = None
        self.defaultFar = None
        self.stomperSfx = None
        return

    def destroy(self):
        self.unload()

    def load(self):
        if self._isLoaded:
            return
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.stash()
        self.model = loader.loadModel(CogdoBarrelRoomConsts.BarrelRoomModel)
        self.model.setPos(*CogdoBarrelRoomConsts.BarrelRoomModelPos)
        self.model.reparentTo(render)
        self.model.stash()
        self.dummyElevInNode = self.model.attachNewNode('elevator-in')
        self.dummyElevInNode.hide()
        self.entranceNode = self.model.attachNewNode('door-entrance')
        self.entranceNode.setPos(0, -65, 0)
        self.nearBattleNode = self.model.attachNewNode('near-battle')
        self.nearBattleNode.setPos(0, -25, 0)
        self.rewardUi = CogdoBarrelRoomRewardPanel.CogdoBarrelRoomRewardPanel()
        self.hideRewardUi()
        self.stomperSfx = base.loadSfx(CogdoBarrelRoomConsts.StomperSound)
        self.fog = Fog('barrel-room-fog')
        self.fog.setColor(CogdoBarrelRoomConsts.BarrelRoomFogColor)
        self.fog.setLinearRange(
            *CogdoBarrelRoomConsts.BarrelRoomFogLinearRange)
        self._isLoaded = True

    def unload(self):
        if self.model:
            self.model.removeNode()
            self.model = None
        if self.timer:
            self.timer.destroy()
            self.timer = None
        if self.rewardUi:
            self.rewardUi.destroy()
            self.rewardUi = None
        if self.fog:
            render.setFogOff()
            del self.fog
        taskMgr.remove(self.rewardUiTaskName)
        taskMgr.remove(self.rewardCameraTaskName)
        self._isLoaded = False
        return

    def isLoaded(self):
        return self._isLoaded

    def show(self):
        if not self.cogdoBarrelsNode:
            self.cogdoBarrelsNode = render.find('**/@@CogdoBarrels')
            self.cogdoBarrelsNode.reparentTo(self.model)
            self.cogdoBarrelsNode.unstash()
        self.defaultFar = base.camLens.getFar()
        base.camLens.setFar(CogdoBarrelRoomConsts.BarrelRoomCameraFar)
        self.showBattleAreaLight(True)
        render.setFog(self.fog)
        self.model.unstash()

    def hide(self):
        self.model.stash()
        render.setFogOff()
        if self.defaultFar is not None:
            base.camLens.setFar(self.defaultFar)
        return

    def activate(self):
        self.notify.info('Activating barrel room: %d sec timer.' %
                         CogdoBarrelRoomConsts.CollectionTime)
        self.timer.unstash()
        self.timer.posAboveShtikerBook()
        self.timer.countdown(CogdoBarrelRoomConsts.CollectionTime)
        base.cr.playGame.getPlace().fsm.request('walk')

    def deactivate(self):
        self.notify.info('Deactivating barrel room.')
        self.timer.stop()
        self.timer.stash()

    def placeToonsAtEntrance(self, toons):
        for i in xrange(len(toons)):
            toons[i].setPosHpr(
                self.entranceNode,
                *CogdoBarrelRoomConsts.BarrelRoomPlayerSpawnPoints[i])

    def placeToonsNearBattle(self, toons):
        for i in xrange(len(toons)):
            toons[i].setPosHpr(
                self.nearBattleNode,
                *CogdoBarrelRoomConsts.BarrelRoomPlayerSpawnPoints[i])

    def showBattleAreaLight(self, visible=True):
        lightConeNode = self.model.find('**/battleCone')
        if lightConeNode != None and not lightConeNode.isEmpty():
            if visible:
                lightConeNode.show()
            else:
                lightConeNode.hide()
        return

    def getIntroInterval(self):
        avatar = base.localAvatar
        trackName = '__introBarrelRoom-%d' % avatar.doId
        track = Parallel(name=trackName)
        track.append(self.__stomperIntervals())
        track.append(
            Sequence(
                Func(base.camera.reparentTo, render),
                Func(base.camera.setPosHpr, self.model, -20.0, -87.9, 12.0,
                     -30, 0, 0), Func(base.transitions.irisIn, 0.5), Wait(1.0),
                LerpHprInterval(base.camera,
                                duration=2.0,
                                startHpr=Vec3(-30, 0, 0),
                                hpr=Vec3(0, 0, 0),
                                blendType='easeInOut'), Wait(2.5),
                LerpHprInterval(base.camera,
                                duration=3.0,
                                startHpr=Vec3(0, 0, 0),
                                hpr=Vec3(-45, 0, 0),
                                blendType='easeInOut'), Wait(2.5)))
        track.delayDelete = DelayDelete.DelayDelete(avatar,
                                                    'introBarrelRoomTrack')
        track.setDoneEvent(trackName)
        return (track, trackName)

    def __stomperIntervals(self):
        ivals = [SoundInterval(self.stomperSfx)]
        i = 0
        for stomperDef in CogdoBarrelRoomConsts.StomperProps:
            stomperNode = render.find(stomperDef['path'])
            if stomperNode:
                maxZ = random.uniform(10, 20)
                minZ = maxZ - 10
                if stomperDef['motion'] == 'up':
                    startZ, destZ = minZ, maxZ
                else:
                    startZ, destZ = maxZ, minZ
                stomperNode.setPos(Point3(0, 0, startZ))
                ivals.append(
                    LerpPosInterval(stomperNode,
                                    CogdoBarrelRoomConsts.StomperHaltTime,
                                    Point3(0, 0, destZ),
                                    blendType='easeOut'))
            i += 1

        return Parallel(*tuple(ivals))

    def __rewardUiTimeout(self, callback):
        self.hideRewardUi()
        if callback is not None:
            callback()
        return

    def __rewardCamera(self):
        trackName = 'cogdoBarrelRoom-RewardCamera'
        track = Sequence(Func(base.camera.reparentTo, render),
                         Func(base.camera.setPosHpr, self.model, 0, 0, 11.0, 0,
                              -14, 0),
                         Func(self.showBattleAreaLight, False),
                         name=trackName)
        return (track, trackName)

    def showRewardUi(self, results, callback=None):
        track, trackName = self.__rewardCamera()
        if CogdoBarrelRoomConsts.ShowRewardUI:
            self.rewardUi.setRewards(results)
            self.rewardUi.unstash()
        taskMgr.doMethodLater(CogdoBarrelRoomConsts.RewardUiTime,
                              self.__rewardUiTimeout,
                              self.rewardUiTaskName,
                              extraArgs=[callback])
        return (track, trackName)

    def setRewardResults(self, results):
        self.rewardUi.setRewards(results)

    def hideRewardUi(self):
        self.rewardUi.stash()
        taskMgr.remove(self.rewardUiTaskName)
コード例 #19
0
class VisualTest(ShowBase):
    def __init__(self):
        super().__init__(self)

        self.scene = loader.loadModel("models/world")
        self.player = self.scene.find("player")
        self.basePlane = self.scene.find("basePlane")
        self.player.reparentTo(self.render)
        self.basePlane.reparentTo(self.render)

        self.scene.remove_node()
        self.taskMgr.add(self.update, "update")

        self.camera.setPos(self.render, 0, -100, 70)
        base.setBackgroundColor(0.1, 0.1, 0.1, 1)

        self.dirLight = DirectionalLight("dir light")
        self.dirLight.setShadowCaster(True, 512, 512)
        self.dirLight.color = (1, 0, 1, 1)
        self.dirLightPath = self.render.attachNewNode(self.dirLight)
        self.dirLightPath.setHpr(45, -60, 0)
        render.setLight(self.dirLightPath)
        self.angleTime = 0.0
        self.totalAngleTime = 10.0
        self.hAngle = 0

        self.ambientLight = AmbientLight("ambient")
        self.ambientLight.color = (0.1, 0.1, 0.1, 1)
        self.ambLightPath = self.render.attachNewNode(self.ambientLight)
        render.setLight(self.ambLightPath)

        self.pointLight = PointLight("point")
        self.pointLight.color = (1, 1, 1, 1)
        self.pointLightPath = self.render.attachNewNode(self.pointLight)
        self.pointLightPath.setPos(0, 5, 5)
        self.pointLight.setShadowCaster(True, 512, 512)
        self.render.setLight(self.pointLightPath)

        self.fog = Fog("fog")
        self.fog.setColor(.1, .1, .1)
        self.fog.setExpDensity(.3)
        self.fog.setLinearRange(150, 200)
        self.fog.setLinearFallback(45, 160, 320)
        render.setFog(self.fog)
        self.render.setShaderAuto()

        self.p = self.render.attachNewNode("particles")
        base.enableParticles()
        p = ParticleEffect()
        p.loadConfig('./mysmoke.ptf')
        p.start(parent=self.p, renderParent=render)
        self.p.setPos(self.player, 0, 0, 2)

        self.font = loader.loadFont('./fonts/Magenta.ttf')
        self.sceneName = DirectLabel(text="Starfox visual test",
                                     parent=self.aspect2d,
                                     scale=0.07,
                                     pos=(-1.2, 0, 0.85),
                                     text_font=self.font,
                                     relief=None,
                                     text_fg=(1, 1, 1, 1),
                                     textMayChange=True,
                                     text_align=TextNode.ALeft)

        self.foxy = OnscreenImage(image='./UI/fox-icon-png-8.png',
                                  pos=(1.2, 9, 0.85),
                                  scale=0.1)
        self.foxy.setTransparency(True)

        self.controlsPanel = DirectDialog(frameSize=(-1.1, 1.1, -0.9, -0.7),
                                          relief=DGG.FLAT)

        btn = DirectButton(text="Rotate",
                           command=self.doRotate,
                           image='./UI/fox-icon-png-8.png',
                           pos=(-0.9, 0, -0.8),
                           parent=self.controlsPanel,
                           scale=0.07,
                           relief=None)

        btn2 = DirectButton(text="Anin Light",
                            command=self.doLight,
                            image='./UI/fox-icon-png-8.png',
                            pos=(-0.7, 0, -0.8),
                            parent=self.controlsPanel,
                            scale=0.07,
                            relief=None)

        self.camera.lookAt(self.player)
        self.makeRotation = False
        self.rotateAngles = 0
        self.animLight = False

        filter = CommonFilters(base.win, base.cam)
        filter.setBloom(size="large", intensity=2)
        #filter.setAmbientOcclusion(strength = 5,  radius = 3)
        filter.setCartoonInk(separation=4)

    def doRotate(self):
        self.makeRotation = True
        return 0

    def doLight(self):
        self.animLight = True
        return 0

    def update(self, evt):
        ang = (self.angleTime / self.totalAngleTime)
        #self.camera.setPos(self.player, ang*100,ang*100,ang*100)

        self.player.setPos(self.render, 0, 0, 1)
        #self.camera.lookAt( Vec3(0,300,0) )

        #self.p.setPos(self.player, 0,0,0,)
        # self.dirLightPath.setHpr(ang*360.0 ,-60,0)
        if (self.makeRotation):
            self.makeRotation = False
            self.rotateAngles = (self.rotateAngles + 90) % 360
            self.player.setHpr(self.rotateAngles, 0, 0)
            self.sceneName[
                "text"] = f"Starfox visual test ({self.rotateAngles})"

        self.camera.setPos(self.render, 10, 10, 10)
        self.camera.lookAt(self.player)

        if (ang >= 1):
            self.angleTime = 0
        self.angleTime = self.angleTime + globalClock.getDt()
        self.dirLight.color = (ang, 0, 1, 1)

        if self.animLight:
            self.pointLightPath.setPos(ang * 10 - 5, ang * 10 - 5, ang * 5)

        return Task.cont
コード例 #20
0
ファイル: zonewalk.py プロジェクト: proxeeus/panda-zonewalk
class World(DirectObject):
    def __init__(self):
        self.last_mousex = 0
        self.last_mousey = 0

        self.zone = None
        self.zone_reload_name = None

        self.winprops = WindowProperties()

        # simple console output
        self.consoleNode = NodePath(PandaNode("console_root"))
        self.consoleNode.reparentTo(aspect2d)

        self.console_num_lines = 24
        self.console_cur_line = -1
        self.console_lines = []
        for i in range(0, self.console_num_lines):
            self.console_lines.append(
                OnscreenText(
                    text="",
                    style=1,
                    fg=(1, 1, 1, 1),
                    pos=(-1.3, 0.4 - i * 0.05),
                    align=TextNode.ALeft,
                    scale=0.035,
                    parent=self.consoleNode,
                )
            )

        # Configuration
        self.consoleOut("zonewalk v.%s loading configuration" % VERSION)
        self.configurator = Configurator(self)
        cfg = self.configurator.config
        resaveRes = False
        if "xres" in cfg:
            self.xres = int(cfg["xres"])
        else:
            self.xres = 1024
            resaveRes = True

        if "yres" in cfg:
            self.yres = int(cfg["yres"])
        else:
            self.yres = 768
            resaveRes = True

        if resaveRes:
            self.saveDefaultRes()

        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.mouse_accum = MouseAccume(lambda: (self.xres_half, self.yres_half))

        self.eyeHeight = 7.0
        self.rSpeed = 80
        self.flyMode = 1

        # application window setup
        base.win.setClearColor(Vec4(0, 0, 0, 1))
        self.winprops.setTitle("zonewalk")
        self.winprops.setSize(self.xres, self.yres)

        base.win.requestProperties(self.winprops)
        base.disableMouse()

        # network test stuff
        self.login_client = None
        if "testnet" in cfg:
            if cfg["testnet"] == "1":
                self.doLogin()

        # Post the instructions
        self.title = addTitle("zonewalk v." + VERSION)
        self.inst0 = addInstructions(0.95, "[FLYMODE][1]")
        self.inst1 = addInstructions(-0.95, "Camera control with WSAD/mouselook. Press K for hotkey list, ESC to exit.")
        self.inst2 = addInstructions(0.9, "Loc:")
        self.inst3 = addInstructions(0.85, "Hdg:")
        self.error_inst = addInstructions(0, "")
        self.kh = []

        self.campos = Point3(155.6, 41.2, 4.93)
        base.camera.setPos(self.campos)

        # Accept the application control keys: currently just esc to exit navgen
        self.accept("escape", self.exitGame)
        self.accept("window-event", self.resizeGame)

        # Create some lighting
        ambient_level = 0.6
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(ambient_level, ambient_level, ambient_level, 1.0))
        render.setLight(render.attachNewNode(ambientLight))

        direct_level = 0.8
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0.0, 0.0, -1.0))
        directionalLight.setColor(Vec4(direct_level, direct_level, direct_level, 1))
        directionalLight.setSpecularColor(Vec4(direct_level, direct_level, direct_level, 1))
        render.setLight(render.attachNewNode(directionalLight))

        # create a point light that will follow our view point (the camera for now)
        # attenuation is set so that this point light has a torch like effect
        self.plight = PointLight("plight")
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        self.plight.setAttenuation(Point3(0.0, 0.0, 0.0002))

        self.plnp = base.camera.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 0)
        render.setLight(self.plnp)
        self.cam_light = 1

        self.keyMap = {
            "left": 0,
            "right": 0,
            "forward": 0,
            "backward": 0,
            "cam-left": 0,
            "cam-right": 0,
            "mouse3": 0,
            "flymode": 1,
        }

        # setup FOG
        self.fog_colour = (0.8, 0.8, 0.8, 1.0)
        self.linfog = Fog("A linear-mode Fog node")
        self.linfog.setColor(self.fog_colour)
        self.linfog.setLinearRange(700, 980)  # onset, opaque distances as params
        # linfog.setLinearFallback(45,160,320)
        base.camera.attachNewNode(self.linfog)
        render.setFog(self.linfog)
        self.fog = 1

        # camera control
        self.campos = Point3(0, 0, 0)
        self.camHeading = 0.0
        self.camPitch = 0.0
        base.camLens.setFov(65.0)
        base.camLens.setFar(1200)

        self.cam_speed = 0  # index into self.camp_speeds
        self.cam_speeds = [40.0, 80.0, 160.0, 320.0, 640.0]

        # Collision Detection for "WALKMODE"
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  The ray will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.

        self.cTrav = CollisionTraverser()
        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0.0, 0.0, 0.0)
        self.camGroundRay.setDirection(0, 0, -1)  # straight down
        self.camGroundCol = CollisionNode("camRay")
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())

        # attach the col node to the camCollider dummy node
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        # Uncomment this line to see the collision rays
        # self.camGroundColNp.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        # self.cTrav.showCollisions(render)

        # Add the spinCameraTask procedure to the task manager.
        # taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        taskMgr.add(self.camTask, "camTask")

        self.toggleControls(1)

        # need to step the task manager once to make our fake console work
        taskMgr.step()

    # CONSOLE ---------------------------------------------------------------------
    def consoleScroll(self):
        for i in range(0, self.console_num_lines - 1):
            self.console_lines[i].setText(self.console_lines[i + 1].getText())

    def consoleOut(self, text):
        print text  # output to stdout/log too

        if self.console_cur_line == self.console_num_lines - 1:
            self.consoleScroll()
        elif self.console_cur_line < self.console_num_lines - 1:
            self.console_cur_line += 1

        self.console_lines[self.console_cur_line].setText(text)

        taskMgr.step()

    def consoleOn(self):
        self.consoleNode.show()

    def consoleOff(self):
        self.consoleNode.hide()

    # User controls -----------------------------------------------------------
    def toggleControls(self, on):
        if on == 1:
            self.accept("escape", self.exitGame)

            self.accept("1", self.setSpeed, ["speed", 0])
            self.accept("2", self.setSpeed, ["speed", 1])
            self.accept("3", self.setSpeed, ["speed", 2])
            self.accept("4", self.setSpeed, ["speed", 3])
            self.accept("5", self.setSpeed, ["speed", 4])

            self.accept("alt-f", self.fogToggle)
            self.accept("t", self.camLightToggle)
            self.accept("k", self.displayKeyHelp)
            self.accept("f", self.toggleFlymode)
            self.accept("l", self.reloadZone)
            self.accept("z", self.saveDefaultZone)
            self.accept("a", self.setKey, ["cam-left", 1])
            self.accept("d", self.setKey, ["cam-right", 1])
            self.accept("w", self.setKey, ["forward", 1])
            self.accept("mouse1", self.setKey, ["forward", 1])
            self.accept("mouse3", self.setKey, ["mouse3", 1])
            self.accept("s", self.setKey, ["backward", 1])

            self.accept("k-up", self.hideKeyHelp)
            self.accept("a-up", self.setKey, ["cam-left", 0])
            self.accept("d-up", self.setKey, ["cam-right", 0])
            self.accept("w-up", self.setKey, ["forward", 0])
            self.accept("mouse1-up", self.setKey, ["forward", 0])
            self.accept("mouse3-up", self.setKey, ["mouse3", 0])
            self.accept("s-up", self.setKey, ["backward", 0])
        else:
            messenger.clear()

    def setSpeed(self, key, value):
        self.cam_speed = value
        self.setFlymodeText()

    def fogToggle(self):
        if self.fog == 1:
            render.clearFog()
            base.camLens.setFar(100000)
            self.fog = 0
        else:
            render.setFog(self.linfog)
            base.camLens.setFar(1200)
            self.fog = 1

    def camLightToggle(self):
        if self.cam_light == 0:
            render.setLight(self.plnp)
            self.cam_light = 1
        else:
            render.clearLight(self.plnp)
            self.cam_light = 0

    def displayKeyHelp(self):
        self.kh = []
        msg = "HOTKEYS:"
        pos = 0.75
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "------------------"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "W: camera fwd, S: camera bck, A: rotate view left, D: rotate view right"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "1-5: set camera movement speed"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "F: toggle Flymode/Walkmode"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "L: load a zone"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "ALT-F: toggle FOG and FAR plane on/off"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = 'T: toggle additional camera "torch" light on/off'
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "Z: set currently loaded zone as new startup default"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )
        msg = "ESC: exit zonewalk"
        pos -= 0.05
        self.kh.append(
            OnscreenText(text=msg, style=1, fg=(1, 1, 1, 1), pos=(-0.5, pos), align=TextNode.ALeft, scale=0.04)
        )

    def hideKeyHelp(self):
        for n in self.kh:
            n.removeNode()

    def setFlymodeText(self):
        zname = ""
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.inst0.setText("[WALKMODE][%i] %s" % (self.cam_speed + 1, zname))
        else:
            self.inst0.setText("[FLYMODE][%i] %s " % (self.cam_speed + 1, zname))

    def toggleFlymode(self):
        zname = ""
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.flyMode = 1
        else:
            self.flyMode = 0

        self.setFlymodeText()

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        base.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        base.camera.setHpr(angleDegrees, 0, 0)
        return task.cont

    def camTask(self, task):
        # query the mouse
        mouse_dx = 0
        mouse_dy = 0

        # if we have a mouse and the right button is depressed
        if base.mouseWatcherNode.hasMouse():
            if self.keyMap["mouse3"] != 0:
                self.mouse_accum.update()
            else:
                self.mouse_accum.reset()

        mouse_dx = self.mouse_accum.dx
        mouse_dy = self.mouse_accum.dy

        self.rXSpeed = fabs(self.mouse_accum.dx) * (self.cam_speed + 1) * max(5 * 1000 / self.xres, 3)
        self.rYSpeed = fabs(self.mouse_accum.dy) * (self.cam_speed + 1) * max(3 * 1000 / self.yres, 1)

        if self.keyMap["cam-left"] != 0 or mouse_dx < 0:
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading += self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading += self.rSpeed * globalClock.getDt()

            if self.camHeading > 360.0:
                self.camHeading = self.camHeading - 360.0
        elif self.keyMap["cam-right"] != 0 or mouse_dx > 0:
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading -= self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading -= self.rSpeed * globalClock.getDt()

            if self.camHeading < 0.0:
                self.camHeading = self.camHeading + 360.0
        else:
            self.rSpeed = 80

        if mouse_dy > 0:
            self.camPitch += self.rYSpeed * globalClock.getDt()
        elif mouse_dy < 0:
            self.camPitch -= self.rYSpeed * globalClock.getDt()

        # set camera heading and pitch
        base.camera.setHpr(self.camHeading, self.camPitch, 0)

        # viewer position (camera) movement control
        v = render.getRelativeVector(base.camera, Vec3.forward())
        if not self.flyMode:
            v.setZ(0.0)

        move_speed = self.cam_speeds[self.cam_speed]
        if self.keyMap["forward"] == 1:
            self.campos += v * move_speed * globalClock.getDt()
        if self.keyMap["backward"] == 1:
            self.campos -= v * move_speed * globalClock.getDt()

        # actually move the camera
        lastPos = base.camera.getPos()
        base.camera.setPos(self.campos)
        # self.plnp.setPos(self.campos)      # move the point light with the viewer position

        # WALKMODE: simple collision detection
        # we simply check a ray from slightly below the "eye point" straight down
        # for geometry collisions and if there are any we detect the point of collision
        # and adjust the camera's Z accordingly
        if self.flyMode == 0:
            # move the camera to where it would be if it made the move
            # the colliderNode moves with it
            # base.camera.setPos(self.campos)
            # check for collissons
            self.cTrav.traverse(render)
            entries = []
            for i in range(self.camGroundHandler.getNumEntries()):
                entry = self.camGroundHandler.getEntry(i)
                entries.append(entry)
                # print 'collision'
            entries.sort(lambda x, y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ()))

            if len(entries) > 0:  # and (entries[0].getIntoNode().getName() == "terrain"):
                # print len(entries)
                self.campos.setZ(entries[0].getSurfacePoint(render).getZ() + self.eyeHeight)
            else:
                self.campos = lastPos
                base.camera.setPos(self.campos)

            # if (base.camera.getZ() < self.player.getZ() + 2.0):
            #    base.camera.setZ(self.player.getZ() + 2.0)

        # update loc and hpr display
        pos = base.camera.getPos()
        hpr = base.camera.getHpr()
        self.inst2.setText("Loc: %.2f, %.2f, %.2f" % (pos.getX(), pos.getY(), pos.getZ()))
        self.inst3.setText("Hdg: %.2f, %.2f, %.2f" % (hpr.getX(), hpr.getY(), hpr.getZ()))
        return task.cont

    def exitGame(self):
        sys.exit(0)

    def resizeGame(self, win):
        props = base.win.getProperties()
        self.xres = props.getXSize()
        self.yres = props.getYSize()
        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.saveDefaultRes()

    # Records the state of the arrow keys
    # this is used for camera control
    def setKey(self, key, value):
        self.keyMap[key] = value

    # -------------------------------------------------------------------------
    # this is the mythical MAIN LOOP :)
    def update(self):

        if self.zone_reload_name != None:
            self.doReload(self.zone_reload_name)
            self.zone_reload_name = None

        if self.zone != None:
            self.zone.update()

        taskMgr.step()

        if self.login_client != None:
            self.login_client.update()

    # ZONE loading ------------------------------------------------------------

    # general zone loader driver
    # removes existing zone (if any) and load the new one
    def loadZone(self, name, path):
        if path[len(path) - 1] != "/":
            path += "/"

        if self.zone:
            self.zone.rootNode.removeNode()

        self.zone = Zone(self, name, path)
        error = self.zone.load()
        if error == 0:
            self.consoleOff()
            self.setFlymodeText()
            base.setBackgroundColor(self.fog_colour)

    def saveDefaultRes(self):
        cfg = self.configurator.config
        cfg["xres"] = str(self.xres)
        cfg["yres"] = str(self.yres)
        self.configurator.saveConfig()

    # initial world load after bootup
    def load(self):
        cfg = self.configurator.config

        if self.login_client != None:
            return

        zone_name = cfg["default_zone"]
        basepath = cfg["basepath"]
        self.loadZone(zone_name, basepath)

    # config save user interfacce
    def saveDefaultZone(self):
        if self.zone:
            cfg = self.configurator.config
            cfg["default_zone"] = self.zone.name
            self.configurator.saveConfig()

    # zone reload user interface

    # this gets called from our update loop when it detects that zone_reload_name has been set
    # we do this in this convoluted fashion in order to keep the main loop taskMgr updates ticking
    # because otherwise our status console output at various stages during the zone load would not
    # be displayed. Yes, this is hacky.
    def doReload(self, name):
        cfg = self.configurator.config
        basepath = cfg["basepath"]
        self.loadZone(name, basepath)

    # form dialog callback
    # this gets called from the form when the user has entered a something
    # (hopefully a correct zone short name)
    def reloadZoneDialogCB(self, name):
        self.frmDialog.end()
        self.zone_reload_name = name
        self.toggleControls(1)

    # this is called when the user presses "l"
    # it disables normal controls and fires up our query form dialog
    def reloadZone(self):
        base.setBackgroundColor((0, 0, 0))
        self.toggleControls(0)
        self.consoleOn()
        self.frmDialog = FileDialog(
            "Please enter the shortname of the zone you wish to load:",
            "Examples: qrg, blackburrow, freportn, crushbone etc.",
            self.reloadZoneDialogCB,
        )

        self.frmDialog.activate()  # relies on the main update loop to run

    ###############################
    # EXPERIMENTAL
    def doLogin(self):

        self.login_client = UDPClientStream("127.0.0.1", 5998)