Exemple #1
0
def showWaitForOthers():
    global WaitForOthersLbl

    if WaitForOthersLbl:
        WaitForOthersLbl.show()
    else:
        from direct.gui.DirectGui import DirectLabel
        WaitForOthersLbl = DirectLabel(text="Waiting for others...", relief=None,
                                text_fg=(1,1,1,1), text_scale=0.08, text_shadow=(0,0,0,1))
        WaitForOthersLbl.setBin('unsorted', 1)
class CogdoFlyingFuelGui(DirectFrame):

    def __init__(self, parent):
        DirectFrame.__init__(self, relief=None, state=DGG.NORMAL, sortOrder=DGG.BACKGROUND_SORT_INDEX)
        self.reparentTo(parent)
        self.active = 0
        self._initModel()
        self._initIntervals()
        return

    def _initModel(self):
        self.setPos(Globals.Gui.FuelPos2D[0], 0.0, Globals.Gui.FuelPos2D[1])
        self.gui = CogdoUtil.loadFlyingModel('propellerMeter', group='gui')
        self.gui.reparentTo(self)
        self.gui.setBin('fixed', 0)
        self.healthBar = self.gui.find('**/healthBar')
        self.healthBar.setBin('fixed', 1)
        self.healthBar.setColor(*Globals.Gui.FuelNormalColor)
        bottomBarLocator = self.gui.find('**/bottomOfBar_loc')
        bottomBarPos = bottomBarLocator.getPos(render)
        topBarLocator = self.gui.find('**/topOfBar_loc')
        topBarPos = topBarLocator.getPos(render)
        zDist = topBarPos.getZ() - bottomBarPos.getZ()
        self.fuelLowIndicator = self.gui.find('**/fuelLowIndicator')
        self.fuelLowIndicator.setBin('fixed', 2)
        pos = self.fuelLowIndicator.getPos(render)
        newPos = pos
        newPos.setZ(bottomBarPos.getZ() + zDist * Globals.Gameplay.FuelLowAmt)
        self.fuelLowIndicator.setPos(render, newPos)
        self.fuelVeryLowIndicator = self.gui.find('**/fuelVeryLowIndicator')
        self.fuelVeryLowIndicator.setBin('fixed', 2)
        pos = self.fuelVeryLowIndicator.getPos(render)
        newPos = pos
        newPos.setZ(bottomBarPos.getZ() + zDist * Globals.Gameplay.FuelVeryLowAmt)
        self.fuelVeryLowIndicator.setPos(render, newPos)
        self.propellerMain = self.gui.find('**/propellers')
        self.propellerMain.setBin('fixed', 3)
        self.propellerHead = self.gui.find('**/propellerHead')
        self.propellerHead.setBin('fixed', 4)
        self.blades = []
        self.activeBlades = []
        index = 1
        blade = self.propellerMain.find('**/propeller%d' % index)
        while not blade.isEmpty():
            self.blades.append(blade)
            index += 1
            blade = self.propellerMain.find('**/propeller%d' % index)

        for blade in self.blades:
            self.activeBlades.append(blade)

        self.bladeNumberLabel = DirectLabel(parent=self.propellerHead, relief=None, pos=(Globals.Gui.FuelNumBladesPos2D[0], 0, Globals.Gui.FuelNumBladesPos2D[1]), scale=Globals.Gui.FuelNumBladesScale, text=str(len(self.activeBlades)), text_align=TextNode.ACenter, text_fg=(0.0,
         0.0,
         -0.002,
         1), text_shadow=(0.75, 0.75, 0.75, 1), text_font=ToontownGlobals.getInterfaceFont())
        self.bladeNumberLabel.setBin('fixed', 5)
        return

    def _initIntervals(self):
        self._healthIval = LerpFunctionInterval(self.healthBar.setSz, fromData=0.0, toData=1.0, duration=2.0)
        self.baseSpinDuration = 2.0
        self._spinIval = LerpFunctionInterval(self.propellerMain.setR, fromData=0.0, toData=-360.0, duration=self.baseSpinDuration)

    def show(self):
        DirectFrame.show(self)
        self._spinIval.loop()

    def hide(self):
        DirectFrame.hide(self)
        self._spinIval.pause()

    def resetBlades(self):
        self.setBlades(len(self.blades))

    def setBlades(self, fuelState):
        if fuelState not in Globals.Gameplay.FuelStates:
            return
        numBlades = fuelState - 1
        if len(self.activeBlades) != numBlades:
            for i in range(len(self.activeBlades)):
                blade = self.activeBlades.pop()
                blade.stash()

            if numBlades > len(self.blades):
                numBlades = len(self.blades)
            for i in range(numBlades):
                blade = self.blades[i]
                self.activeBlades.append(blade)
                blade.unstash()

            self.bladeNumberLabel['text'] = str(len(self.activeBlades))
            self.bladeNumberLabel.setText()
        self.updateHealthBarColor()

    def bladeLost(self):
        if len(self.activeBlades) > 0:
            blade = self.activeBlades.pop()
            blade.stash()
            self.bladeNumberLabel['text'] = str(len(self.activeBlades))
            self.bladeNumberLabel.setText()
        self.updateHealthBarColor()

    def updateHealthBarColor(self):
        color = Globals.Gui.NumBlades2FuelColor[len(self.activeBlades)]
        self.healthBar.setColor(*color)

    def setPropellerSpinRate(self, newRate):
        self._spinIval.setPlayRate(newRate)

    def setRefuelLerpFromData(self):
        startScale = self.healthBar.getSz()
        self._healthIval.fromData = startScale

    def setFuel(self, fuel):
        self.fuel = fuel

    def update(self):
        self.healthBar.setSz(self.fuel)

    def destroy(self):
        self.bladeNumberLabel.removeNode()
        self.bladeNumberLabel = None
        self._healthIval.clearToInitial()
        del self._healthIval
        self.healthBar = None
        self.fuelLowIndicator = None
        self.fuelVeryLowIndicator = None
        self.propellerMain = None
        self.propellerHead = None
        del self.blades[:]
        del self.activeBlades[:]
        self.gui.detachNode()
        self.gui = None
        DirectFrame.destroy(self)
        return
Exemple #3
0
class RepairGameButton(GuiButton):
    def __init__(self, parent, **kw):
        optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0,
                                                                 1.0), None))
        self.defineoptions(kw, optiondefs)
        GuiButton.__init__(self, parent)
        self.initialiseoptions(RepairGameButton)
        self.disabledStateNode = self.stateNodePath[3].getChild(0)
        self.downStateNode = self.stateNodePath[1].getChild(0)
        self.overStateNode = self.stateNodePath[2].getChild(0)
        self.inProgress = False
        self._initGUI()

    def _initGUI(self):
        self.setBin('fixed', 33)
        mainGui = loader.loadModel('models/gui/gui_main')
        gui = loader.loadModel('models/gui/toplevel_gui')
        self.checkMark = gui.find('**/generic_check')
        self.checkMark.reparentTo(self)
        self.checkMark.stash()
        self.checkMark.setScale(1.0)
        self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0)
        self.checkMark.setPos(0.02, 0.0, 0.02)
        self.checkMark.setBin('fixed', 34)
        self.skillRing = DialMeter(self,
                                   wantCover=False,
                                   dangerRatio=0.0,
                                   meterColor=Vec4(0.90000000000000002,
                                                   0.90000000000000002,
                                                   0.10000000000000001, 1.0),
                                   baseColor=Vec4(0.14999999999999999,
                                                  0.070000000000000007,
                                                  0.029999999999999999, 1.0),
                                   completeColor=Vec4(0.10000000000000001,
                                                      0.90000000000000002,
                                                      0.10000000000000001,
                                                      1.0))
        self.skillRing.reparentTo(self)
        self.skillRing.setScale(0.28499999999999998, 0.29999999999999999,
                                0.26500000000000001)
        self.skillRing.setBin('fixed', 32)
        self.skillGlow = OnscreenImage(parent=self,
                                       image=mainGui.find('**/icon_glow'),
                                       scale=(1.0, 1.0, 1.0),
                                       color=(1.0, 1.0, 0.59999999999999998,
                                              1.0))
        self.glow = OnscreenImage(parent=self,
                                  image=mainGui.find('**/icon_glow'),
                                  scale=(1.0, 1.0, 1.0),
                                  color=(1.0, 1.0, 0.59999999999999998, 1.0))
        self.skillGlow.reparentTo(self)
        self.skillGlow.setBin('fixed', 31)
        self.skillGlow.stash()
        self.pirateNameBox = None
        self.pirateNameLabel = None

    def showGlow(self):
        self.inProgress = False
        if self.pirateNameLabel == None and self.checkMark.isStashed():
            self.skillGlow.unstash()

    def hideGlow(self):
        self.inProgress = True
        self.skillGlow.stash()

    def setProgress(self, percent):
        self.skillGlow.stash()
        ratio = max(0.0, percent / 100.0)
        if ratio >= 1.0:
            if self.checkMark.isStashed():
                self.checkMark.unstash()

        elif not self.checkMark.isStashed():
            self.checkMark.stash()

        if self.pirateNameLabel == None and not (self.inProgress):
            self.skillGlow.unstash()

        self.skillRing.update(ratio, 1.0)
        self.skillRing.wrtReparentTo(self.getParent())
        self.reparentTo(self.getParent())

    def updatePirateNameBox(self, pirateName):
        if self.pirateNameLabel != None and self.pirateNameLabel[
                'text'] != pirateName:
            if self.pirateNameBox:
                self.pirateNameBox.destroy()

            if self.pirateNameLabel:
                self.pirateNameLabel.destroy()

            self.pirateNameBox = None
            self.pirateNameLabel = None

        if pirateName != '':
            if self.pirateNameBox:
                pass
            if not (self.pirateNameLabel['text'] == pirateName):
                self.createPirateNameBox(pirateName)

    def createPirateNameBox(self, pirateName):
        self.pirateNameLabel = DirectLabel(
            relief=None,
            state=DGG.DISABLED,
            text=pirateName,
            text_align=TextNode.ACenter,
            text_scale=PiratesGuiGlobals.TextScaleMed,
            text_fg=PiratesGuiGlobals.TextFG1,
            text_wordwrap=12,
            textMayChange=0,
            sortOrder=91)
        self.pirateNameLabel.setBin('fixed', 33)
        height = self.pirateNameLabel.getHeight()
        width = self.pirateNameLabel.getWidth() + 0.050000000000000003
        pos = [0.0, 0.0, height / 2 - 0.035000000000000003]
        fs = [
            -(width / 2 + 0.01), width / 2 + 0.01,
            -(height / 2 + 0.014999999999999999),
            height / 2 + 0.014999999999999999
        ]
        self.pirateNameBox = BorderFrame(parent=self,
                                         state=DGG.DISABLED,
                                         frameSize=(fs[0], fs[1], fs[2],
                                                    fs[3]),
                                         modelName='general_frame_f',
                                         pos=(0.0, 0.0, 0.0))
        self.pirateNameLabel.reparentTo(self.pirateNameBox)
        self.pirateNameLabel.setPos(pos[0], pos[1], pos[2])
        self.pirateNameBox.setClipPlaneOff()
        pos = self.pirateNameBox.getPos(aspect2d)
        x = min(pos[0], base.a2dRight - width)
        z = max(pos[2], base.a2dBottom - height)
        self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.17499999999999999)
        self.pirateNameBox.flattenLight()
        self.pirateNameBox.setBin('fixed', 32)
        self.pirateNameBox.reparentTo(self)
