Beispiel #1
0
    def initCollisions(self):
        # Make a sphere, give it a unique name, and parent it
        # to the suit.
        self.collSphere = CollisionSphere(0, 0, 0, 1.25)
        # Make he sphere intangible
        self.collSphere.setTangible(1)
        name = "CogThiefSphere-%d" % self.cogIndex
        self.collSphereName = self.uniqueName(name)
        self.collNode = CollisionNode(self.collSphereName)
        self.collNode.setIntoCollideMask(CTGG.BarrelBitmask
                                         | ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.suit.attachNewNode(self.collNode)
        #self.collNodePath.hide()

        # Add a hook looking for collisions with localToon
        self.accept('enter' + self.collSphereName, self.handleEnterSphere)

        # we need a taller collision tube to collide against for pie
        self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4,
                                           self.CollisionRadius)
        # Make he sphere intangible
        self.pieCollSphere.setTangible(1)
        name = "CogThiefPieSphere-%d" % self.cogIndex
        self.pieCollSphereName = self.uniqueName(name)
        self.pieCollNode = CollisionNode(self.pieCollSphereName)
        self.pieCollNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.pieCollNode.addSolid(self.pieCollSphere)
        self.pieCollNodePath = self.suit.attachNewNode(self.pieCollNode)
Beispiel #2
0
 def _initCollisions(self, triggerRadius, triggerOffset):
     self.collSphere = CollisionSphere(triggerOffset[0], triggerOffset[1],
                                       triggerOffset[2], triggerRadius)
     self.collSphere.setTangible(0)
     self.collNode = CollisionNode(self.getName())
     self.collNode.addSolid(self.collSphere)
     self.collNodePath = self.attachNewNode(self.collNode)
Beispiel #3
0
    def loadAssets(self):
        """Load our assets."""
        self.root = render.attachNewNode('golfSpot-%d' % self.index)
        self.root.setPos(*self.positions[self.index])
        self.ballModel = loader.loadModel('phase_6/models/golf/golf_ball')
        self.ballColor = VBase4(1, 1, 1, 1)
        if self.index < len(GolfGlobals.PlayerColors):
            self.ballColor = VBase4(*GolfGlobals.PlayerColors[self.index])
            self.ballModel.setColorScale(self.ballColor)
        self.ballModel.reparentTo(self.root)
        self.club = loader.loadModel('phase_6/models/golf/putter')
        self.clubLookatSpot = self.root.attachNewNode('clubLookat')
        self.clubLookatSpot.setY(-(GolfGlobals.GOLF_BALL_RADIUS + 0.1))

        # create a collision sphere to trigger when we touch the ball

        # Make a trigger sphere so we can detect when the local avatar
        # runs up to the controls.  We bury the sphere mostly under
        # the floor to minimize accidental collisions.
        cs = CollisionSphere(0, 0, 0, 1)
        cs.setTangible(0)
        cn = CollisionNode(self.triggerName)
        cn.addSolid(cs)
        cn.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.trigger = self.root.attachNewNode(cn)
        self.trigger.stash()

        self.hitBallSfx = loader.loadSfx('phase_6/audio/sfx/Golf_Hit_Ball.mp3')
Beispiel #4
0
 def _initCollisions(self):
     offset = Globals.WaterCoolerTriggerOffset
     self.collSphere = CollisionSphere(offset[0], offset[1], offset[2], Globals.WaterCoolerTriggerRadius)
     self.collSphere.setTangible(0)
     name = Globals.WaterCoolerCollisionName
     self.collNode = CollisionNode(name)
     self.collNode.addSolid(self.collSphere)
     self.collNodePath = self.attachNewNode(self.collNode)
    def _initCollisions(self):
        name = "CogdoMazeLock-%d" % self.id
        collSphere = CollisionSphere(0, 0, 0.0, 0.25)
        collSphere.setTangible(0)
        collNode = CollisionNode(name)
        collNode.setFromCollideMask(ToontownGlobals.CatchGameBitmask)
        collNode.addSolid(collSphere)
        self.model.attachNewNode(collNode)

        self.enterCollisionEventName = "enter" + name
Beispiel #6
0
 def initCollision(self):
     self.collSphere = CollisionSphere(0, 0, 0, 0)
     self.collSphere.setTangible(0)
     self.collNode = CollisionNode('%s-%s' % (self.CollSphereName, self.index))
     self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
     self.collNode.addSolid(self.collSphere)
     self.collNodePath = self.suit.attachNewNode(self.collNode)
     self.collNodePath.hide()
     self.accept('enter%s-%s' % (self.CollSphereName, self.index), self.handleEnterSphere)
     self.setCollSphereToNest()
Beispiel #7
0
    def pieThrow(self, avId, timestamp, heading, pos, power):
        """Show local or remote toon throwing a pie."""

        toon = self.activity.getAvatar(avId)

        if toon is None:
            return

        tossTrack, pieTrack, flyPie = self.getTossPieInterval(
            toon, pos[0], pos[1], pos[2], heading, 0, 0, power)

        if avId == base.localAvatar.doId:
            flyPie.setTag('throwerId', str(avId))

            collSphere = CollisionSphere(0, 0, 0, 0.5)
            # Make the sphere intangible
            collSphere.setTangible(0)
            name = "PieSphere-%d" % avId
            collSphereName = self.activity.uniqueName(name)
            collNode = CollisionNode(collSphereName)
            collNode.setFromCollideMask(ToontownGlobals.PieBitmask)
            collNode.addSolid(collSphere)
            collNP = flyPie.attachNewNode(collNode)

            base.cTrav.addCollider(collNP, self.pieHandler)

            self.toonPieEventNames[collNP] = 'pieHit-' + collSphereName
            self.accept(self.toonPieEventNames[collNP],
                        self.handlePieCollision)
        else:
            player = self.players.get(avId)
            if player is not None:
                player.faceForward()

        def matchRunningAnim(toon=toon):
            toon.playingAnim = None
            toon.setSpeed(toon.forwardSpeed, toon.rotateSpeed)

        newTossTrack = Sequence(tossTrack, Func(matchRunningAnim))

        pieTrack = Parallel(newTossTrack,
                            pieTrack,
                            name="PartyCogActivity.pieTrack-%d-%s" %
                            (avId, timestamp))

        elapsedTime = globalClockDelta.localElapsedTime(timestamp)

        if elapsedTime < 16. / 24.:
            elapsedTime = 16. / 24.  # make the pie fly immediately

        pieTrack.start(elapsedTime)

        self.pieIvals.append(pieTrack)
        self.toonPieTracks[avId] = pieTrack
Beispiel #8
0
 def createThrowGag(self, gag):
     throwGag = CogdoMazePlayer.createThrowGag(self, gag)
     collSphere = CollisionSphere(0, 0, 0, 0.5)
     collSphere.setTangible(0)
     name = Globals.GagCollisionName
     collNode = CollisionNode(name)
     collNode.setFromCollideMask(ToontownGlobals.PieBitmask)
     collNode.addSolid(collSphere)
     colNp = throwGag.attachNewNode(collNode)
     base.cTrav.addCollider(colNp, self.gagHandler)
     return throwGag
Beispiel #9
0
 def __initCollisions(self):
     collSphere = CollisionSphere(0, 0, 0, Globals.PlayerCollisionRadius)
     collSphere.setTangible(0)
     self.mazeCollisionName = Globals.LocalPlayerCollisionName
     collNode = CollisionNode(self.mazeCollisionName)
     collNode.addSolid(collSphere)
     collNodePath = self.toon.attachNewNode(collNode)
     collNodePath.hide()
     handler = CollisionHandlerEvent()
     handler.addInPattern('%fn-into-%in')
     base.cTrav.addCollider(collNodePath, handler)
     self.handler = handler
     self._collNodePath = collNodePath
Beispiel #10
0
 def setupHeadSphere(self, avatarNodePath):
     collSphere = CollisionSphere(0, 0, 0, 1)
     collSphere.setTangible(1)
     collNode = CollisionNode('Flyer.cHeadCollSphere')
     collNode.setFromCollideMask(ToontownGlobals.CeilingBitmask)
     collNode.setIntoCollideMask(BitMask32.allOff())
     collNode.addSolid(collSphere)
     self.cHeadSphereNodePath = avatarNodePath.attachNewNode(collNode)
     self.cHeadSphereNodePath.setZ(base.localAvatar.getHeight() + 1.0)
     self.headCollisionEvent = CollisionHandlerEvent()
     self.headCollisionEvent.addInPattern('%fn-enter-%in')
     self.headCollisionEvent.addOutPattern('%fn-exit-%in')
     base.cTrav.addCollider(self.cHeadSphereNodePath,
                            self.headCollisionEvent)
Beispiel #11
0
 def setupEventSphere(self, bitmask, avatarRadius):
     self.avatarRadius = avatarRadius
     cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75,
                               self.avatarRadius * 1.04)
     cSphere.setTangible(0)
     cSphereNode = CollisionNode('Flyer.cEventSphereNode')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     self.event = CollisionHandlerEvent()
     self.event.addInPattern('enter%in')
     self.event.addOutPattern('exit%in')
     self.cEventSphereNodePath = cSphereNodePath
Beispiel #12
0
    def loadCollision( self ):
        collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4)
        collTube.setTangible(True)
        self.trampolineCollision = CollisionNode(self.uniqueName("TrampolineCollision"))
        self.trampolineCollision.addSolid(collTube)
        self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask)
        self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision)

        collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0)
        collSphere.setTangible(False)
        self.trampolineTrigger = CollisionNode(self.uniqueName("TrampolineTrigger"))
        self.trampolineTrigger.addSolid(collSphere)
        self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger)
        self.accept( "enter%s" % self.uniqueName("TrampolineTrigger"), self.onTrampolineTrigger )
Beispiel #13
0
 def loadModel(self):
     """Load the necessary assets."""
     self.hill = loader.loadModel("phase_12/models/bossbotHQ/mole_hole")
     self.hill.setZ(0.0)
     self.hill.reparentTo(self)
     #self.hill.setScale(20.0)
     # find the collision node of the hill and rename it
     #hillCollision = self.hill.find('**/dirt_collision')
     self.hillColName = 'moleHillCol-%d-%d' % (self.moleField.doId, self.index)
     #hillCollision.setName(self.hillColName)
     self.moleField.accept('enter' + self.hillColName, self.moleField.handleEnterHill)
     self.mole = self.attachNewNode("mole")#loader.loadModel("phase_12/models/bossbotHQ/mole_norm")
     self.mole.reparentTo(self)
     self.mole.setScale(0.75)
     self.mole.setZ(-2.5)
     self.moleHead = loader.loadModel("phase_12/models/bossbotHQ/mole_norm")
     self.moleHead.reparentTo(self.mole)
     # setup mole collision
     moleColName = "moleCol-%d-%s" % (self.moleField.doId,self.index)
     moleSphere = CollisionSphere(0, 0, 0, 1.0)
     collNode = CollisionNode(moleColName)
     collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
     collNode.addSolid(moleSphere)
     self.moleColNodePath = self.mole.attachNewNode(collNode)
     self.moleColNodePath.stash()
     self.moleColNodePath.setScale(1.0)
     self.moleField.accept('enter' + moleColName, self.moleField.handleEnterMole)
