Esempio n. 1
0
 def setupPhysics(self):
     shape = BulletSphereShape(1.0)
     bnode = BulletGhostNode(self.uniqueName('codeNumberPhys'))
     bnode.addShape(shape)
     bnode.setIntoCollideMask(CIGlobals.EventGroup)
     DistributedEntity.setupPhysics(self, bnode, True)
     self.stopWaterCheck()
     self.acceptOnce('enter' + self.uniqueName('codeNumberPhys'),
                     self.__handlePickup)
 def __initializeEventSphere(self):
     sphere = BulletSphereShape(2)
     node = BulletGhostNode(self.uniqueName("DEagleSuit-eventSphere"))
     node.addShape(sphere)
     node.setIntoCollideMask(CIGlobals.WallBitmask)
     np = self.attachNewNode(node)
     np.setSz(2.5)
     np.setZ(5.5)
     base.physicsWorld.attach(node)
     #np.show()
     self.eventSphereNodePath = np
Esempio n. 3
0
    def _add_chassis(self, pg_physics_world: PGPhysicsWorld):
        para = self.get_config()
        self.LENGTH = self.vehicle_config["vehicle_length"]
        self.WIDTH = self.vehicle_config["vehicle_width"]
        chassis = BaseVehicleNode(BodyName.Base_vehicle, self)
        chassis.setIntoCollideMask(BitMask32.bit(CollisionGroup.EgoVehicle))
        chassis_shape = BulletBoxShape(
            Vec3(self.WIDTH / 2, self.LENGTH / 2,
                 para[Parameter.vehicle_height] / 2))
        ts = TransformState.makePos(
            Vec3(0, 0, para[Parameter.chassis_height] * 2))
        chassis.addShape(chassis_shape, ts)
        heading = np.deg2rad(-para[Parameter.heading] - 90)
        chassis.setMass(para[Parameter.mass])
        self.chassis_np = self.node_path.attachNewNode(chassis)
        # not random spawn now
        self.chassis_np.setPos(Vec3(*self.spawn_place, 1))
        self.chassis_np.setQuat(
            LQuaternionf(math.cos(heading / 2), 0, 0, math.sin(heading / 2)))
        chassis.setDeactivationEnabled(False)
        chassis.notifyCollisions(
            True
        )  # advance collision check, do callback in pg_collision_callback
        self.dynamic_nodes.append(chassis)

        chassis_beneath = BulletGhostNode(BodyName.Base_vehicle_beneath)
        chassis_beneath.setIntoCollideMask(
            BitMask32.bit(CollisionGroup.EgoVehicleBeneath))
        chassis_beneath.addShape(chassis_shape)
        self.chassis_beneath_np = self.chassis_np.attachNewNode(
            chassis_beneath)
        self.dynamic_nodes.append(chassis_beneath)

        self.system = BulletVehicle(pg_physics_world.dynamic_world, chassis)
        self.system.setCoordinateSystem(ZUp)
        self.dynamic_nodes.append(
            self.system
        )  # detach chassis will also detach system, so a waring will generate

        if self.render:
            if self.MODEL is None:
                model_path = 'models/ferra/scene.gltf'
                self.MODEL = self.loader.loadModel(
                    AssetLoader.file_path(model_path))
                self.MODEL.setZ(para[Parameter.vehicle_vis_z])
                self.MODEL.setY(para[Parameter.vehicle_vis_y])
                self.MODEL.setH(para[Parameter.vehicle_vis_h])
                self.MODEL.set_scale(para[Parameter.vehicle_vis_scale])
            self.MODEL.instanceTo(self.chassis_np)
