def setupSignText(self):
     loader = self.cr.playGame.hood.loader
     partyGate = loader.geom.find('**/partyGateSignGroup')
     if partyGate.isEmpty():
         self.notify.warning('Could not find partyGate_grp in loader.geom')
         return
     gateFont = ToontownGlobals.getMinnieFont()
     leftSign = partyGate.find('**/signTextL_locatorBack')
     signScale = 0.35
     wordWrap = 8
     leftText = DirectLabel.DirectLabel(parent=leftSign,
                                        pos=(0, 0.0, 0.0),
                                        relief=None,
                                        text=TTLocalizer.PartyGateLeftSign,
                                        text_align=TextNode.ACenter,
                                        text_font=gateFont,
                                        text_wordwrap=wordWrap,
                                        text_fg=Vec4(0.7, 0.3, 0.3, 1.0),
                                        scale=signScale)
     rightSign = partyGate.find('**/signTextR_locatorFront')
     rightText = DirectLabel.DirectLabel(
         parent=rightSign,
         pos=(0, 0.0, 0.0),
         relief=None,
         text=TTLocalizer.PartyGateRightSign,
         text_align=TextNode.ACenter,
         text_font=gateFont,
         text_wordwrap=wordWrap,
         text_fg=Vec4(0.7, 0.3, 0.3, 1.0),
         scale=signScale)
     return
 def enter(self):
     doneStatus = {}
     questHistory = base.localAvatar.getQuestHistory()
     imgScale = 0.5
     if questHistory != [] and questHistory != [1000] and questHistory != [101, 110]:
         doneStatus['mode'] = 'complete'
         messenger.send(self.doneEvent, [doneStatus])
     elif len(base.localAvatar.quests) > 1 or len(base.localAvatar.quests) == 0:
         doneStatus['mode'] = 'complete'
         messenger.send(self.doneEvent, [doneStatus])
     elif base.localAvatar.quests[0][0] != Quests.TROLLEY_QUEST_ID:
         doneStatus['mode'] = 'complete'
         messenger.send(self.doneEvent, [doneStatus])
     else:
         base.localAvatar.b_setAnimState('neutral', 1)
         doneStatus['mode'] = 'incomplete'
         self.doneStatus = doneStatus
         imageModel = loader.loadModel('phase_4/models/gui/tfa_images')
         if Quests.avatarHasTrolleyQuest(base.localAvatar):
             if base.localAvatar.quests[0][4] != 0:
                 imgNodePath = imageModel.find('**/hq-dialog-image')
                 imgPos = (0, 0, -0.02)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage2
             else:
                 imgNodePath = imageModel.find('**/trolley-dialog-image')
                 imgPos = (0, 0, 0.04)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage
         self.dialog = TTDialog.TTDialog(text=msg, command=self.handleOk, style=TTDialog.Acknowledge)
         imgLabel = DirectLabel.DirectLabel(parent=self.dialog, relief=None, pos=imgPos, scale=TTLocalizer.NPCFimgLabel, image=imgNodePath, image_scale=imgScale)
Exemplo n.º 3
0
 def _createIface(self):
     textFg = PiratesGuiGlobals.TextFG1
     if self.world != None:
         scoreText = self.world.getScoreText(self.scoreValue)
     else:
         scoreText = ''
     self.descText = DirectLabel(
         parent=self,
         relief=None,
         text=scoreText,
         text_align=TextNode.ALeft,
         text_scale=PiratesGuiGlobals.TextScaleLarge,
         text_fg=textFg,
         text_shadow=PiratesGuiGlobals.TextShadow,
         textMayChange=1,
         pos=(0.04, 0, 0.015))
     if self.itemColorScale:
         self.colorLabel(self.itemColorScale)
     if self.blink:
         textPos = self.descText['text_pos']
         textPosX = textPos[0]
         textPosY = textPos[1]
         self.scaleSeq = Parallel(
             Sequence(
                 LerpFunctionInterval(self.descText.setScale,
                                      duration=0.2,
                                      toData=1.05,
                                      fromData=1.0,
                                      blendType='easeInOut'),
                 LerpFunctionInterval(self.descText.setScale,
                                      duration=0.7,
                                      toData=1.0,
                                      fromData=1.05,
                                      blendType='easeInOut')),
             Sequence(
                 Func(self.colorLabel, (1, 1, 1, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 0, 0, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 1, 1, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 0, 0, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 1, 1, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 0, 0, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, (1, 1, 1, 1)),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.moveLabel, (textPosX, textPosY)), Wait(0.05),
                 Func(self.colorLabel, PiratesGuiGlobals.TextFG1),
                 Func(self.moveLabel, (textPosX, textPosY))))
         self.scaleSeq.start()
     return
 def _createIface(self):
     textFg = PiratesGuiGlobals.TextFG1
     if self.world != None:
         scoreText = self.world.getScoreText(self.scoreValue)
     else:
         scoreText = ''
     self.descText = DirectLabel(parent = self, relief = None, text = scoreText, text_align = TextNode.ALeft, text_scale = PiratesGuiGlobals.TextScaleLarge, text_fg = textFg, text_shadow = PiratesGuiGlobals.TextShadow, textMayChange = 1, pos = (0.040000000000000001, 0, 0.014999999999999999))
     if self.itemColorScale:
         self.colorLabel(self.itemColorScale)
     
     if self.blink:
         textPos = self.descText['text_pos']
         textPosX = textPos[0]
         textPosY = textPos[1]
         self.scaleSeq = Parallel(Sequence(LerpFunctionInterval(self.descText.setScale, duration = 0.20000000000000001, toData = 1.05, fromData = 1.0, blendType = 'easeInOut'), LerpFunctionInterval(self.descText.setScale, duration = 0.69999999999999996, toData = 1.0, fromData = 1.05, blendType = 'easeInOut')), Sequence(Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, PiratesGuiGlobals.TextFG1), Func(self.moveLabel, (textPosX, textPosY))))
         self.scaleSeq.start()