Beispiel #14
0
    def setupElevatorKart(self):
        """Setup elevator related fields."""
        # Establish a collision sphere. There must be an easier way!
        collisionRadius = ElevatorConstants.ElevatorData[self.type]['collRadius']
        self.elevatorSphere = CollisionSphere(0, 0, 0, collisionRadius)
        self.elevatorSphere.setTangible(1)
        self.elevatorSphereNode = CollisionNode(self.uniqueName("elevatorSphere"))
        self.elevatorSphereNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.elevatorSphereNode.addSolid(self.elevatorSphere)
        self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(
            self.elevatorSphereNode)
        self.elevatorSphereNodePath.hide()
        self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
        self.elevatorSphereNodePath.stash()

        self.boardedAvIds = {}
        self.finishSetup()
Beispiel #15
0
    def generateInit(self):
        DistributedFireworkShow.DistributedFireworkShow.generateInit(self)
        """generateInit(self)
        This method is called when the DistributedObject is first introduced
        to the world... Not when it is pulled from the cache.
        """
        self.fireworksSphereEvent = self.uniqueName("fireworksSphere")
        self.fireworksSphereEnterEvent = "enter" + self.fireworksSphereEvent
        self.fireworksGuiDoneEvent = "fireworksGuiDone"
        self.shootEvent = "fireworkShootEvent"

        self.collSphere = CollisionSphere(0, 0, 0, 2.5)
        # Make the sphere intangible
        self.collSphere.setTangible(1)
        self.collNode = CollisionNode(self.fireworksSphereEvent)
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.geom.attachNewNode(self.collNode)
Beispiel #16
0
 def setupFloorEventSphere(self, avatarNodePath, bitmask, avatarRadius):
     cSphere = CollisionSphere(0.0, 0.0, 0.0, 0.75)
     cSphereNode = CollisionNode('Flyer.cFloorEventSphere')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     self.floorCollisionEvent = CollisionHandlerEvent()
     self.floorCollisionEvent.addInPattern('%fn-enter-%in')
     self.floorCollisionEvent.addAgainPattern('%fn-again-%in')
     self.floorCollisionEvent.addOutPattern('%fn-exit-%in')
     base.cTrav.addCollider(cSphereNodePath, self.floorCollisionEvent)
     self.cFloorEventSphereNodePath = cSphereNodePath
Beispiel #17
0
 def getFlyBallBubble(self):
     if self.__flyBallBubble == None:
         bubble = CollisionSphere(0, 0, 0, GolfGlobals.GOLF_BALL_RADIUS)
         node = CollisionNode('flyBallBubble')
         node.addSolid(bubble)
         node.setFromCollideMask(ToontownGlobals.PieBitmask
                                 | ToontownGlobals.CameraBitmask
                                 | ToontownGlobals.FloorBitmask)
         node.setIntoCollideMask(BitMask32.allOff())
         self.__flyBallBubble = NodePath(node)
         self.flyBallHandler = CollisionHandlerEvent()
         self.flyBallHandler.addInPattern('flyBallHit-%d' % self.index)
         #self.flyBallHandler.addInPattern('flyBallHit-%d--%in')
     return self.__flyBallBubble
Beispiel #18
0
 def setupWallSphere(self, bitmask, avatarRadius):
     self.avatarRadius = avatarRadius
     cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75,
                               self.avatarRadius)
     cSphereNode = CollisionNode('Flyer.cWallSphereNode')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     if ConfigVariableBool('want-fluid-pusher', 0).getValue():
         self.pusher = CollisionHandlerFluidPusher()
     else:
         self.pusher = CollisionHandlerPusher()
     self.pusher.addCollider(cSphereNodePath, self.avatarNodePath)
     self.cWallSphereNodePath = cSphereNodePath
Beispiel #19
0
    def generate(self):
        """generate(self)
        This method is called when the DistributedObject is reintroduced
        to the world, either for the first time or from the cache.
        """
        DistributedObject.DistributedObject.generate(self)

        loader = self.cr.playGame.hood.loader
        partyGate = loader.geom.find('**/partyGate_grp')
        if partyGate.isEmpty():
            self.notify.warning('Could not find partyGate_grp in loader.geom')
            return
        self.clockFlat = partyGate.find("**/clock_flat")
        collSphere = CollisionSphere(0, 0, 0, 6.9)
        collSphere.setTangible(1)
        self.partyGateSphere = CollisionNode("PartyGateSphere")
        self.partyGateSphere.addSolid(collSphere)
        self.partyGateCollNodePath = partyGate.find(
            "**/partyGate_stepsLocator").attachNewNode(self.partyGateSphere)
        self.__enableCollisions()
        #        self.tunnelOrigin = NodePath("PartyGateTunnelOrigin")
        #        self.tunnelOrigin.reparentTo(partyGate)
        #        self.tunnelOrigin.setPos(partyGate.find("**/clockText_locator").getPos() + Point3(0.0, 0.0, -12.0))

        self.toontownTimeGui = ServerTimeGui(partyGate,
                                             hourCallback=self.hourChange)
        self.toontownTimeGui.setPos(
            partyGate.find("**/clockText_locator").getPos() +
            Point3(0.0, 0.0, -0.2))
        self.toontownTimeGui.setHpr(
            partyGate.find("**/clockText_locator").getHpr())
        self.toontownTimeGui.setScale(12.0, 1.0, 26.0)
        self.toontownTimeGui.amLabel.setPos(-0.035, 0, -0.032)
        self.toontownTimeGui.amLabel.setScale(0.5)
        self.toontownTimeGui.updateTime()
        self.setupSignText()
Beispiel #20
0
    def load(self):
        self.root = NodePath("PartyCog-%d" % self.id)
        self.root.reparentTo(self.parentNode)

        path = "phase_13/models/parties/cogPinata_"
        self.actor = Actor(
            path + "actor", {
                "idle": path + "idle_anim",
                "down": path + "down_anim",
                "up": path + "up_anim",
                "bodyHitBack": path + "bodyHitBack_anim",
                "bodyHitFront": path + "bodyHitFront_anim",
                "headHitBack": path + "headHitBack_anim",
                "headHitFront": path + "headHitFront_anim",
            })
        self.actor.reparentTo(self.root)

        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode("temphead")

        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)

        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)

        # Cog's Left Arm
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)

        # Cog's Right Arm
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)

        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)

        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3')

        self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole")
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin("ground", 3)
        self.hole.reparentTo(self.parentNode)
Beispiel #21
0
class CogdoGameGatherable(NodePath, DirectObject):
    EnterEventName = 'CogdoGameGatherable_Enter'

    def __init__(self,
                 serialNum,
                 model,
                 triggerRadius,
                 triggerOffset=(0, 0, 0),
                 animate=True,
                 animDuration=0.2,
                 instanceModel=True,
                 name='CogdoGameGatherable'):
        NodePath.__init__(self, '%s-%d' % (name, serialNum))
        self.serialNum = serialNum
        self._animate = animate
        if instanceModel:
            model.instanceTo(self)
            self._model = self
        else:
            self._model = model
            self._model.reparentTo(self)
            self._model.setPosHpr(0, 0, 0, 0, 0, 0)
        self._animDuration = animDuration
        self._animSeq = None
        self._initCollisions(triggerRadius, triggerOffset)
        self._update = None
        self._wasPickedUp = False
        return

    def _initCollisions(self, triggerRadius, triggerOffset):
        self.collSphere = CollisionSphere(triggerOffset[0], triggerOffset[1],
                                          triggerOffset[2], triggerRadius)
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode(self.getName())
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.attachNewNode(self.collNode)

    def destroy(self):
        self.disable()
        del self._model
        if self._animSeq is not None:
            self._animSeq.finish()
            self._animSeq = None
        self.collNodePath.removeNode()
        self.removeNode()
        return

    def enable(self):
        self.accept('enter' + self.getName(), self._handleEnterCollision)
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)

    def disable(self):
        self.ignoreAll()
        self.collNode.setIntoCollideMask(BitMask32(0))

    def show(self):
        if not self.wasPickedUp():
            NodePath.show(self)
            self.enable()

    def hide(self):
        self.disable()
        NodePath.hide(self)

    def _handleEnterCollision(self, collEntry):
        messenger.send(CogdoGameGatherable.EnterEventName, [self])

    def wasPickedUp(self):
        return self._wasPickedUp

    def wasPickedUpByToon(self):
        pass

    def update(self, dt):
        pass

    def getModel(self):
        return self._model

    def pickUp(self, toon, elapsedSeconds=0.0):
        self._wasPickedUp = True
        if self._animSeq is not None:
            self._animSeq.finish()
            self._animSeq = None
        if self._animate:

            def lerpFlyToToon(t):
                vec = toon.getPos(render) - self.getPos(render)
                vec[2] += toon.getHeight()
                self.setPos(self.getPos() + vec * t)
                self.setScale(1.0 - t * 0.8)

            self._animSeq = Sequence(
                LerpFunc(lerpFlyToToon,
                         fromData=0.0,
                         toData=1.0,
                         duration=self._animDuration), Wait(0.1),
                Func(self.hide))
            self._animSeq.start(elapsedSeconds)
        else:
            self.hide()
        return