Esempio n. 4
0
    def _add_chassis(self, pg_physics_world: PGPhysicsWorld):
        para = self.get_config()
        chassis = BulletRigidBodyNode(BodyName.Ego_vehicle_top)
        chassis.setIntoCollideMask(BitMask32.bit(self.COLLISION_MASK))
        chassis_shape = BulletBoxShape(
            Vec3(para[Parameter.vehicle_width] / 2,
                 para[Parameter.vehicle_length] / 2,
                 para[Parameter.vehicle_height] / 2))
        ts = TransformState.makePos(
            Vec3(0, 0, para[Parameter.chassis_height] * 2))
        chassis.addShape(chassis_shape, ts)
        heading = np.deg2rad(-para[Parameter.heading] - 90)
        chassis.setMass(para[Parameter.mass])
        self.chassis_np = self.node_path.attachNewNode(chassis)
        # not random born now
        self.chassis_np.setPos(Vec3(*self.born_place, 1))
        self.chassis_np.setQuat(
            LQuaternionf(np.cos(heading / 2), 0, 0, np.sin(heading / 2)))
        chassis.setDeactivationEnabled(False)
        chassis.notifyCollisions(True)  # advance collision check
        self.pg_world.physics_world.dynamic_world.setContactAddedCallback(
            PythonCallbackObject(self._collision_check))
        self.dynamic_nodes.append(chassis)

        chassis_beneath = BulletGhostNode(BodyName.Ego_vehicle)
        chassis_beneath.setIntoCollideMask(BitMask32.bit(self.COLLISION_MASK))
        chassis_beneath.addShape(chassis_shape)
        self.chassis_beneath_np = self.chassis_np.attachNewNode(
            chassis_beneath)
        self.dynamic_nodes.append(chassis_beneath)

        self.system = BulletVehicle(pg_physics_world.dynamic_world, chassis)
        self.system.setCoordinateSystem(ZUp)
        self.dynamic_nodes.append(
            self.system
        )  # detach chassis will also detach system, so a waring will generate
        self.LENGTH = para[Parameter.vehicle_length]
        self.WIDTH = para[Parameter.vehicle_width]

        if self.render:
            model_path = 'models/ferra/scene.gltf'
            self.chassis_vis = self.loader.loadModel(
                AssetLoader.file_path(model_path))
            self.chassis_vis.setZ(para[Parameter.vehicle_vis_z])
            self.chassis_vis.setY(para[Parameter.vehicle_vis_y])
            self.chassis_vis.setH(para[Parameter.vehicle_vis_h])
            self.chassis_vis.set_scale(para[Parameter.vehicle_vis_scale])
            self.chassis_vis.reparentTo(self.chassis_np)
Esempio n. 5
0
 def __initCollisions(self, name):
     self.notify.debug("Initializing collision sphere...")
     numSlots = len(self.circles)
     ss = BulletSphereShape(self.numPlayers2SphereRadius[numSlots])
     snode = BulletGhostNode(name)
     snode.addShape(ss)
     snode.setKinematic(True)
     snode.setIntoCollideMask(CIGlobals.LocalAvGroup)
     self.snp = self.attach_new_node(snode)
     self.snp.setZ(3)
     self.snp.setY(self.numPlayers2SphereY[numSlots])
     self.snp.setSx(self.numPlayers2SphereSx[numSlots])
     self.snp.setSy(self.numPlayers2SphereSy[numSlots])
     base.physicsWorld.attachGhost(snode)
     self.acceptOnce("enter" + self.snp.node().getName(),
                     self.__handleEnterCollisionSphere)
Esempio n. 6
0
    def __init__(self,
                 parent_node_np: NodePath,
                 num_lasers: int = 16,
                 distance: float = 50,
                 enable_show=False):
        # properties
        assert num_lasers > 0
        show = enable_show and (AssetLoader.loader is not None)
        self.dim = num_lasers
        self.num_lasers = num_lasers
        self.perceive_distance = distance
        self.height = self.DEFAULT_HEIGHT
        self.radian_unit = 2 * np.pi / num_lasers
        self.start_phase_offset = 0
        self.node_path = parent_node_np.attachNewNode("Could_points")
        self._lidar_range = np.arange(
            0, self.num_lasers) * self.radian_unit + self.start_phase_offset

        # detection result
        self.cloud_points = np.ones((self.num_lasers, ), dtype=float)
        self.detected_objects = []

        # override these properties to decide which elements to detect and show
        self.node_path.hide(CamMask.RgbCam | CamMask.Shadow | CamMask.Shadow
                            | CamMask.DepthCam)
        self.mask = BitMask32.bit(CollisionGroup.BrokenLaneLine)
        self.cloud_points_vis = [] if show else None
        logging.debug("Load Vehicle Module: {}".format(
            self.__class__.__name__))
        if show:
            for laser_debug in range(self.num_lasers):
                ball = AssetLoader.loader.loadModel(
                    AssetLoader.file_path("models", "box.bam"))
                ball.setScale(0.001)
                ball.setColor(0., 0.5, 0.5, 1)
                shape = BulletSphereShape(0.1)
                ghost = BulletGhostNode('Lidar Point')
                ghost.setIntoCollideMask(BitMask32.allOff())
                ghost.addShape(shape)
                laser_np = self.node_path.attachNewNode(ghost)
                self.cloud_points_vis.append(laser_np)
                ball.getChildren().reparentTo(laser_np)