class RaceGUI:
    GagPie = 0
    gagRoot = 'phase_3.5/maps/inventory_'

    class RacerInfo:
        def __init__(self, face, mapSpot):
            self.curvetime = 0
            self.maxlaphit = 0
            self.face = face
            self.mapspot = mapSpot
            self.place = 1
            self.enabled = True
            self.finished = False
            self.gag = None
            return

        def update(self,
                   curvetime=None,
                   maxlaphit=None,
                   faceX=None,
                   mapspotPt=None,
                   place=None,
                   finished=None):
            if self.enabled:
                if not curvetime == None:
                    self.curvetime = curvetime
                if not maxlaphit == None:
                    self.maxlaphit = maxlaphit
                if not faceX == None:
                    self.face.setX(faceX)
                if not mapspotPt == None:
                    self.mapspot.setPos(mapspotPt)
                if not place == None:
                    self.place = place
                if not finished == None:
                    self.finished = finished
            return

        def disable(self):
            self.enabled = False
            if not self.finished:
                self.face.hide()
            self.mapspot.hide()

        def enable(self):
            self.enabled = True
            self.face.show()
            self.mapspot.show()

    def __init__(self, distRace):
        self.race = distRace
        self.timerEnabled = False
        self.maxLapHit = 0
        self.photoFinish = False
        toonInteriorTextures = loader.loadModel(
            'phase_3.5/models/modules/toon_interior_textures')
        invTextures = loader.loadModel('phase_3.5/models/gui/inventory_icons')
        racingTextures = loader.loadModel(
            'phase_6/models/karting/racing_textures')
        self.gagTextures = [
            toonInteriorTextures.find('**/couch'),
            invTextures.find('**/inventory_bannana_peel'),
            racingTextures.find('**/boost_arrow'),
            invTextures.find('**/inventory_anvil'),
            invTextures.find('**/inventory_creampie')
        ]
        self.gagTextures[1].setScale(7.5)
        self.gagTextures[3].setScale(7.5)
        self.gagTextures[4].setScale(7.5)
        self.cardMaker = CardMaker('card')
        self.racerDict = {}
        self.render2dRoot = render2d.attachNewNode('RaceGuiRender2dRoot')
        self.render2dRoot.setDepthWrite(1)
        self.directObjList = []
        self.aspect2dRoot = aspect2d.attachNewNode('RaceGuiAspect2dRoot')
        self.aspect2dRoot.setDepthWrite(1)
        self.raceModeRoot = self.aspect2dRoot.attachNewNode('RaceModeRoot')
        gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui')
        self.closeButton = DirectButton(image=(gui.find('**/CloseBtn_UP'),
                                               gui.find('**/CloseBtn_DN'),
                                               gui.find('**/CloseBtn_Rllvr'),
                                               gui.find('**/CloseBtn_UP')),
                                        relief=None,
                                        scale=1.05,
                                        text=TTLocalizer.KartRace_Leave,
                                        text_scale=0.04,
                                        text_pos=(0, -0.07),
                                        text_fg=VBase4(1, 1, 1, 1),
                                        pos=(-0.99, 0, 0.925),
                                        command=self.race.leaveRace)
        self.closeButton.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.closeButton)
        self.raceTimeDelta = 0
        self.raceModeReady = False
        self.resultModeReady = False
        self.gagCycleSound = base.loadSfx(
            'phase_3.5/audio/sfx/tick_counter.mp3')
        if hasattr(self.gagCycleSound, 'setPlayRate'):
            self.gagCycleSound.setPlayRate(0.2)
        self.gagCycleSound.setLoop(1)
        self.gagAcquireSound = base.loadSfx(
            'phase_6/audio/sfx/SZ_MM_gliss.mp3')
        self.disable()
        return

    def initRaceMode(self):
        self.mapScene = self.raceModeRoot.attachNewNode('MapScene')
        self.mapScene.setPos(1.1, 0, 0.75)
        self.mapScene.setScale(0.25, 0.001, 0.25)
        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)
        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)
        for x in range(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if x == 0:
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 *
                               RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)
        self.faceStartPos = Vec3(-0.8, 0, 0.93)
        self.faceEndPos = Vec3(0.8, 0, 0.93)
        self.placeLabelNum = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelNumPos,
            text='1',
            text_scale=0.35,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.placeLabelNum.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelNum)
        self.placeLabelStr = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelStrPos,
            text=TTLocalizer.KartRace_FirstSuffix,
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.placeLabelStr.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelStr)
        self.lapLabel = DirectLabel(relief=None,
                                    pos=(1.1, 0, 0.45),
                                    text='1/' + str(self.race.lapCount),
                                    text_scale=0.1,
                                    text_fg=(0.95, 0.95, 0, 1),
                                    text_font=ToontownGlobals.getSignFont())
        self.lapLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.lapLabel)
        self.photoFinishLabel = DirectLabel(
            relief=None,
            pos=(0, 0, -0.1),
            text=TTLocalizer.KartRace_PhotoFinish,
            text_scale=TTLocalizer.RGUIphotoFinish,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)
        self.wrongWayLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.85),
            text=TTLocalizer.KartRace_WrongWay,
            text_scale=0.1,
            text_fg=(0.95, 0, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.wrongWayLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))
        self.wrongWaySeq = Sequence(
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 1),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 0)),
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 0),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 1)))
        interpolateFacePos = lambda x: self.faceStartPos * (
            1.0 - x) + self.faceEndPos * x
        self.timeLabels = []
        for x in range(self.race.lapCount):
            minLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0,
                     0.84),
                text="0'",
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0,
                     0.84),
                text="00''",
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0,
                     0.84),
                text='00',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)
        self.gagPanel = DirectFrame(
            parent=self.raceModeRoot,
            relief=None,
            image=loader.loadModel('phase_6/models/karting/gag_panel'),
            image_scale=0.25,
            pos=(-1.13, 0, -0.5))
        self.directObjList.append(self.gagPanel)
        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])
        self.cardMaker.setName('RaceProgressLineHash')
        for n in range(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(
                self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t,
                self.faceStartPos[1], self.faceStartPos[2])

        self.raceModeReady = True
        self.disable()
        return

    def initResultMode(self):
        self.endPanel = RaceEndPanel(len(self.race.avIds), self.race)
        self.endPanel.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.endPanel)
        self.resultModeReady = True
        self.disable()

    def showGag(self, gagIndex):
        if gagIndex < len(self.gagTextures):
            for gag in self.gagTextures:
                gag.hide()

            self.gagTextures[gagIndex].show()

    def updateGag(self, gagIndex):
        if self.gag:
            if hasattr(self, 'gagCycleInterval'):
                self.gagCycleInterval.finish()
                del self.gagCycleInterval
            self.gag.setHpr(0, 0, 0)
            self.showGag(gagIndex)
            if gagIndex == 0:
                self.gag.hide()
            else:
                self.gag.show()
                self.gagAcquireSound.play()
                self.gagAcquireInterval = LerpHprInterval(self.gag,
                                                          duration=0.5,
                                                          blendType='easeOut',
                                                          startHpr=Point3(
                                                              0, -90, 0),
                                                          hpr=Point3(0, 0, 0))
                self.gagAcquireInterval.start()

    def waitingOnGag(self, cycleTime):
        if self.gag:
            numTextures = len(self.gagTextures)
            startOffset = random.choice(range(0, numTextures))
            self.gag.show()
            self.gagCycleInterval = Parallel(
                LerpFunc(self.showNextGag,
                         fromData=startOffset,
                         toData=numTextures * 2 * cycleTime + startOffset,
                         blendType='easeOut',
                         duration=cycleTime),
                LerpHprInterval(self.gag,
                                duration=cycleTime,
                                hpr=Point3(
                                    0, 180 * numTextures * 2 * cycleTime - 90,
                                    0),
                                blendType='easeOut',
                                startHpr=Point3(0, 0, 0)),
                SoundInterval(self.gagCycleSound,
                              loop=1,
                              duration=cycleTime,
                              startTime=0),
                name='gagCycleInterval')
            self.gagCycleInterval.start()

    def showNextGag(self, t):
        if self.gag:
            currGagIndex = int(t % (len(self.gagTextures) - 1)) + 1
            self.showGag(currGagIndex)

    def enableSpeedometer(self):
        self.race.localKart.showSpeedometer()

    def disableSpeedometer(self):
        self.race.localKart.hideSpeedometer()

    def disableRaceMode(self):
        self.disableSpeedometer()
        self.render2dRoot.hide()
        self.raceModeRoot.hide()
        for x in self.timeLabels:
            for y in x:
                y.hide()

        self.setTimerEnabled(False)

    def disableResultMode(self):
        self.endPanel.disable()

    def disable(self):
        self.closeButton.hide()
        taskMgr.removeTasksMatching('clearRaceEndPanel')
        if self.raceModeReady:
            self.disableRaceMode()
        if self.resultModeReady:
            self.disableResultMode()

    def enableRaceMode(self):
        self.enableSpeedometer()
        self.render2dRoot.show()
        self.raceModeRoot.show()
        self.maxLapHit = min(self.maxLapHit, self.race.lapCount - 1)
        for x in range(self.maxLapHit + 1):
            for y in self.timeLabels[x]:
                y.configure(text_font=ToontownGlobals.getSignFont())
                y.show()

        for y in self.timeLabels[self.maxLapHit]:
            y.configure(text_font=ToontownGlobals.getSignFont())

    def enableResultMode(self):
        self.endPanel.enable()
        if not self.race.circuitLoop:
            taskMgr.doMethodLater(180,
                                  self.endPanel.closeButtonPressed,
                                  'clearRaceEndPanel',
                                  extraArgs=[])

    def destroy(self):
        self.disable()
        if hasattr(self, 'wrongWaySeq'):
            self.wrongWaySeq.finish()
            self.wrongWaySeq = None
        taskMgr.removeTasksMatching('removeIt')
        taskMgr.removeTasksMatching('removeCam*')
        taskMgr.removeTasksMatching('clearRaceEndPanel')
        for obj in self.directObjList:
            obj.destroy()

        if hasattr(self, 'mapScene'):
            self.mapScene.removeNode()
            self.mapScene = None
        self.aspect2dRoot.removeNode()
        self.aspect2dRoot = None
        self.raceModeRoot.removeNode()
        self.raceModeRoot = None
        self.render2dRoot.removeNode()
        self.render2dRoot = None
        self.closeButton = None
        self.gag = None
        self.lapLabel = None
        self.timeLabels = None
        self.placeLabelStr = None
        self.placeLabelNum = None
        self.photoFinishLabel = None
        self.mapScene = None
        self.race = None
        return

    def setSpotAsymptotic(self, diffT, spot):
        p = (-1, 1)[diffT > 0] * (1 - 1 / pow(abs(diffT) / self.cutoff + 1, 2))
        spot.setX(p)

    def setSpotRaceLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t / self.lapCount))

    def setSpotLapLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t - int(t)))

    def update(self, time):
        placeSorter = []
        placeCount = 0
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit
            if not racer.finished and racer.enabled:
                placeSorter.append((curvetime, key))
            if racer.finished or racer.enabled:
                placeCount += 1
            pt = Vec3(0, 0, 0)
            mapT = (curvetime % 1 + self.race.startT /
                    self.race.curve.getMaxT()) % 1 * self.race.curve.getMaxT()
            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint(mapT % self.race.curve.getMaxT(), pt)
            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)
            faceX = self.faceStartPos[0] * (1 -
                                            lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)
            t = time - self.race.baseTime - self.raceTimeDelta
            if key == localAvatar.doId:
                if self.race.laps > maxlaphit:
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit
                    if self.maxLapHit < self.race.lapCount:
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()

                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime(
                        ) - self.race.baseTime
                        lapNotice = DirectLabel()
                        lapNotice.setScale(0.1)
                        if self.maxLapHit == self.race.lapCount - 1:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_LapText % str(
                                    self.maxLapHit + 1)
                        taskMgr.doMethodLater(2,
                                              lapNotice.remove,
                                              'removeIt',
                                              extraArgs=[])
                self.lapLabel['text'] = str(
                    clampScalar(self.maxLapHit + 1, 1,
                                self.race.lapCount)) + '/' + str(
                                    self.race.lapCount)

        suffix = {
            1: TTLocalizer.KartRace_FirstSuffix,
            2: TTLocalizer.KartRace_SecondSuffix,
            3: TTLocalizer.KartRace_ThirdSuffix,
            4: TTLocalizer.KartRace_FourthSuffix
        }
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=p + placeCount -
                                        len(placeSorter))

        localRacer = self.racerDict[localAvatar.doId]
        nearDiff, farDiff = RaceGlobals.TrackDict[self.race.trackId][8]
        if not localRacer.finished and self.faceEndPos[
                0] - localRacer.face.getX() < nearDiff:
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if not racer.enabled or racerId == localAvatar.doId or racer.face.getX(
                ) >= self.faceEndPos[0]:
                    continue
                if self.faceEndPos[0] - racer.face.getX() < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ''
            self.placeLabelStr['text'] = ''
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(
                self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[
                localAvatar.doId].place]
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if self.timerEnabled and self.maxLapHit < self.race.lapCount:
            self.timeLabels[self.maxLapHit][0]['text'] = "%d'" % minutes
            self.timeLabels[self.maxLapHit][1]['text'] = "%s%d''" % (padding,
                                                                     seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % fraction
        if self.race.wrongWay and not self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.loop()
        elif not self.race.wrongWay and self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.finish()

    def updateRacerInfo(self, avId, curvetime=None, maxlaphit=None):
        if avId in self.racerDict.keys():
            self.racerDict[avId].update(curvetime=curvetime,
                                        maxlaphit=maxlaphit)

    def racerEntered(self, avId):
        toon = base.cr.doId2do.get(avId, None)
        kart = base.cr.doId2do.get(self.race.kartMap.get(avId, None), None)
        if not toon or not kart:
            return
        if kart.getBodyColor() == InvalidEntry:
            bodyColor = getDefaultColor()
        else:
            bodyColor = getAccessory(kart.getBodyColor())
        headframe = RaceHeadFrame(av=toon, color=bodyColor)
        eyes = headframe.head.find('**/eyes*')
        eyes.setDepthTest(1)
        eyes.setDepthWrite(1)
        headframe.configure(geom_scale=(0.5, 0.5, 0.5))
        headframe.setZ(self.faceStartPos[2])
        headframe.setDepthWrite(True)
        headframe.setDepthTest(True)
        headframe.reparentTo(self.raceModeRoot)
        self.directObjList.append(headframe)
        mapspot = loader.loadModel('phase_6/models/karting/race_mapspot')
        mapspot.setColor(bodyColor)
        mapspot.reparentTo(self.mapLines)
        mapspot.setHpr(self.mapScene, 0, 0, 0)
        self.racerDict[avId] = self.RacerInfo(headframe, mapspot)
        for key, i in zip(self.racerDict.keys(),
                          range(len(self.racerDict.keys()))):
            face = self.racerDict[key].face
            mapspot = self.racerDict[key].mapspot
            face.setX(self.faceStartPos[0])
            face.setY(-1 - 5 * (i + 1))
            face.setScale(0.15)
            mapspot.getChild(0).setY((-5 - 5 * (i + 1)) * 1000)
            mapspot.setScale(self.mapScene, 0.15)
            mapspot.setPos(self.race.startingPos[0][0])
            if key == localAvatar.doId:
                face.setY(-1)
                face.setScale(face.getScale() * 1.25)
                mapspot.getChild(0).setY(-5 * 1000)
                mapspot.setScale(mapspot.getScale() * 1.25)
                self.face = face
                self.mapspot = mapspot

        return

    def racerLeft(self, avId, unexpected=False):
        racer = self.racerDict.get(avId, None)
        if racer:
            racer.disable()
        return

    def racerFinished(self, avId, trackId, place, totalTime, entryFee, qualify,
                      winnings, bonus, trophies, circuitPoints, circuitTime):
        racer = self.racerDict.get(avId, None)
        if racer:
            racer.update(finished=True)
            racer.disable()
            self.endPanel.displayRacer(place, entryFee, qualify, winnings,
                                       trackId, bonus, trophies, racer.face,
                                       base.cr.doId2do[avId].getName(),
                                       totalTime, circuitPoints, circuitTime)
            self.directObjList.remove(racer.face)
            if avId == localAvatar.doId:
                self.disableRaceMode()
                self.enableResultMode()
                self.endPanel.startWinningsPanel(entryFee, winnings, trackId,
                                                 bonus, trophies)
        return

    def racerFinishedCircuit(self, avId, place, entryFee, winnings, bonus,
                             trophies):
        racer = self.racerDict.get(avId, None)
        if racer:
            newTotalTickets = winnings + entryFee + bonus
            self.endPanel.updateWinnings(place, newTotalTickets)
            if avId == localAvatar.doId:
                self.endPanel.updateWinningsFromCircuit(
                    place, entryFee, winnings, bonus, trophies)
        return

    def circuitFinished(self, placeFixup):
        self.endPanel.circuitFinished(placeFixup)

    def setTimerEnabled(self, enabled):
        self.timerEnabled = enabled
    def initRaceMode(self):
        self.mapScene = self.raceModeRoot.attachNewNode('MapScene')
        self.mapScene.setPos(1.1, 0, 0.75)
        self.mapScene.setScale(0.25, 0.001, 0.25)
        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)
        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)
        for x in range(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if x == 0:
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 *
                               RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)
        self.faceStartPos = Vec3(-0.8, 0, 0.93)
        self.faceEndPos = Vec3(0.8, 0, 0.93)
        self.placeLabelNum = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelNumPos,
            text='1',
            text_scale=0.35,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.placeLabelNum.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelNum)
        self.placeLabelStr = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelStrPos,
            text=TTLocalizer.KartRace_FirstSuffix,
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.placeLabelStr.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelStr)
        self.lapLabel = DirectLabel(relief=None,
                                    pos=(1.1, 0, 0.45),
                                    text='1/' + str(self.race.lapCount),
                                    text_scale=0.1,
                                    text_fg=(0.95, 0.95, 0, 1),
                                    text_font=ToontownGlobals.getSignFont())
        self.lapLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.lapLabel)
        self.photoFinishLabel = DirectLabel(
            relief=None,
            pos=(0, 0, -0.1),
            text=TTLocalizer.KartRace_PhotoFinish,
            text_scale=TTLocalizer.RGUIphotoFinish,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)
        self.wrongWayLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.85),
            text=TTLocalizer.KartRace_WrongWay,
            text_scale=0.1,
            text_fg=(0.95, 0, 0, 1),
            text_font=ToontownGlobals.getSignFont())
        self.wrongWayLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))
        self.wrongWaySeq = Sequence(
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 1),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 0)),
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 0),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 1)))
        interpolateFacePos = lambda x: self.faceStartPos * (
            1.0 - x) + self.faceEndPos * x
        self.timeLabels = []
        for x in range(self.race.lapCount):
            minLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0,
                     0.84),
                text="0'",
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0,
                     0.84),
                text="00''",
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0,
                     0.84),
                text='00',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight)
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)
        self.gagPanel = DirectFrame(
            parent=self.raceModeRoot,
            relief=None,
            image=loader.loadModel('phase_6/models/karting/gag_panel'),
            image_scale=0.25,
            pos=(-1.13, 0, -0.5))
        self.directObjList.append(self.gagPanel)
        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])
        self.cardMaker.setName('RaceProgressLineHash')
        for n in range(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(
                self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t,
                self.faceStartPos[1], self.faceStartPos[2])

        self.raceModeReady = True
        self.disable()
        return
Exemplo n.º 7
0
 def enterWaiting(self):
     self.waitingLabel = DirectLabel()
     self.waitingLabel['text'] = TTLocalizer.BuildingWaitingForVictors
     self.waitingLabel.setScale(TTLocalizer.DRenterWaiting)
Exemplo n.º 8
0
class DistributedRace(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedRace')
    ReadyPost = 'RaceReady'
    WinEvent = 'RaceWinEvent'
    BGM_BaseDir = 'phase_6/audio/bgm/'
    SFX_BaseDir = 'phase_6/audio/sfx/'
    SFX_StartBoop = SFX_BaseDir + 'KART_raceStart1.ogg'
    SFX_StartBoop2 = SFX_BaseDir + 'KART_raceStart2.ogg'
    SFX_Applause = SFX_BaseDir + 'KART_Applause_%d.ogg'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def exitJoin(self):
        pass

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

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

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

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

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

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

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

    def exitPrep(self):
        pass

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

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

    def getTitle(self):
        return TTLocalizer.KartRace_TitleInfo

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

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

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

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

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

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

    def exitStart(self):
        pass

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

    def exitRacing(self):
        pass

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

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

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

    def exitFinished(self):
        pass

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

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

    def exitLeave(self):
        pass

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

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

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

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

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

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

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

    def loadUrbanTrack(self):
        self.dnaStore = DNAStorage()
        files = ('phase_4/dna/storage.pdna', 'phase_5/dna/storage_town.pdna', 'phase_4/dna/storage_TT.pdna', 'phase_5/dna/storage_TT_town.pdna', 'phase_8/dna/storage_BR.pdna', 'phase_8/dna/storage_BR_town.pdna', 'phase_8/dna/storage_DL.pdna', 'phase_8/dna/storage_DL_town.pdna')
        dnaBulk = DNABulkLoader(self.dnaStore, files)
        dnaBulk.loadDNAFiles()
        dnaFile = 'phase_6/dna/urban_track_town.pdna'
        if self.trackId in (RaceGlobals.RT_Urban_2, RaceGlobals.RT_Urban_2_rev):
            dnaFile = 'phase_6/dna/urban_track_town_B.pdna'
        node = loader.loadDNAFile(self.dnaStore, dnaFile)
        self.townGeom = self.geom.attachNewNode(node)
        self.townGeom.findAllMatches('**/+CollisionNode').stash()
        self.buildingGroups = {}
        self.currBldgInd = {}
        self.currBldgGroups = {}
        bgGeom = self.geom.find('**/polySurface8')
        if self.dummyNode:
            bgGeom.reparentTo(self.dummyNode)
        else:
            bgGeom.reparentTo(localAvatar)
        bgGeom.setScale(0.1)
        ce = CompassEffect.make(NodePath(), CompassEffect.PRot)
        bgGeom.node().setEffect(ce)
        bgGeom.setDepthTest(0)
        bgGeom.setDepthWrite(0)
        bgGeom.setBin('background', 102)
        bgGeom.setZ(-1)
        self.bgGeom = bgGeom
        l = self.geom.findAllMatches('**/+ModelNode')
        for n in l:
            n.node().setPreserveTransform(0)

        self.geom.flattenLight()
        maxNum = 0
        for side in ['inner', 'outer']:
            self.buildingGroups[side] = []
            self.currBldgInd[side] = None
            self.currBldgGroups[side] = None
            i = 0
            while 1:
                bldgGroup = self.townGeom.find('**/Buildings_' + side + '-' + str(i))
                if bldgGroup.isEmpty():
                    break
                l = bldgGroup.findAllMatches('**/+ModelNode')
                for n in l:
                    n2 = n.getParent().attachNewNode(n.getName())
                    n.getChildren().reparentTo(n2)
                    n.removeNode()

                bldgGroup.flattenStrong()
                if not bldgGroup.getNode(0).getBounds().isEmpty():
                    self.buildingGroups[side].append(bldgGroup)
                i += 1

            if i > maxNum:
                maxNum = i

        for side in ['innersidest', 'outersidest']:
            self.buildingGroups[side] = []
            self.currBldgInd[side] = None
            self.currBldgGroups[side] = None
            for i in xrange(maxNum):
                for barricade in ('innerbarricade', 'outerbarricade'):
                    bldgGroup = self.townGeom.find('**/Buildings_' + side + '-' + barricade + '_' + str(i))
                    if bldgGroup.isEmpty():
                        continue
                    l = bldgGroup.findAllMatches('**/+ModelNode')
                    for n in l:
                        n2 = n.getParent().attachNewNode(n.getName())
                        n.getChildren().reparentTo(n2)
                        n.removeNode()

                    self.buildingGroups[side].append(bldgGroup)

        treeNodes = self.townGeom.findAllMatches('**/prop_tree_*')
        for tree in treeNodes:
            tree.flattenStrong()

        snowTreeNodes = self.townGeom.findAllMatches('**/prop_snow_tree_*')
        for snowTree in snowTreeNodes:
            snowTree.flattenStrong()

        for side in ['inner',
         'outer',
         'innersidest',
         'outersidest']:
            for grp in self.buildingGroups[side]:
                grp.stash()

        self.showBuildings(0)

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

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

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

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

                self.currBldgInd[side] = bldgInd

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

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

                    self.currBldgInd[side] = segmentInd

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def changeMusicTempo(self, newPR):
        return
        if self.musicTrack:
            self.musicTrack.finish()
        curPR = self.raceMusic.getPlayRate()
        interval = LerpFunctionInterval(self.raceMusic.setPlayRate, fromData=curPR, toData=newPR, duration=3)
        self.musicTrack = Sequence(interval)
        self.musicTrack.start()

    def setRaceZone(self, zoneId, trackId):
        hoodId = self.cr.playGame.hood.hoodId
        base.loader.endBulkLoad('atRace')
        self.kartCleanup()
        self.doneBarrier('waitingForExit')
        self.sendUpdate('racerLeft', [localAvatar.doId])
        out = {'loader': 'racetrack',
         'where': 'racetrack',
         'hoodId': hoodId,
         'zoneId': zoneId,
         'trackId': trackId,
         'shardId': None,
         'reason': RaceGlobals.Exit_UserReq}
        base.cr.playGame.hood.loader.fsm.request('quietZone', [out])
Exemplo n.º 9
0
    def initRaceMode(self):
        ##         #setup the 'map' display region
        ##         self.mapScene = NodePath('MapScene')
        ##         self.mapScene.setTransparency(1)
        ##         self.mapSize = 0.15
        ##         self.mapX = 0.84
        ##         self.mapY = 0.84
        ##         self.mapCam = None
        ##         if (base.win.getNumDisplayRegions()>4):
        ##             for x in range(base.win.getNumDisplayRegions()-4):
        ##                 dr = base.win.getDisplayRegion(x+4)
        ##                 if (dr.getCamera().getName() == 'MapCam'):
        ##                     self.mapCam = dr.getCamera()
        ##                     break

        ##         if(self.mapCam == None):
        ##             self.mapCam = base.makeCamera(base.win,sort=30,displayRegion = (self.mapX,self.mapX+self.mapSize,self.mapY,self.mapY+self.mapSize),camName = 'MapCam')

        ##         self.mapCam.setY(-10)
        ##         self.mapCam.node().setLens(OrthographicLens())
        ##         self.mapCam.node().getLens().setFilmSize(2)
        ##         self.mapCam.node().getLens().setAspectRatio(4.0/3.0)
        ##         self.mapCam.reparentTo(self.mapScene)

        ##         self.cardMaker.reset()
        ##         self.cardMaker.setName('MapBackground')
        ##         self.cardMaker.setFrame(-1,1,-1,1)
        ##         self.cardMaker.setColor(1,1,1,0.25)
        ##         card = self.mapScene.attachNewNode(self.cardMaker.generate())

        #setup the 'map' display region
        self.mapScene = self.raceModeRoot.attachNewNode('MapScene')
        self.mapScene.setPos(1.1, 0, 0.75)
        self.mapScene.setScale(0.25, 0.001, 0.25)

        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)

        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)

        for x in range(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if (x == 0):
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 *
                               RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)

        #setup face info
        self.faceStartPos = Vec3(-0.80, 0, 0.93)
        self.faceEndPos = Vec3(0.80, 0, 0.93)

        #setup place(1st,2nd,...) reporting
        self.placeLabelNum = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelNumPos,
            text='1',
            text_scale=0.35,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.placeLabelNum.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelNum)

        self.placeLabelStr = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelStrPos,
            text=TTLocalizer.KartRace_FirstSuffix,
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.placeLabelStr.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelStr)

        #setup lap reporting
        self.lapLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.45),
            text='1/' + str(self.race.lapCount),
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.lapLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.lapLabel)

        #setup photo finish label
        self.photoFinishLabel = DirectLabel(
            relief=None,
            pos=(0, 0, -0.1),
            text=TTLocalizer.KartRace_PhotoFinish,
            text_scale=TTLocalizer.RGUIphotoFinish,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)

        #setup wrong way reporting
        self.wrongWayLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.85),
            text=TTLocalizer.KartRace_WrongWay,
            text_scale=0.1,
            text_fg=(0.95, 0, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.wrongWayLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))

        self.wrongWaySeq = Sequence(
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 1),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 0)),
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 0),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 1)),
        )

        #setup time reporting
        interpolateFacePos = lambda x: self.faceStartPos * (
            1.0 - x) + self.faceEndPos * (x)
        self.timeLabels = []
        for x in range(self.race.lapCount):
            minLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0,
                     0.84),
                text='0\'',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0,
                     0.84),
                text='00\'\'',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0,
                     0.84),
                text='00',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        #setup gag indicator
        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)

        self.gagPanel = DirectFrame(
            parent=self.raceModeRoot,
            relief=None,
            image=loader.loadModel('phase_6/models/karting/gag_panel'),
            image_scale=0.25,
            pos=(-1.13, 0, -0.5),
        )
        self.directObjList.append(self.gagPanel)

        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        #setup face line
        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])

        self.cardMaker.setName('RaceProgressLineHash')
        for n in range(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(
                self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t,
                self.faceStartPos[1], self.faceStartPos[2])
        self.raceModeReady = True
        self.disable()
Exemplo n.º 10
0
class RaceGUI:
    GagPie = 0
    gagRoot = 'phase_3.5/maps/inventory_'

    class RacerInfo:

        def __init__(self, face, mapSpot):
            self.curvetime = 0
            self.maxlaphit = 0
            self.face = face
            self.mapspot = mapSpot
            self.place = 1
            self.enabled = True
            self.finished = False
            self.gag = None
            return

        def update(self, curvetime = None, maxlaphit = None, faceX = None, mapspotPt = None, place = None, finished = None):
            if self.enabled:
                if not curvetime == None:
                    self.curvetime = curvetime
                if not maxlaphit == None:
                    self.maxlaphit = maxlaphit
                if not faceX == None:
                    self.face.setX(faceX)
                if not mapspotPt == None:
                    self.mapspot.setPos(mapspotPt)
                if not place == None:
                    self.place = place
                if not finished == None:
                    self.finished = finished
            return

        def disable(self):
            self.enabled = False
            if not self.finished:
                self.face.hide()
            self.mapspot.hide()

        def enable(self):
            self.enabled = True
            self.face.show()
            self.mapspot.show()

    def __init__(self, distRace):
        self.race = distRace
        self.timerEnabled = False
        self.maxLapHit = 0
        self.photoFinish = False
        toonInteriorTextures = loader.loadModel('phase_3.5/models/modules/toon_interior_textures')
        invTextures = loader.loadModel('phase_3.5/models/gui/inventory_icons')
        racingTextures = loader.loadModel('phase_6/models/karting/racing_textures')
        self.gagTextures = [toonInteriorTextures.find('**/couch'),
         invTextures.find('**/inventory_bannana_peel'),
         racingTextures.find('**/boost_arrow'),
         invTextures.find('**/inventory_anvil'),
         invTextures.find('**/inventory_creampie')]
        self.gagTextures[1].setScale(7.5)
        self.gagTextures[3].setScale(7.5)
        self.gagTextures[4].setScale(7.5)
        self.cardMaker = CardMaker('card')
        self.racerDict = {}
        self.render2dRoot = render2d.attachNewNode('RaceGuiRender2dRoot')
        self.render2dRoot.setDepthWrite(1)
        self.directObjList = []
        self.aspect2dRoot = aspect2d.attachNewNode('RaceGuiAspect2dRoot')
        self.aspect2dRoot.setDepthWrite(1)
        self.raceModeRoot = self.aspect2dRoot.attachNewNode('RaceModeRoot')
        gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui')
        self.closeButton = DirectButton(image=(gui.find('**/CloseBtn_UP'),
         gui.find('**/CloseBtn_DN'),
         gui.find('**/CloseBtn_Rllvr'),
         gui.find('**/CloseBtn_UP')), relief=None, scale=1.05, text=TTLocalizer.KartRace_Leave, text_scale=0.04, text_pos=(0, -0.07), text_fg=VBase4(1, 1, 1, 1), pos=(-0.99, 0, 0.925), command=self.race.leaveRace)
        self.closeButton.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.closeButton)
        self.raceTimeDelta = 0
        self.raceModeReady = False
        self.resultModeReady = False
        self.gagCycleSound = base.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
        if hasattr(self.gagCycleSound, 'setPlayRate'):
            self.gagCycleSound.setPlayRate(0.2)
        self.gagCycleSound.setLoop(1)
        self.gagAcquireSound = base.loadSfx('phase_6/audio/sfx/SZ_MM_gliss.ogg')
        self.disable()
        return

    def initRaceMode(self):
        self.mapScene = base.a2dTopRight.attachNewNode('MapScene')
        self.mapScene.setPos(-0.2, 0, -0.2)
        self.mapScene.setScale(0.25, 0.001, 0.25)
        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)
        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)
        for x in xrange(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if x == 0:
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 * RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)
        self.faceStartPos = Vec3(-0.8, 0, 0.93)
        self.faceEndPos = Vec3(0.8, 0, 0.93)
        self.placeLabelNum = DirectLabel(relief=None, pos=TTLocalizer.RGUIplaceLabelNumPos, text='1', text_scale=0.35, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.placeLabelNum.reparentTo(base.a2dBottomLeft)
        self.directObjList.append(self.placeLabelNum)
        self.placeLabelStr = DirectLabel(relief=None, pos=TTLocalizer.RGUIplaceLabelStrPos, text=TTLocalizer.KartRace_FirstSuffix, text_scale=0.1, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.placeLabelStr.reparentTo(base.a2dBottomLeft)
        self.directObjList.append(self.placeLabelStr)
        self.lapLabel = DirectLabel(relief=None, pos=(-0.22, 0, -0.5), text='1/' + str(self.race.lapCount), text_scale=0.1, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.lapLabel.reparentTo(base.a2dTopRight)
        self.directObjList.append(self.lapLabel)
        self.photoFinishLabel = DirectLabel(relief=None, pos=(0, 0, -0.1), text=TTLocalizer.KartRace_PhotoFinish, text_scale=TTLocalizer.RGUIphotoFinish, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)
        self.wrongWayLabel = DirectLabel(relief=None, pos=(-0.22, 0, -0.2), text=TTLocalizer.KartRace_WrongWay, text_scale=0.1, text_fg=(0.95, 0, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.wrongWayLabel.reparentTo(base.a2dTopRight)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))
        self.wrongWaySeq = Sequence(self.wrongWayLabel.colorScaleInterval(0.25, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), self.wrongWayLabel.colorScaleInterval(0.25, colorScale=Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1)))
        interpolateFacePos = lambda x: self.faceStartPos * (1.0 - x) + self.faceEndPos * x
        self.timeLabels = []
        for x in xrange(self.race.lapCount):
            minLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0, 0.84), text="0'", text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0, 0.84), text="00''", text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0, 0.84), text='00', text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)
        self.gagPanel = DirectFrame(parent=base.a2dBottomLeft, relief=None, image=loader.loadModel('phase_6/models/karting/gag_panel'), image_scale=0.25, pos=(0.2, 0, 0.55))
        self.directObjList.append(self.gagPanel)
        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])
        self.cardMaker.setName('RaceProgressLineHash')
        for n in xrange(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t, self.faceStartPos[1], self.faceStartPos[2])

        self.raceModeReady = True
        self.disable()
        return

    def initResultMode(self):
        self.endPanel = RaceEndPanel(len(self.race.avIds), self.race)
        self.endPanel.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.endPanel)
        self.resultModeReady = True
        self.disable()

    def showGag(self, gagIndex):
        if gagIndex < len(self.gagTextures):
            for gag in self.gagTextures:
                gag.hide()

            self.gagTextures[gagIndex].show()

    def updateGag(self, gagIndex):
        if self.gag:
            if hasattr(self, 'gagCycleInterval'):
                self.gagCycleInterval.finish()
                del self.gagCycleInterval
            self.gag.setHpr(0, 0, 0)
            self.showGag(gagIndex)
            if gagIndex == 0:
                self.gag.hide()
            else:
                self.gag.show()
                self.gagAcquireSound.play()
                self.gagAcquireInterval = LerpHprInterval(self.gag, duration=0.5, blendType='easeOut', startHpr=Point3(0, -90, 0), hpr=Point3(0, 0, 0))
                self.gagAcquireInterval.start()

    def waitingOnGag(self, cycleTime):
        if self.gag:
            numTextures = len(self.gagTextures)
            startOffset = random.choice(range(0, numTextures))
            self.gag.show()
            self.gagCycleInterval = Parallel(LerpFunc(self.showNextGag, fromData=startOffset, toData=numTextures * 2 * cycleTime + startOffset, blendType='easeOut', duration=cycleTime), LerpHprInterval(self.gag, duration=cycleTime, hpr=Point3(0, 180 * numTextures * 2 * cycleTime - 90, 0), blendType='easeOut', startHpr=Point3(0, 0, 0)), SoundInterval(self.gagCycleSound, loop=1, duration=cycleTime, startTime=0), name='gagCycleInterval')
            self.gagCycleInterval.start()

    def showNextGag(self, t):
        if self.gag:
            currGagIndex = int(t % (len(self.gagTextures) - 1)) + 1
            self.showGag(currGagIndex)

    def enableSpeedometer(self):
        self.race.localKart.showSpeedometer()

    def disableSpeedometer(self):
        self.race.localKart.hideSpeedometer()

    def disableRaceMode(self):
        self.disableSpeedometer()
        self.render2dRoot.hide()
        self.raceModeRoot.hide()
        for x in self.timeLabels:
            for y in x:
                y.hide()

        self.setTimerEnabled(False)

    def disableResultMode(self):
        self.endPanel.disable()

    def disable(self):
        self.closeButton.hide()
        taskMgr.removeTasksMatching('clearRaceEndPanel')
        if self.raceModeReady:
            self.disableRaceMode()
        if self.resultModeReady:
            self.disableResultMode()

    def enableRaceMode(self):
        self.enableSpeedometer()
        self.render2dRoot.show()
        self.raceModeRoot.show()
        self.maxLapHit = min(self.maxLapHit, self.race.lapCount - 1)
        for x in xrange(self.maxLapHit + 1):
            for y in self.timeLabels[x]:
                y.configure(text_font=ToontownGlobals.getSignFont())
                y.show()

        for y in self.timeLabels[self.maxLapHit]:
            y.configure(text_font=ToontownGlobals.getSignFont())

    def enableResultMode(self):
        self.endPanel.enable()
        if len(self.race.circuitLoop) > 1:
            taskMgr.doMethodLater(180, self.endPanel.closeButtonPressed, 'clearRaceEndPanel', extraArgs=[])

    def destroy(self):
        self.disable()
        if hasattr(self, 'wrongWaySeq'):
            self.wrongWaySeq.finish()
            self.wrongWaySeq = None
        taskMgr.removeTasksMatching('removeIt')
        taskMgr.removeTasksMatching('removeCam*')
        taskMgr.removeTasksMatching('clearRaceEndPanel')
        for obj in self.directObjList:
            obj.destroy()

        if hasattr(self, 'mapScene'):
            self.mapScene.removeNode()
            self.mapScene = None
        self.aspect2dRoot.removeNode()
        self.aspect2dRoot = None
        self.raceModeRoot.removeNode()
        self.raceModeRoot = None
        self.render2dRoot.removeNode()
        self.render2dRoot = None
        self.closeButton = None
        self.gag = None
        self.lapLabel = None
        self.timeLabels = None
        self.placeLabelStr = None
        self.placeLabelNum = None
        self.photoFinishLabel = None
        self.mapScene = None
        self.race = None
        return

    def setSpotAsymptotic(self, diffT, spot):
        p = (-1, 1)[diffT > 0] * (1 - 1 / pow(abs(diffT) / self.cutoff + 1, 2))
        spot.setX(p)

    def setSpotRaceLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t / self.lapCount))

    def setSpotLapLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t - int(t)))

    def update(self, time):
        placeSorter = []
        placeCount = 0
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit
            if not racer.finished and racer.enabled:
                placeSorter.append((curvetime, key))
            if racer.finished or racer.enabled:
                placeCount += 1
            pt = Vec3(0, 0, 0)
            mapT = (curvetime % 1 + self.race.startT / self.race.curve.getMaxT()) % 1 * self.race.curve.getMaxT()
            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint(mapT % self.race.curve.getMaxT(), pt)
            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)
            faceX = self.faceStartPos[0] * (1 - lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)
            t = time - self.race.baseTime - self.raceTimeDelta
            if key == localAvatar.doId:
                if self.race.laps > maxlaphit:
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit
                    if self.maxLapHit < self.race.lapCount:
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(text_font=ToontownGlobals.getSignFont())

                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()

                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime() - self.race.baseTime
                        lapNotice = DirectLabel()
                        lapNotice.setScale(0.1)
                        if self.maxLapHit == self.race.lapCount - 1:
                            lapNotice['text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice['text'] = TTLocalizer.KartRace_LapText % str(self.maxLapHit + 1)
                        taskMgr.doMethodLater(2, lapNotice.remove, 'removeIt', extraArgs=[])
                self.lapLabel['text'] = str(clampScalar(self.maxLapHit + 1, 1, self.race.lapCount)) + '/' + str(self.race.lapCount)

        suffix = {1: TTLocalizer.KartRace_FirstSuffix,
         2: TTLocalizer.KartRace_SecondSuffix,
         3: TTLocalizer.KartRace_ThirdSuffix,
         4: TTLocalizer.KartRace_FourthSuffix}
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=p + placeCount - len(placeSorter))

        localRacer = self.racerDict[localAvatar.doId]
        nearDiff, farDiff = RaceGlobals.TrackDict[self.race.trackId][8]
        if not localRacer.finished and self.faceEndPos[0] - localRacer.face.getX() < nearDiff:
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if not racer.enabled or racerId == localAvatar.doId or racer.face.getX() >= self.faceEndPos[0]:
                    continue
                if self.faceEndPos[0] - racer.face.getX() < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ''
            self.placeLabelStr['text'] = ''
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[localAvatar.doId].place]
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if self.timerEnabled and self.maxLapHit < self.race.lapCount:
            self.timeLabels[self.maxLapHit][0]['text'] = "%d'" % minutes
            self.timeLabels[self.maxLapHit][1]['text'] = "%s%d''" % (padding, seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % fraction
        if self.race.wrongWay and not self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.loop()
        elif not self.race.wrongWay and self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.finish()

    def updateRacerInfo(self, avId, curvetime = None, maxlaphit = None):
        if avId in self.racerDict.keys():
            self.racerDict[avId].update(curvetime=curvetime, maxlaphit=maxlaphit)

    def racerEntered(self, avId):
        toon = base.cr.doId2do.get(avId, None)
        kart = base.cr.doId2do.get(self.race.kartMap.get(avId, None), None)
        if not toon or not kart:
            return
        if kart.getBodyColor() == InvalidEntry:
            bodyColor = getDefaultColor()
        else:
            bodyColor = getAccessory(kart.getBodyColor())
        headframe = RaceHeadFrame(av=toon, color=bodyColor)
        eyes = headframe.head.find('**/eyes*')
        eyes.setDepthTest(1)
        eyes.setDepthWrite(1)
        headframe.configure(geom_scale=(0.5, 0.5, 0.5))
        headframe.setZ(self.faceStartPos[2])
        headframe.setDepthWrite(True)
        headframe.setDepthTest(True)
        headframe.reparentTo(self.raceModeRoot)
        self.directObjList.append(headframe)
        mapspot = loader.loadModel('phase_6/models/karting/race_mapspot')
        mapspot.setColor(bodyColor)
        mapspot.reparentTo(self.mapLines)
        mapspot.setHpr(self.mapScene, 0, 0, 0)
        self.racerDict[avId] = self.RacerInfo(headframe, mapspot)
        for key, i in zip(self.racerDict.keys(), range(len(self.racerDict.keys()))):
            face = self.racerDict[key].face
            mapspot = self.racerDict[key].mapspot
            face.setX(self.faceStartPos[0])
            face.setY(-1 - 5 * (i + 1))
            face.setScale(0.15)
            mapspot.getChild(0).setY((-5 - 5 * (i + 1)) * 1000)
            mapspot.setScale(self.mapScene, 0.15)
            mapspot.setPos(self.race.startingPos[0][0])
            if key == localAvatar.doId:
                face.setY(-1)
                face.setScale(face.getScale() * 1.25)
                mapspot.getChild(0).setY(-5 * 1000)
                mapspot.setScale(mapspot.getScale() * 1.25)
                self.face = face
                self.mapspot = mapspot

        return

    def racerLeft(self, avId, unexpected = False):
        racer = self.racerDict.get(avId, None)
        if racer:
            racer.disable()
        return

    def racerFinished(self, avId, trackId, place, totalTime, entryFee, qualify, winnings, bonus, trophies, circuitPoints, circuitTime):
        racer = self.racerDict.get(avId, None)
        if racer:
            racer.update(finished=True)
            racer.disable()
            self.endPanel.displayRacer(place, entryFee, qualify, winnings, trackId, bonus, trophies, racer.face, base.cr.doId2do[avId].getName(), totalTime, circuitPoints, circuitTime)
            if racer.face in self.directObjList:
                self.directObjList.remove(racer.face)
            if avId == localAvatar.doId:
                self.disableRaceMode()
                self.enableResultMode()
                self.endPanel.startWinningsPanel(entryFee, winnings, trackId, bonus, trophies)
        return

    def racerFinishedCircuit(self, avId, place, entryFee, winnings, bonus, trophies):
        racer = self.racerDict.get(avId, None)
        if racer:
            newTotalTickets = winnings + entryFee + bonus
            self.endPanel.updateWinnings(place, newTotalTickets)
            if avId == localAvatar.doId:
                self.endPanel.updateWinningsFromCircuit(place, entryFee, winnings, bonus, trophies)
        return

    def circuitFinished(self, placeFixup):
        self.endPanel.circuitFinished(placeFixup)

    def setTimerEnabled(self, enabled):
        self.timerEnabled = enabled
Exemplo n.º 11
0
 def enterWaiting(self):
     self.waitingLabel = DirectLabel()
     self.waitingLabel['text'] = TTLocalizer.WaitingForOtherToons
     self.waitingLabel.setScale(TTLocalizer.DRenterWaiting)
Exemplo n.º 12
0
class MiniScoreItemGui(DirectFrame.DirectFrame):
    Width = PiratesGuiGlobals.PVPPanelWidth - PiratesGuiGlobals.GridSize
    Height = 0.055
    
    def __init__(self, scoreValue, parent = None, world = None, itemColorScale = None, blink = False, **kw):
        optiondefs = (('state', DGG.NORMAL, None), ('frameColor', (0, 0, 0, 0.0), None), ('borderWidth', PiratesGuiGlobals.BorderWidth, None), ('frameSize', (0.0, MiniScoreItemGui.Width, 0.0, MiniScoreItemGui.Height), None))
        self.defineoptions(kw, optiondefs)
        DirectFrame.DirectFrame.__init__(self, parent)
        self.initialiseoptions(MiniScoreItemGui)
        self.scoreValue = scoreValue
        self.world = world
        self.itemColorScale = itemColorScale
        self.blink = blink
        self.scaleSeq = None
        self._createIface()

    
    def destroy(self):
        self._destroyIface()
        DirectFrame.DirectFrame.destroy(self)
        del self.scoreValue
        self.ignoreAll()

    
    def _createIface(self):
        textFg = PiratesGuiGlobals.TextFG1
        if self.world != None:
            scoreText = self.world.getScoreText(self.scoreValue)
        else:
            scoreText = ''
        self.descText = DirectLabel(parent = self, relief = None, text = scoreText, text_align = TextNode.ALeft, text_scale = PiratesGuiGlobals.TextScaleLarge, text_fg = textFg, text_shadow = PiratesGuiGlobals.TextShadow, textMayChange = 1, pos = (0.040000000000000001, 0, 0.014999999999999999))
        if self.itemColorScale:
            self.colorLabel(self.itemColorScale)
        
        if self.blink:
            textPos = self.descText['text_pos']
            textPosX = textPos[0]
            textPosY = textPos[1]
            self.scaleSeq = Parallel(Sequence(LerpFunctionInterval(self.descText.setScale, duration = 0.20000000000000001, toData = 1.05, fromData = 1.0, blendType = 'easeInOut'), LerpFunctionInterval(self.descText.setScale, duration = 0.69999999999999996, toData = 1.0, fromData = 1.05, blendType = 'easeInOut')), Sequence(Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 0, 0, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, (1, 1, 1, 1)), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.moveLabel, (textPosX, textPosY)), Wait(0.050000000000000003), Func(self.colorLabel, PiratesGuiGlobals.TextFG1), Func(self.moveLabel, (textPosX, textPosY))))
            self.scaleSeq.start()
        

    
    def moveLabel(self, xy):
        randX = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        randY = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        self.descText['text_pos'] = (xy[0] + randX, xy[1] + randY)

    
    def colorLabel(self, color):
        self.descText['text_fg'] = color

    
    def shakeItUp(self, .2):
        (x, y, r, g, b, a) = .2
        self.colorLabel((r, g, b, a))
        randX = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        randY = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        self.moveLabel((x + randX, y + randY))
        Wait(0.050000000000000003)
        randX = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        randY = random.random() * 0.0050000000000000001 + 0.0050000000000000001
        self.moveLabel((x + randX, y + randY))
        Wait(0.050000000000000003)

    
    def _destroyIface(self):
        if self.scaleSeq:
            self.scaleSeq.finish()
            self.scaleSeq = None
        
        self.descText.destroy()
        del self.descText