Beispiel #22
0
class CogThief(DirectObject):
    """This represents a single cog thief in the cog thief game"""
    notify = directNotify.newCategory("CogThief")
    DefaultSpeedWalkAnim = 4.
    CollisionRadius = 1.25
    MaxFriendsVisible = 4
    Infinity = 100000.0  # just a really big number
    SeparationDistance = 6.0
    MinUrgency = 0.5
    MaxUrgency = 0.75

    def __init__(self, cogIndex, suitType, game, cogSpeed):
        self.cogIndex = cogIndex
        self.suitType = suitType
        self.game = game
        self.cogSpeed = cogSpeed
        suit = Suit.Suit()
        d = SuitDNA.SuitDNA()
        d.newSuit(suitType)
        suit.setDNA(d)
        # cache the walk anim
        suit.pose('walk', 0)
        self.suit = suit
        self.goal = CTGG.NoGoal
        self.goalId = CTGG.InvalidGoalId
        self.lastLocalTimeStampFromAI = 0
        self.lastPosFromAI = Point3(0, 0, 0)
        self.lastThinkTime = 0
        self.doneAdjust = False
        self.barrel = CTGG.NoBarrelCarried
        self.signalledAtReturnPos = False
        self.defaultPlayRate = 1.0
        self.netTimeSentToStartByHit = 0

        # steering loosely based on boid code game programming gems #1
        # "Portions Copyright (C) Steven Woodcock, 2000"
        self.velocity = Vec3(0, 0, 0)
        self.oldVelocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)
        self.bodyLength = self.CollisionRadius * 2
        # Desired distance from closest neighbor when flying.
        self.cruiseDistance = 2 * self.bodyLength
        self.maxVelocity = self.cogSpeed
        # Maximum magnitude of acceleration as a fraction of maxSpeed.
        self.maxAcceleration = 5.0
        self.perceptionRange = 6
        self.notify.debug('cogSpeed=%s' % self.cogSpeed)

        self.kaboomSound = loader.loadSfx(
            "phase_4/audio/sfx/MG_cannon_fire_alt.mp3")
        self.kaboom = loader.loadModel(
            'phase_4/models/minigames/ice_game_kaboom')
        self.kaboom.setScale(2.0)
        self.kaboom.setBillboardPointEye()
        self.kaboom.hide()
        self.kaboomTrack = None

        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)

        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')

    def destroy(self):
        self.ignoreAll()
        self.suit.delete()
        self.game = None

    def uniqueName(self, baseStr):
        return baseStr + '-' + str(self.game.doId)

    def handleEnterSphere(self, collEntry):
        """Handle the suit colliding with localToon."""
        #assert self.notify.debugStateCall(self)
        intoNp = collEntry.getIntoNodePath()
        self.notify.debug('handleEnterSphere suit %d hit %s' %
                          (self.cogIndex, intoNp))
        if self.game:
            self.game.handleEnterSphere(collEntry)

    def gameStart(self, gameStartTime):
        self.gameStartTime = gameStartTime

        self.initCollisions()
        self.startWalkAnim()

    def gameEnd(self):
        self.moveIval.pause()
        del self.moveIval

        self.shutdownCollisions()

        # keep the suits from walking in place
        self.suit.loop('neutral')

    def initCollisions(self):
        # Make a sphere, give it a unique name, and parent it
        # to the suit.
        self.collSphere = CollisionSphere(0, 0, 0, 1.25)
        # Make he sphere intangible
        self.collSphere.setTangible(1)
        name = "CogThiefSphere-%d" % self.cogIndex
        self.collSphereName = self.uniqueName(name)
        self.collNode = CollisionNode(self.collSphereName)
        self.collNode.setIntoCollideMask(CTGG.BarrelBitmask
                                         | ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.suit.attachNewNode(self.collNode)
        #self.collNodePath.hide()

        # Add a hook looking for collisions with localToon
        self.accept('enter' + self.collSphereName, self.handleEnterSphere)

        # we need a taller collision tube to collide against for pie
        self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4,
                                           self.CollisionRadius)
        # Make he sphere intangible
        self.pieCollSphere.setTangible(1)
        name = "CogThiefPieSphere-%d" % self.cogIndex
        self.pieCollSphereName = self.uniqueName(name)
        self.pieCollNode = CollisionNode(self.pieCollSphereName)
        self.pieCollNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.pieCollNode.addSolid(self.pieCollSphere)
        self.pieCollNodePath = self.suit.attachNewNode(self.pieCollNode)
        #self.pieCollNodePath.show()

        # Add a hook looking for collisions with localToon
        #self.accept('enter' + self.pieCollSphereName,
        #            self.handleEnter)

    def shutdownCollisions(self):
        self.ignore(self.uniqueName('enter' + self.collSphereName))

        del self.collSphere
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode

    def updateGoal(self, timestamp, inResponseClientStamp, goalType, goalId,
                   pos):
        """Update our goal and position."""
        assert self.notify.debugStateCall(self)
        self.notify.debug('self.netTimeSentToStartByHit =%s' %
                          self.netTimeSentToStartByHit)
        if not self.game:
            self.notify.debug('updateGoal self.game is None, just returning')
            return
        if not self.suit:
            self.notify.debug('updateGoal self.suit is None, just returning')
            return
        if self.goal == CTGG.NoGoal:
            self.startWalkAnim()

        if goalType == CTGG.NoGoal:
            self.notify.debug('updateGoal setting position to %s' % pos)
            self.suit.setPos(pos)

        self.lastThinkTime = 0
        self.velocity = Vec3(0, 0, 0)
        self.oldVelocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)

        if goalType == CTGG.RunAwayGoal:
            #import pdb; pdb.set_trace()
            pass

        if inResponseClientStamp < self.netTimeSentToStartByHit and \
           self.goal == CTGG.NoGoal and \
           goalType == CTGG.RunAwayGoal:
            #import pdb; pdb.set_trace()
            self.notify.warning(
                'ignoring newGoal %s as cog %d was recently hit responsetime=%s hitTime=%s'
                % (CTGG.GoalStr[goalType], self.cogIndex,
                   inResponseClientStamp, self.netTimeSentToStartByHit))
        else:
            self.lastLocalTimeStampFromAI = globalClockDelta.networkToLocalTime(
                timestamp, bits=32)
            self.goal = goalType
            self.goalId = goalId
            self.lastPosFromAI = pos
            self.doneAdjust = False
        self.signalledAtReturnPos = False
        # TODO move the suit to where we expect him to be given the time difference

    def startWalkAnim(self):
        if self.suit:
            self.suit.loop('walk')
            speed = self.cogSpeed  # float(MazeData.CELL_WIDTH) / self.cellWalkDuration
            self.defaultPlayRate = float(self.cogSpeed /
                                         self.DefaultSpeedWalkAnim)
            self.suit.setPlayRate(self.defaultPlayRate, 'walk')

    def think(self):
        """Calculate where we should go."""
        if self.goal == CTGG.ToonGoal:
            self.thinkAboutCatchingToon()
        elif self.goal == CTGG.BarrelGoal:
            self.thinkAboutGettingBarrel()
        elif self.goal == CTGG.RunAwayGoal:
            self.thinkAboutRunAway()

    def thinkAboutCatchingToon(self):
        if not self.game:
            return

        av = self.game.getAvatar(self.goalId)
        if av:
            if not self.lastThinkTime:
                self.lastThinkTime = globalClock.getFrameTime()
            diffTime = globalClock.getFrameTime() - self.lastThinkTime
            avPos = av.getPos()
            myPos = self.suit.getPos()

            if not self.doneAdjust:
                myPos = self.lastPosFromAI
                self.notify.debug(
                    'thinkAboutCatchingToon not doneAdjust setting pos %s' %
                    myPos)
                self.doneAdjust = True

            self.suit.setPos(myPos)

            if self.game.isToonPlayingHitTrack(self.goalId):
                # do nothing, just look at toon
                self.suit.headsUp(av)
                self.velocity = Vec3(0, 0, 0)
                self.oldVelocity = Vec3(0, 0, 0)
                self.acceleration = Vec3(0, 0, 0)
            else:
                self.commonMove()

            newPos = self.suit.getPos()
            self.adjustPlayRate(newPos, myPos, diffTime)

        self.lastThinkTime = globalClock.getFrameTime()

    def convertNetworkStampToGameTime(self, timestamp):
        """Convert a network timestamp to game time."""
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        gameTime = self.game.local2GameTime(localStamp)
        return gameTime

    def respondToToonHit(self, timestamp):
        """The toon hit us, react appropriately."""
        assert self.notify.debugStateCall(self)
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        # using 1.0 sec as fudge
        #if localStamp > self.lastLocalTimeStampFromAI:
        if self.netTimeSentToStartByHit < timestamp:
            self.clearGoal()
            self.showKaboom()
            # move him to his starting postion
            startPos = CTGG.CogStartingPositions[self.cogIndex]
            oldPos = self.suit.getPos()
            self.suit.setPos(startPos)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToToonHit'
                % (localStamp, self.lastLocalTimeStampFromAI))
        self.notify.debug(
            'respondToToonHit self.netTimeSentToStartByHit = %s' %
            self.netTimeSentToStartByHit)

    def clearGoal(self):
        """Clear goal and goal id."""
        self.goal = CTGG.NoGoal
        self.goalId = CTGG.InvalidGoalId

    def thinkAboutGettingBarrel(self):
        """Go for  a barrel."""
        if not self.game:
            return

        if not hasattr(self.game, 'barrels'):
            return
        if not self.goalId in range(len(self.game.barrels)):
            return

        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        diffTime = globalClock.getFrameTime() - self.lastThinkTime
        barrel = self.game.barrels[self.goalId]
        barrelPos = barrel.getPos()
        myPos = self.suit.getPos()
        if not self.doneAdjust:
            myPos = self.lastPosFromAI
            self.notify.debug(
                'thinkAboutGettingBarrel not doneAdjust setting position to %s'
                % myPos)
            self.suit.setPos(myPos)
            """
            diffTime = globalClock.getFrameTime()- self.lastLocalTimeStampFromAI
            self.notify.debug('doing adjust, diffTime = %s' % diffTime)
            if diffTime < 0:
                # it just looks really weird when it moves backwards
                diffTime = 0
                self.notify.debug('forcing diffTime to %s' % diffTime)
            """
            self.doneAdjust = True
        displacement = barrelPos - myPos
        distanceToToon = displacement.length()
        #self.notify.debug('diffTime = %s' % diffTime)
        self.suit.headsUp(barrel)
        lengthTravelled = diffTime * self.cogSpeed
        #self.notify.debug('lengthTravelled = %s' % lengthTravelled)
        # don't overshoot our target
        if lengthTravelled > distanceToToon:
            lengthTravelled = distanceToToon
            #self.notify.debug('overshooting lengthTravelled = %s' % lengthTravelled)
        displacement.normalize()
        dirVector = displacement
        dirVector *= lengthTravelled
        newPos = myPos + dirVector
        # always keep them grounded
        newPos.setZ(0)
        self.suit.setPos(newPos)
        self.adjustPlayRate(newPos, myPos, diffTime)

        self.lastThinkTime = globalClock.getFrameTime()

    def stopWalking(self, timestamp):
        """Stop the cog from walking."""
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        if localStamp > self.lastLocalTimeStampFromAI:
            self.suit.loop('neutral')
            self.clearGoal()

    def thinkAboutRunAway(self):
        """Go for  a barrel."""
        if not self.game:
            return
        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        diffTime = globalClock.getFrameTime() - self.lastThinkTime

        returnPos = CTGG.CogReturnPositions[self.goalId]
        myPos = self.suit.getPos()
        if not self.doneAdjust:
            myPos = self.lastPosFromAI
            self.suit.setPos(myPos)
            """
            diffTime = globalClock.getFrameTime()- self.lastLocalTimeStampFromAI
            self.notify.debug('run away doing adjust, diffTime = %s' % diffTime)
            if diffTime < 0:
                # it just looks really weird when it moves backwards
                diffTime = 0
                self.notify.debug('forcing diffTime to %s' % diffTime)
            """
            self.doneAdjust = True
        displacement = returnPos - myPos
        distanceToToon = displacement.length()
        #self.notify.debug('diffTime = %s' % diffTime)
        tempNp = render.attachNewNode('tempRet')
        tempNp.setPos(returnPos)
        self.suit.headsUp(tempNp)
        tempNp.removeNode()
        lengthTravelled = diffTime * self.cogSpeed
        #self.notify.debug('lengthTravelled = %s' % lengthTravelled)
        # don't overshoot our target
        if lengthTravelled > distanceToToon:
            lengthTravelled = distanceToToon
            #self.notify.debug('overshooting lengthTravelled = %s' % lengthTravelled)
        displacement.normalize()
        dirVector = displacement
        dirVector *= lengthTravelled
        newPos = myPos + dirVector
        # always keep them grounded
        newPos.setZ(0)
        self.suit.setPos(newPos)
        self.adjustPlayRate(newPos, myPos, diffTime)

        if (self.suit.getPos() - returnPos).length() < 0.0001:
            if not self.signalledAtReturnPos and self.barrel >= 0:
                # tell the AI we're at return Pos
                self.game.sendCogAtReturnPos(self.cogIndex, self.barrel)
                self.signalledAtReturnPos = True

        self.lastThinkTime = globalClock.getFrameTime()

    def makeCogCarryBarrel(self, timestamp, inResponseClientStamp, barrelModel,
                           barrelIndex, cogPos):
        """Handle the AI telling us the barrel is attached to a cog."""
        #assert self.notify.debugStateCall(self)
        if not self.game:
            return
        localTimeStamp = globalClockDelta.networkToLocalTime(timestamp,
                                                             bits=32)
        # TODO validate time?
        self.lastLocalTimeStampFromAI = localTimeStamp
        inResponseGameTime = self.convertNetworkStampToGameTime(
            inResponseClientStamp)

        self.notify.debug('inResponseGameTime =%s timeSentToStart=%s' %
                          (inResponseGameTime, self.netTimeSentToStartByHit))
        if inResponseClientStamp  < self.netTimeSentToStartByHit and \
           self.goal == CTGG.NoGoal:
            self.notify.warning('ignoring makeCogCarrybarrel')
        else:
            barrelModel.setPos(0, -1.0, 1.5)
            barrelModel.reparentTo(self.suit)
            self.suit.setPos(cogPos)
            self.barrel = barrelIndex

    def makeCogDropBarrel(self, timestamp, inResponseClientStamp, barrelModel,
                          barrelIndex, barrelPos):
        """Handle the AI telling us the barrel is attached to a cog."""
        #assert self.notify.debugStateCall(self)
        localTimeStamp = globalClockDelta.networkToLocalTime(timestamp,
                                                             bits=32)
        # TODO validate time?
        self.lastLocalTimeStampFromAI = localTimeStamp

        barrelModel.reparentTo(render)
        barrelModel.setPos(barrelPos)

        self.barrel = CTGG.NoBarrelCarried

        #
        #self.suit.setPos(cogPos)

    def respondToPieHit(self, timestamp):
        """The toon hit us, react appropriately."""
        assert self.notify.debugStateCall(self)
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        # argh using 1.0 sec as fudge
        #if localStamp  > self.lastLocalTimeStampFromAI:
        if self.netTimeSentToStartByHit < timestamp:
            self.clearGoal()
            self.showSplat()
            # move him to his starting postion
            startPos = CTGG.CogStartingPositions[self.cogIndex]
            oldPos = self.suit.getPos()
            self.suit.setPos(startPos)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit'
                % (localStamp, self.lastLocalTimeStampFromAI))
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def cleanup(self):
        """Do whatever is necessary to cleanup properly."""
        self.clearGoal()
        self.ignoreAll()
        self.suit.delete()
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.suit = None
        self.game = None

    def adjustPlayRate(self, newPos, oldPos, diffTime):
        """Adjust animation rate based on how far he's moved."""
        # lets slowdown playrate if they're not moving much
        lengthTravelled = (newPos - oldPos).length()
        if diffTime:
            speed = lengthTravelled / diffTime
        else:
            speed = self.cogSpeed
        rateMult = speed / self.cogSpeed
        newRate = rateMult * self.defaultPlayRate
        self.suit.setPlayRate(newRate, 'walk')

    def commonMove(self):
        """Move the cog thief. Common for all 3 behaviors """
        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        dt = globalClock.getFrameTime() - self.lastThinkTime

        # Step 1:  Update our position.
        # Update our position based on the velocity
        # vector we computed last time around.

        self.oldpos = self.suit.getPos()
        # save off our previous position

        pos = self.suit.getPos()
        pos += self.velocity * dt
        # apply velocities.
        self.suit.setPos(pos)

        # Step 2:  SeeFriends.
        # Determine if we can see any of our flockmates.

        self.seeFriends()

        acc = Vec3(0, 0, 0)

        # well first off we want to move to our target
        self.accumulate(acc, self.getTargetVector())

        # Step 3:  Flocking behavior.
        # Do we see any of our flockmates?  If yes, it's time to implement
        # the first Three Rules (they don't matter if we can't see anybody)

        if self.numFlockmatesSeen > 0:
            #if hasattr(base,'doDebug') and base.doDebug:
            #    import pdb; pdb.set_trace()
            keepDistanceVector = self.keepDistance()
            oldAcc = Vec3(acc)
            self.accumulate(acc, keepDistanceVector)
            if self.cogIndex == 0:
                #self.notify.debug('oldAcc=%s, keepDist=%s newAcc=%s' %
                #                  (oldAcc,keepDistanceVector, acc))
                pass

        # Step 8:  Constrain acceleration
        # If our acceleration change is more than we allow, constrain it

        if (acc.length() > self.maxAcceleration):
            # definitely too much...constrain to maximum change
            acc.normalize()
            acc *= self.maxAcceleration

        # Step 9:  Implementation.
        # Here's where we apply our newly computed acceleration vector
        # to create a new velocity vector to use next update cycle.

        self.oldVelocity = self.velocity
        # save off our previous velocity

        # now add in the acceleration

        self.velocity += acc

        # Step 10:  constraint Y velocity changes.
        # Attempt to restrict flight straight up/down by damping out Y axis velocity.
        # This isn't strictly necessary, but does lead to more realistic looking flight.

        # Step 11:  Constrain our speed.
        # If we're moving faster than we're allowed to move, constrain our velocity.
        if self.velocity.length() > self.maxVelocity:
            self.velocity.normalize()
            self.velocity *= self.maxVelocity

        # Step 12:  Compute roll/pitch/yaw.
        # Compute our orientation after all this speed adjustment nonsense.
        # bah no need, we turn on a dime towards our velocity
        forwardVec = Vec3(1, 0, 0)
        heading = rad2Deg(math.atan2(self.velocity[1], self.velocity[0]))
        heading -= 90
        self.suit.setH(heading)

    def getTargetVector(self):
        """Return a vector to my goal."""
        targetPos = Point3(0, 0, 0)
        if self.goal == CTGG.ToonGoal:
            av = self.game.getAvatar(self.goalId)
            if av:
                targetPos = av.getPos()
        elif self.goal == CTGG.BarrelGoal:
            barrel = self.game.barrels[self.goalId]
            targetPos = barrel.getPos()
        elif self.goal == CTGG.RunAwayGoal:
            targetPos = CTGG.CogReturnPositions[self.goalId]
        targetPos.setZ(0)
        myPos = self.suit.getPos()
        diff = targetPos - myPos
        if diff.length() > 1.0:
            diff.normalize()
            diff *= 1.0

        return diff

    def accumulate(self, accumulator, valueToAdd):
        """Return the magnitude of the accumulated vector."""

        accumulator += valueToAdd

        return accumulator.length()

    def seeFriends(self):
        """Determines which flockmates a given flock boid can see."""
        # clear the existing visibility list of any holdover from last round

        self.clearVisibleList()

        for cogIndex in list(self.game.cogInfo.keys()):
            if cogIndex == self.cogIndex:
                continue

            if self.sameGoal(cogIndex):
                dist = self.canISee(cogIndex)
                if dist != self.Infinity:
                    self.addToVisibleList(cogIndex)
                    if dist < self.distToNearestFlockmate:
                        self.nearestFlockmate = cogIndex
                        self.distToNearestFlockmate = dist

        return self.numFlockmatesSeen

    def clearVisibleList(self):
        """Clears the visibility list and associated fields."""
        self.visibleFriendsList = []
        self.numFlockmatesSeen = 0
        self.nearestFlockmate = None
        self.distToNearestFlockmate = self.Infinity

    def addToVisibleList(self, cogIndex):
        """Add the cog to the visible list."""
        # test:  do we see enough buddies already?
        if self.numFlockmatesSeen < self.MaxFriendsVisible:
            #nope--we can add to this one to the list
            self.visibleFriendsList.append(cogIndex)
            self.numFlockmatesSeen += 1
            if self.cogIndex == 0:
                #self.notify.debug('self.numFlockmatesSeen = %s' % self.numFlockmatesSeen)
                pass

    def canISee(self, cogIndex):
        """Return distance if I can see the other cog, infinity otherwise"""

        if self.cogIndex == cogIndex:
            # well we should never see ourself
            return self.Infinity

        cogThief = self.game.getCogThief(cogIndex)
        distance = self.suit.getDistance(cogThief.suit)

        if distance < self.perceptionRange:
            #self.notify.debug('%s can see %s' % (self.cogIndex, cogIndex))
            return distance

        # fell through; can not see it
        return self.Infinity

    def sameGoal(self, cogIndex):
        """Return true if we have the same goal."""
        cogThief = self.game.getCogThief(cogIndex)
        result = (cogThief.goalId == self.goalId) and (cogThief.goal
                                                       == self.goal)
        return result

    def keepDistance(self):
        """Generates a vector for a flock boid to maintain his
        desired separation distance from the nearest flockmate he sees.
        """
        ratio = self.distToNearestFlockmate / self.SeparationDistance
        nearestThief = self.game.getCogThief(self.nearestFlockmate)
        change = nearestThief.suit.getPos() - self.suit.getPos()

        if ratio < self.MinUrgency:
            ratio = self.MinUrgency
        if ratio > self.MaxUrgency:
            ratio = self.MaxUrgency

        # test:  are we too close to our nearest flockmate?
        if self.distToNearestFlockmate < self.SeparationDistance:
            #self.notify.debug('%d is too close to %d' % (self.cogIndex, self.nearestFlockmate))

            # too close...move away from our neighbor
            change.normalize()
            change *= -(1 - ratio
                        )  # the close we are the more we are pushed away
        elif self.distToNearestFlockmate > self.SeparationDistance:
            # too far away move towards our neighbor
            change.normalize()
            change *= ratio
        else:
            # in the UNLIKELY event we're exactly the right distance away, do nothing
            change = Vec3(0, 0, 0)

        return change

    def showKaboom(self):
        """Show the kaboom graphic and sound."""
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboom.reparentTo(render)
        self.kaboom.setPos(self.suit.getPos())
        self.kaboom.setZ(3)

        self.kaboomTrack = Parallel(
            SoundInterval(self.kaboomSound, volume=0.5),
            Sequence(
                Func(self.kaboom.showThrough),
                LerpScaleInterval(self.kaboom,
                                  duration=0.5,
                                  scale=Point3(10, 10, 10),
                                  startScale=Point3(1, 1, 1),
                                  blendType='easeOut'),
                Func(self.kaboom.hide),
            ))
        self.kaboomTrack.start()

    def showSplat(self):
        """Show the splat graphic and sound."""
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.splat.reparentTo(render)
        self.splat.setPos(self.suit.getPos())
        self.splat.setZ(3)

        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound, volume=1.0),
            Sequence(
                Func(self.splat.showThrough),
                LerpScaleInterval(self.splat,
                                  duration=0.5,
                                  scale=1.75,
                                  startScale=Point3(0.1, 0.1, 0.1),
                                  blendType='easeOut'),
                Func(self.splat.hide),
            ))
        self.kaboomTrack.start()