Esempio n. 7
0
    def announceGenerate(self):
        DistributedEntity.announceGenerate(self)

        self.addSound("pickup", "sound/items/jellybean_pickup.ogg")

        import random
        color = random.choice(self.Colors)
        self.getModelNP().setColorScale(color, 1)

        from direct.interval.IntervalGlobal import LerpHprInterval
        self.rot = LerpHprInterval(self.getModelNP(), 1.0, (360, 0, 0), (0, 0, 0))
        self.rot.loop()

        from src.coginvasion.globals import CIGlobals
        from panda3d.bullet import BulletSphereShape, BulletGhostNode
        sph = BulletSphereShape(0.5)
        body = BulletGhostNode(self.uniqueName('jellybean-trigger'))
        body.addShape(sph)
        body.setIntoCollideMask(CIGlobals.EventGroup)
        self.setupPhysics(body, True)
        self.acceptOnce('enter' + self.uniqueName('jellybean-trigger'), self.__enterJellybeanTrigger)
    def makeNodePath(self):
        self.nodePath = NodePath('treasure')
        if self.billboard: self.nodePath.setBillboardPointEye()
        self.nodePath.setScale(0.9 * self.scale)
        self.treasure = self.nodePath.attachNewNode('treasure')
        if self.shadow:
            if not self.dropShadow:
                self.dropShadow = loader.loadModel(
                    'phase_3/models/props/drop_shadow.bam')
                self.dropShadow.setColor(0, 0, 0, 0.5)
                self.dropShadow.setPos(0, 0, 0.025)
                self.dropShadow.setScale(0.4 * self.scale)
                self.dropShadow.flattenLight()
            self.dropShadow.reparentTo(self.nodePath)

        sphere = BulletSphereShape(self.sphereRadius)
        ghost = BulletGhostNode(self.uniqueName('treasureSphere'))
        ghost.addShape(sphere)
        ghost.setIntoCollideMask(CIGlobals.EventGroup)
        self.collNodePath = self.nodePath.attachNewNode(ghost)
        self.collNodePath.stash()
Esempio n. 9
0
  def __init__(self,name,right_side_ledge, size = __DEFAULT_SIZE__):
    '''
    Ledge(string name,Bool right_side_ledge, Platform parent_platform, Vec3 size = default)
    
      Creates a ledge object used to detect the extent of a platform at a given location
      The size should be [diameter, height, 0] and the cylinder shape axis is oriented
      in the Y+ direction.
    '''
    
    # storing members
    radius = size.getX()*0.5
    height = size.getY();
    self.size_ = size
    self.parent_platform_ = None #parent_platform
    self.is_right_side_ledge_ = right_side_ledge

    
    ledge_gn = BulletGhostNode(name)
    ledge_gn.addShape(BulletCylinderShape(radius,height, Y_up) )
    ledge_gn.setIntoCollideMask(CollisionMasks.LEDGE)  
    
    GameObject.__init__(self,ledge_gn)
Esempio n. 10
0
 def __init__(self, parent_node_np: NodePath, laser_num: int = 240, distance: float = 50):
     show = self.enable_show and (AssetLoader.loader is not None)
     self.Lidar_point_cloud_obs_dim = laser_num
     self.laser_num = laser_num
     self.perceive_distance = distance
     self.radian_unit = 2 * np.pi / laser_num
     self.detection_results = []
     self.node_path = parent_node_np.attachNewNode("cloudPoints")
     self.node_path.hide(CamMask.RgbCam | CamMask.Shadow)
     self.cloud_points = [] if show else None
     logging.debug("Load Vehicle Module: {}".format(self.__class__.__name__))
     if show:
         for laser_debug in range(self.laser_num):
             ball = AssetLoader.loader.loadModel(AssetLoader.file_path("models", "box.egg"))
             ball.setScale(0.001)
             ball.setColor(0., 0.5, 0.5, 1)
             shape = BulletSphereShape(0.1)
             ghost = BulletGhostNode('Lidar Point')
             ghost.setIntoCollideMask(BitMask32.allOff())
             ghost.addShape(shape)
             laser_np = self.node_path.attachNewNode(ghost)
             self.cloud_points.append(laser_np)
             ball.getChildren().reparentTo(laser_np)