Exemplo n.º 13
0
    def enterTeleportIn(self, requestStatus):
        assert (self.notify.debug("enterTeleportIn()"))
        imgScale = 0.25

        # see if someone else is already showing a dialog
        if self.dialog:
            x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
                self.loader.hood.id)

        # See if we're sad
        elif (base.localAvatar.hp < 1):
            requestStatus['nextState'] = 'popup'
            x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
                self.loader.hood.id)
            self.accept("deathAck",
                        self.__handleDeathAck,
                        extraArgs=[requestStatus])
            self.deathAckBox = DeathForceAcknowledge.DeathForceAcknowledge(
                doneEvent="deathAck")

        # Check to see if the toon has a tier zero quest
        elif ((base.localAvatar.hp > 0)
              and ((Quests.avatarHasTrolleyQuest(base.localAvatar)) or
                   (Quests.avatarHasFirstCogQuest(base.localAvatar)) or
                   (Quests.avatarHasFriendQuest(base.localAvatar)) or
                   ((Quests.avatarHasPhoneQuest(base.localAvatar)) and
                    (Quests.avatarHasCompletedPhoneQuest(base.localAvatar))))
              and (self.loader.hood.id == ToontownGlobals.ToontownCentral)):
            requestStatus['nextState'] = 'popup'
            imageModel = loader.loadModel("phase_4/models/gui/tfa_images")
            # trolley quest
            if (base.localAvatar.quests[0][0] == Quests.TROLLEY_QUEST_ID):
                if not Quests.avatarHasCompletedTrolleyQuest(base.localAvatar):
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralInitialDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage3
                    imgNodePath = imageModel.find("**/trolley-dialog-image")
                    imgPos = (0, 0, 0.04)
                    imgScale = 0.5
                else:
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralHQDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage4
                    imgNodePath = imageModel.find("**/hq-dialog-image")
                    imgPos = (0, 0, -0.02)
                    imgScale = 0.5
            # first cog quest
            elif (base.localAvatar.quests[0][0] == Quests.FIRST_COG_QUEST_ID):
                if not Quests.avatarHasCompletedFirstCogQuest(
                        base.localAvatar):
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralTunnelDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage5
                    imgNodePath = imageModel.find("**/tunnelSignA")
                    imgPos = (0, 0, 0.04)
                    imgScale = 0.5
                else:
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralHQDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage6
                    imgNodePath = imageModel.find("**/hq-dialog-image")
                    imgPos = (0, 0, 0.05)
                    imgScale = 0.5
            # make a friend quest
            elif (base.localAvatar.quests[0][0] == Quests.FRIEND_QUEST_ID):
                if not Quests.avatarHasCompletedFriendQuest(base.localAvatar):
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralInitialDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage7
                    gui = loader.loadModel(
                        "phase_3.5/models/gui/friendslist_gui")
                    imgNodePath = gui.find("**/FriendsBox_Closed")
                    imgPos = (0, 0, 0.04)
                    imgScale = 1.0
                    gui.removeNode()
                else:
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralHQDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage8
                    imgNodePath = imageModel.find("**/hq-dialog-image")
                    imgPos = (0, 0, 0.05)
                    imgScale = 0.5
            # phone quest
            elif (base.localAvatar.quests[0][0] == Quests.PHONE_QUEST_ID):
                if Quests.avatarHasCompletedPhoneQuest(base.localAvatar):
                    x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                        base.cr.hoodMgr.ToontownCentralHQDropPoints)
                    msg = TTLocalizer.NPCForceAcknowledgeMessage9
                    imgNodePath = imageModel.find("**/hq-dialog-image")
                    imgPos = (0, 0, 0.05)
                    imgScale = 0.5

            self.dialog = TTDialog.TTDialog(text=msg,
                                            command=self.__cleanupDialog,
                                            style=TTDialog.Acknowledge)
            imgLabel = DirectLabel.DirectLabel(parent=self.dialog,
                                               relief=None,
                                               pos=imgPos,
                                               scale=TTLocalizer.PimgLabel,
                                               image=imgNodePath,
                                               image_scale=imgScale)
            imageModel.removeNode()
        else:
            # ...this toon has completed their trolley quest.
            # Choose a random location within the safezone to drop you.
            # We do this even if we plan to be teleporting to a toon,
            # because the gotoToon option may fail if the toon has moved
            # on.
            requestStatus['nextState'] = 'walk'
            x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
                self.loader.hood.id)

        # toon may not be parented to hidden at this point, if say the boat or piano
        # on-floor event has detected an intersection (which seems to occur when Toon
        # who lost a connection in battle re-enters in melodyland).  In that case,
        # it would be parented to the moving platform, and for that case the coords below
        # are wrong, so before doing a setPos, reparent to hidden.
        base.localAvatar.detachNode()
        base.localAvatar.setPosHpr(render, x, y, z, h, p, r)

        Place.Place.enterTeleportIn(self, requestStatus)