Beispiel #23
0
class PartyCog(FSM):
    notify = directNotify.newCategory("PartyCog")

    HpTextGenerator = TextNode("HpTextGenerator")
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id

        FSM.__init__(self, "PartyCogFSM-%d" % self.id)

        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0

        self.load()
        self.request("Down")

    def load(self):
        self.root = NodePath("PartyCog-%d" % self.id)
        self.root.reparentTo(self.parentNode)

        path = "phase_13/models/parties/cogPinata_"
        self.actor = Actor(
            path + "actor", {
                "idle": path + "idle_anim",
                "down": path + "down_anim",
                "up": path + "up_anim",
                "bodyHitBack": path + "bodyHitBack_anim",
                "bodyHitFront": path + "bodyHitFront_anim",
                "headHitBack": path + "headHitBack_anim",
                "headHitFront": path + "headHitFront_anim",
            })
        self.actor.reparentTo(self.root)

        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode("temphead")

        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)

        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)

        # Cog's Left Arm
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)

        # Cog's Right Arm
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)

        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)

        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3')

        self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole")
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin("ground", 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request("Off")
        self.clearHitInterval()

        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        if self.root is not None:
            self.root.removeNode()
            self.root = None

        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None

        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None

        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None

        del self.upSound
        del self.pieHitSound

#===============================================================================
# FSM States
#===============================================================================

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)

        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime

        taskMgr.add(updateTask, "PartyCog.update-%d" % self.id)

    def exitActive(self):
        taskMgr.remove("PartyCog.update-%d" % self.id)
        taskMgr.remove("PartyCog.bounceTask-%d" % self.id)

        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType="easeInOut")
        self.resetRollIval.start()

        self.actor.stop()

    def enterDown(self):
        if self.oldState == "Off":
            self.actor.pose("down", self.actor.getNumFrames("down") - 1)
            return

        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType="easeIn"),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, "down", loop=0),
            ),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType="easeOut"),
        )
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType="easeIn"),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, "up", loop=0),
            ),
            Func(self.actor.loop, "idle"),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType="easeOut"),
        )
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == "Down":
            return None
        else:
            return self.defaultFilter(request, args)