Exemple #4
0
class RepairSawingGame(RepairMincroGame):
    sawSounds = None
    boardComplet = None
    boardDestroyed = None

    def __init__(self, repairGame):
        self.config = RepairGlobals.Sawing
        notify = DirectNotifyGlobal.directNotify.newCategory(
            'RepairSawingGame')
        RepairMincroGame.__init__(self, repairGame, 'sawing',
                                  PLocalizer.Minigame_Repair_Sawing_Start)

    def _initVars(self):
        RepairMincroGame._initVars(self)
        self.boardsPool = {}
        self.currentBoard = None
        self.currentBoardIndex = 0
        self.onDeckBoard = None
        self.onDeckBoardIndex = 0
        self.totalScore = 0.0
        self.hitZone1Penalty = False
        self.hitZone2Penalty = False
        self.hitBoardPenalty = False
        self.moveDiffForSound = 0.0
        self.startPositions = (Point3(0.0, 0.0, 0.0), )
        self.currentStartIndex = 0
        self.lastMousePos = None
        self.board_left = None
        self.board_right = None
        self.cut = None
        self.zone1_right = None
        self.zone1_left = None
        self.zone2_right = None
        self.zone2_left = None
        self.piece1 = None
        self.piece2 = None
        self.lastHitIndex = -1
        self.sawWaypoints = []

    def _initAudio(self):
        RepairMincroGame._initAudio(self)
        if not self.sawSounds:
            RepairSawingGame.sawSounds = (
                loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT01),
                loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT02),
                loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT03),
                loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT04))
            RepairSawingGame.boardComplete = loadSfx(
                SoundGlobals.SFX_MINIGAME_REPAIR_SAW_COMPLETE)
            RepairSawingGame.boardDestroyed = loadSfx(
                SoundGlobals.SFX_MINIGAME_REPAIR_SAW_FAIL)

    def _initVisuals(self):
        RepairMincroGame._initVisuals(self)
        self.setBin('fixed', 36)
        self.model = loader.loadModel('models/gui/pir_m_gui_srp_sawing_main')
        sawModel = self.model.find('**/saw')
        sawModel.setR(193)
        sawModel.setPos(0.90000000000000002, 0.0, -0.16500000000000001)
        sawModel.setBin('gui-popup', 0)
        self.sawButton = RepairSaw(
            parent=self,
            clickDownCommand=self.sawAttachedToMouse,
            clickUpCommand=self.sawRemovedFromMouse,
            geom=sawModel,
            text_pos=(0.20000000000000001, -0.29999999999999999),
            text_fg=(1, 0, 0, 1),
            scale=(0.29999999999999999, 0.29999999999999999,
                   0.29999999999999999),
            relief=None,
            pressEffect=0,
            frameSize=(-0.050000000000000003, 1.05, -0.29999999999999999,
                       0.050000000000000003),
            rolloverSound=None,
            clickSound=None)
        self.sawingLine = RepairSawingLine(self,
                                           self.config.sawlineLineThickness,
                                           self.config.sawlineColor,
                                           self.config.sawlineLinespawnDist)
        self.progressDescriptionLabel = DirectLabel(
            text=PLocalizer.Minigame_Repair_Sawing_Description,
            text_fg=(1.0, 1.0, 1.0, 1.0),
            text_pos=(0.0, 0.0),
            text_shadow=(0.0, 0.0, 0.0, 1.0),
            text_font=PiratesGlobals.getPirateFont(),
            text_align=TextNode.ARight,
            relief=None,
            scale=(0.080000000000000002, 0.080000000000000002,
                   0.080000000000000002),
            pos=(-0.20000000000000001, 0.0, 0.5),
            parent=self)
        self.progressLabel = DirectLabel(
            text=PLocalizer.Minigame_Repair_Sawing_Thresholds[3],
            text_fg=(1.0, 1.0, 1.0, 1.0),
            text_pos=(0.0, 0.0),
            text_shadow=(0.0, 0.0, 0.0, 1.0),
            text_font=PiratesGlobals.getPirateFont(),
            text_align=TextNode.ALeft,
            relief=None,
            scale=(0.080000000000000002, 0.080000000000000002,
                   0.080000000000000002),
            pos=(-0.17999999999999999, 0.0, 0.5),
            parent=self)
        self.boardDestroyedLabel = DirectLabel(
            text=PLocalizer.Minigame_Repair_Sawing_Board_Destroyed,
            text_fg=(1.0, 0.0, 0.0, 1.0),
            text_pos=(0.0, 0.0),
            text_font=PiratesGlobals.getPirateFont(),
            text_shadow=(0.0, 0.0, 0.0, 1.0),
            relief=None,
            scale=(0.10000000000000001, 0.10000000000000001,
                   0.10000000000000001),
            pos=(0.0, 0.0, 0.10000000000000001),
            parent=self)
        self.boardDestroyedLabel.setBin('fixed', 38)
        self.boardDestroyedLabel.stash()

    def _initIntervals(self):
        RepairMincroGame._initIntervals(self)
        self.newBoardSequence = Sequence(
            name='RepairSawingGame.newBoardSequence')
        self.splitBoardSequence = Sequence(
            name='RepairSawGame.splitBoardSequence')
        self.dropBoardSequence = Sequence(
            name='RepairSawGame.dropBoardSequence')

    def getNewBoard(self, boardIndex):
        board = self.model.find('**/wood%i' % boardIndex).copyTo(
            NodePath('board%i' % len(self.boardsPool)))
        board.reparentTo(self)
        piece1 = board.find('**/piece_1')
        piece1.setPythonTag('piece_1', self.piece1)
        piece1.setY(self.config.boardYDist)
        piece2 = board.find('**/piece_2')
        piece2.setPythonTag('piece_2', self.piece2)
        piece2.setY(self.config.boardYDist)
        pieceCut = board.find('**/piece_cut')
        pieceCut.setPythonTag('cut', self.cut)
        pieceCut.setColor(self.config.cutColor)
        pieceCut.setY(self.config.boardYDist)
        board_left = piece1.find('**/board')
        board_left.setPythonTag('left', self.board_left)
        board_right = piece2.find('**/board')
        board_right.setPythonTag('right', self.board_right)
        zone1_right = piece2.find('**/zone_1')
        zone1_right.setPythonTag('zone1_right', self.zone1_right)
        zone1_right.setColor(self.config.zone1Color)
        zone1_left = piece1.find('**/zone_1')
        zone1_left.setPythonTag('zone1_left', self.zone1_left)
        zone1_left.setColor(self.config.zone1Color)
        zone2_right = piece2.find('**/zone_2')
        zone2_right.setPythonTag('zone2_right', self.zone2_right)
        zone2_right.setColor(self.config.zone2Color)
        zone2_left = piece1.find('**/zone_2')
        zone2_left.setPythonTag('zone2_left', self.zone2_left)
        zone2_left.setColor(self.config.zone2Color)
        board.stash()
        return board

    def reset(self):
        for key in self.boardsPool.keys():
            board = self.boardsPool[key]
            board.removeNode()

        self.boardsPool.clear()
        if self.currentBoard:
            self.currentBoard.removeNode()
            self.currentBoard = None

        if self.onDeckBoard:
            self.onDeckBoard.removeNode()
            self.onDeckBoard = None

        for boardIndex in self.currentDifficultySet:
            boardIndex -= 1
            if 'copy1_%s' % boardIndex not in self.boardsPool:
                board = self.getNewBoard(boardIndex)
                self.boardsPool['copy1_%s' % boardIndex] = board

            if 'copy2_%s' % boardIndex not in self.boardsPool:
                board = self.getNewBoard(boardIndex)
                self.boardsPool['copy2_%s' % boardIndex] = board
                continue

        self.currentBoardIndex = 0
        self.currentBoard = None
        self.moveNewBoardOnDeck()
        self.onDeckBoard.unstash()
        self.totalScore = 0
        self.startPositions = (Point3(0.0, 0.0, 0.0), )
        self.sawButton.stash()
        self.sawButton.reparentTo(self)
        self.lastHitIndex = -1
        self.moveDiffForSound = 0.0
        RepairMincroGame.reset(self)
        self.repairGame.gui.setTutorial(self.name)
        self.repairGame.gui.setTitle(self.name)

    def destroy(self):
        RepairMincroGame.destroy(self)
        taskMgr.remove('SawingGame.updateSawTask')
        self.sawButton.destroy()
        self.sawButton.removeNode()
        del self.sawButton
        if self.currentBoard:
            self.currentBoard.removeNode()
            self.currentBoard = None

        if self.onDeckBoard:
            self.onDeckBoard.removeNode()
            self.onDeckBoard = None

        self.sawingLine = None
        self.progressDescriptionLabel.destroy()
        self.progressDescriptionLabel = None
        self.progressLabel.destroy()
        self.progressLabel = None
        self.boardDestroyedLabel.destroy()
        self.boardDestroyedLabel = None
        for key in self.boardsPool.keys():
            board = self.boardsPool[key]
            if not board.isEmpty():
                board.removeNode()
                continue

        self.boardsPool.clear()
        self.newBoardSequence.clearToInitial()
        del self.newBoardSequence
        self.splitBoardSequence.clearToInitial()
        del self.splitBoardSequence
        self.dropBoardSequence.clearToInitial()
        del self.dropBoardSequence

    def setDifficulty(self, difficulty):
        RepairMincroGame.setDifficulty(self, difficulty)
        percent = difficulty / self.repairGame.difficultyMax
        difIndex = int(
            math.floor(percent * (len(self.config.difficultySets) - 1)))
        self.currentDifficultySet = self.config.difficultySets[difIndex]

    def splitBoard(self):
        self.sawingLine.reset()
        board = self.currentBoard
        boardIndex = self.currentBoardIndex
        if self.hitZone2Penalty:
            boardSplitAnim = Parallel(
                LerpPosInterval(self.board_left,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(-2.0, 0.0, 0.0)),
                LerpPosInterval(self.board_right,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(2.0, 0.0, 0.0)),
                LerpFunc(self.zone2_left.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.zone2_right.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.zone1_left.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.zone1_right.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.cut.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0))
        elif self.hitZone1Penalty:
            boardSplitAnim = Parallel(
                LerpPosInterval(self.board_left,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(-2.0, 0.0, 0.0)),
                LerpPosInterval(self.board_right,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(2.0, 0.0, 0.0)),
                LerpPosInterval(self.zone2_left,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(-2.0, 0.0, 0.0)),
                LerpPosInterval(self.zone2_right,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(2.0, 0.0, 0.0)),
                LerpFunc(self.zone1_left.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.zone1_right.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0),
                LerpFunc(self.cut.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0))
        else:
            boardSplitAnim = Parallel(
                LerpPosInterval(self.piece1,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(-2.0, self.config.boardYDist, 0.0)),
                LerpPosInterval(self.piece2,
                                duration=self.config.splitBoardAnimTime,
                                pos=Point3(2.0, self.config.boardYDist, 0.0)),
                LerpFunc(self.cut.setSa,
                         duration=self.config.splitBoardAnimTime / 2.0,
                         fromData=1.0,
                         toData=0.0))
        self.splitBoardSequence = Sequence(
            Func(self.updateScore),
            Func(self.boardComplete.play),
            boardSplitAnim,
            Func(board.stash),
            Func(self.piece1.setPos, self.piece1.getPos()),
            Func(self.piece2.setPos, self.piece2.getPos()),
            Func(self.board_right.setPos, self.board_right.getPos()),
            Func(self.board_left.setPos, self.board_left.getPos()),
            Func(self.zone2_right.setPos, self.zone2_right.getPos()),
            Func(self.zone2_left.setPos, self.zone2_left.getPos()),
            Func(self.zone1_right.setPos, self.zone1_right.getPos()),
            Func(self.zone1_left.setPos, self.zone1_left.getPos()),
            Func(self.cut.setSa, 1.0),
            Func(self.zone1_right.setSa, 1.0),
            Func(self.zone1_left.setSa, 1.0),
            Func(self.zone2_right.setSa, 1.0),
            Func(self.zone2_left.setSa, 1.0),
            Func(self.board_right.setSa, 1.0),
            Func(self.board_left.setSa, 1.0),
            Func(self.loadNewBoard),
            Func(self.addBoardBackToPool, board, boardIndex),
            name='RepairSawGame.splitBoardSequence')
        self.splitBoardSequence.start()

    def dropBoard(self):
        board = self.currentBoard
        boardIndex = self.currentBoardIndex
        self.dropBoardSequence = Sequence(
            Parallel(
                Sequence(Func(self.boardDestroyedLabel.unstash), Wait(1.5),
                         Func(self.boardDestroyedLabel.stash)),
                Sequence(
                    Wait(0.5), Func(self.boardDestroyed.play),
                    Func(self.sawingLine.reset),
                    LerpPosInterval(board,
                                    duration=self.config.splitBoardAnimTime,
                                    pos=Point3(0.0, 0.0, -2.0)),
                    Func(board.stash), Wait(0.5), Func(self.loadNewBoard),
                    Func(self.addBoardBackToPool, board, boardIndex))),
            name='RepairSawGame.dropBoardSequence')
        self.dropBoardSequence.start()

    def addBoardBackToPool(self, board, boardIndex):
        if 'copy1_%s' % boardIndex not in self.boardsPool:
            self.boardsPool['copy1_%s' % boardIndex] = board
        elif 'copy2_%s' % boardIndex not in self.boardsPool:
            self.boardsPool['copy2_%s' % boardIndex] = board
        else:
            self.notify.error(
                'Two copies of board type %i already in the boardsPool!' %
                boardIndex)

    def updateScoreText(self):
        self.progressLabel.unstash()
        self.progressDescriptionLabel.unstash()
        if self.hitBoardPenalty:
            self.progressLabel[
                'text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[0]
            self.progressLabel['text_fg'] = Vec4(1.0, 0.0, 0.0, 1.0)
            self.progressLabel.setText()
        elif self.hitZone2Penalty:
            self.progressLabel[
                'text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[1]
            self.progressLabel['text_fg'] = Vec4(1.0, 0.5, 0.0, 1.0)
            self.progressLabel.setText()
        elif self.hitZone1Penalty:
            self.progressLabel[
                'text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[2]
            self.progressLabel['text_fg'] = Vec4(1.0, 1.0, 0.0, 1.0)
            self.progressLabel.setText()
        else:
            self.progressLabel[
                'text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[3]
            self.progressLabel['text_fg'] = Vec4(0.0, 1.0, 0.0, 1.0)
            self.progressLabel.setText()

    def moveNewBoardOnDeck(self):
        boardIndex = random.randint(0, len(self.currentDifficultySet) - 1)
        boardType = self.currentDifficultySet[boardIndex]
        boardType -= 1
        if 'copy1_%s' % boardType in self.boardsPool:
            self.onDeckBoard = self.boardsPool['copy1_%s' % boardType]
            del self.boardsPool['copy1_%s' % boardType]
        elif 'copy2_%s' % boardType in self.boardsPool:
            self.onDeckBoard = self.boardsPool['copy2_%s' % boardType]
            del self.boardsPool['copy2_%s' % boardType]
        else:
            self.notify.error('No copies of board type %i in the boardsPool!' %
                              boardType)
        self.onDeckBoardIndex = boardType
        self.onDeckBoard.setScale(0.25)
        self.onDeckBoard.setPos(0.5, -2.0, 0.56000000000000005)
        self.onDeckBoard.unstash()

    def loadNewBoard(self):
        self.progressLabel.stash()
        self.progressDescriptionLabel.stash()
        if self.totalScore >= self.config.totalPoints:
            if self.onDeckBoard:
                self.onDeckBoard.stash()

            self.progressDescriptionLabel.stash()
            taskMgr.remove('SawingGame.updateSawTask')
            self.request('Outro')
            return None

        self.currentBoard = self.onDeckBoard
        self.currentBoardIndex = self.onDeckBoardIndex
        self.piece1 = self.currentBoard.find('**/piece_1')
        self.piece1.setTransparency(1)
        self.piece2 = self.currentBoard.find('**/piece_2')
        self.piece2.setTransparency(1)
        self.cut = self.currentBoard.find('**/piece_cut')
        self.cut.setColor(self.config.cutColor)
        self.cut.setTransparency(1)
        self.board_left = self.piece1.find('**/board')
        self.board_left.setTransparency(1)
        self.zone1_left = self.piece1.find('**/zone_1')
        self.zone1_left.setTransparency(1)
        self.zone2_left = self.piece1.find('**/zone_2')
        self.zone2_left.setTransparency(1)
        self.board_right = self.piece2.find('**/board')
        self.board_right.setTransparency(1)
        self.zone1_right = self.piece2.find('**/zone_1')
        self.zone1_right.setTransparency(1)
        self.zone2_right = self.piece2.find('**/zone_2')
        self.zone2_right.setTransparency(1)
        self.board_left.setCollideMask(SAW_COLLIDE_MASK)
        self.board_right.setCollideMask(SAW_COLLIDE_MASK)
        self.cut.setCollideMask(SAW_COLLIDE_MASK)
        self.zone1_right.setCollideMask(SAW_COLLIDE_MASK)
        self.zone1_left.setCollideMask(SAW_COLLIDE_MASK)
        self.zone2_right.setCollideMask(SAW_COLLIDE_MASK)
        self.zone2_left.setCollideMask(SAW_COLLIDE_MASK)
        self.startPositions = (
            self.currentBoard.find('**/locator_start_0').getPos() +
            Point3(*self.config.activeBoardPosition),
            self.currentBoard.find('**/locator_start_1').getPos() +
            Point3(*self.config.activeBoardPosition))
        self.currentStartIndex = 0
        for waypoint in self.sawWaypoints:
            waypoint.removeNode()

        self.sawWaypoints = []
        locator = self.currentBoard.find('**/locator_0')
        index = 0
        while not locator.isEmpty():
            self.sawWaypoints.append(
                SawWaypoint(index, self.currentBoard, locator.getPos()))
            locator = self.currentBoard.find('**/locator_%i' % (index + 1))
            index += 1
        self.sawButton.deactivate()
        self.sawButton.setPos(self.startPositions[self.currentStartIndex])
        self.hitBoardPenalty = False
        self.hitZone1Penalty = False
        self.hitZone2Penalty = False
        self.lastMousePos = None
        self.moveDiffForSound = self.config.playSawingSoundDelta + 0.10000000000000001
        self.newBoardSequence = Sequence(
            Parallel(
                self.currentBoard.posInterval(
                    self.config.newBoardAnimTime,
                    Point3(*self.config.activeBoardPosition)),
                self.currentBoard.scaleInterval(self.config.newBoardAnimTime,
                                                1.0)),
            name='RepairSawingGame.newBoardSequence')
        if self.state in ['Game']:
            self.newBoardSequence.append(Func(self.sawButton.activate))

        self.newBoardSequence.append(Wait(0.5))
        self.newBoardSequence.append(Func(self.moveNewBoardOnDeck))
        self.newBoardSequence.start()

    def updateSawTask(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            relative = Point3(mpos.getX(), 0.0, mpos.getY())
            relative = self.getRelativePoint(render2d, relative)
            moveDiff = 0.0
            if self.lastMousePos != None:
                moveDiff = (relative - self.lastMousePos).length()

            pickedObjects = self.repairGame.mousePicker.getCollisions(
                self.currentBoard, useIntoNodePaths=True)
            self.updateWaypoints()
            if len(pickedObjects) > 0:
                self.moveDiffForSound += moveDiff
                if self.moveDiffForSound > self.config.playSawingSoundDelta:
                    sawSoundPlaying = False
                    for sound in self.sawSounds:
                        if sound.status() == 2:
                            sawSoundPlaying = True
                            break
                            continue

                    if sawSoundPlaying == False:
                        sound = random.choice(self.sawSounds)
                        sound.play()
                        self.moveDiffForSound = 0.0

                if self.board_right in pickedObjects or self.board_left in pickedObjects:
                    for waypoint in self.sawWaypoints:
                        waypoint.hit = False

                    self.hitBoardPenalty = True
                    self.dropBoard()
                    self.sawButton.deactivate()
                elif self.cut in pickedObjects:
                    self.updateWaypoints()
                elif self.zone1_right in pickedObjects or self.zone1_left in pickedObjects:
                    self.updateWaypoints()
                    if self.hitZone1Penalty == False:
                        self.hitZone1Penalty = True

                elif self.zone2_right in pickedObjects or self.zone2_left in pickedObjects:
                    self.updateWaypoints()
                    if self.hitZone2Penalty == False:
                        self.hitZone2Penalty = True

                self.updateScoreText()
            else:
                boardComplete = True
                for waypoint in self.sawWaypoints:
                    if not waypoint.hit:
                        boardComplete = False
                        break
                        continue

                if boardComplete:
                    self.splitBoard()
                    self.sawButton.deactivate()

            self.lastMousePos = self.sawButton.getPos()

        return Task.cont

    def updateScore(self):
        if not self.hitBoardPenalty:
            currBoardScore = self.config.pointsPerBoard
            if not self.hitZone1Penalty:
                pass
            currBoardScore -= self.config.pointsLostForZone1 * self.hitZone2Penalty
            currBoardScore -= self.config.pointsLostForZone2 * self.hitZone2Penalty
            rating = 4 - 1 * self.hitZone2Penalty - 3 * self.hitZone1Penalty
            self.totalScore += currBoardScore
            self.totalScore = min(self.totalScore, self.config.totalPoints)
            percent = int((self.totalScore / self.config.totalPoints) * 100.0)
            self.repairGame.d_reportMincroGameProgress(percent, rating)

    def resetWaypoints(self):
        for waypoint in self.sawWaypoints:
            waypoint.hit = False

    def updateWaypoints(self):
        waypointList = self.getHitWaypoints()
        for waypointIndex in waypointList:
            self.lastHitIndex = waypointIndex
            self.sawWaypoints[waypointIndex].hit = True
            if waypointIndex == 0 and not (self.sawWaypoints[-1].hit):
                self.currentStartIndex = 0
                continue
            if waypointIndex == len(
                    self.sawWaypoints) - 1 and not (self.sawWaypoints[0].hit):
                self.currentStartIndex = 1
                continue

    def getHitWaypoints(self):
        waypointsHit = []
        testDelta = self.config.testWaypointDelta
        for i in range(len(self.sawWaypoints)):
            waypointPos = self.sawWaypoints[i].getPos(self)
            closestDistance = 9999
            if self.lastMousePos != None:
                currMousePos = self.sawButton.getPos()
                lastMousePos = self.lastMousePos
                totalLength = (currMousePos - lastMousePos).length()
                testLength = testDelta
                while testLength < totalLength:
                    testPos = (currMousePos - lastMousePos) * (
                        testLength / totalLength) + lastMousePos
                    self.updateSawLine(testPos)
                    testDistance = (testPos - waypointPos).length()
                    closestDistance = min(testDistance, closestDistance)
                    testLength += testDelta

            self.updateSawLine(self.sawButton.getPos())
            testDistance = (self.sawButton.getPos() - waypointPos).length()
            closestDistance = min(testDistance, closestDistance)
            if closestDistance < self.config.waypointRange[
                    self.currentBoardIndex]:
                waypointsHit.append(i)
                continue

        return waypointsHit

    def updateSawLine(self, pos):
        if pos.getX() < -0.63300000000000001 or pos.getX(
        ) > 0.63300000000000001:
            self.sawingLine.reset()
            return None

        if pos.getZ() < -0.183 or pos.getZ() > 0.375:
            self.sawingLine.reset()
            return None

        self.sawingLine.update(pos)

    def getClosestPosition(self, positions):
        closestIndex = -1
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            relative = Point3(mpos.getX(), 0.0, mpos.getY())
            relative = self.getRelativePoint(base.a2dBackground, relative)
            bestDistance = 99999.0
            for i in range(len(positions)):
                dX = relative.getX() - positions[i].getX()
                dZ = relative.getZ() - positions[i].getZ()
                newDistance = dX * dX + dZ * dZ
                if newDistance < bestDistance:
                    bestDistance = newDistance
                    closestIndex = i
                    continue

        return closestIndex

    def sawAttachedToMouse(self):
        self.lastHitIndex = -1
        if not taskMgr.hasTaskNamed('SawingGame.updateSawTask'):
            taskMgr.add(self.updateSawTask,
                        'SawingGame.updateSawTask',
                        priority=2)

    def sawRemovedFromMouse(self):
        if not self.sawButton.isStashed():
            self.sawButton.setPos(self.startPositions[self.currentStartIndex])
            self.lastHitIndex = -1
            self.resetWaypoints()
            self.lastMousePos = None
            self.progressLabel.stash()
            self.progressDescriptionLabel.stash()
            self.sawingLine.reset()
            self.hitBoardPenalty = False
            self.hitZone1Penalty = False
            self.hitZone2Penalty = False

        taskMgr.remove('SawingGame.updateSawTask')

    def enterIntro(self):
        RepairMincroGame.enterIntro(self)
        self.loadNewBoard()

    def enterGame(self):
        RepairMincroGame.enterGame(self)
        self.repairGame.mousePicker.setCollisionMask(SAW_COLLIDE_MASK)
        self.sawButton.activate()

    def exitGame(self):
        RepairMincroGame.exitGame(self)
        self.sawButton.deactivate()
        self.repairGame.mousePicker.clearCollisionMask()
        taskMgr.remove('SawingGame.updateSawTask')
        self.splitBoardSequence.clearToInitial()
        self.dropBoardSequence.clearToInitial()
        localAvatar.guiMgr._showCursor()

    def enterOutro(self):
        RepairMincroGame.enterOutro(self)
        self.repairGame.d_reportMincroGameScore(150)
class RepairMincroGame(DirectFrame, FSM.FSM):
    readySound = None
    goSound = None
    completeSound = None
    
    def __init__(self, repairGame, name, startText):
        DirectFrame.__init__(self, parent = repairGame.gui, relief = None)
        FSM.FSM.__init__(self, '%sFSM' % name)
        self.defaultTransitions = {
            'Idle': [
                'Intro',
                'Final'],
            'Intro': [
                'Game',
                'Idle',
                'Final'],
            'Game': [
                'Outro',
                'Idle',
                'Final'],
            'Outro': [
                'Idle',
                'Final'],
            'Final': [] }
        self.name = name
        self.repairGame = repairGame
        self.startText = startText
        self._initVars()
        self._initAudio()
        self._initVisuals()
        self._initIntervals()
        self.request('Idle')

    
    def _initVars(self):
        self.complete = False
        self.difficulty = 0

    
    def _initAudio(self):
        if not self.readySound:
            RepairMincroGame.readySound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_READY)
            RepairMincroGame.goSound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_GO)
            RepairMincroGame.completeSound = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_GENERAL_GAMECOMPLETE)
        

    
    def _initVisuals(self):
        self.countDownLabel = DirectLabel(text = self.startText, text_fg = (1.0, 1.0, 1.0, 1.0), text_shadow = (0.0, 0.0, 0.0, 1.0), text_font = PiratesGlobals.getPirateFont(), scale = (0.16, 0.16, 0.16), pos = (0.0, 0.0, 0.14999999999999999), parent = self, relief = None, textMayChange = 1)
        self.countDownLabel.setBin('fixed', 37)
        self.winLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Win, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.16, 0.16, 0.16), pos = RepairGlobals.Common.youWinPos[self.name], relief = None, parent = self)
        self.winLabel.setBin('fixed', 37)
        self.winLabel.stash()
        self.scoreLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Win, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.10000000000000001, 0.10000000000000001, 0.10000000000000001), pos = RepairGlobals.Common.scorePos[self.name], relief = None, parent = self)
        self.scoreLabel.setBin('fixed', 37)
        self.scoreLabel.stash()
        self.postWinLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Pick_New_Game, text_fg = (1.0, 1.0, 1.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), scale = (0.14000000000000001, 0.14000000000000001, 0.14000000000000001), pos = RepairGlobals.Common.youWinPos[self.name], relief = None, textMayChange = 1, parent = self.repairGame.gui)
        self.postWinLabel.setBin('fixed', 37)
        self.postWinLabel.stash()

    
    def _initIntervals(self):
        normalPos = Vec3(0.0, 0.0, 0.14999999999999999)
        belowScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() - 0.25)
        aboveScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() + 0.25)
        self.introSequence = Sequence(Func(self.setCountDown, PLocalizer.Minigame_Repair_Countdown_Ready), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.readySound.play), Wait(0.5), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.setCountDown, self.startText), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.goSound.play), Wait(0.5), Parallel(LerpFunc(self.countDownLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.countDownLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.request, 'Game'), name = 'RepairMincroGame.introSequence')
        normalPos = Vec3(RepairGlobals.Common.youWinPos[self.name])
        normalScorePos = Vec3(RepairGlobals.Common.scorePos[self.name])
        belowScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() - 0.25)
        aboveScreenPos = Vec3(normalPos.getX(), normalPos.getY(), normalPos.getZ() + 0.25)
        belowScreenScorePos = Vec3(normalScorePos.getX(), normalScorePos.getY(), normalScorePos.getZ() - 0.25)
        aboveScreenScorePos = Vec3(normalScorePos.getX(), normalScorePos.getY(), normalScorePos.getZ() + 0.25)
        self.outroSequence = Sequence(Func(self.winLabel.setAlphaScale, 0), Func(self.scoreLabel.setAlphaScale, 0), Func(self.postWinLabel.setAlphaScale, 0), Func(self.winLabel.setPos, belowScreenPos), Func(self.scoreLabel.setPos, belowScreenScorePos), Func(self.postWinLabel.setPos, belowScreenPos), Func(self.setScoreLabelText), Func(self.winLabel.unstash), Func(self.scoreLabel.unstash), Func(self.postWinLabel.unstash), Parallel(LerpFunc(self.scoreLabel.setPos, fromData = belowScreenScorePos, toData = normalScorePos, duration = 0.25), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25), LerpFunc(self.winLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.winLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), Func(self.completeSound.play), Wait(1.0), Parallel(LerpFunc(self.winLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.25), LerpFunc(self.winLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25), LerpFunc(self.scoreLabel.setPos, fromData = normalScorePos, toData = aboveScreenScorePos, duration = 0.25), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.25)), Func(self.winLabel.stash), Func(self.scoreLabel.stash), Func(self.stashPostWinLabelIfCycleComplete), Wait(0.25), Parallel(LerpFunc(self.postWinLabel.setPos, fromData = belowScreenPos, toData = normalPos, duration = 0.25), LerpFunc(self.postWinLabel.setAlphaScale, fromData = 0.0, toData = 1.0, duration = 0.25)), name = 'outroSequence')
        self.cleanupSequence = Sequence(Parallel(LerpFunc(self.postWinLabel.setPos, fromData = normalPos, toData = aboveScreenPos, duration = 0.5), LerpFunc(self.postWinLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.5), LerpFunc(self.scoreLabel.setAlphaScale, fromData = 1.0, toData = 0.0, duration = 0.5)), Func(self.scoreLabel.stash), Func(self.postWinLabel.stash), name = 'cleanupSequence')

    
    def updatePostWinLabel(self):
        if self.repairGame.isThereAnOpenGame():
            self.postWinLabel['text'] = PLocalizer.Minigame_Repair_Pick_New_Game
        else:
            self.postWinLabel['text'] = PLocalizer.Minigame_Repair_Waiting_For_Players
        self.postWinLabel.setText()

    
    def setScoreLabelText(self):
        labelSet = False
        for i in [
            0,
            1,
            2]:
            if not labelSet:
                percent = self.difficulty / self.repairGame.difficultyMax
                dif = RepairGlobals.Common.speedThresholds[self.name][i][1] - RepairGlobals.Common.speedThresholds[self.name][i][0]
                goalTime = RepairGlobals.Common.speedThresholds[self.name][i][0] + dif * percent
                if self.repairGame.repairClock.gameTime < goalTime:
                    labelSet = True
                    self.scoreLabel['text'] = PLocalizer.Minigame_Repair_Speed_Thresholds[i]
                
            self.repairGame.repairClock.gameTime < goalTime
        
        if not labelSet:
            self.scoreLabel['text'] = PLocalizer.Minigame_Repair_Speed_Thresholds[3]
        

    
    def stashPostWinLabelIfCycleComplete(self):
        if self.repairGame.isCycleComplete():
            self.postWinLabel.stash()
        

    
    def setDifficulty(self, difficulty):
        self.difficulty = difficulty

    
    def setCountDown(self, text):
        self.countDownLabel['text'] = text
        self.countDownLabel.setText()
        self.countDownLabel.setAlphaScale(0.0)

    
    def destroy(self):
        DirectFrame.destroy(self)
        self.countDownLabel.destroy()
        del self.countDownLabel
        self.winLabel.destroy()
        del self.winLabel
        self.introSequence.clearToInitial()
        del self.introSequence
        self.outroSequence.clearToInitial()
        del self.outroSequence
        self.cleanupSequence.clearToInitial()
        del self.cleanupSequence
        del self.repairGame
        self.cleanup()

    
    def reset(self):
        self.complete = False
        self.repairGame.repairClock.stop()

    
    def enterIdle(self):
        self.stash()

    
    def exitIdle(self):
        pass

    
    def enterIntro(self):
        self.unstash()
        self.countDownLabel.unstash()
        self.introSequence.start()
        self.reset()
        self.countDownLabel.reparentTo(self)

    
    def exitIntro(self):
        self.countDownLabel.stash()
        self.introSequence.clearToInitial()

    
    def enterGame(self):
        self.repairGame.repairClock.restart()

    
    def exitGame(self):
        self.repairGame.repairClock.pause()

    
    def enterOutro(self):
        self.outroSequence.start()
        self.complete = True

    
    def exitOutro(self):
        self.outroSequence.finish()
        self.cleanupSequence.start()
        self.reset()
        self.repairGame.gui.clearTutorial()
        self.repairGame.gui.clearTitle()

    
    def enterFinal(self):
        pass