class DistributedElevator(DistributedObject):
    notify = directNotify.newCategory('DistributedElevator')

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        self.openSfx = base.audio3d.loadSfx(
            'phase_5/audio/sfx/elevator_door_open.ogg')
        self.closeSfx = base.audio3d.loadSfx(
            'phase_5/audio/sfx/elevator_door_close.ogg')
        self.elevatorPoints = ElevatorPoints
        self.type = ELEVATOR_NORMAL
        self.countdownTime = ElevatorData[self.type]['countdown']
        self.localAvOnElevator = False
        self.thebldg = None
        self.bldgDoId = None
        self.toZoneId = None
        self.elevatorModel = None
        self.countdownTextNP = None
        self.toonsInElevator = []
        self.hopOffButton = None
        self.fsm = ClassicFSM.ClassicFSM('DistributedElevator', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('opening', self.enterOpening, self.exitOpening),
            State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty),
            State.State('waitCountdown', self.enterWaitCountdown,
                        self.exitWaitCountdown),
            State.State('closing', self.enterClosing, self.exitClosing),
            State.State('closed', self.enterClosed, self.exitClosed)
        ], 'off', 'off')
        self.fsm.enterInitialState()

    # The following is a workaround to fix the issue where self.cr is apparently not set.
    def sendUpdate(self, fieldName, args=[], sendToId=None):
        if hasattr(self, 'cr') and not self.cr:
            self.cr = base.cr
        DistributedObject.sendUpdate(self,
                                     fieldName,
                                     args=args,
                                     sendToId=sendToId)

    def setElevatorType(self, etype):
        self.type = etype

    def getElevatorType(self):
        return self.type

    def setBldgDoId(self, doId):
        self.bldgDoId = doId

    def getBldgDoId(self):
        return self.bldgDoId

    def setToZoneId(self, zoneId):
        self.toZoneId = zoneId

    def getToZoneId(self):
        return self.toZoneId

    def enterOpening(self, ts=0):
        self.openDoors.start(ts)

    def exitOpening(self):
        self.openDoors.finish()

    def enterClosing(self, ts=0):
        if self.localAvOnElevator:
            self.hideHopOffButton()
        self.closeDoors.start(ts)

    def exitClosing(self):
        if self.closeDoors.isPlaying():
            self.closeDoors.finish()

    def enterClosed(self, ts=0):
        closeDoors(self.getLeftDoor(), self.getRightDoor())

    def exitClosed(self):
        pass

    def __handleElevatorTrigger(self, collNp):
        if not self.localAvOnElevator:
            self.cr.playGame.getPlace().fsm.request('stop')
            self.sendUpdate('requestEnter')

    def enterWaitEmpty(self, ts=0):
        if not self.localAvOnElevator:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        openDoors(self.getLeftDoor(), self.getRightDoor())

    def exitWaitEmpty(self):
        self.ignore('enter' + self.uniqueName('elevatorSphere'))

    def enterWaitCountdown(self, ts=0):
        if not self.localAvOnElevator:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        openDoors(self.getLeftDoor(), self.getRightDoor())
        if self.countdownTextNP:
            self.countdownTextNP.show()
            self.countdownTrack = Sequence()
            time = int(ElevatorData[self.type]['countdown'])
            for i in range(time):
                self.countdownTrack.append(
                    Func(self.countdownTextNP.node().setText, str(time - i)))
                self.countdownTrack.append(Wait(1.0))
            self.countdownTrack.start(ts)

    def exitWaitCountdown(self):
        if self.countdownTextNP:
            self.countdownTextNP.hide()
        self.countdownTrack.finish()
        del self.countdownTrack

    def enterOff(self, ts=0):
        pass

    def exitOff(self):
        pass

    def getLeftDoor(self):
        # Can be overridden by inheritors.
        return self.thebldg.leftDoor

    def getRightDoor(self):
        return self.thebldg.rightDoor

    def startPoll(self):
        # Start polling for the building
        taskMgr.add(self.__pollBuilding, self.uniqueName('pollBuilding'))

    def __pollBuilding(self, task):
        self.getTheBldg()
        if self.thebldg:
            self.postAnnounceGenerate()
            return task.done
        return task.cont

    def stopPoll(self):
        taskMgr.remove(self.uniqueName('pollBuilding'))

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        self.getTheBldg()
        if not self.thebldg:
            self.startPoll()
            return
        self.postAnnounceGenerate()

    def postAnnounceGenerate(self, makeIvals=True):
        self.leftDoor = self.getLeftDoor()
        self.rightDoor = self.getRightDoor()
        self.setupElevator(makeIvals)
        self.setupCountdownText()
        base.audio3d.attachSoundToObject(self.closeSfx,
                                         self.getElevatorModel())
        base.audio3d.attachSoundToObject(self.openSfx, self.getElevatorModel())
        self.sendUpdate('requestStateAndTimestamp')

    def setState(self, state, timestamp):
        if not self.thebldg:
            return
        self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])

    def stateAndTimestamp(self, state, timestamp):
        self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])

    def setupCountdownText(self):
        tn = TextNode('countdownText')
        tn.setFont(CIGlobals.getMickeyFont())
        tn.setTextColor(VBase4(0.5, 0.5, 0.5, 1.0))
        tn.setAlign(TextNode.ACenter)
        self.countdownTextNP = self.getElevatorModel().attachNewNode(tn)
        self.countdownTextNP.setScale(2)
        self.countdownTextNP.setPos(0, 1, 7)
        #self.countdownTextNP.setH(180)

    def setupElevator(self, makeIvals=True):
        collisionRadius = ElevatorData[self.type]['collRadius']
        self.elevatorSphere = BulletSphereShape(collisionRadius)
        self.elevatorSphereNode = BulletGhostNode(
            self.uniqueName('elevatorSphere'))
        self.elevatorSphereNode.setKinematic(True)
        self.elevatorSphereNode.setIntoCollideMask(CIGlobals.EventGroup)
        self.elevatorSphereNode.addShape(
            self.elevatorSphere, TransformState.makePos(Point3(0, 5, 0)))
        self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(
            self.elevatorSphereNode)
        self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
        base.physicsWorld.attachGhost(self.elevatorSphereNode)
        if makeIvals:
            self.makeIvals()

    def makeIvals(self):
        self.openDoors = getOpenInterval(self, self.getLeftDoor(),
                                         self.getRightDoor(), self.openSfx,
                                         None, self.type)

        closeIval = getCloseInterval(self, self.getLeftDoor(),
                                     self.getRightDoor(), self.closeSfx, None,
                                     self.type)

        def maybeDoTransition():
            if self.localAvOnElevator:
                base.transitions.irisOut(t=closeIval.getDuration() / 1.75,
                                         blendType='easeIn')

        self.closeDoors = Parallel(
            Func(maybeDoTransition),
            Sequence(closeIval, Func(self.onDoorCloseFinish)))
        self.closeDoors.setDoneEvent(self.uniqueName('closeDoorsElevatorIval'))

    def disable(self):
        self.stopPoll()
        if hasattr(self, 'openDoors'):
            self.openDoors.pause()
        if hasattr(self, 'closeDoors'):
            self.closeDoors.pause()
        self.ignore('enter' + self.uniqueName('elevatorSphere'))
        base.physicsWorld.removeGhost(self.elevatorSphereNode)
        self.elevatorSphereNodePath.removeNode()
        del self.elevatorSphereNodePath
        del self.elevatorSphereNode
        del self.elevatorSphere
        self.fsm.request('off')
        self.openSfx = None
        self.closeSfx = None
        self.elevatorPoints = None
        self.type = None
        self.countdownTime = None
        self.localAvOnElevator = None
        self.thebldg = None
        self.bldgDoId = None
        self.toZoneId = None
        self.elevatorModel = None
        self.toonsInElevator = None
        self.hopOffButton = None
        self.leftDoor = None
        self.rightDoor = None
        self.openDoors = None
        self.closeDoors = None
        if self.countdownTextNP:
            self.countdownTextNP.removeNode()
            self.countdownTextNP = None
        DistributedObject.disable(self)

    def onDoorCloseFinish(self):
        print "Door close finish"
        if self.localAvOnElevator:
            base.localAvatar.wrtReparentTo(render)

            loader = 'suitInterior'
            where = 'suitInterior'
            how = 'IDK'
            world = base.cr.playGame.getCurrentWorldName()

            if self.thebldg.fsm.getCurrentState().getName() == 'bldgComplete':
                loader = 'townLoader'
                where = 'street'
                how = 'elevatorIn'
                world = ZoneUtil.CogTropolis

            requestStatus = {
                'zoneId': self.getToZoneId(),
                'hoodId': self.cr.playGame.hood.hoodId,
                'where': where,
                'avId': base.localAvatar.doId,
                'loader': loader,
                'shardId': None,
                'wantLaffMeter': 1,
                'world': world,
                'how': how
            }

            self.cr.playGame.getPlace().doneStatus = requestStatus
            messenger.send(self.cr.playGame.getPlace().doneEvent)

    def doMusic(self):
        self.elevMusic = base.loadMusic('phase_7/audio/bgm/tt_elevator.ogg')
        base.playMusic(self.elevMusic, looping=1)

    def fillSlot(self, index, avId):
        toon = self.cr.doId2do.get(avId)
        if toon:

            print "fillSlot", toon

            point = ElevatorPoints[index]

            track = Sequence()
            track.append(Func(toon.animFSM.request, 'run'))
            track.append(
                LerpPosInterval(toon,
                                duration=0.5,
                                pos=point,
                                startPos=toon.getPos(self.getElevatorModel())))
            track.append(
                LerpHprInterval(toon,
                                duration=0.3,
                                hpr=(180, 0, 0),
                                startHpr=toon.getHpr(self.getElevatorModel())))
            track.append(Func(toon.animFSM.request, 'neutral'))

            if avId == base.localAvatar.doId:
                self.localAvOnElevator = True
                print "We are now on this elevator"
                track.append(Func(self.showHopOffButton))
                base.localAvatar.stopSmartCamera()
                base.localAvatar.walkControls.setCollisionsActive(0)

                netTrans = base.camera.getNetTransform()
                base.camera.reparentTo(self.getElevatorModel())
                base.camera.setTransform(render, netTrans)
                cameraBoardTrack = LerpPosHprInterval(camera, 1.5,
                                                      Point3(0, -16, 5.5),
                                                      Point3(0, 0, 0))
                cameraBoardTrack.start()

            toon.stopSmooth()
            toon.wrtReparentTo(self.getElevatorModel())
            toon.headsUp(point)
            track.start()

    def emptySlot(self, index, avId):
        toon = self.cr.doId2do.get(avId)

        if toon:

            print "emptySlot", toon

            OutPoint = ElevatorOutPoints[index]
            InPoint = ElevatorPoints[index]
            toon.stopSmooth()
            toon.headsUp(OutPoint)
            track = Sequence(
                Func(toon.animFSM.request, 'run'),
                LerpPosInterval(toon,
                                duration=0.5,
                                pos=OutPoint,
                                startPos=InPoint),
                Func(toon.animFSM.request, 'neutral'),
                Func(toon.wrtReparentTo, render), Func(toon.startSmooth))
            if avId == base.localAvatar.doId:
                self.localAvOnElevator = False
                track.append(Func(self.freedom))
            track.start()

    def freedom(self):
        if self.fsm.getCurrentState().getName() in [
                'waitEmpty', 'waitCountdown'
        ]:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        base.localAvatar.walkControls.setCollisionsActive(1)
        self.cr.playGame.getPlace().fsm.request('walk')

    def setToonsInElevator(self, toonsInElevator):
        for i in xrange(len(toonsInElevator)):
            avId = toonsInElevator[i]
            toon = self.cr.doId2do.get(avId)
            if toon:
                toon.reparentTo(self.getElevatorModel())
                toon.stopSmooth()
                point = ElevatorPoints[i]
                toon.setPos(point)
                toon.setHpr(180, 0, 0)
                toon.animFSM.request('neutral')

    def getTheBldg(self):
        self.thebldg = self.cr.doId2do.get(self.bldgDoId)

    def getElevatorModel(self):
        return self.thebldg.getElevatorModel()

    def enterRejected(self):
        self.cr.playGame.getPlace().fsm.request('walk')

    def showHopOffButton(self):
        if self.fsm.getCurrentState().getName() not in [
                'waitEmpty', 'waitCountdown'
        ]:
            return

        gui = loader.loadModel('phase_3.5/models/gui/inventory_gui.bam')
        upButton = gui.find('**/InventoryButtonUp')
        downButton = gui.find('**/InventoryButtonDown')
        rlvrButton = gui.find('**/InventoryButtonRollover')
        self.hopOffBtn = DirectButton(relief=None,
                                      text="Hop off",
                                      text_fg=(0.9, 0.9, 0.9, 1),
                                      text_pos=(0, -0.23),
                                      text_scale=0.75,
                                      image=(upButton, downButton, rlvrButton),
                                      image_color=(0.5, 0.5, 0.5, 1),
                                      image_scale=(20, 1, 11),
                                      pos=(0, 0, 0.8),
                                      scale=0.15,
                                      command=self.handleHopOffButton)

    def hideHopOffButton(self):
        if hasattr(self, 'hopOffBtn'):
            self.hopOffBtn.destroy()
            del self.hopOffBtn

    def handleHopOffButton(self):
        self.hideHopOffButton()
        self.sendUpdate('requestExit')