#------------------------------------------------------------------------------

    def setEndPoints(self, start, end, amplitude=1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0

        self.root.setR(angle)

        #        if self.id == 0:
        #            print angle

        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)

        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)

        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0

        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)

        self.root.setH(self.currentFacing)

        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(
            t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, "PartyCog.bounceTask-%d" % self.id)

    def bounce(self, task):
        #self.root.setH(self.root.getH() - self.rotateSpeed)
        self.root.setZ((math.sin((self.bounceOffset + task.time) *
                                 self.bounceSpeed) * self.bounceHeight) +
                       self.heightShift)

        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        """The toon hit us, react appropriately."""
        assert (self.notify.debugStateCall(self))

        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)

            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            #self.notify.debug('localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI))
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()

    def __showSplat(self, position, direction, hot=False):
        """Show the splat graphic and sound."""
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()

        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()

        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)

        if not direction == 1.0:
            #self.splat.setColorScale(Vec4(0.0, 0.0, 50.0, 1.0))
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = "HitFront"
            else:
                facing = "HitBack"
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            #self.splat.setColorScale(Vec4(1.0, 0.6, 0.08, 1.0))
            if self.currentFacing > 0.0:
                facing = "HitBack"
            else:
                facing = "HitFront"

        if hot:
            targetscale = 0.75
            part = "head"
        else:
            targetscale = 0.5
            part = "body"

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, "idle"),
        )
        self.hitInterval.start()

        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType="easeOut"),
                        Wait(0.175),
                    ),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(
                            setSplatAlpha,
                            duration=1.0,  #0.4,
                            fromData=1.0,
                            toData=0.0,
                            blendType="easeOut"))),
                Func(self.splat.cleanup),
                Func(self.splat.removeNode),
            ))
        self.kaboomTrack.start()

    def showHitScore(self, number, scale=1):
        """
        Shows the hit score.
        Borrowed from otp.avatar.DistributedAvatar.showHpText
        """
        if number <= 0:
            return

        # Get rid of the number if it is already there.
        if self.hpText:
            self.hideHitScore()

        # Set the font
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())

        # Show both negative and positive signs
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText("+" + str(number))

        # No shadow
        self.HpTextGenerator.clearShadow()

        # Center the number
        self.HpTextGenerator.setAlign(TextNode.ACenter)

        # Red, always
        #if number < 0:
        r = 1  #0.9
        g = 1  #0
        b = 0
        a = 1

        self.HpTextGenerator.setTextColor(r, g, b, a)

        self.hpTextNode = self.HpTextGenerator.generate()

        # Put the hpText over the head of the avatar
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        # Make sure it is a billboard
        self.hpText.setBillboardPointEye()
        # Render it after other things in the scene.
        self.hpText.setBin('fixed', 100)

        # Initial position ... Center of the body... the "tan tien"
        self.hpText.setPos(self.root, 0, 0, self.height / 2)

        # Black magic from the early days of Panda3D, later replaced by a Sequence
        seq = Task.sequence(
            # Fly the number out of the character
            self.hpText.lerpPos(Point3(
                self.root.getX(render), self.root.getY(render),
                self.root.getZ(render) + self.height + 1.0),
                                0.25,
                                blendType='easeOut'),
            Task.pause(0.25),
            # Fade the number
            self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1),
            # Get rid of the number
            Task.Task(self.__hideHitScoreTask))

        taskMgr.add(seq, "PartyCogHpText" + str(self.id))

    def __hideHitScoreTask(self, task):
        self.hideHitScore()

        return Task.done

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove("PartyCogHpText" + str(self.id))
            self.hpText.removeNode()
            self.hpText = None

    def getHeadLocation(self):
        (self.actor.getJoints(jointName="head")[0]).getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        #print self.head_locator.getZ()

        return self.head_locator.getZ(self.root)
Beispiel #24
0
class CogdoMazeWaterCooler(NodePath, DirectObject):
    UpdateTaskName = 'CogdoMazeWaterCooler_Update'

    def __init__(self, serialNum, model):
        NodePath.__init__(self, 'CogdoMazeWaterCooler-%i' % serialNum)
        self.serialNum = serialNum
        self._model = model
        self._model.reparentTo(self)
        self._model.setPosHpr(0, 0, 0, 0, 0, 0)
        self._initCollisions()
        self._initArrow()
        self._update = None
        self.__startUpdateTask()
        return

    def destroy(self):
        self.ignoreAll()
        self.__stopUpdateTask()
        self.collNodePath.removeNode()
        self.removeNode()

    def _initCollisions(self):
        offset = Globals.WaterCoolerTriggerOffset
        self.collSphere = CollisionSphere(offset[0], offset[1], offset[2], Globals.WaterCoolerTriggerRadius)
        self.collSphere.setTangible(0)
        name = Globals.WaterCoolerCollisionName
        self.collNode = CollisionNode(name)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.attachNewNode(self.collNode)

    def _initArrow(self):
        matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui')
        arrow = matchingGameGui.find('**/minnieArrow')
        arrow.setScale(Globals.CoolerArrowScale)
        arrow.setColor(*Globals.CoolerArrowColor)
        arrow.setPos(0, 0, Globals.CoolerArrowZ)
        arrow.setHpr(0, 0, 90)
        arrow.setBillboardAxis()
        self._arrow = NodePath('Arrow')
        arrow.reparentTo(self._arrow)
        self._arrow.reparentTo(self)
        self._arrowTime = 0
        self.accept(Globals.WaterCoolerShowEventName, self.showArrow)
        self.accept(Globals.WaterCoolerHideEventName, self.hideArrow)
        matchingGameGui.removeNode()

    def showArrow(self):
        self._arrow.unstash()

    def hideArrow(self):
        self._arrow.stash()

    def update(self, dt):
        newZ = math.sin(globalClock.getFrameTime() * Globals.CoolerArrowSpeed) * Globals.CoolerArrowBounce
        self._arrow.setZ(newZ)

    def __startUpdateTask(self):
        self.__stopUpdateTask()
        self._update = taskMgr.add(self._updateTask, self.UpdateTaskName, 45)

    def __stopUpdateTask(self):
        if self._update is not None:
            taskMgr.remove(self._update)
        return

    def _updateTask(self, task):
        dt = globalClock.getDt()
        self.update(dt)
        return Task.cont
Beispiel #25
0
    def loadLever(self):
        """
        SubClasses can override this if they want to move their lever somewhere
        special... call this, then change the position.
        """
        self.lever = self.root.attachNewNode('%sLever' % self.activityName)
        self.leverModel = self.party.defaultLeverModel.copyTo(self.lever)
        # Do some crazy reparenting so you can scale the whole thing nicely
        self.controlColumn = NodePath('cc')
        column = self.leverModel.find('**/column')
        column.getChildren().reparentTo(self.controlColumn)
        self.controlColumn.reparentTo(column)
        self.stickHinge = self.controlColumn.attachNewNode('stickHinge')
        self.stick = self.party.defaultStickModel.copyTo(self.stickHinge)
        self.stickHinge.setHpr(0.0, 90.0, 0.0)
        self.stick.setHpr(0, -90.0, 0)
        self.stick.flattenLight()
        self.bottom = self.leverModel.find('**/bottom')
        self.bottom.wrtReparentTo(self.controlColumn)
        self.bottomPos = self.bottom.getPos()

        # Make a trigger sphere so we can detect when the local avatar
        # runs up to the lever.
        cs = CollisionSphere(0.0, 1.35, 2.0, 1.0)
        cs.setTangible(False)
        cn = CollisionNode(self.leverTriggerEvent)
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTrigger = self.root.attachNewNode(cn)
        self.leverTrigger.reparentTo(self.lever)
        self.leverTrigger.stash()

        # Also, a solid tube to keep us from running through the
        # lever itself.  This one scales with the control
        # model.
        cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2)
        cn = CollisionNode('levertube')
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTube = self.leverModel.attachNewNode(cn)

        # Let's set the height of the lever to the height of the host
        host = base.cr.doId2do.get(self.party.partyInfo.hostId)
        if host is None:
            self.notify.debug(
                "%s loadLever : Host has left the game before lever could be created."
                % self.activityName)
            return

        # We start by figuring out where we are going by setting the
        # scale and position appropriately
#        origScale = self.leverModel.getSz()
#        origCcPos = self.controlColumn.getPos()
#        origBottomPos = self.bottom.getPos()
#        origStickHingeHpr = self.stickHinge.getHpr()