class CogdoFlyingFuelGui(DirectFrame):

    def __init__(self, parent):
        DirectFrame.__init__(self, relief=None, state=DGG.NORMAL, sortOrder=DGG.BACKGROUND_SORT_INDEX)
        self.reparentTo(parent)
        self.active = 0
        self._initModel()
        self._initIntervals()
        return

    def _initModel(self):
        self.setPos(Globals.Gui.FuelPos2D[0], 0.0, Globals.Gui.FuelPos2D[1])
        self.gui = CogdoUtil.loadFlyingModel('propellerMeter', group='gui')
        self.gui.reparentTo(self)
        self.gui.setBin('fixed', 0)
        self.healthBar = self.gui.find('**/healthBar')
        self.healthBar.setBin('fixed', 1)
        self.healthBar.setColor(*Globals.Gui.FuelNormalColor)
        bottomBarLocator = self.gui.find('**/bottomOfBar_loc')
        bottomBarPos = bottomBarLocator.getPos(render)
        topBarLocator = self.gui.find('**/topOfBar_loc')
        topBarPos = topBarLocator.getPos(render)
        zDist = topBarPos.getZ() - bottomBarPos.getZ()
        self.fuelLowIndicator = self.gui.find('**/fuelLowIndicator')
        self.fuelLowIndicator.setBin('fixed', 2)
        pos = self.fuelLowIndicator.getPos(render)
        newPos = pos
        newPos.setZ(bottomBarPos.getZ() + zDist * Globals.Gameplay.FuelLowAmt)
        self.fuelLowIndicator.setPos(render, newPos)
        self.fuelVeryLowIndicator = self.gui.find('**/fuelVeryLowIndicator')
        self.fuelVeryLowIndicator.setBin('fixed', 2)
        pos = self.fuelVeryLowIndicator.getPos(render)
        newPos = pos
        newPos.setZ(bottomBarPos.getZ() + zDist * Globals.Gameplay.FuelVeryLowAmt)
        self.fuelVeryLowIndicator.setPos(render, newPos)
        self.propellerMain = self.gui.find('**/propellers')
        self.propellerMain.setBin('fixed', 3)
        self.propellerHead = self.gui.find('**/propellerHead')
        self.propellerHead.setBin('fixed', 4)
        self.blades = []
        self.activeBlades = []
        index = 1
        blade = self.propellerMain.find('**/propeller%d' % index)
        while not blade.isEmpty():
            self.blades.append(blade)
            index += 1
            blade = self.propellerMain.find('**/propeller%d' % index)

        for blade in self.blades:
            self.activeBlades.append(blade)

        self.bladeNumberLabel = DirectLabel(parent=self.propellerHead, relief=None, pos=(Globals.Gui.FuelNumBladesPos2D[0], 0, Globals.Gui.FuelNumBladesPos2D[1]), scale=Globals.Gui.FuelNumBladesScale, text=str(len(self.activeBlades)), text_align=TextNode.ACenter, text_fg=(0.0,
         0.0,
         -0.002,
         1), text_shadow=(0.75, 0.75, 0.75, 1), text_font=ToontownGlobals.getInterfaceFont())
        self.bladeNumberLabel.setBin('fixed', 5)
        return

    def _initIntervals(self):
        self._healthIval = LerpFunctionInterval(self.healthBar.setSz, fromData=0.0, toData=1.0, duration=2.0)
        self.baseSpinDuration = 2.0
        self._spinIval = LerpFunctionInterval(self.propellerMain.setR, fromData=0.0, toData=-360.0, duration=self.baseSpinDuration)

    def show(self):
        DirectFrame.show(self)
        self._spinIval.loop()

    def hide(self):
        DirectFrame.hide(self)
        self._spinIval.pause()

    def resetBlades(self):
        self.setBlades(len(self.blades))

    def setBlades(self, fuelState):
        if fuelState not in Globals.Gameplay.FuelStates:
            return
        numBlades = fuelState - 1
        if len(self.activeBlades) != numBlades:
            for i in range(len(self.activeBlades)):
                blade = self.activeBlades.pop()
                blade.stash()

            if numBlades > len(self.blades):
                numBlades = len(self.blades)
            for i in range(numBlades):
                blade = self.blades[i]
                self.activeBlades.append(blade)
                blade.unstash()

            self.bladeNumberLabel['text'] = str(len(self.activeBlades))
            self.bladeNumberLabel.setText()
        self.updateHealthBarColor()

    def bladeLost(self):
        if len(self.activeBlades) > 0:
            blade = self.activeBlades.pop()
            blade.stash()
            self.bladeNumberLabel['text'] = str(len(self.activeBlades))
            self.bladeNumberLabel.setText()
        self.updateHealthBarColor()

    def updateHealthBarColor(self):
        color = Globals.Gui.NumBlades2FuelColor[len(self.activeBlades)]
        self.healthBar.setColor(*color)

    def setPropellerSpinRate(self, newRate):
        self._spinIval.setPlayRate(newRate)

    def setRefuelLerpFromData(self):
        startScale = self.healthBar.getSz()
        self._healthIval.fromData = startScale

    def setFuel(self, fuel):
        self.fuel = fuel

    def update(self):
        self.healthBar.setSz(self.fuel)

    def destroy(self):
        self.bladeNumberLabel.removeNode()
        self.bladeNumberLabel = None
        self._healthIval.clearToInitial()
        del self._healthIval
        self.healthBar = None
        self.fuelLowIndicator = None
        self.fuelVeryLowIndicator = None
        self.propellerMain = None
        self.propellerHead = None
        del self.blades[:]
        del self.activeBlades[:]
        self.gui.detachNode()
        self.gui = None
        DirectFrame.destroy(self)
        return