Exemplo n.º 14
0
    def update(self, time):
        placeSorter = []
        placeCount = 0

        # begin updates for all racers
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit

            if (not racer.finished and racer.enabled):
                placeSorter.append((curvetime, key))
            if (racer.finished or racer.enabled):
                placeCount += 1

            pt = Vec3(0, 0, 0)

            mapT = (
                (curvetime % 1 + self.race.startT / self.race.curve.getMaxT())
                % 1) * self.race.curve.getMaxT()

            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint((mapT % self.race.curve.getMaxT()), pt)

            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)

            faceX = self.faceStartPos[0] * (1 -
                                            lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)

            # subtract out previous lap times
            t = time - self.race.baseTime - self.raceTimeDelta

            # begin updates for self only
            if (key == localAvatar.doId):
                if (self.race.laps > maxlaphit):
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit

                    if (self.maxLapHit < self.race.lapCount):
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())
                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()
                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime(
                        ) - self.race.baseTime

                        lapNotice = DirectLabel()
                        lapNotice.setScale(.1)
                        if (self.maxLapHit == self.race.lapCount - 1):
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_LapText % str(
                                    self.maxLapHit + 1)
                        taskMgr.doMethodLater(2,
                                              lapNotice.remove,
                                              "removeIt",
                                              extraArgs=[])

                self.lapLabel['text'] = str(
                    clampScalar(self.maxLapHit + 1, 1,
                                self.race.lapCount)) + '/' + str(
                                    self.race.lapCount)

        suffix = {
            1: TTLocalizer.KartRace_FirstSuffix,
            2: TTLocalizer.KartRace_SecondSuffix,
            3: TTLocalizer.KartRace_ThirdSuffix,
            4: TTLocalizer.KartRace_FourthSuffix,
        }
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=(p + placeCount -
                                               len(placeSorter)))

        # if we are close to the finish line, and so is someone else,
        # declare a 'photo finish'
        localRacer = self.racerDict[localAvatar.doId]
        (nearDiff, farDiff) = RaceGlobals.TrackDict[self.race.trackId][8]
        if (not localRacer.finished) and (
                self.faceEndPos[0] - localRacer.face.getX() < nearDiff):
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if (not racer.enabled or (racerId == localAvatar.doId)
                        or (racer.face.getX() >= self.faceEndPos[0])):
                    continue

                if (self.faceEndPos[0] - racer.face.getX()) < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ""
            self.placeLabelStr['text'] = ""
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(
                self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[
                localAvatar.doId].place]

        # convert the time into a label displayable string
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        # quick python ternary operator
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if (self.timerEnabled and self.maxLapHit < self.race.lapCount):
            self.timeLabels[self.maxLapHit][0]['text'] = '%d\'' % (minutes)
            self.timeLabels[self.maxLapHit][1]['text'] = '%s%d\'\'' % (padding,
                                                                       seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % (fraction)

        if (self.race.wrongWay and not self.wrongWaySeq.isPlaying()):
            self.wrongWaySeq.loop()
        elif (not self.race.wrongWay and self.wrongWaySeq.isPlaying()):
            self.wrongWaySeq.finish()
Exemplo n.º 15
0
class RaceGUI:
    GagPie = 0
    gagRoot = "phase_3.5/maps/inventory_"

    class RacerInfo:
        def __init__(self, face, mapSpot):
            self.curvetime = 0
            self.maxlaphit = 0
            self.face = face
            self.mapspot = mapSpot
            self.place = 1
            self.enabled = True
            self.finished = False
            self.gag = None

        def update(self,
                   curvetime=None,
                   maxlaphit=None,
                   faceX=None,
                   mapspotPt=None,
                   place=None,
                   finished=None):
            if (self.enabled):
                if (not curvetime == None):
                    self.curvetime = curvetime
                if (not maxlaphit == None):
                    self.maxlaphit = maxlaphit
                if (not faceX == None):
                    self.face.setX(faceX)
                if (not mapspotPt == None):
                    self.mapspot.setPos(mapspotPt)
                if (not place == None):
                    self.place = place
                if (not finished == None):
                    self.finished = finished

        def disable(self):
            self.enabled = False
            if (not self.finished):
                self.face.hide()
            self.mapspot.hide()

        def enable(self):
            self.enabled = True
            self.face.show()
            self.mapspot.show()

    def __init__(self, distRace):
        self.race = distRace
        self.timerEnabled = False
        self.maxLapHit = 0
        self.photoFinish = False

        toonInteriorTextures = loader.loadModel(
            'phase_3.5/models/modules/toon_interior_textures')
        invTextures = loader.loadModel('phase_3.5/models/gui/inventory_icons')
        racingTextures = loader.loadModel(
            'phase_6/models/karting/racing_textures')
        self.gagTextures = [
            toonInteriorTextures.find('**/couch'),
            invTextures.find('**/inventory_bannana_peel'),
            racingTextures.find('**/boost_arrow'),
            invTextures.find('**/inventory_anvil'),
            invTextures.find('**/inventory_creampie'),
        ]
        self.gagTextures[1].setScale(7.5)
        self.gagTextures[3].setScale(7.5)
        self.gagTextures[4].setScale(7.5)

        self.cardMaker = CardMaker('card')

        #racer info
        self.racerDict = {}

        #setup render2d
        self.render2dRoot = render2d.attachNewNode('RaceGuiRender2dRoot')
        self.render2dRoot.setDepthWrite(1)

        #setup a list of directobjects
        self.directObjList = []

        #setup aspect2d
        self.aspect2dRoot = aspect2d.attachNewNode('RaceGuiAspect2dRoot')
        self.aspect2dRoot.setDepthWrite(1)

        #setup raceModeRoot
        self.raceModeRoot = self.aspect2dRoot.attachNewNode('RaceModeRoot')

        #setup the 'leave race' button
        gui = loader.loadModel("phase_3.5/models/gui/avatar_panel_gui")
        self.closeButton = DirectButton(
            image=(
                gui.find("**/CloseBtn_UP"),
                gui.find("**/CloseBtn_DN"),
                gui.find("**/CloseBtn_Rllvr"),
                gui.find("**/CloseBtn_UP"),
            ),
            relief=None,
            scale=1.05,
            text=TTLocalizer.KartRace_Leave,
            text_scale=0.04,
            text_pos=(0, -0.07),
            text_fg=VBase4(1, 1, 1, 1),
            pos=(-0.99, 0, 0.925),
            command=self.race.leaveRace,
        )
        self.closeButton.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.closeButton)

        #setup the race gui
        self.raceTimeDelta = 0
        self.raceModeReady = False
        #        self.initRaceMode()

        #setup the end result mode gui
        self.resultModeReady = False
        #        self.initResultMode()

        # Load the sounds for cycling through and picking a gag.
        # Since the methods for gag cycling are all here, it makes sense
        # for the sounds to be here as well.
        self.gagCycleSound = base.loadSfx(
            "phase_3.5/audio/sfx/tick_counter.mp3")
        if hasattr(self.gagCycleSound, "setPlayRate"):
            self.gagCycleSound.setPlayRate(0.2)
        self.gagCycleSound.setLoop(1)
        self.gagAcquireSound = base.loadSfx(
            "phase_6/audio/sfx/SZ_MM_gliss.mp3")

        self.disable()

    def initRaceMode(self):
        ##         #setup the 'map' display region
        ##         self.mapScene = NodePath('MapScene')
        ##         self.mapScene.setTransparency(1)
        ##         self.mapSize = 0.15
        ##         self.mapX = 0.84
        ##         self.mapY = 0.84
        ##         self.mapCam = None
        ##         if (base.win.getNumDisplayRegions()>4):
        ##             for x in range(base.win.getNumDisplayRegions()-4):
        ##                 dr = base.win.getDisplayRegion(x+4)
        ##                 if (dr.getCamera().getName() == 'MapCam'):
        ##                     self.mapCam = dr.getCamera()
        ##                     break

        ##         if(self.mapCam == None):
        ##             self.mapCam = base.makeCamera(base.win,sort=30,displayRegion = (self.mapX,self.mapX+self.mapSize,self.mapY,self.mapY+self.mapSize),camName = 'MapCam')

        ##         self.mapCam.setY(-10)
        ##         self.mapCam.node().setLens(OrthographicLens())
        ##         self.mapCam.node().getLens().setFilmSize(2)
        ##         self.mapCam.node().getLens().setAspectRatio(4.0/3.0)
        ##         self.mapCam.reparentTo(self.mapScene)

        ##         self.cardMaker.reset()
        ##         self.cardMaker.setName('MapBackground')
        ##         self.cardMaker.setFrame(-1,1,-1,1)
        ##         self.cardMaker.setColor(1,1,1,0.25)
        ##         card = self.mapScene.attachNewNode(self.cardMaker.generate())

        #setup the 'map' display region
        self.mapScene = self.raceModeRoot.attachNewNode('MapScene')
        self.mapScene.setPos(1.1, 0, 0.75)
        self.mapScene.setScale(0.25, 0.001, 0.25)

        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)

        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)

        for x in range(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if (x == 0):
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 *
                               RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)

        #setup face info
        self.faceStartPos = Vec3(-0.80, 0, 0.93)
        self.faceEndPos = Vec3(0.80, 0, 0.93)

        #setup place(1st,2nd,...) reporting
        self.placeLabelNum = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelNumPos,
            text='1',
            text_scale=0.35,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.placeLabelNum.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelNum)

        self.placeLabelStr = DirectLabel(
            relief=None,
            pos=TTLocalizer.RGUIplaceLabelStrPos,
            text=TTLocalizer.KartRace_FirstSuffix,
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.placeLabelStr.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.placeLabelStr)

        #setup lap reporting
        self.lapLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.45),
            text='1/' + str(self.race.lapCount),
            text_scale=0.1,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.lapLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.lapLabel)

        #setup photo finish label
        self.photoFinishLabel = DirectLabel(
            relief=None,
            pos=(0, 0, -0.1),
            text=TTLocalizer.KartRace_PhotoFinish,
            text_scale=TTLocalizer.RGUIphotoFinish,
            text_fg=(0.95, 0.95, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)

        #setup wrong way reporting
        self.wrongWayLabel = DirectLabel(
            relief=None,
            pos=(1.1, 0, 0.85),
            text=TTLocalizer.KartRace_WrongWay,
            text_scale=0.1,
            text_fg=(0.95, 0, 0, 1),
            text_font=ToontownGlobals.getSignFont(),
        )
        self.wrongWayLabel.reparentTo(self.raceModeRoot)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))

        self.wrongWaySeq = Sequence(
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 1),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 0)),
            self.wrongWayLabel.colorScaleInterval(0.25,
                                                  colorScale=Vec4(1, 1, 1, 0),
                                                  startColorScale=Vec4(
                                                      1, 1, 1, 1)),
        )

        #setup time reporting
        interpolateFacePos = lambda x: self.faceStartPos * (
            1.0 - x) + self.faceEndPos * (x)
        self.timeLabels = []
        for x in range(self.race.lapCount):
            minLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0,
                     0.84),
                text='0\'',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0,
                     0.84),
                text='00\'\'',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(
                relief=None,
                pos=(interpolateFacePos(
                    (2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0,
                     0.84),
                text='00',
                text_scale=0.06,
                text_fg=(0.95, 0.95, 0, 1),
                text_font=ToontownGlobals.getSignFont(),
                text_align=TextNode.ARight,
            )
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        #setup gag indicator
        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)

        self.gagPanel = DirectFrame(
            parent=self.raceModeRoot,
            relief=None,
            image=loader.loadModel('phase_6/models/karting/gag_panel'),
            image_scale=0.25,
            pos=(-1.13, 0, -0.5),
        )
        self.directObjList.append(self.gagPanel)

        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        #setup face line
        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])

        self.cardMaker.setName('RaceProgressLineHash')
        for n in range(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(
                self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t,
                self.faceStartPos[1], self.faceStartPos[2])
        self.raceModeReady = True
        self.disable()

    def initResultMode(self):
        self.endPanel = RaceEndPanel(len(self.race.avIds), self.race)
        self.endPanel.reparentTo(self.aspect2dRoot)
        self.directObjList.append(self.endPanel)
        self.resultModeReady = True
        self.disable()

    def showGag(self, gagIndex):
        if gagIndex < len(self.gagTextures):
            for gag in self.gagTextures:
                gag.hide()
            self.gagTextures[gagIndex].show()

    def updateGag(self, gagIndex):
        if (self.gag):
            # Make sure the gag cycle interval is cleaned up.
            # Do this before setting the final gag texture.
            if hasattr(self, "gagCycleInterval"):
                self.gagCycleInterval.finish()
                del self.gagCycleInterval
            #self.gagCycleSound.stop()
            self.gag.setHpr(0, 0, 0)
            # Set the actual gag texture.
            self.showGag(gagIndex)
            if gagIndex == 0:
                self.gag.hide()
            else:
                self.gag.show()
                self.gagAcquireSound.play()
                self.gagAcquireInterval = LerpHprInterval(self.gag,
                                                          duration=0.5,
                                                          blendType="easeOut",
                                                          startHpr=Point3(
                                                              0, -90, 0),
                                                          hpr=Point3(0, 0, 0))
                self.gagAcquireInterval.start()

    def waitingOnGag(self, cycleTime):
        if (self.gag):
            numTextures = len(self.gagTextures)
            startOffset = random.choice(range(0, numTextures))
            self.gag.show()
            self.gagCycleInterval = Parallel(
                LerpFunc(self.showNextGag,
                         fromData=startOffset,
                         toData=numTextures * 2 * cycleTime + startOffset,
                         blendType="easeOut",
                         duration=cycleTime),
                LerpHprInterval(self.gag,
                                duration=cycleTime,
                                hpr=Point3(
                                    0, 180 * numTextures * 2 * cycleTime - 90,
                                    0),
                                blendType="easeOut",
                                startHpr=Point3(0, 0, 0)),
                SoundInterval(self.gagCycleSound,
                              loop=1,
                              duration=cycleTime,
                              startTime=0),
                name="gagCycleInterval")
            self.gagCycleInterval.start()

    def showNextGag(self, t):
        if (self.gag):
            # We don't want to show the texture at index 0.
            currGagIndex = int(t % (len(self.gagTextures) - 1)) + 1
            self.showGag(currGagIndex)

    def enableSpeedometer(self):
        self.race.localKart.showSpeedometer()

    def disableSpeedometer(self):
        self.race.localKart.hideSpeedometer()

    def disableRaceMode(self):
        self.disableSpeedometer()
        ##         self.mapCam.node().getDisplayRegion(0).setActive(False)
        self.render2dRoot.hide()
        self.raceModeRoot.hide()

        for x in self.timeLabels:
            for y in x:
                y.hide()

        self.setTimerEnabled(False)

    def disableResultMode(self):
        self.endPanel.disable()

    def disable(self):
        self.closeButton.hide()
        taskMgr.removeTasksMatching("clearRaceEndPanel")

        if self.raceModeReady:
            self.disableRaceMode()

        if self.resultModeReady:
            self.disableResultMode()

    def enableRaceMode(self):
        self.enableSpeedometer()

        ##        self.closeButton.show()

        ##         self.mapCam.node().getDisplayRegion(0).setActive(True)
        self.render2dRoot.show()
        self.raceModeRoot.show()

        self.maxLapHit = min(self.maxLapHit, self.race.lapCount - 1)

        for x in range(self.maxLapHit + 1):
            for y in self.timeLabels[x]:
                y.configure(text_font=ToontownGlobals.getSignFont())
                y.show()
        for y in self.timeLabels[self.maxLapHit]:
            y.configure(text_font=ToontownGlobals.getSignFont())

    def enableResultMode(self):
        self.endPanel.enable()
        # make this panel eventually go away eventually if this is the last race
        if not self.race.circuitLoop:
            taskMgr.doMethodLater(180,
                                  self.endPanel.closeButtonPressed,
                                  "clearRaceEndPanel",
                                  extraArgs=[])

    def destroy(self):
        self.disable()

        if hasattr(self, "wrongWaySeq"):
            self.wrongWaySeq.finish()
            self.wrongWaySeq = None

        taskMgr.removeTasksMatching('removeIt')
        taskMgr.removeTasksMatching('removeCam*')
        taskMgr.removeTasksMatching("clearRaceEndPanel")

        for obj in self.directObjList:
            obj.destroy()

        if hasattr(self, "mapScene"):
            self.mapScene.removeNode()
            self.mapScene = None

        self.aspect2dRoot.removeNode()
        self.aspect2dRoot = None

        self.raceModeRoot.removeNode()
        self.raceModeRoot = None

        self.render2dRoot.removeNode()
        self.render2dRoot = None

        self.closeButton = None
        self.gag = None
        self.lapLabel = None
        self.timeLabels = None
        self.placeLabelStr = None
        self.placeLabelNum = None
        self.photoFinishLabel = None
        self.mapScene = None
        self.race = None

    def setSpotAsymptotic(self, diffT, spot):
        p = (-1, 1)[diffT > 0] * (1 - 1 / pow(abs(diffT) / self.cutoff + 1, 2))
        spot.setX(p)

    def setSpotRaceLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t / self.lapCount))

    def setSpotLapLinear(self, t, spot):
        spot.setX(-1.0 + 2.0 * (t - int(t)))

    def update(self, time):
        placeSorter = []
        placeCount = 0

        # begin updates for all racers
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit

            if (not racer.finished and racer.enabled):
                placeSorter.append((curvetime, key))
            if (racer.finished or racer.enabled):
                placeCount += 1

            pt = Vec3(0, 0, 0)

            mapT = (
                (curvetime % 1 + self.race.startT / self.race.curve.getMaxT())
                % 1) * self.race.curve.getMaxT()

            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint((mapT % self.race.curve.getMaxT()), pt)

            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)

            faceX = self.faceStartPos[0] * (1 -
                                            lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)

            # subtract out previous lap times
            t = time - self.race.baseTime - self.raceTimeDelta

            # begin updates for self only
            if (key == localAvatar.doId):
                if (self.race.laps > maxlaphit):
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit

                    if (self.maxLapHit < self.race.lapCount):
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())
                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()
                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime(
                        ) - self.race.baseTime

                        lapNotice = DirectLabel()
                        lapNotice.setScale(.1)
                        if (self.maxLapHit == self.race.lapCount - 1):
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_LapText % str(
                                    self.maxLapHit + 1)
                        taskMgr.doMethodLater(2,
                                              lapNotice.remove,
                                              "removeIt",
                                              extraArgs=[])

                self.lapLabel['text'] = str(
                    clampScalar(self.maxLapHit + 1, 1,
                                self.race.lapCount)) + '/' + str(
                                    self.race.lapCount)

        suffix = {
            1: TTLocalizer.KartRace_FirstSuffix,
            2: TTLocalizer.KartRace_SecondSuffix,
            3: TTLocalizer.KartRace_ThirdSuffix,
            4: TTLocalizer.KartRace_FourthSuffix,
        }
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=(p + placeCount -
                                               len(placeSorter)))

        # if we are close to the finish line, and so is someone else,
        # declare a 'photo finish'
        localRacer = self.racerDict[localAvatar.doId]
        (nearDiff, farDiff) = RaceGlobals.TrackDict[self.race.trackId][8]
        if (not localRacer.finished) and (
                self.faceEndPos[0] - localRacer.face.getX() < nearDiff):
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if (not racer.enabled or (racerId == localAvatar.doId)
                        or (racer.face.getX() >= self.faceEndPos[0])):
                    continue

                if (self.faceEndPos[0] - racer.face.getX()) < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ""
            self.placeLabelStr['text'] = ""
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(
                self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[
                localAvatar.doId].place]

        # convert the time into a label displayable string
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        # quick python ternary operator
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if (self.timerEnabled and self.maxLapHit < self.race.lapCount):
            self.timeLabels[self.maxLapHit][0]['text'] = '%d\'' % (minutes)
            self.timeLabels[self.maxLapHit][1]['text'] = '%s%d\'\'' % (padding,
                                                                       seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % (fraction)

        if (self.race.wrongWay and not self.wrongWaySeq.isPlaying()):
            self.wrongWaySeq.loop()
        elif (not self.race.wrongWay and self.wrongWaySeq.isPlaying()):
            self.wrongWaySeq.finish()

    def updateRacerInfo(self, avId, curvetime=None, maxlaphit=None):
        if (avId in self.racerDict.keys()):
            self.racerDict[avId].update(curvetime=curvetime,
                                        maxlaphit=maxlaphit)

    #####################################################
    # Begin populating the gui elements with racer data #
    #####################################################
    def racerEntered(self, avId):
        toon = base.cr.doId2do.get(avId, None)
        kart = base.cr.doId2do.get(self.race.kartMap.get(avId, None), None)

        if (not toon or not kart):
            return

        if (kart.getBodyColor() == InvalidEntry):
            bodyColor = getDefaultColor()
        else:
            bodyColor = getAccessory(kart.getBodyColor())

#########################################################
# When offscreen buffers are supported, this works...   #
#########################################################
##         # setup temporary portrait scene graph
##         buf = base.graphicsEngine.makeBuffer(base.win.getGsg(),'test',0,128,128)
##         par = buf.makeTextureBuffer('par',128,128)
##         parcam = base.makeCamera(par,0,'parCam')
##         parcam.node().setLens(OrthographicLens())
##         parcam.node().getLens().setFilmSize(0.5,0.5)
##         portraitSceneGraph = NodePath('Portrait:%d'%avId)
##         parcam.reparentTo(portraitSceneGraph)
##         tex = par.getTexture()

##         headframe = RaceHeadFrame(toon,bodyColor)
##         headframe.configure(geom_scale=(0.5,0.5,0.5))
##         headframe.setY(10)
##         headframe.reparentTo(portraitSceneGraph)

##         # take picture and initialize cleanup
##         buf.setOneShot(True)
##         def cleanUpPortrait(task,s = portraitSceneGraph,f = headframe):
##             f.destroy()
##             s.removeNode()
##         # if using this doMethodLater, be sure to remove it from the taskMgr
##         #
##         taskMgr.doMethodLater(1,cleanUpPortrait,'removeCam:%d'%avId)

##         #setup face
##         self.cardMaker.reset()
##         self.cardMaker.setName('Face:%d'%avId)
##         self.cardMaker.setFrame(-0.5,0.5,-0.5,0.5)
##         face = NodePath(self.cardMaker.generate())
##         face.setTexture(tex,1)
##         face.setZ(self.faceStartPos[2])
##         face.reparentTo(self.raceModeRoot)

        headframe = RaceHeadFrame(av=toon, color=bodyColor)
        eyes = headframe.head.find('**/eyes*')
        eyes.setDepthTest(1)
        eyes.setDepthWrite(1)
        headframe.configure(geom_scale=(0.5, 0.5, 0.5))
        headframe.setZ(self.faceStartPos[2])
        headframe.setDepthWrite(True)
        headframe.setDepthTest(True)
        headframe.reparentTo(self.raceModeRoot)
        self.directObjList.append(headframe)

        #setup map place
        mapspot = loader.loadModel('phase_6/models/karting/race_mapspot')
        mapspot.setColor(bodyColor)
        mapspot.reparentTo(self.mapLines)
        mapspot.setHpr(self.mapScene, 0, 0, 0)

        self.racerDict[avId] = self.RacerInfo(headframe, mapspot)
        for key, i in zip(self.racerDict.keys(),
                          range(len(self.racerDict.keys()))):
            face = self.racerDict[key].face
            mapspot = self.racerDict[key].mapspot

            face.setX(self.faceStartPos[0])
            face.setY(-1 - 5 * (i + 1))
            face.setScale(0.15)

            mapspot.getChild(0).setY((-5 - 5 * (i + 1)) * 1000)
            mapspot.setScale(self.mapScene, 0.15)
            mapspot.setPos(self.race.startingPos[0][0])

            if (key == localAvatar.doId):
                face.setY(-1)
                face.setScale(face.getScale() * 1.25)

                mapspot.getChild(0).setY((-5) * 1000)
                mapspot.setScale(mapspot.getScale() * 1.25)

                self.face = face
                self.mapspot = mapspot

    def racerLeft(self, avId, unexpected=False):
        racer = self.racerDict.get(avId, None)
        if (racer):
            racer.disable()

    def racerFinished(self, avId, trackId, place, totalTime, entryFee, qualify,
                      winnings, bonus, trophies, circuitPoints, circuitTime):
        racer = self.racerDict.get(avId, None)
        if (racer):
            racer.update(finished=True)
            racer.disable()
            self.endPanel.displayRacer(place, entryFee, qualify, winnings,
                                       trackId, bonus, trophies, racer.face,
                                       base.cr.doId2do[avId].getName(),
                                       totalTime, circuitPoints, circuitTime)
            self.directObjList.remove(racer.face)

            if (avId == localAvatar.doId):
                self.disableRaceMode()
                self.enableResultMode()
                self.endPanel.startWinningsPanel(entryFee, winnings, trackId,
                                                 bonus, trophies)

    def racerFinishedCircuit(self, avId, place, entryFee, winnings, bonus,
                             trophies):
        #print("racerFinishedCircuit")
        racer = self.racerDict.get(avId, None)
        if (racer):
            newTotalTickets = winnings + entryFee + bonus
            self.endPanel.updateWinnings(place, newTotalTickets)

            if (avId == localAvatar.doId):
                self.endPanel.updateWinningsFromCircuit(
                    place, entryFee, winnings, bonus, trophies)
                pass
            #    self.disableRaceMode()
            #    self.enableResultMode()
            #    self.endPanel.startWinningsPanel(entryFee,winnings,trackId,bonus,trophies)

    def circuitFinished(self, placeFixup):
        #print "circuit finished"
        self.endPanel.circuitFinished(placeFixup)

    def setTimerEnabled(self, enabled):
        self.timerEnabled = enabled
    def update(self, time):
        placeSorter = []
        placeCount = 0
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit
            if not racer.finished and racer.enabled:
                placeSorter.append((curvetime, key))
            if racer.finished or racer.enabled:
                placeCount += 1
            pt = Vec3(0, 0, 0)
            mapT = (curvetime % 1 + self.race.startT /
                    self.race.curve.getMaxT()) % 1 * self.race.curve.getMaxT()
            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint(mapT % self.race.curve.getMaxT(), pt)
            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)
            faceX = self.faceStartPos[0] * (1 -
                                            lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)
            t = time - self.race.baseTime - self.raceTimeDelta
            if key == localAvatar.doId:
                if self.race.laps > maxlaphit:
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit
                    if self.maxLapHit < self.race.lapCount:
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()

                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(
                                text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime(
                        ) - self.race.baseTime
                        lapNotice = DirectLabel()
                        lapNotice.setScale(0.1)
                        if self.maxLapHit == self.race.lapCount - 1:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice[
                                'text'] = TTLocalizer.KartRace_LapText % str(
                                    self.maxLapHit + 1)
                        taskMgr.doMethodLater(2,
                                              lapNotice.remove,
                                              'removeIt',
                                              extraArgs=[])
                self.lapLabel['text'] = str(
                    clampScalar(self.maxLapHit + 1, 1,
                                self.race.lapCount)) + '/' + str(
                                    self.race.lapCount)

        suffix = {
            1: TTLocalizer.KartRace_FirstSuffix,
            2: TTLocalizer.KartRace_SecondSuffix,
            3: TTLocalizer.KartRace_ThirdSuffix,
            4: TTLocalizer.KartRace_FourthSuffix
        }
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=p + placeCount -
                                        len(placeSorter))

        localRacer = self.racerDict[localAvatar.doId]
        nearDiff, farDiff = RaceGlobals.TrackDict[self.race.trackId][8]
        if not localRacer.finished and self.faceEndPos[
                0] - localRacer.face.getX() < nearDiff:
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if not racer.enabled or racerId == localAvatar.doId or racer.face.getX(
                ) >= self.faceEndPos[0]:
                    continue
                if self.faceEndPos[0] - racer.face.getX() < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ''
            self.placeLabelStr['text'] = ''
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(
                self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[
                localAvatar.doId].place]
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if self.timerEnabled and self.maxLapHit < self.race.lapCount:
            self.timeLabels[self.maxLapHit][0]['text'] = "%d'" % minutes
            self.timeLabels[self.maxLapHit][1]['text'] = "%s%d''" % (padding,
                                                                     seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % fraction
        if self.race.wrongWay and not self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.loop()
        elif not self.race.wrongWay and self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.finish()
 def enterTeleportIn(self, requestStatus):
     imgScale = 0.25
     if self.dialog:
         x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
             self.loader.hood.id)
     elif base.localAvatar.hp < 1:
         requestStatus['nextState'] = 'popup'
         x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
             self.loader.hood.id)
         self.accept('deathAck',
                     self.__handleDeathAck,
                     extraArgs=[requestStatus])
         self.deathAckBox = DeathForceAcknowledge.DeathForceAcknowledge(
             doneEvent='deathAck')
     elif base.localAvatar.hp > 0 and (
             Quests.avatarHasTrolleyQuest(base.localAvatar)
             or Quests.avatarHasFirstCogQuest(base.localAvatar)
             or Quests.avatarHasFriendQuest(base.localAvatar)
             or Quests.avatarHasPhoneQuest(base.localAvatar)
             and Quests.avatarHasCompletedPhoneQuest(base.localAvatar)
     ) and self.loader.hood.id == ToontownGlobals.ToontownCentral:
         requestStatus['nextState'] = 'popup'
         imageModel = loader.loadModel('phase_4/models/gui/tfa_images')
         if base.localAvatar.quests[0][0] == Quests.TROLLEY_QUEST_ID:
             if not Quests.avatarHasCompletedTrolleyQuest(base.localAvatar):
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralInitialDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage3
                 imgNodePath = imageModel.find('**/trolley-dialog-image')
                 imgPos = (0, 0, 0.04)
                 imgScale = 0.5
             else:
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralHQDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage4
                 imgNodePath = imageModel.find('**/hq-dialog-image')
                 imgPos = (0, 0, -0.02)
                 imgScale = 0.5
         elif base.localAvatar.quests[0][0] == Quests.FIRST_COG_QUEST_ID:
             if not Quests.avatarHasCompletedFirstCogQuest(
                     base.localAvatar):
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralTunnelDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage5
                 imgNodePath = imageModel.find('**/tunnelSignA')
                 imgPos = (0, 0, 0.04)
                 imgScale = 0.5
             else:
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralHQDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage6
                 imgNodePath = imageModel.find('**/hq-dialog-image')
                 imgPos = (0, 0, 0.05)
                 imgScale = 0.5
         elif base.localAvatar.quests[0][0] == Quests.FRIEND_QUEST_ID:
             if not Quests.avatarHasCompletedFriendQuest(base.localAvatar):
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralInitialDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage7
                 gui = loader.loadModel(
                     'phase_3.5/models/gui/friendslist_gui')
                 imgNodePath = gui.find('**/FriendsBox_Closed')
                 imgPos = (0, 0, 0.04)
                 imgScale = 1.0
                 gui.removeNode()
             else:
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralHQDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage8
                 imgNodePath = imageModel.find('**/hq-dialog-image')
                 imgPos = (0, 0, 0.05)
                 imgScale = 0.5
         elif base.localAvatar.quests[0][0] == Quests.PHONE_QUEST_ID:
             if Quests.avatarHasCompletedPhoneQuest(base.localAvatar):
                 x, y, z, h, p, r = base.cr.hoodMgr.getDropPoint(
                     base.cr.hoodMgr.ToontownCentralHQDropPoints)
                 msg = TTLocalizer.NPCForceAcknowledgeMessage9
                 imgNodePath = imageModel.find('**/hq-dialog-image')
                 imgPos = (0, 0, 0.05)
                 imgScale = 0.5
         self.dialog = TTDialog.TTDialog(text=msg,
                                         command=self.__cleanupDialog,
                                         style=TTDialog.Acknowledge)
         imgLabel = DirectLabel.DirectLabel(parent=self.dialog,
                                            relief=None,
                                            pos=imgPos,
                                            scale=TTLocalizer.PimgLabel,
                                            image=imgNodePath,
                                            image_scale=imgScale)
         imageModel.removeNode()
     else:
         requestStatus['nextState'] = 'walk'
         x, y, z, h, p, r = base.cr.hoodMgr.getPlaygroundCenterFromId(
             self.loader.hood.id)
     base.localAvatar.detachNode()
     base.localAvatar.setPosHpr(render, x, y, z, h, p, r)
     Place.Place.enterTeleportIn(self, requestStatus)
     return
 def enterWaiting(self):
     self.waitingLabel = DirectLabel()
     self.waitingLabel["text"] = TTLocalizer.WaitingForOtherToons
     self.waitingLabel.setScale(TTLocalizer.DRenterWaiting)