# First, scale the thing overall to match the host's scale,
# including cheesy effect scales.
        scale = host.getGeomNode().getChild(0).getSz(render)
        self.leverModel.setScale(scale)

        # Then get the position of the host's right hand when he's
        # standing at the controls in a leverNeutral pose.
        self.controlColumn.setPos(0, 0, 0)
        host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0)
        host.pose('leverNeutral', 0)
        host.update()
        pos = host.rightHand.getPos(self.controlColumn)

        # Now set the control column to the right height and position
        # to put the top of the stick approximately in his hand.
        self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1)

        # And put the bottom piece back on the floor, wherever that
        # is from here.
        self.bottom.setZ(host, 0.0)
        self.bottom.setPos(self.bottomPos[0], self.bottomPos[1],
                           self.bottom.getZ())

        # Also put the joystick in his hand.
        lookAtPoint = Point3(0.3, 0, 0.1)
        lookAtUp = Vec3(0, -1, 0)
        self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp)

        host.play('walk')
        host.update()
Beispiel #26
0
 def _initCollisions(self):
     collSphere = CollisionSphere(0, 0, 0, 3.0)
     collSphere.setTangible(0)
     self.collNode = CollisionNode(self.getName())
     self.collNode.addSolid(collSphere)
     self.collNP = self.attachNewNode(self.collNode)
Beispiel #27
0
    def __init__(self, model, pos, serialNum, gameId, penalty=False):
        # there are going to be MANY (~650) of these created and destroyed
        # all at once for 4-player games; make it lean
        self.serialNum = serialNum

        self.penalty = penalty

        # the fruit has a bit of height, lets recenter
        center = model.getBounds().getCenter()
        center = Point3(0, 0, 0)
        self.nodePath = model.copyTo(render)
        self.nodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                             pos[2] - center[2])
        self.nodePath.setZ(0)  # real assets have bottom at zero
        self.notify.debug('newPos = %s' % self.nodePath.getPos())
        #self.nodePath.setScale(1.0)

        #if self.penalty:
        #    self.nodePath.setColorScale(0.5,0.5,0.5,1.0)

        # Make a sphere, name it uniquely, and child it
        # to the nodepath.
        if self.penalty:
            self.sphereName = "penaltySphere-%s-%s" % (gameId, self.serialNum)
        else:
            self.sphereName = "treasureSphere-%s-%s" % (gameId, self.serialNum)
        self.collSphere = CollisionSphere(center[0], center[1], center[2],
                                          self.RADIUS)
        # Make the sphere intangible
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode(self.sphereName)
        self.collNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = render.attachNewNode(self.collNode)
        self.collNodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                                 pos[2] - center[2])
        self.collNodePath.hide()
        self.track = None

        # Add a hook looking for collisions with localToon
        #self.accept('enter' + self.sphereName, self.__handleEnterSphere)

        # now that the treasure and sphere have been placed, flatten the
        # whole silly thing
        # self.nodePath.flattenLight()

        if self.penalty:
            #self.nodePath.setScale(1,1,0.5)
            self.tip = self.nodePath.find('**/fusetip')
            #self.tip.setX(2)
            #self.tip.setY(0.5)
            #self.tip.setZ(1.5)
            sparks = BattleParticles.createParticleEffect(file='icetnt')
            self.sparksEffect = sparks
            sparks.start(self.tip)
            self.penaltyGrabSound = loader.loadSfx(
                "phase_4/audio/sfx/MG_cannon_fire_alt.mp3")
            self.penaltyGrabSound.setVolume(0.75)
            kaboomAttachPoint = self.nodePath.attachNewNode('kaboomAttach')
            kaboomAttachPoint.setZ(3)
            self.kaboom = loader.loadModel(
                'phase_4/models/minigames/ice_game_kaboom')
            self.kaboom.reparentTo(kaboomAttachPoint)
            #self.kaboom.hide()
            self.kaboom.setScale(2.0)
            self.kaboom.setBillboardPointEye()
Beispiel #28
0
class IceTreasure(DirectObject):
    """
    Treasures toons can pickup swinging from ice to ice.  Based on MazeTreasure
    """

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

    RADIUS = 1.0

    def __init__(self, model, pos, serialNum, gameId, penalty=False):
        # there are going to be MANY (~650) of these created and destroyed
        # all at once for 4-player games; make it lean
        self.serialNum = serialNum

        self.penalty = penalty

        # the fruit has a bit of height, lets recenter
        center = model.getBounds().getCenter()
        center = Point3(0, 0, 0)
        self.nodePath = model.copyTo(render)
        self.nodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                             pos[2] - center[2])
        self.nodePath.setZ(0)  # real assets have bottom at zero
        self.notify.debug('newPos = %s' % self.nodePath.getPos())
        #self.nodePath.setScale(1.0)

        #if self.penalty:
        #    self.nodePath.setColorScale(0.5,0.5,0.5,1.0)

        # Make a sphere, name it uniquely, and child it
        # to the nodepath.
        if self.penalty:
            self.sphereName = "penaltySphere-%s-%s" % (gameId, self.serialNum)
        else:
            self.sphereName = "treasureSphere-%s-%s" % (gameId, self.serialNum)
        self.collSphere = CollisionSphere(center[0], center[1], center[2],
                                          self.RADIUS)
        # Make the sphere intangible
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode(self.sphereName)
        self.collNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = render.attachNewNode(self.collNode)
        self.collNodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                                 pos[2] - center[2])
        self.collNodePath.hide()
        self.track = None

        # Add a hook looking for collisions with localToon
        #self.accept('enter' + self.sphereName, self.__handleEnterSphere)

        # now that the treasure and sphere have been placed, flatten the
        # whole silly thing
        # self.nodePath.flattenLight()

        if self.penalty:
            #self.nodePath.setScale(1,1,0.5)
            self.tip = self.nodePath.find('**/fusetip')
            #self.tip.setX(2)
            #self.tip.setY(0.5)
            #self.tip.setZ(1.5)
            sparks = BattleParticles.createParticleEffect(file='icetnt')
            self.sparksEffect = sparks
            sparks.start(self.tip)
            self.penaltyGrabSound = loader.loadSfx(
                "phase_4/audio/sfx/MG_cannon_fire_alt.mp3")
            self.penaltyGrabSound.setVolume(0.75)
            kaboomAttachPoint = self.nodePath.attachNewNode('kaboomAttach')
            kaboomAttachPoint.setZ(3)
            self.kaboom = loader.loadModel(
                'phase_4/models/minigames/ice_game_kaboom')
            self.kaboom.reparentTo(kaboomAttachPoint)
            #self.kaboom.hide()
            self.kaboom.setScale(2.0)
            self.kaboom.setBillboardPointEye()
            #self.kaboom.setBin('fixed', serialNum)
            #self.kaboom.setDepthTest(False)
            #self.kaboom.setDepthWrite(False)

    def destroy(self):
        self.ignoreAll()
        if self.penalty:
            self.sparksEffect.cleanup()
            if self.track:
                self.track.finish()

        self.nodePath.removeNode()
        del self.nodePath
        del self.collSphere
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode

##     def __handleEnterSphere(self, collEntry):
##         self.ignoreAll()
##         # announce that this treasure was grabbed
##         self.notify.debug('treasuerGrabbed')
##         messenger.send("IceTreasureGrabbed", [self.serialNum])

    def showGrab(self):
        self.nodePath.hide()
        self.collNodePath.hide()
        # disable collisions
        self.collNode.setIntoCollideMask(BitMask32(0))
        if self.penalty:
            self.track = Parallel(
                SoundInterval(self.penaltyGrabSound),
                Sequence(
                    Func(self.kaboom.showThrough),
                    LerpScaleInterval(self.kaboom,
                                      duration=0.5,
                                      scale=Point3(10, 10, 10),
                                      blendType='easeOut'),
                    Func(self.kaboom.hide),
                ))
            self.track.start()