class RepairSawingGame(RepairMincroGame):
    sawSounds = None
    boardComplet = None
    boardDestroyed = None
    
    def __init__(self, repairGame):
        self.config = RepairGlobals.Sawing
        notify = DirectNotifyGlobal.directNotify.newCategory('RepairSawingGame')
        RepairMincroGame.__init__(self, repairGame, 'sawing', PLocalizer.Minigame_Repair_Sawing_Start)

    
    def _initVars(self):
        RepairMincroGame._initVars(self)
        self.boardsPool = { }
        self.currentBoard = None
        self.currentBoardIndex = 0
        self.onDeckBoard = None
        self.onDeckBoardIndex = 0
        self.totalScore = 0.0
        self.hitZone1Penalty = False
        self.hitZone2Penalty = False
        self.hitBoardPenalty = False
        self.moveDiffForSound = 0.0
        self.startPositions = (Point3(0.0, 0.0, 0.0),)
        self.currentStartIndex = 0
        self.lastMousePos = None
        self.board_left = None
        self.board_right = None
        self.cut = None
        self.zone1_right = None
        self.zone1_left = None
        self.zone2_right = None
        self.zone2_left = None
        self.piece1 = None
        self.piece2 = None
        self.lastHitIndex = -1
        self.sawWaypoints = []

    
    def _initAudio(self):
        RepairMincroGame._initAudio(self)
        if not self.sawSounds:
            RepairSawingGame.sawSounds = (loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT01), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT02), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT03), loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_INOUT04))
            RepairSawingGame.boardComplete = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_COMPLETE)
            RepairSawingGame.boardDestroyed = loadSfx(SoundGlobals.SFX_MINIGAME_REPAIR_SAW_FAIL)
        

    
    def _initVisuals(self):
        RepairMincroGame._initVisuals(self)
        self.setBin('fixed', 36)
        self.model = loader.loadModel('models/gui/pir_m_gui_srp_sawing_main')
        sawModel = self.model.find('**/saw')
        sawModel.setR(193)
        sawModel.setPos(0.90000000000000002, 0.0, -0.16500000000000001)
        sawModel.setBin('gui-popup', 0)
        self.sawButton = RepairSaw(parent = self, clickDownCommand = self.sawAttachedToMouse, clickUpCommand = self.sawRemovedFromMouse, geom = sawModel, text_pos = (0.20000000000000001, -0.29999999999999999), text_fg = (1, 0, 0, 1), scale = (0.29999999999999999, 0.29999999999999999, 0.29999999999999999), relief = None, pressEffect = 0, frameSize = (-0.050000000000000003, 1.05, -0.29999999999999999, 0.050000000000000003), rolloverSound = None, clickSound = None)
        self.sawingLine = RepairSawingLine(self, self.config.sawlineLineThickness, self.config.sawlineColor, self.config.sawlineLinespawnDist)
        self.progressDescriptionLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Sawing_Description, text_fg = (1.0, 1.0, 1.0, 1.0), text_pos = (0.0, 0.0), text_shadow = (0.0, 0.0, 0.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_align = TextNode.ARight, relief = None, scale = (0.080000000000000002, 0.080000000000000002, 0.080000000000000002), pos = (-0.20000000000000001, 0.0, 0.5), parent = self)
        self.progressLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Sawing_Thresholds[3], text_fg = (1.0, 1.0, 1.0, 1.0), text_pos = (0.0, 0.0), text_shadow = (0.0, 0.0, 0.0, 1.0), text_font = PiratesGlobals.getPirateFont(), text_align = TextNode.ALeft, relief = None, scale = (0.080000000000000002, 0.080000000000000002, 0.080000000000000002), pos = (-0.17999999999999999, 0.0, 0.5), parent = self)
        self.boardDestroyedLabel = DirectLabel(text = PLocalizer.Minigame_Repair_Sawing_Board_Destroyed, text_fg = (1.0, 0.0, 0.0, 1.0), text_pos = (0.0, 0.0), text_font = PiratesGlobals.getPirateFont(), text_shadow = (0.0, 0.0, 0.0, 1.0), relief = None, scale = (0.10000000000000001, 0.10000000000000001, 0.10000000000000001), pos = (0.0, 0.0, 0.10000000000000001), parent = self)
        self.boardDestroyedLabel.setBin('fixed', 38)
        self.boardDestroyedLabel.stash()

    
    def _initIntervals(self):
        RepairMincroGame._initIntervals(self)
        self.newBoardSequence = Sequence(name = 'RepairSawingGame.newBoardSequence')
        self.splitBoardSequence = Sequence(name = 'RepairSawGame.splitBoardSequence')
        self.dropBoardSequence = Sequence(name = 'RepairSawGame.dropBoardSequence')

    
    def getNewBoard(self, boardIndex):
        board = self.model.find('**/wood%i' % boardIndex).copyTo(NodePath('board%i' % len(self.boardsPool)))
        board.reparentTo(self)
        piece1 = board.find('**/piece_1')
        piece1.setPythonTag('piece_1', self.piece1)
        piece1.setY(self.config.boardYDist)
        piece2 = board.find('**/piece_2')
        piece2.setPythonTag('piece_2', self.piece2)
        piece2.setY(self.config.boardYDist)
        pieceCut = board.find('**/piece_cut')
        pieceCut.setPythonTag('cut', self.cut)
        pieceCut.setColor(self.config.cutColor)
        pieceCut.setY(self.config.boardYDist)
        board_left = piece1.find('**/board')
        board_left.setPythonTag('left', self.board_left)
        board_right = piece2.find('**/board')
        board_right.setPythonTag('right', self.board_right)
        zone1_right = piece2.find('**/zone_1')
        zone1_right.setPythonTag('zone1_right', self.zone1_right)
        zone1_right.setColor(self.config.zone1Color)
        zone1_left = piece1.find('**/zone_1')
        zone1_left.setPythonTag('zone1_left', self.zone1_left)
        zone1_left.setColor(self.config.zone1Color)
        zone2_right = piece2.find('**/zone_2')
        zone2_right.setPythonTag('zone2_right', self.zone2_right)
        zone2_right.setColor(self.config.zone2Color)
        zone2_left = piece1.find('**/zone_2')
        zone2_left.setPythonTag('zone2_left', self.zone2_left)
        zone2_left.setColor(self.config.zone2Color)
        board.stash()
        return board

    
    def reset(self):
        for key in self.boardsPool.keys():
            board = self.boardsPool[key]
            board.removeNode()
        
        self.boardsPool.clear()
        if self.currentBoard:
            self.currentBoard.removeNode()
            self.currentBoard = None
        
        if self.onDeckBoard:
            self.onDeckBoard.removeNode()
            self.onDeckBoard = None
        
        for boardIndex in self.currentDifficultySet:
            boardIndex -= 1
            if 'copy1_%s' % boardIndex not in self.boardsPool:
                board = self.getNewBoard(boardIndex)
                self.boardsPool['copy1_%s' % boardIndex] = board
            
            if 'copy2_%s' % boardIndex not in self.boardsPool:
                board = self.getNewBoard(boardIndex)
                self.boardsPool['copy2_%s' % boardIndex] = board
                continue
        
        self.currentBoardIndex = 0
        self.currentBoard = None
        self.moveNewBoardOnDeck()
        self.onDeckBoard.unstash()
        self.totalScore = 0
        self.startPositions = (Point3(0.0, 0.0, 0.0),)
        self.sawButton.stash()
        self.sawButton.reparentTo(self)
        self.lastHitIndex = -1
        self.moveDiffForSound = 0.0
        RepairMincroGame.reset(self)
        self.repairGame.gui.setTutorial(self.name)
        self.repairGame.gui.setTitle(self.name)

    
    def destroy(self):
        RepairMincroGame.destroy(self)
        taskMgr.remove('SawingGame.updateSawTask')
        self.sawButton.destroy()
        self.sawButton.removeNode()
        del self.sawButton
        if self.currentBoard:
            self.currentBoard.removeNode()
            self.currentBoard = None
        
        if self.onDeckBoard:
            self.onDeckBoard.removeNode()
            self.onDeckBoard = None
        
        self.sawingLine = None
        self.progressDescriptionLabel.destroy()
        self.progressDescriptionLabel = None
        self.progressLabel.destroy()
        self.progressLabel = None
        self.boardDestroyedLabel.destroy()
        self.boardDestroyedLabel = None
        for key in self.boardsPool.keys():
            board = self.boardsPool[key]
            if not board.isEmpty():
                board.removeNode()
                continue
        
        self.boardsPool.clear()
        self.newBoardSequence.clearToInitial()
        del self.newBoardSequence
        self.splitBoardSequence.clearToInitial()
        del self.splitBoardSequence
        self.dropBoardSequence.clearToInitial()
        del self.dropBoardSequence

    
    def setDifficulty(self, difficulty):
        RepairMincroGame.setDifficulty(self, difficulty)
        percent = difficulty / self.repairGame.difficultyMax
        difIndex = int(math.floor(percent * (len(self.config.difficultySets) - 1)))
        self.currentDifficultySet = self.config.difficultySets[difIndex]

    
    def splitBoard(self):
        self.sawingLine.reset()
        board = self.currentBoard
        boardIndex = self.currentBoardIndex
        if self.hitZone2Penalty:
            boardSplitAnim = Parallel(LerpPosInterval(self.board_left, duration = self.config.splitBoardAnimTime, pos = Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.board_right, duration = self.config.splitBoardAnimTime, pos = Point3(2.0, 0.0, 0.0)), LerpFunc(self.zone2_left.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.zone2_right.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.zone1_left.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.zone1_right.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.cut.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0))
        elif self.hitZone1Penalty:
            boardSplitAnim = Parallel(LerpPosInterval(self.board_left, duration = self.config.splitBoardAnimTime, pos = Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.board_right, duration = self.config.splitBoardAnimTime, pos = Point3(2.0, 0.0, 0.0)), LerpPosInterval(self.zone2_left, duration = self.config.splitBoardAnimTime, pos = Point3(-2.0, 0.0, 0.0)), LerpPosInterval(self.zone2_right, duration = self.config.splitBoardAnimTime, pos = Point3(2.0, 0.0, 0.0)), LerpFunc(self.zone1_left.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.zone1_right.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0), LerpFunc(self.cut.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0))
        else:
            boardSplitAnim = Parallel(LerpPosInterval(self.piece1, duration = self.config.splitBoardAnimTime, pos = Point3(-2.0, self.config.boardYDist, 0.0)), LerpPosInterval(self.piece2, duration = self.config.splitBoardAnimTime, pos = Point3(2.0, self.config.boardYDist, 0.0)), LerpFunc(self.cut.setSa, duration = self.config.splitBoardAnimTime / 2.0, fromData = 1.0, toData = 0.0))
        self.splitBoardSequence = Sequence(Func(self.updateScore), Func(self.boardComplete.play), boardSplitAnim, Func(board.stash), Func(self.piece1.setPos, self.piece1.getPos()), Func(self.piece2.setPos, self.piece2.getPos()), Func(self.board_right.setPos, self.board_right.getPos()), Func(self.board_left.setPos, self.board_left.getPos()), Func(self.zone2_right.setPos, self.zone2_right.getPos()), Func(self.zone2_left.setPos, self.zone2_left.getPos()), Func(self.zone1_right.setPos, self.zone1_right.getPos()), Func(self.zone1_left.setPos, self.zone1_left.getPos()), Func(self.cut.setSa, 1.0), Func(self.zone1_right.setSa, 1.0), Func(self.zone1_left.setSa, 1.0), Func(self.zone2_right.setSa, 1.0), Func(self.zone2_left.setSa, 1.0), Func(self.board_right.setSa, 1.0), Func(self.board_left.setSa, 1.0), Func(self.loadNewBoard), Func(self.addBoardBackToPool, board, boardIndex), name = 'RepairSawGame.splitBoardSequence')
        self.splitBoardSequence.start()

    
    def dropBoard(self):
        board = self.currentBoard
        boardIndex = self.currentBoardIndex
        self.dropBoardSequence = Sequence(Parallel(Sequence(Func(self.boardDestroyedLabel.unstash), Wait(1.5), Func(self.boardDestroyedLabel.stash)), Sequence(Wait(0.5), Func(self.boardDestroyed.play), Func(self.sawingLine.reset), LerpPosInterval(board, duration = self.config.splitBoardAnimTime, pos = Point3(0.0, 0.0, -2.0)), Func(board.stash), Wait(0.5), Func(self.loadNewBoard), Func(self.addBoardBackToPool, board, boardIndex))), name = 'RepairSawGame.dropBoardSequence')
        self.dropBoardSequence.start()

    
    def addBoardBackToPool(self, board, boardIndex):
        if 'copy1_%s' % boardIndex not in self.boardsPool:
            self.boardsPool['copy1_%s' % boardIndex] = board
        elif 'copy2_%s' % boardIndex not in self.boardsPool:
            self.boardsPool['copy2_%s' % boardIndex] = board
        else:
            self.notify.error('Two copies of board type %i already in the boardsPool!' % boardIndex)

    
    def updateScoreText(self):
        self.progressLabel.unstash()
        self.progressDescriptionLabel.unstash()
        if self.hitBoardPenalty:
            self.progressLabel['text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[0]
            self.progressLabel['text_fg'] = Vec4(1.0, 0.0, 0.0, 1.0)
            self.progressLabel.setText()
        elif self.hitZone2Penalty:
            self.progressLabel['text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[1]
            self.progressLabel['text_fg'] = Vec4(1.0, 0.5, 0.0, 1.0)
            self.progressLabel.setText()
        elif self.hitZone1Penalty:
            self.progressLabel['text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[2]
            self.progressLabel['text_fg'] = Vec4(1.0, 1.0, 0.0, 1.0)
            self.progressLabel.setText()
        else:
            self.progressLabel['text'] = PLocalizer.Minigame_Repair_Sawing_Thresholds[3]
            self.progressLabel['text_fg'] = Vec4(0.0, 1.0, 0.0, 1.0)
            self.progressLabel.setText()

    
    def moveNewBoardOnDeck(self):
        boardIndex = random.randint(0, len(self.currentDifficultySet) - 1)
        boardType = self.currentDifficultySet[boardIndex]
        boardType -= 1
        if 'copy1_%s' % boardType in self.boardsPool:
            self.onDeckBoard = self.boardsPool['copy1_%s' % boardType]
            del self.boardsPool['copy1_%s' % boardType]
        elif 'copy2_%s' % boardType in self.boardsPool:
            self.onDeckBoard = self.boardsPool['copy2_%s' % boardType]
            del self.boardsPool['copy2_%s' % boardType]
        else:
            self.notify.error('No copies of board type %i in the boardsPool!' % boardType)
        self.onDeckBoardIndex = boardType
        self.onDeckBoard.setScale(0.25)
        self.onDeckBoard.setPos(0.5, -2.0, 0.56000000000000005)
        self.onDeckBoard.unstash()

    
    def loadNewBoard(self):
        self.progressLabel.stash()
        self.progressDescriptionLabel.stash()
        if self.totalScore >= self.config.totalPoints:
            if self.onDeckBoard:
                self.onDeckBoard.stash()
            
            self.progressDescriptionLabel.stash()
            taskMgr.remove('SawingGame.updateSawTask')
            self.request('Outro')
            return None
        
        self.currentBoard = self.onDeckBoard
        self.currentBoardIndex = self.onDeckBoardIndex
        self.piece1 = self.currentBoard.find('**/piece_1')
        self.piece1.setTransparency(1)
        self.piece2 = self.currentBoard.find('**/piece_2')
        self.piece2.setTransparency(1)
        self.cut = self.currentBoard.find('**/piece_cut')
        self.cut.setColor(self.config.cutColor)
        self.cut.setTransparency(1)
        self.board_left = self.piece1.find('**/board')
        self.board_left.setTransparency(1)
        self.zone1_left = self.piece1.find('**/zone_1')
        self.zone1_left.setTransparency(1)
        self.zone2_left = self.piece1.find('**/zone_2')
        self.zone2_left.setTransparency(1)
        self.board_right = self.piece2.find('**/board')
        self.board_right.setTransparency(1)
        self.zone1_right = self.piece2.find('**/zone_1')
        self.zone1_right.setTransparency(1)
        self.zone2_right = self.piece2.find('**/zone_2')
        self.zone2_right.setTransparency(1)
        self.board_left.setCollideMask(SAW_COLLIDE_MASK)
        self.board_right.setCollideMask(SAW_COLLIDE_MASK)
        self.cut.setCollideMask(SAW_COLLIDE_MASK)
        self.zone1_right.setCollideMask(SAW_COLLIDE_MASK)
        self.zone1_left.setCollideMask(SAW_COLLIDE_MASK)
        self.zone2_right.setCollideMask(SAW_COLLIDE_MASK)
        self.zone2_left.setCollideMask(SAW_COLLIDE_MASK)
        self.startPositions = (self.currentBoard.find('**/locator_start_0').getPos() + Point3(*self.config.activeBoardPosition), self.currentBoard.find('**/locator_start_1').getPos() + Point3(*self.config.activeBoardPosition))
        self.currentStartIndex = 0
        for waypoint in self.sawWaypoints:
            waypoint.removeNode()
        
        self.sawWaypoints = []
        locator = self.currentBoard.find('**/locator_0')
        index = 0
        while not locator.isEmpty():
            self.sawWaypoints.append(SawWaypoint(index, self.currentBoard, locator.getPos()))
            locator = self.currentBoard.find('**/locator_%i' % (index + 1))
            index += 1
        self.sawButton.deactivate()
        self.sawButton.setPos(self.startPositions[self.currentStartIndex])
        self.hitBoardPenalty = False
        self.hitZone1Penalty = False
        self.hitZone2Penalty = False
        self.lastMousePos = None
        self.moveDiffForSound = self.config.playSawingSoundDelta + 0.10000000000000001
        self.newBoardSequence = Sequence(Parallel(self.currentBoard.posInterval(self.config.newBoardAnimTime, Point3(*self.config.activeBoardPosition)), self.currentBoard.scaleInterval(self.config.newBoardAnimTime, 1.0)), name = 'RepairSawingGame.newBoardSequence')
        if self.state in [
            'Game']:
            self.newBoardSequence.append(Func(self.sawButton.activate))
        
        self.newBoardSequence.append(Wait(0.5))
        self.newBoardSequence.append(Func(self.moveNewBoardOnDeck))
        self.newBoardSequence.start()

    
    def updateSawTask(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            relative = Point3(mpos.getX(), 0.0, mpos.getY())
            relative = self.getRelativePoint(render2d, relative)
            moveDiff = 0.0
            if self.lastMousePos != None:
                moveDiff = (relative - self.lastMousePos).length()
            
            pickedObjects = self.repairGame.mousePicker.getCollisions(self.currentBoard, useIntoNodePaths = True)
            self.updateWaypoints()
            if len(pickedObjects) > 0:
                self.moveDiffForSound += moveDiff
                if self.moveDiffForSound > self.config.playSawingSoundDelta:
                    sawSoundPlaying = False
                    for sound in self.sawSounds:
                        if sound.status() == 2:
                            sawSoundPlaying = True
                            break
                            continue
                    
                    if sawSoundPlaying == False:
                        sound = random.choice(self.sawSounds)
                        sound.play()
                        self.moveDiffForSound = 0.0
                    
                
                if self.board_right in pickedObjects or self.board_left in pickedObjects:
                    for waypoint in self.sawWaypoints:
                        waypoint.hit = False
                    
                    self.hitBoardPenalty = True
                    self.dropBoard()
                    self.sawButton.deactivate()
                elif self.cut in pickedObjects:
                    self.updateWaypoints()
                elif self.zone1_right in pickedObjects or self.zone1_left in pickedObjects:
                    self.updateWaypoints()
                    if self.hitZone1Penalty == False:
                        self.hitZone1Penalty = True
                    
                elif self.zone2_right in pickedObjects or self.zone2_left in pickedObjects:
                    self.updateWaypoints()
                    if self.hitZone2Penalty == False:
                        self.hitZone2Penalty = True
                    
                
                self.updateScoreText()
            else:
                boardComplete = True
                for waypoint in self.sawWaypoints:
                    if not waypoint.hit:
                        boardComplete = False
                        break
                        continue
                
                if boardComplete:
                    self.splitBoard()
                    self.sawButton.deactivate()
                
            self.lastMousePos = self.sawButton.getPos()
        
        return Task.cont

    
    def updateScore(self):
        if not self.hitBoardPenalty:
            currBoardScore = self.config.pointsPerBoard
            if not self.hitZone1Penalty:
                pass
            currBoardScore -= self.config.pointsLostForZone1 * self.hitZone2Penalty
            currBoardScore -= self.config.pointsLostForZone2 * self.hitZone2Penalty
            rating = 4 - 1 * self.hitZone2Penalty - 3 * self.hitZone1Penalty
            self.totalScore += currBoardScore
            self.totalScore = min(self.totalScore, self.config.totalPoints)
            percent = int((self.totalScore / self.config.totalPoints) * 100.0)
            self.repairGame.d_reportMincroGameProgress(percent, rating)
        

    
    def resetWaypoints(self):
        for waypoint in self.sawWaypoints:
            waypoint.hit = False
        

    
    def updateWaypoints(self):
        waypointList = self.getHitWaypoints()
        for waypointIndex in waypointList:
            self.lastHitIndex = waypointIndex
            self.sawWaypoints[waypointIndex].hit = True
            if waypointIndex == 0 and not (self.sawWaypoints[-1].hit):
                self.currentStartIndex = 0
                continue
            if waypointIndex == len(self.sawWaypoints) - 1 and not (self.sawWaypoints[0].hit):
                self.currentStartIndex = 1
                continue
        

    
    def getHitWaypoints(self):
        waypointsHit = []
        testDelta = self.config.testWaypointDelta
        for i in range(len(self.sawWaypoints)):
            waypointPos = self.sawWaypoints[i].getPos(self)
            closestDistance = 9999
            if self.lastMousePos != None:
                currMousePos = self.sawButton.getPos()
                lastMousePos = self.lastMousePos
                totalLength = (currMousePos - lastMousePos).length()
                testLength = testDelta
                while testLength < totalLength:
                    testPos = (currMousePos - lastMousePos) * (testLength / totalLength) + lastMousePos
                    self.updateSawLine(testPos)
                    testDistance = (testPos - waypointPos).length()
                    closestDistance = min(testDistance, closestDistance)
                    testLength += testDelta
            
            self.updateSawLine(self.sawButton.getPos())
            testDistance = (self.sawButton.getPos() - waypointPos).length()
            closestDistance = min(testDistance, closestDistance)
            if closestDistance < self.config.waypointRange[self.currentBoardIndex]:
                waypointsHit.append(i)
                continue
        
        return waypointsHit

    
    def updateSawLine(self, pos):
        if pos.getX() < -0.63300000000000001 or pos.getX() > 0.63300000000000001:
            self.sawingLine.reset()
            return None
        
        if pos.getZ() < -0.183 or pos.getZ() > 0.375:
            self.sawingLine.reset()
            return None
        
        self.sawingLine.update(pos)

    
    def getClosestPosition(self, positions):
        closestIndex = -1
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            relative = Point3(mpos.getX(), 0.0, mpos.getY())
            relative = self.getRelativePoint(base.a2dBackground, relative)
            bestDistance = 99999.0
            for i in range(len(positions)):
                dX = relative.getX() - positions[i].getX()
                dZ = relative.getZ() - positions[i].getZ()
                newDistance = dX * dX + dZ * dZ
                if newDistance < bestDistance:
                    bestDistance = newDistance
                    closestIndex = i
                    continue
            
        
        return closestIndex

    
    def sawAttachedToMouse(self):
        self.lastHitIndex = -1
        if not taskMgr.hasTaskNamed('SawingGame.updateSawTask'):
            taskMgr.add(self.updateSawTask, 'SawingGame.updateSawTask', priority = 2)
        

    
    def sawRemovedFromMouse(self):
        if not self.sawButton.isStashed():
            self.sawButton.setPos(self.startPositions[self.currentStartIndex])
            self.lastHitIndex = -1
            self.resetWaypoints()
            self.lastMousePos = None
            self.progressLabel.stash()
            self.progressDescriptionLabel.stash()
            self.sawingLine.reset()
            self.hitBoardPenalty = False
            self.hitZone1Penalty = False
            self.hitZone2Penalty = False
        
        taskMgr.remove('SawingGame.updateSawTask')

    
    def enterIntro(self):
        RepairMincroGame.enterIntro(self)
        self.loadNewBoard()

    
    def enterGame(self):
        RepairMincroGame.enterGame(self)
        self.repairGame.mousePicker.setCollisionMask(SAW_COLLIDE_MASK)
        self.sawButton.activate()

    
    def exitGame(self):
        RepairMincroGame.exitGame(self)
        self.sawButton.deactivate()
        self.repairGame.mousePicker.clearCollisionMask()
        taskMgr.remove('SawingGame.updateSawTask')
        self.splitBoardSequence.clearToInitial()
        self.dropBoardSequence.clearToInitial()
        localAvatar.guiMgr._showCursor()

    
    def enterOutro(self):
        RepairMincroGame.enterOutro(self)
        self.repairGame.d_reportMincroGameScore(150)
class RepairGameButton(GuiButton):
    
    def __init__(self, parent, **kw):
        optiondefs = (('nodePath', None, None), ('image_scale', (1.0, 1.0, 1.0), None))
        self.defineoptions(kw, optiondefs)
        GuiButton.__init__(self, parent)
        self.initialiseoptions(RepairGameButton)
        self.disabledStateNode = self.stateNodePath[3].getChild(0)
        self.downStateNode = self.stateNodePath[1].getChild(0)
        self.overStateNode = self.stateNodePath[2].getChild(0)
        self.inProgress = False
        self._initGUI()

    
    def _initGUI(self):
        self.setBin('fixed', 33)
        mainGui = loader.loadModel('models/gui/gui_main')
        gui = loader.loadModel('models/gui/toplevel_gui')
        self.checkMark = gui.find('**/generic_check')
        self.checkMark.reparentTo(self)
        self.checkMark.stash()
        self.checkMark.setScale(1.0)
        self.checkMark.setColorScale(0.0, 1.0, 0.0, 1.0)
        self.checkMark.setPos(0.02, 0.0, 0.02)
        self.checkMark.setBin('fixed', 34)
        self.skillRing = DialMeter(self, wantCover = False, dangerRatio = 0.0, meterColor = Vec4(0.90000000000000002, 0.90000000000000002, 0.10000000000000001, 1.0), baseColor = Vec4(0.14999999999999999, 0.070000000000000007, 0.029999999999999999, 1.0), completeColor = Vec4(0.10000000000000001, 0.90000000000000002, 0.10000000000000001, 1.0))
        self.skillRing.reparentTo(self)
        self.skillRing.setScale(0.28499999999999998, 0.29999999999999999, 0.26500000000000001)
        self.skillRing.setBin('fixed', 32)
        self.skillGlow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0))
        self.glow = OnscreenImage(parent = self, image = mainGui.find('**/icon_glow'), scale = (1.0, 1.0, 1.0), color = (1.0, 1.0, 0.59999999999999998, 1.0))
        self.skillGlow.reparentTo(self)
        self.skillGlow.setBin('fixed', 31)
        self.skillGlow.stash()
        self.pirateNameBox = None
        self.pirateNameLabel = None

    
    def showGlow(self):
        self.inProgress = False
        if self.pirateNameLabel == None and self.checkMark.isStashed():
            self.skillGlow.unstash()
        

    
    def hideGlow(self):
        self.inProgress = True
        self.skillGlow.stash()

    
    def setProgress(self, percent):
        self.skillGlow.stash()
        ratio = max(0.0, percent / 100.0)
        if ratio >= 1.0:
            if self.checkMark.isStashed():
                self.checkMark.unstash()
            
        elif not self.checkMark.isStashed():
            self.checkMark.stash()
        
        if self.pirateNameLabel == None and not (self.inProgress):
            self.skillGlow.unstash()
        
        self.skillRing.update(ratio, 1.0)
        self.skillRing.wrtReparentTo(self.getParent())
        self.reparentTo(self.getParent())

    
    def updatePirateNameBox(self, pirateName):
        if self.pirateNameLabel != None and self.pirateNameLabel['text'] != pirateName:
            if self.pirateNameBox:
                self.pirateNameBox.destroy()
            
            if self.pirateNameLabel:
                self.pirateNameLabel.destroy()
            
            self.pirateNameBox = None
            self.pirateNameLabel = None
        
        if pirateName != '':
            if self.pirateNameBox:
                pass
            if not (self.pirateNameLabel['text'] == pirateName):
                self.createPirateNameBox(pirateName)
            

    
    def createPirateNameBox(self, pirateName):
        self.pirateNameLabel = DirectLabel(relief = None, state = DGG.DISABLED, text = pirateName, text_align = TextNode.ACenter, text_scale = PiratesGuiGlobals.TextScaleMed, text_fg = PiratesGuiGlobals.TextFG1, text_wordwrap = 12, textMayChange = 0, sortOrder = 91)
        self.pirateNameLabel.setBin('fixed', 33)
        height = self.pirateNameLabel.getHeight()
        width = self.pirateNameLabel.getWidth() + 0.050000000000000003
        pos = [
            0.0,
            0.0,
            height / 2 - 0.035000000000000003]
        fs = [
            -(width / 2 + 0.01),
            width / 2 + 0.01,
            -(height / 2 + 0.014999999999999999),
            height / 2 + 0.014999999999999999]
        self.pirateNameBox = BorderFrame(parent = self, state = DGG.DISABLED, frameSize = (fs[0], fs[1], fs[2], fs[3]), modelName = 'general_frame_f', pos = (0.0, 0.0, 0.0))
        self.pirateNameLabel.reparentTo(self.pirateNameBox)
        self.pirateNameLabel.setPos(pos[0], pos[1], pos[2])
        self.pirateNameBox.setClipPlaneOff()
        pos = self.pirateNameBox.getPos(aspect2d)
        x = min(pos[0], base.a2dRight - width)
        z = max(pos[2], base.a2dBottom - height)
        self.pirateNameBox.setPos(aspect2d, x, 0, z - 0.17499999999999999)
        self.pirateNameBox.flattenLight()
        self.pirateNameBox.setBin('fixed', 32)
        self.pirateNameBox.reparentTo(self)