Exemplo n.º 19
0
    def initRaceMode(self):
        self.mapScene = base.a2dTopRight.attachNewNode('MapScene')
        self.mapScene.setPos(-0.2, 0, -0.2)
        self.mapScene.setScale(0.25, 0.001, 0.25)
        maxT = self.race.curve.getMaxT()
        pt = Vec3(0, 0, 0)
        ls = LineSegs('MapLines')
        ls.setColor(1, 1, 1, 1)
        ls.setThickness(2)
        for x in xrange(101):
            self.race.curve.getPoint(x / 100.0 * maxT, pt)
            if x == 0:
                ls.moveTo(pt[0], pt[1], pt[2])
            else:
                ls.drawTo(pt[0], pt[1], pt[2])

        self.mapLines = self.mapScene.attachNewNode(ls.create())
        self.mapLines.setScale(0.00025 * RaceGlobals.TrackDict[self.race.trackId][6])
        self.mapLines.setP(90)
        self.faceStartPos = Vec3(-0.8, 0, 0.93)
        self.faceEndPos = Vec3(0.8, 0, 0.93)
        self.placeLabelNum = DirectLabel(relief=None, pos=TTLocalizer.RGUIplaceLabelNumPos, text='1', text_scale=0.35, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.placeLabelNum.reparentTo(base.a2dBottomLeft)
        self.directObjList.append(self.placeLabelNum)
        self.placeLabelStr = DirectLabel(relief=None, pos=TTLocalizer.RGUIplaceLabelStrPos, text=TTLocalizer.KartRace_FirstSuffix, text_scale=0.1, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.placeLabelStr.reparentTo(base.a2dBottomLeft)
        self.directObjList.append(self.placeLabelStr)
        self.lapLabel = DirectLabel(relief=None, pos=(-0.22, 0, -0.5), text='1/' + str(self.race.lapCount), text_scale=0.1, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.lapLabel.reparentTo(base.a2dTopRight)
        self.directObjList.append(self.lapLabel)
        self.photoFinishLabel = DirectLabel(relief=None, pos=(0, 0, -0.1), text=TTLocalizer.KartRace_PhotoFinish, text_scale=TTLocalizer.RGUIphotoFinish, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.photoFinishLabel.hide()
        self.directObjList.append(self.photoFinishLabel)
        self.wrongWayLabel = DirectLabel(relief=None, pos=(-0.22, 0, -0.2), text=TTLocalizer.KartRace_WrongWay, text_scale=0.1, text_fg=(0.95, 0, 0, 1), text_font=ToontownGlobals.getSignFont())
        self.wrongWayLabel.reparentTo(base.a2dTopRight)
        self.directObjList.append(self.wrongWayLabel)
        self.wrongWayLabel.setColorScale(Vec4(1, 1, 1, 0))
        self.wrongWaySeq = Sequence(self.wrongWayLabel.colorScaleInterval(0.25, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), self.wrongWayLabel.colorScaleInterval(0.25, colorScale=Vec4(1, 1, 1, 0), startColorScale=Vec4(1, 1, 1, 1)))
        interpolateFacePos = lambda x: self.faceStartPos * (1.0 - x) + self.faceEndPos * x
        self.timeLabels = []
        for x in xrange(self.race.lapCount):
            minLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] - 0.06, 0, 0.84), text="0'", text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            minLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(minLabel)
            secLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.06, 0, 0.84), text="00''", text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            secLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(secLabel)
            fractionLabel = DirectLabel(relief=None, pos=(interpolateFacePos((2.0 * x + 1) / (self.race.lapCount * 2))[0] + 0.14, 0, 0.84), text='00', text_scale=0.06, text_fg=(0.95, 0.95, 0, 1), text_font=ToontownGlobals.getSignFont(), text_align=TextNode.ARight)
            fractionLabel.reparentTo(self.raceModeRoot)
            self.directObjList.append(fractionLabel)
            self.timeLabels.append((minLabel, secLabel, fractionLabel))

        self.cardMaker.reset()
        self.cardMaker.setName('GagIndicator')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        self.cardMaker.setColor(1, 1, 1, 1)
        self.gagPanel = DirectFrame(parent=base.a2dBottomLeft, relief=None, image=loader.loadModel('phase_6/models/karting/gag_panel'), image_scale=0.25, pos=(0.2, 0, 0.55))
        self.directObjList.append(self.gagPanel)
        self.gag = self.gagPanel.attachNewNode('gag')
        self.gag.setScale(0.2)
        for gag in self.gagTextures:
            gag.reparentTo(self.gag)
            gag.hide()

        self.cardMaker.reset()
        self.cardMaker.setName('RaceProgressLine')
        self.cardMaker.setFrame(-0.5, 0.5, -0.5, 0.5)
        line = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
        line.setScale(self.faceEndPos[0] - self.faceStartPos[0], 1, 0.01)
        line.setPos(0, 0, self.faceStartPos[2])
        self.cardMaker.setName('RaceProgressLineHash')
        for n in xrange(self.race.lapCount + 1):
            hash = self.raceModeRoot.attachNewNode(self.cardMaker.generate())
            hash.setScale(line.getScale()[2], 1, line.getScale()[2] * 5)
            t = float(n) / self.race.lapCount
            hash.setPos(self.faceStartPos[0] * (1 - t) + self.faceEndPos[0] * t, self.faceStartPos[1], self.faceStartPos[2])

        self.raceModeReady = True
        self.disable()
        return
class DistributedRace(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedRace')
    ReadyPost = 'RaceReady'
    WinEvent = 'RaceWinEvent'
    BGM_BaseDir = 'phase_6/audio/bgm/'
    SFX_BaseDir = 'phase_6/audio/sfx/'
    SFX_StartBoop = SFX_BaseDir + 'KART_raceStart1.ogg'
    SFX_StartBoop2 = SFX_BaseDir + 'KART_raceStart2.ogg'
    SFX_Applause = SFX_BaseDir + 'KART_Applause_%d.ogg'

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def exitJoin(self):
        pass

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

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

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

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

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

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

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

    def exitPrep(self):
        pass

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

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

    def getTitle(self):
        return TTLocalizer.KartRace_TitleInfo

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

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

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

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

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

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

    def exitStart(self):
        pass

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

    def exitRacing(self):
        pass

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

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

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

    def exitFinished(self):
        pass

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

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

    def exitLeave(self):
        pass

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

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

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

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

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

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

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

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

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

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

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

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

                self.currBldgInd[side] = bldgInd

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

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

                    self.currBldgInd[side] = segmentInd

        return

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def setRaceZone(self, zoneId, trackId):
        hoodId = self.cr.playGame.hood.hoodId
        base.loader.endBulkLoad('atRace')
        self.kartCleanup()
        self.doneBarrier('waitingForExit')
        self.sendUpdate('racerLeft', [localAvatar.doId])
        out = {'loader': 'racetrack',
         'where': 'racetrack',
         'hoodId': hoodId,
         'zoneId': zoneId,
         'trackId': trackId,
         'shardId': None,
         'reason': RaceGlobals.Exit_UserReq}
        base.cr.playGame.hood.loader.fsm.request('quietZone', [out])
        return
Exemplo n.º 21
0
    def update(self, time):
        placeSorter = []
        placeCount = 0
        for key in self.racerDict.keys():
            racer = self.racerDict[key]
            curvetime = racer.curvetime
            face = racer.face
            mapspot = racer.mapspot
            maxlaphit = racer.maxlaphit
            if not racer.finished and racer.enabled:
                placeSorter.append((curvetime, key))
            if racer.finished or racer.enabled:
                placeCount += 1
            pt = Vec3(0, 0, 0)
            mapT = (curvetime % 1 + self.race.startT / self.race.curve.getMaxT()) % 1 * self.race.curve.getMaxT()
            self.race.curve.getPoint(mapT, pt)
            self.race.curve.getPoint(mapT % self.race.curve.getMaxT(), pt)
            lapT = clampScalar(curvetime / self.race.lapCount, 0.0, 1.0)
            faceX = self.faceStartPos[0] * (1 - lapT) + self.faceEndPos[0] * lapT
            racer.update(faceX=faceX, mapspotPt=pt)
            t = time - self.race.baseTime - self.raceTimeDelta
            if key == localAvatar.doId:
                if self.race.laps > maxlaphit:
                    racer.update(maxlaphit=self.race.laps)
                    self.maxLapHit = racer.maxlaphit
                    if self.maxLapHit < self.race.lapCount:
                        for y in self.timeLabels[self.maxLapHit - 1]:
                            y.configure(text_font=ToontownGlobals.getSignFont())

                        for y in self.timeLabels[self.maxLapHit]:
                            y.show()

                        for y in self.timeLabels[self.maxLapHit]:
                            y.configure(text_font=ToontownGlobals.getSignFont())

                        self.raceTimeDelta = globalClock.getFrameTime() - self.race.baseTime
                        lapNotice = DirectLabel()
                        lapNotice.setScale(0.1)
                        if self.maxLapHit == self.race.lapCount - 1:
                            lapNotice['text'] = TTLocalizer.KartRace_FinalLapText
                        else:
                            lapNotice['text'] = TTLocalizer.KartRace_LapText % str(self.maxLapHit + 1)
                        taskMgr.doMethodLater(2, lapNotice.remove, 'removeIt', extraArgs=[])
                self.lapLabel['text'] = str(clampScalar(self.maxLapHit + 1, 1, self.race.lapCount)) + '/' + str(self.race.lapCount)

        suffix = {1: TTLocalizer.KartRace_FirstSuffix,
         2: TTLocalizer.KartRace_SecondSuffix,
         3: TTLocalizer.KartRace_ThirdSuffix,
         4: TTLocalizer.KartRace_FourthSuffix}
        placeSorter.sort()
        for x, p in zip(placeSorter, xrange(len(placeSorter), 0, -1)):
            self.racerDict[x[1]].update(place=p + placeCount - len(placeSorter))

        localRacer = self.racerDict[localAvatar.doId]
        nearDiff, farDiff = RaceGlobals.TrackDict[self.race.trackId][8]
        if not localRacer.finished and self.faceEndPos[0] - localRacer.face.getX() < nearDiff:
            for racerId in self.racerDict.keys():
                racer = self.racerDict[racerId]
                if not racer.enabled or racerId == localAvatar.doId or racer.face.getX() >= self.faceEndPos[0]:
                    continue
                if self.faceEndPos[0] - racer.face.getX() < farDiff:
                    self.photoFinish = True

        if self.photoFinish:
            self.photoFinishLabel.show()
            self.placeLabelNum['text'] = ''
            self.placeLabelStr['text'] = ''
        else:
            self.photoFinishLabel.hide()
            self.placeLabelNum['text'] = str(self.racerDict[localAvatar.doId].place)
            self.placeLabelStr['text'] = suffix[self.racerDict[localAvatar.doId].place]
        minutes = int(t / 60)
        t -= minutes * 60
        seconds = int(t)
        padding = (seconds < 10 and ['0'] or [''])[0]
        t -= seconds
        fraction = str(t)[2:4]
        fraction = fraction + '0' * (2 - len(fraction))
        if self.timerEnabled and self.maxLapHit < self.race.lapCount:
            self.timeLabels[self.maxLapHit][0]['text'] = "%d'" % minutes
            self.timeLabels[self.maxLapHit][1]['text'] = "%s%d''" % (padding, seconds)
            self.timeLabels[self.maxLapHit][2]['text'] = '%s' % fraction
        if self.race.wrongWay and not self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.loop()
        elif not self.race.wrongWay and self.wrongWaySeq.isPlaying():
            self.wrongWaySeq.finish()
 def enterWaiting(self):
     self.waitingLabel = DirectLabel()
     self.waitingLabel['text'] = TTLocalizer.BuildingWaitingForVictors
     self.waitingLabel.setScale(TTLocalizer.DRenterWaiting)