Beispiel #29
0
class DistributedCogKart(DistributedElevatorExt.DistributedElevatorExt):

    notify = DirectNotifyGlobal.directNotify.newCategory("DistributedCogKart")
    JumpOutOffsets = ((6.5, -2, -0.025),
                      (-6.5, -2, -0.025),
                      (3.75, 5, -0.025),
                      (-3.75, 5, -0.025))

    def __init__(self, cr):
        """__init__(cr)
        """
        DistributedElevatorExt.DistributedElevatorExt.__init__(self, cr)
        self.type = ElevatorConstants.ELEVATOR_COUNTRY_CLUB
        # note since we did elevator init last, self.fsm is DistributedElevator.fsm
        self.kartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam'
        self.leftDoor = None
        self.rightDoor = None
        self.fillSlotTrack = None

    def generate(self):
        """generate(self)
        This method is called when the DistributedObject is reintroduced
        to the world, either for the first time or from the cache.
        """
        DistributedElevatorExt.DistributedElevatorExt.generate(self)

        # Get the state machine stuff for playGame
        self.loader = self.cr.playGame.hood.loader
        if(self.loader):
            self.notify.debug("Loader has been loaded")
            self.notify.debug(str(self.loader))
        else:
            self.notify.debug("Loader has not been loaded")

        self.golfKart = render.attachNewNode('golfKartNode')
        self.kart = loader.loadModel(self.kartModelPath)
        self.kart.setPos(0, 0, 0)
        self.kart.setScale(1)
        self.kart.reparentTo(self.golfKart)
        self.golfKart.reparentTo(self.loader.geom)

        # Wheels
        self.wheels = self.kart.findAllMatches('**/wheelNode*')
        self.numWheels = self.wheels.getNumPaths()


    def announceGenerate(self):
        """Setup other fields dependent on the required fields."""
        DistributedElevatorExt.DistributedElevatorExt.announceGenerate(self)

        angle = self.startingHpr[0]
        angle -= 90
        radAngle = deg2Rad(angle)
        unitVec = Vec3( math.cos(radAngle), math.sin(radAngle), 0)
        unitVec *= 45.0
        self.endPos =  self.startingPos + unitVec
        self.endPos.setZ(0.5)

        dist = Vec3(self.endPos - self.enteringPos).length()
        wheelAngle = (dist / (4.8 * 1.4 * math.pi)) * 360

        self.kartEnterAnimateInterval = Parallel(
            # start a lerp HPR for each wheel
            LerpHprInterval(self.wheels[0], 5.0, Vec3(self.wheels[0].getH(), wheelAngle, self.wheels[0].getR())),
            LerpHprInterval(self.wheels[1], 5.0, Vec3(self.wheels[1].getH(), wheelAngle, self.wheels[1].getR())),
            LerpHprInterval(self.wheels[2], 5.0, Vec3(self.wheels[2].getH(), wheelAngle, self.wheels[2].getR())),
            LerpHprInterval(self.wheels[3], 5.0, Vec3(self.wheels[3].getH(), wheelAngle, self.wheels[3].getR())),
            name = "CogKartAnimate")

        trolleyExitTrack1 = Parallel(
            LerpPosInterval(self.golfKart, 5.0, self.endPos),
            self.kartEnterAnimateInterval,
            name = "CogKartExitTrack")
        self.trolleyExitTrack = Sequence(
            trolleyExitTrack1,
            # Func(self.hideSittingToons), # we may not need this
            )

        self.trolleyEnterTrack = Sequence(
            LerpPosInterval(self.golfKart, 5.0, self.startingPos, startPos = self.enteringPos))

        self.closeDoors = Sequence(
            self.trolleyExitTrack,
            Func(self.onDoorCloseFinish))
        self.openDoors = Sequence(
            self.trolleyEnterTrack
            )

    def delete(self):
        """
        This method is called when the DistributedObject is permanently
        removed from the world and deleted from the cache.
        """
        DistributedElevatorExt.DistributedElevatorExt.delete(self)
        if hasattr(self, 'elevatorFSM') :
            del self.elevatorFSM

    def setBldgDoId(self, bldgDoId):
        """Handle the AI telling us the associated bldg doid."""
        # The doId is junk, there is no building object for the factory
        # exterior elevators. Do the appropriate things that
        # DistributedElevator.gotBldg does.
        self.bldg = None
        self.setupElevatorKart()

    def setupElevatorKart(self):
        """Setup elevator related fields."""
        # Establish a collision sphere. There must be an easier way!
        collisionRadius = ElevatorConstants.ElevatorData[self.type]['collRadius']
        self.elevatorSphere = CollisionSphere(0, 0, 0, collisionRadius)
        self.elevatorSphere.setTangible(1)
        self.elevatorSphereNode = CollisionNode(self.uniqueName("elevatorSphere"))
        self.elevatorSphereNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.elevatorSphereNode.addSolid(self.elevatorSphere)
        self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(
            self.elevatorSphereNode)
        self.elevatorSphereNodePath.hide()
        self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
        self.elevatorSphereNodePath.stash()

        self.boardedAvIds = {}
        self.finishSetup()

    def setColor(self, r, g, b):
        """Ignore this AI message to make it look cog grayish."""
        pass

    def getElevatorModel(self):
        return self.golfKart

    def enterWaitEmpty(self, ts):
        """Handle entering the wait empty state."""
        DistributedElevatorExt.DistributedElevatorExt.enterWaitEmpty(self, ts)

    def exitWaitEmpty(self):
        """Handle exiting the wait empty state."""
        DistributedElevatorExt.DistributedElevatorExt.exitWaitEmpty(self)

    def forceDoorsOpen(self):
        """Deliberately do nothing."""
        pass

    def forceDoorsClosed(self):
        """Deliberately do nothing."""
        pass

    def setPosHpr(self, x, y, z, h, p ,r):
        """Set the pos hpr as dictated by the AI."""
        self.startingPos = Vec3(x, y, z)
        self.enteringPos = Vec3(x, y, z - 10)
        self.startingHpr = Vec3(h, 0, 0)
        self.golfKart.setPosHpr( x, y, z, h, 0, 0 )

    def enterClosing(self, ts):
        # Close the elevator doors
        if self.localToonOnBoard:
            elevator = self.getPlaceElevator()
            if elevator:
                elevator.fsm.request("elevatorClosing")
        self.closeDoors.start(ts)

    def enterClosed(self, ts):
        self.forceDoorsClosed()
        self.kartDoorsClosed(self.getZoneId())
        return

    def kartDoorsClosed(self, zoneId):
        assert(self.notify.debug('doorsClosed()'))
        if (self.localToonOnBoard):
            hoodId = ZoneUtil.getHoodId(zoneId)
            doneStatus = {
                'loader' : 'suitInterior',
                'where' : 'suitInterior',
                'hoodId' : hoodId,
                'zoneId' : zoneId,
                'shardId' : None,
                }

            elevator = self.elevatorFSM #self.getPlaceElevator()
            del self.elevatorFSM
            elevator.signalDone(doneStatus)


    def setCountryClubInteriorZone(self, zoneId):
        if (self.localToonOnBoard):
            hoodId = self.cr.playGame.hood.hoodId
            countryClubId = self.countryClubId
            if bboard.has('countryClubIdOverride'):
                countryClubId = bboard.get('countryClubIdOverride')
            doneStatus = {
                'loader' : "cogHQLoader",
                'where'  : "countryClubInterior",
                'how'    : "teleportIn",
                'zoneId' : zoneId,
                'countryClubId' : self.countryClubId,
                'hoodId' : hoodId,
                }
            self.cr.playGame.getPlace().elevator.signalDone(doneStatus)

    def setCountryClubInteriorZoneForce(self, zoneId):
        place = self.cr.playGame.getPlace()
        if place:
            place.fsm.request("elevator", [self, 1])
            hoodId = self.cr.playGame.hood.hoodId
            countryClubId = self.countryClubId
            if bboard.has('countryClubIdOverride'):
                countryClubId = bboard.get('countryClubIdOverride')
            doneStatus = {
                'loader' : "cogHQLoader",
                'where'  : "countryClubInterior",
                'how'    : "teleportIn",
                'zoneId' : zoneId,
                'countryClubId' : self.countryClubId,
                'hoodId' : hoodId,
                }
            if hasattr(place, 'elevator') and place.elevator:
                place.elevator.signalDone(doneStatus)
            else:
                self.notify.warning("setMintInteriorZoneForce: Couldn't find playGame.getPlace().elevator, zoneId: %s" %zoneId)
        else:
            self.notify.warning("setCountryClubInteriorZoneForce: Couldn't find playGame.getPlace(), zoneId: %s" %zoneId)

    def setCountryClubId(self, countryClubId):
        self.countryClubId = countryClubId

    def getZoneId(self):
        return 0

    def fillSlot(self, index, avId, wantBoardingShow = 0):
        """Put someone in the kart, as dictated by the AI."""
        self.notify.debug("%s.fillSlot(%s, %s, ... %s)" % (self.doId, index, avId, globalClock.getRealTime()))
        request = self.toonRequests.get(index)
        if request:
            self.cr.relatedObjectMgr.abortRequest(request)
            del self.toonRequests[index]

        if avId == 0:
            # This means that the slot is now empty, and no action should
            # be taken.
            pass

        elif avId not in self.cr.doId2do:
            # It's someone who hasn't been generated yet.
            func = PythonUtil.Functor(
                self.gotToon, index, avId)

            assert index not in self.toonRequests
            self.toonRequests[index] = self.cr.relatedObjectMgr.requestObjects(
                [avId], allCallback = func)

        elif not self.isSetup:
            # We haven't set up the elevator yet.
            self.deferredSlots.append((index, avId, wantBoardingShow))

        else:
            # If localToon is boarding, he needs to change state
            if avId == base.localAvatar.getDoId():
                place = base.cr.playGame.getPlace()
                if not place:
                    return
                elevator = self.getPlaceElevator()
                if elevator == None:
                    place.fsm.request('elevator')
                    elevator = self.getPlaceElevator()
                if not elevator:
                    return

                self.localToonOnBoard = 1

                if hasattr(localAvatar, "boardingParty") and localAvatar.boardingParty:
                    localAvatar.boardingParty.forceCleanupInviteePanel()
                    localAvatar.boardingParty.forceCleanupInviterPanels()

                # Cleanup any leftover elevator messages before boarding the elevator.
                if hasattr(base.localAvatar, "elevatorNotifier"):
                    base.localAvatar.elevatorNotifier.cleanup()

                cameraTrack = Sequence()
                # Move the camera towards and face the elevator.
                cameraTrack.append(Func(elevator.fsm.request, "boarding", [self.getElevatorModel()]))
                # Enable the Hop off button.
                cameraTrack.append(Func(elevator.fsm.request, "boarded"))

            toon = self.cr.doId2do[avId]
            # Parent it to the elevator
            toon.stopSmooth()
            toon.wrtReparentTo(self.golfKart)

            sitStartDuration = toon.getDuration("sit-start")
            jumpTrack = self.generateToonJumpTrack(toon, index)

            track = Sequence(
				jumpTrack,
                Func(toon.setAnimState, "Sit", 1.0),
                Func(self.clearToonTrack, avId),
                name = toon.uniqueName("fillElevator"),
                autoPause = 1)

            if wantBoardingShow:
                boardingTrack, boardingTrackType = self.getBoardingTrack(toon, index, True)
                track = Sequence(boardingTrack, track)

                if avId == base.localAvatar.getDoId():
                    cameraWaitTime = 2.5
                    if (boardingTrackType == BoardingGroupShow.TRACK_TYPE_RUN):
                        cameraWaitTime = 0.5
                    cameraTrack = Sequence(Wait(cameraWaitTime), cameraTrack)

            if self.canHideBoardingQuitBtn(avId):
                track = Sequence(Func(localAvatar.boardingParty.groupPanel.disableQuitButton),
                                 track)

            # Start the camera track in parallel here
            if avId == base.localAvatar.getDoId():
                track = Parallel(cameraTrack, track)

            track.delayDelete = DelayDelete.DelayDelete(toon, 'CogKart.fillSlot')
            self.storeToonTrack(avId, track)
            track.start()

            self.fillSlotTrack = track

            assert avId not in self.boardedAvIds
            self.boardedAvIds[avId] = None

    def generateToonJumpTrack(self, av, seatIndex):
        """Return an interval of the toon jumping into the golf kart."""
        av.pose('sit', 47)
        hipOffset = av.getHipsParts()[2].getPos(av)

        def getToonJumpTrack( av, seatIndex ):
            # using a local func allows the ProjectileInterval to
            # calculate this pos at run-time
            def getJumpDest(av = av, node = self.golfKart):
                dest = Point3(0,0,0)
                if hasattr(self, 'golfKart') and self.golfKart:
                    dest = Vec3(self.golfKart.getPos(av.getParent()))
                    seatNode = self.golfKart.find("**/seat" + str(seatIndex + 1))
                    dest += seatNode.getPos(self.golfKart)
                    dna = av.getStyle()
                    dest -= hipOffset
                    if(seatIndex < 2):
                        dest.setY( dest.getY() + 2 * hipOffset.getY())
                    dest.setZ(dest.getZ() + 0.1)
                else:
                    self.notify.warning('getJumpDestinvalid golfKart, returning (0,0,0)')
                return dest

            def getJumpHpr(av = av, node = self.golfKart):
                hpr = Point3(0,0,0)
                if hasattr(self, 'golfKart') and self.golfKart:
                    hpr = self.golfKart.getHpr(av.getParent())
                    if(seatIndex < 2):
                        hpr.setX( hpr.getX() + 180)
                    else:
                        hpr.setX( hpr.getX() )
                    angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
                    hpr.setX(angle)
                else:
                    self.notify.warning('getJumpHpr invalid golfKart, returning (0,0,0)')
                return hpr

            toonJumpTrack = Parallel(ActorInterval( av, 'jump' ),
                                     Sequence(Wait( 0.43 ),
                                              Parallel(LerpHprInterval(av,
                                                                       hpr = getJumpHpr,
                                                                       duration = .9 ),
                                                       ProjectileInterval(av,
                                                                          endPos = getJumpDest,
                                                                          duration = .9 ),
                                                      ),
                                             ),
                                    )
            return toonJumpTrack

        def getToonSitTrack( av ):
            toonSitTrack = Sequence(

                ActorInterval( av, 'sit-start' ),
                Func( av.loop, 'sit' )
                )
            return toonSitTrack

        toonJumpTrack = getToonJumpTrack( av, seatIndex )
        toonSitTrack = getToonSitTrack( av )

        jumpTrack = Sequence(
            Parallel(
                toonJumpTrack,
                Sequence( Wait(1),
                          toonSitTrack,
                          ),
                ),
##            Func( av.wrtReparentTo, self.golfKart ),
            )

        return jumpTrack


    def emptySlot(self, index, avId, bailFlag, timestamp, timeSent=0):
        """Remove someone as dictated by the AI."""
        if self.fillSlotTrack:
            self.fillSlotTrack.finish()
            self.fillSlotTrack = None

        # If localToon is exiting, he needs to change state
        if avId == 0:
            # This means that no one is currently exiting, and no action
            # should be taken
            pass

        elif not self.isSetup:
            # We haven't set up the elevator yet.  Remove the toon
            # from the deferredSlots list, if it is there.
            newSlots = []
            for slot in self.deferredSlots:
                if slot[0] != index:
                    newSlots.append(slot)

            self.deferredSlots = newSlots

        else:
            if avId in self.cr.doId2do:
                # See if we need to reset the clock
                # (countdown assumes we've created a clockNode already)
                if (bailFlag == 1 and hasattr(self, 'clockNode')):
                    if (timestamp < self.countdownTime and
                        timestamp >= 0):
                        self.countdown(self.countdownTime - timestamp)
                    else:
                        self.countdown(self.countdownTime)
                # If the toon exists, look it up
                toon = self.cr.doId2do[avId]
                # avoid wrtReparent so that we don't muck with the toon's scale
                # Parent it to render
                #toon.wrtReparentTo(render)
                toon.stopSmooth()

                sitStartDuration = toon.getDuration("sit-start")
                jumpOutTrack = self.generateToonReverseJumpTrack(toon, index)

                # Place it on the appropriate spot relative to the
                # elevator

                track = Sequence(
                    # TODO: Find the right coords for the elevator
                    jumpOutTrack,
                    # Tell the toon he is free to roam now
                    Func(self.notifyToonOffElevator, toon),
                    Func(self.clearToonTrack, avId),
                    name = toon.uniqueName("emptyElevator"),
                    autoPause = 1)

                if self.canHideBoardingQuitBtn(avId):
                    # Enable the Boarding Group Panel Quit Button here if it is relevant.
                    track.append(Func(localAvatar.boardingParty.groupPanel.enableQuitButton))
                    # Enable the Boarding Group GO Button here if it is relevant.
                    track.append(Func(localAvatar.boardingParty.enableGoButton))

                track.delayDelete = DelayDelete.DelayDelete(toon, 'CogKart.emptySlot')
                self.storeToonTrack(toon.doId, track)
                track.start()

                # Tell localToon he is exiting (if localToon is on board)
                if avId == base.localAvatar.getDoId():
                    messenger.send("exitElevator")

                # if the elevator is generated as a toon is leaving it,
                # we will not have gotten a corresponding 'fillSlot' message
                # for that toon, hence the toon will not be found in
                # boardedAvIds
                if avId in self.boardedAvIds:
                    del self.boardedAvIds[avId]

            else:
                self.notify.warning("toon: " + str(avId) +
                                                  " doesn't exist, and" +
                                                  " cannot exit the elevator!")

    def generateToonReverseJumpTrack( self, av, seatIndex ):
        """Return an interval of the toon jumping out of the golf kart."""
        self.notify.debug("av.getH() = %s" % av.getH())
        def getToonJumpTrack( av, destNode ):
            # using a local func allows the ProjectileInterval to
            # calculate this pos at run-time
            def getJumpDest(av = av, node = destNode):
                dest = node.getPos(av.getParent())
                dest += Vec3(*self.JumpOutOffsets[seatIndex])
                return dest

            def getJumpHpr(av = av, node = destNode):
                hpr = node.getHpr(av.getParent())
                hpr.setX( hpr.getX() + 180)
                angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
                hpr.setX(angle)
                return hpr

            toonJumpTrack = Parallel(
                ActorInterval( av, 'jump' ),
                Sequence(
                  Wait( 0.1), #43 ),
                  Parallel( #LerpHprInterval( av,
                            #                 hpr = getJumpHpr,
                            #                 duration = .9 ),
                            ProjectileInterval( av,
                                                endPos = getJumpDest,
                                                duration = .9 ) )
                  )
                )
            return toonJumpTrack

        toonJumpTrack = getToonJumpTrack( av, self.golfKart)
        jumpTrack = Sequence(
            toonJumpTrack,
            Func( av.loop, 'neutral' ),
            Func( av.wrtReparentTo, render ),
            #Func( self.av.setPosHpr, self.exitMovieNode, 0,0,0,0,0,0 ),
            )
        return jumpTrack

    def startCountdownClock(self, countdownTime, ts):
        """Start the countdown clock."""
        # just reverse the text counter
        DistributedElevatorExt.DistributedElevatorExt.startCountdownClock(self, countdownTime, ts)
        self.clock.setH(self.clock.getH() + 180)

    def rejectBoard(self, avId, reason = 0):
        """Show the reason why he was rejected."""
        # Only difference from base clase is the use of KartMinLaff
        # This should only be sent to us if our localToon requested
        # permission to board the elevator.
        # reason 0: unknown, 1: shuffle, 2: too low laff, 3: no seat, 4: need promotion
        print(("rejectBoard %s" % (reason)))
        if hasattr(base.localAvatar, "elevatorNotifier"):
            if reason == ElevatorConstants.REJECT_SHUFFLE:
                base.localAvatar.elevatorNotifier.showMe(TTLocalizer.ElevatorHoppedOff)
            elif reason == ElevatorConstants.REJECT_MINLAFF:
                base.localAvatar.elevatorNotifier.showMe((TTLocalizer.KartMinLaff % (self.minLaff)))
            elif reason == ElevatorConstants.REJECT_PROMOTION:
                base.localAvatar.elevatorNotifier.showMe(TTLocalizer.BossElevatorRejectMessage)
            elif reason == ElevatorConstants.REJECT_NOT_YET_AVAILABLE:
                base.localAvatar.elevatorNotifier.showMe(TTLocalizer.NotYetAvailable)
        assert(base.localAvatar.getDoId() == avId)

        doneStatus = {
                'where' : 'reject',
                }
        elevator = self.getPlaceElevator()
        if elevator:
            elevator.signalDone(doneStatus)

    def getDestName(self):
        if self.countryClubId == ToontownGlobals.BossbotCountryClubIntA:
            return TTLocalizer.ElevatorBossBotCourse0
        elif self.countryClubId == ToontownGlobals.BossbotCountryClubIntB:
            return TTLocalizer.ElevatorBossBotCourse1
        elif self.countryClubId == ToontownGlobals.BossbotCountryClubIntC:
            return TTLocalizer.ElevatorBossBotCourse2
Beispiel #30
0
class DistributedFireworksCannon(DistributedFireworkShow.DistributedFireworkShow):

    notify = directNotify.newCategory("DistributedFireworksCannon")

    def __init__(self, cr):
        DistributedFireworkShow.DistributedFireworkShow.__init__(self,cr)
        self.fireworksGui = None
        self.load()

    def generateInit(self):
        DistributedFireworkShow.DistributedFireworkShow.generateInit(self)
        """generateInit(self)
        This method is called when the DistributedObject is first introduced
        to the world... Not when it is pulled from the cache.
        """
        self.fireworksSphereEvent = self.uniqueName("fireworksSphere")
        self.fireworksSphereEnterEvent = "enter" + self.fireworksSphereEvent
        self.fireworksGuiDoneEvent = "fireworksGuiDone"
        self.shootEvent = "fireworkShootEvent"

        self.collSphere = CollisionSphere(0, 0, 0, 2.5)
        # Make the sphere intangible
        self.collSphere.setTangible(1)
        self.collNode = CollisionNode(self.fireworksSphereEvent)
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.geom.attachNewNode(self.collNode)

    def generate(self):
        """generate(self)
        This method is called when the DistributedObject is reintroduced
        to the world, either for the first time or from the cache.
        """
        DistributedFireworkShow.DistributedFireworkShow.generate(self)

    def announceGenerate(self):
        self.notify.debug("announceGenerate")
        self.accept(self.fireworksSphereEnterEvent,  self.__handleEnterSphere)

    def disable(self):
        self.notify.debug("disable")
        self.ignore(self.fireworksSphereEnterEvent)
        self.ignore(self.shootEvent)
        self.ignore(self.fireworksGuiDoneEvent)
        if self.fireworksGui:
            self.fireworksGui.destroy()
            self.fireworksGui = None
        DistributedFireworkShow.DistributedFireworkShow.disable(self)

    def delete(self):
        self.notify.debug("delete")
        self.geom.removeNode()
        DistributedFireworkShow.DistributedFireworkShow.delete(self)

    def load(self):
        self.geom = loader.loadModel("phase_5/models/props/trashcan_TT.bam")
        self.geom.reparentTo(base.cr.playGame.hood.loader.geom)
        self.geom.setScale(.5)

    def __handleEnterSphere(self, collEntry):
        self.notify.debug("handleEnterSphere()")
        # don't let other toons access the fireworks now
        self.ignore(self.fireworksSphereEnterEvent)
        self.sendUpdate("avatarEnter", [])

    def __handleFireworksDone(self):
        self.ignore(self.fireworksGuiDoneEvent)
        self.ignore(self.shootEvent)
        self.sendUpdate("avatarExit")
        self.fireworksGui.destroy()
        self.fireworksGui = None

    def freeAvatar(self):
        """
        This is a message from the AI used to free the avatar from movie mode
        """
        # If we are the local toon and we have simply taken too long,
        # just free us
        base.localAvatar.posCamera(0,0)
        base.cr.playGame.getPlace().setState("walk")
        # Start accepting the fireworks collision sphere event again
        self.accept(self.fireworksSphereEnterEvent, self.__handleEnterSphere)


    def setMovie(self, mode, avId, timestamp):
        """
        This is a message from the AI describing a movie between this fireworks
        cannon and a Toon that has approached us.
        """
        timeStamp = globalClockDelta.localElapsedTime(timestamp)
        # See if this is the local toon
        isLocalToon = (avId == base.localAvatar.doId)

        if (mode == FIREWORKS_MOVIE_CLEAR):
            self.notify.debug("setMovie: clear")
            return
        elif (mode == FIREWORKS_MOVIE_GUI):
            self.notify.debug("setMovie: gui")
            if isLocalToon:
                self.fireworksGui = FireworksGui.FireworksGui(self.fireworksGuiDoneEvent, self.shootEvent)
                self.accept(self.fireworksGuiDoneEvent, self.__handleFireworksDone)
                self.accept(self.shootEvent, self.localShootFirework)
            return
        else:
            self.notify.warning("unknown mode in setMovie: %s" % (mode))

    def setPosition(self, x, y, z):
        self.pos = [x,y,z]
        self.geom.setPos(x,y,z)

    def localShootFirework(self, index):
        style = index
        col1,col2 = self.fireworksGui.getCurColor()
        amp = 30

        # attach a dummy node to the toon that always in front of him.
        # This is where the fireworks will shoot from.
        dummy = base.localAvatar.attachNewNode("dummy")
        dummy.setPos(0,100,60)
        pos = dummy.getPos(render)
        dummy.removeNode()

        print(("lauFirework: %s, col=%s" % (index,col1)))
        self.d_requestFirework(pos[0],pos[1],pos[2],style,col1,col2)