Esempio n. 1
0
class Result():
    def __init__(self):
        self.txtresult = DirectLabel(
            scale = 0.25,
            frameColor = (0, 0, 0, 0),
            text = "",
            #text_align = TextNode.ACenter,
            text_fg = (0,0,0,1))
        self.txtresult.setTransparency(1)

    def setTeam(self, team):
        self.txtresult["text"] = "Team %s win" % team
        if team == "Yellow":
            self.txtresult["text_fg"] = (1,1,0,1)
        else:
            self.txtresult["text_fg"] = (0,0,1,1)

    def show(self):
        self.txtresult.show()

    def hide(self):
        self.txtresult.hide()
Esempio n. 2
0
class DoubleFrameQuestPoster(QuestPoster):
    notify = directNotify.newCategory('DoubleFrameQuestPoster')

    def __init__(self, quest, parent=aspect2d, **kw):
        QuestPoster.__init__(self, quest, parent, **kw)

        # This text is in between the two frames and it usually says
        # either "from:" or "to:"
        self.fromToMiddleText = DirectLabel(
            parent=self,
            relief=None,
            text=QuestGlobals.FROM,
            text_font=CIGlobals.getToonFont(),
            text_scale=QuestGlobals.QPauxText,
            text_fg=QuestGlobals.TEXT_COLOR,
            text_align=TextNode.ACenter,
            textMayChange=1,
            pos=QuestGlobals.DEFAULT_MIDDLE_POS)
        self.fromToMiddleText.hide()

        ##########################################################################
        #           THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER            #
        ##########################################################################
        # We need this again for certain geometry.
        circleGui = loader.loadModel(
            'phase_4/models/gui/CircleIconBackgroundGui.bam')

        # The background frame where the objective image is displayed.
        # This is the colored background frame.
        self.goalFrame = DirectFrame(
            parent=self,
            relief=None,
            image=circleGui.find('**/circle_display_interior'),
            image_scale=0.18,
            text='',
            text_pos=(0, -0.11),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=QuestGlobals.QPtextScale,
            text_align=TextNode.ACenter,
            text_wordwrap=11.0,
            pos=QuestGlobals.DEFAULT_RIGHT_PICTURE_POS)
        self.goalFrame.hide()

        # The icon that goes on top of the goal frame.
        self.goalIcon = DirectFrame(parent=self.goalFrame,
                                    relief=None,
                                    text=' ',
                                    text_font=CIGlobals.getSuitFont(),
                                    text_pos=(0, -0.03),
                                    text_fg=QuestGlobals.TEXT_COLOR,
                                    text_scale=0.13,
                                    text_align=TextNode.ACenter,
                                    text_wordwrap=13.0,
                                    textMayChange=1)
        self.goalIcon.setColorOff(-1)
        self.goalIcon.hide()

        self.goalOutline = DirectLabel(
            parent=self.goalFrame,
            relief=None,
            image=circleGui.find('**/circle_display_outline'),
            image_scale=0.18)
        self.goalOutline.hide()

        # Information displayed about the additional goal.
        self.goalInfo = DirectLabel(parent=self,
                                    relief=None,
                                    text='',
                                    text_font=CIGlobals.getToonFont(),
                                    text_fg=QuestGlobals.TEXT_COLOR,
                                    text_scale=0.04,
                                    text_align=TextNode.ACenter,
                                    text_wordwrap=QuestGlobals.QPtextWordwrap,
                                    textMayChange=1,
                                    pos=(QuestGlobals.DEFAULT_INFO2_POS))
        self.goalInfo.hide()

        circleGui.removeNode()
        return

        ##########################################################################

    def setup(self):
        QuestPoster.setup(self)
        objective = self.viewObjective

        # Let's reset our icon.
        self.goalIcon.setScale(1, 1, 1)
        self.goalIcon.setPos(0, 0, 0)
        self.goalIcon.setHpr(0, 0, 0)

        if objective.__class__ in DoubleFrameObjectives:
            if objective.__class__ == DeliverItemObjective:
                # It's kind of hard to return delivered stuff to somebody.
                # We're not handling complete objectives from here.
                self.handleDeliverItemObjective()
            elif objective.__class__ == RecoverItemObjective:
                self.handleRecoverItemObjective()

            if len(self.quest.accessibleObjectives) > 1:
                self.prevObjArrow.setPos(QuestGlobals.SECONDARY_LEFT_ARROW_POS)
                self.nextObjArrow.setPos(
                    QuestGlobals.SECONDARY_RIGHT_ARROW_POS)

            self.goalFrame.show()
            self.goalIcon.show()
            self.goalOutline.show()
            self.goalInfo.show()
            self.fromToMiddleText.show()
        else:
            self.goalFrame.hide()
            self.goalIcon.hide()
            self.goalOutline.hide()
            self.goalInfo.hide()
            self.fromToMiddleText.hide()
        self.goalIcon.initialiseoptions(DirectFrame)
        self.initialiseoptions(DoubleFrameQuestPoster)

    def handleRecoverItemObjective(self):
        objective = self.viewObjective

        # Let's make sure we have a current objective that is
        # an instance of the RecoverItemObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, RecoverItemObjective):
            return

        # Let's make the left icon use the item icon we chose.
        self.handleSimpleIcon(objective.itemIcon, 0.12, self.auxIcon)

        # Handle the objective information.
        infoText = '%d %s' % (objective.goal,
                              CIGlobals.makePlural(objective.itemName))
        if objective.goal == 1:
            infoText = objective.itemName

        # Update the positions and information regarding the left side.
        self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS)
        self.auxFrame['image_color'] = QuestGlobals.GREEN
        self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS)
        self.objectiveInfo['text'] = infoText
        self.fromToMiddleText[
            'text'] = QuestGlobals.FROM if not objective.isComplete(
            ) else QuestGlobals.TO

        if not objective.isComplete():
            self.handleCogObjective(self.goalIcon,
                                    auxText=QuestGlobals.RECOVER,
                                    frameColor=QuestGlobals.GREEN)

            # Let's set the progress bar text
            pgBarText = '%d of %d %s' % (objective.progress, objective.goal,
                                         CIGlobals.makePastTense(
                                             QuestGlobals.RECOVER))
            self.progressBar['text'] = pgBarText
            self.progressBar['value'] = objective.progress & pow(2, 16) - 1
        else:
            self.handleNPCObjective(self.goalIcon,
                                    auxText=QuestGlobals.RETURN,
                                    frameColor=QuestGlobals.BLUE)

    def handleDeliverItemObjective(self):
        objective = self.viewObjective

        # Let's make sure we have a current objective that is
        # an instance of the DeliverItemObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, DeliverItemObjective):
            return

        # Correct the scaling if we need to and set the icon.
        scale = 0.12 if objective.itemIcon.getName() == 'package' else 0.85
        self.handleSimpleIcon(objective.itemIcon, scale, self.auxIcon)
        self.auxFrame.setPos(QuestGlobals.RECOVER_LEFT_PICTURE_POS)
        self.auxFrame['image_color'] = QuestGlobals.RED

        infoText = '%d %s' % (objective.goal,
                              CIGlobals.makePlural(objective.itemName))
        if objective.goal == 1:
            infoText = objective.itemName
        self.objectiveInfo.setPos(QuestGlobals.RECOVER_INFO_POS)
        self.objectiveInfo['text'] = infoText
        self.fromToMiddleText['text'] = QuestGlobals.TO

        # Let's set the progress bar text
        pgBarText = '%d of %d %s' % (objective.progress, objective.goal,
                                     CIGlobals.makePastTense(
                                         QuestGlobals.DELIVER))
        self.progressBar['text'] = pgBarText
        self.progressBar['value'] = objective.progress & pow(2, 16) - 1

        self.handleNPCObjective(self.goalIcon,
                                auxText=QuestGlobals.DELIVER,
                                frameColor=QuestGlobals.RED)

    def destroy(self):
        self.fromToMiddleText.destroy()
        self.goalFrame.destroy()
        self.goalIcon.destroy()
        self.goalOutline.destroy()
        self.goalInfo.destroy()
        del self.fromToMiddleText
        del self.goalFrame
        del self.goalIcon
        del self.goalOutline
        del self.goalInfo
        QuestPoster.destroy(self)
Esempio n. 3
0
class ShopWindow(DirectFrame):

    def __init__(self, shop, image):
        DirectFrame.__init__(self)
        self.shop = shop
        self.bgImage = image
        self.title = None
        self.okBtn = None
        self.clBtn = None
        self.infoLbl = None
        self.nPage = -1
        self.nPages = 0
        self.nextPage = 0
        self.prevPage = -1
        self.pages = []
        self.isSetup = False
        return

    def setup(self, title = 'CHOOSE WHAT YOU WANT TO BUY'):
        font = CIGlobals.getMickeyFont()
        txtFg = (0, 0, 0, 1)
        txtScale = 0.05
        txtPos = (0, -0.1)
        buttons = loader.loadModel('phase_3.5/models/gui/QT_buttons.bam')
        self.window = OnscreenImage(image=self.bgImage, scale=(0.9, 1, 0.7), parent=self)
        self.title = DirectLabel(text=title, relief=None, pos=(0, 0, 0.5), text_wordwrap=10, text_font=font, text_fg=(1, 1, 0, 1), scale=0.1, parent=self)
        self.infoLbl = DirectLabel(text='Welcome!', relief=None, text_scale=0.075, text_fg=txtFg, text_shadow=(0, 0, 0, 0), pos=(0, 0, 0.215))
        self.okBtn = DirectButton(geom=CIGlobals.getOkayBtnGeom(), relief=None, text='OK', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(-0.1, 0, -0.5), parent=self)
        self.clBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(), relief=None, text='Cancel', text_fg=txtFg, text_scale=txtScale, text_pos=txtPos, pos=(0.1, 0, -0.5), parent=self)
        buttonGeom = (buttons.find('**/QT_back'),
         buttons.find('**/QT_back'),
         buttons.find('**/QT_back'),
         buttons.find('**/QT_back'))
        self.backBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(-0.3, 0, -0.25), parent=self, command=self.changePage, extraArgs=[0])
        self.nextBtn = DirectButton(geom=buttonGeom, relief=None, scale=0.05, pos=(0.3, 0, -0.25), hpr=(0, 0, 180), command=self.changePage, extraArgs=[1], parent=self)
        self.hideInfo()
        return

    def changePage(self, direction):
        var = self.prevPage
        if direction == 1:
            var = self.nextPage
        self.setPage(var)

    def __makeGagEntry(self, pos, item, values, page):
        itemImage = values.get('image')
        button = DirectButton(geom=itemImage, scale=1.3, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item])
        supply = base.localAvatar.getBackpack().getSupply(item().getName())
        maxSupply = base.localAvatar.getBackpack().getMaxSupply(item().getName())
        buttonLabel = DirectLabel(text='%s/%s\n%s JBS' % (str(supply), str(maxSupply), str(values.get('price'))), relief=None, parent=button, text_scale=0.05, pos=(0, 0, -0.11))
        self.addEntryToPage(page, item, values, button, buttonLabel)
        return

    def __makeUpgradeEntry(self, pos, item, values, page):
        itemImage = values.get('image')
        button = DirectButton(image=itemImage, scale=0.15, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item])
        button.setTransparency(TransparencyAttrib.MAlpha)
        upgradeID = values.get('upgradeID')
        supply = base.localAvatar.getPUInventory()[0]
        if supply < 0:
            supply = 0
        maxSupply = values.get('maxUpgrades')
        if upgradeID == 0 and base.localAvatar.getMyBattle().getTurretManager().myTurret:
            supply = 1
        buttonLabel = DirectLabel(text='%s\n%s/%s\n%s JBS' % (item,
         str(supply),
         str(maxSupply),
         str(values.get('price'))), relief=None, parent=button, text_scale=0.3, pos=(0, 0, -1.2))
        self.addEntryToPage(page, item, values, button, buttonLabel)
        return

    def __makeHealEntry(self, pos, item, values, page):
        label = '%s' % item
        itemImage = values.get('image')
        if 'showTitle' in values:
            label = '%s\n%s JBS' % (item, values.get('price'))
        button = DirectButton(image=itemImage, scale=0.105, pos=pos, relief=None, parent=page, command=self.shop.purchaseItem, extraArgs=[item])
        button.setTransparency(TransparencyAttrib.MAlpha)
        buttonLabel = DirectLabel(text=label, relief=None, parent=button, text_scale=0.55, pos=(0, 0, -1.6))
        self.addEntryToPage(page, item, values, button, buttonLabel)
        return

    def addEntryToPage(self, page, item, values, button, buttonLabel):
        page.addItemEntry(item, [button, buttonLabel])
        page.addItem({item: values})

    def makePages(self, items):
        newItems = dict(items)
        loadout = []
        for slot in base.localAvatar.getBackpack().gagGUI.getSlots():
            loadout.append(slot.getGag().getID())

        for item, values in newItems.items():
            if values.get('type') == ItemType.GAG:
                gag = item()
                if gag.getID() not in loadout or not base.localAvatar.getBackpack().isInBackpack(gag.getName()):
                    del newItems[item]

        self.nPages = int(len(newItems) / 4)
        if self.nPages % 4 != 0 and len(newItems) > 4:
            self.nPages += 1
        elif self.nPages == 0:
            self.nPages = 1
        itemPos = [(-0.45, 0, 0),
         (-0.15, 0, 0),
         (0.15, 0, 0),
         (0.45, 0, 0)]
        pageIndex = 0
        itemIndex = 0
        index = 1
        for _ in range(self.nPages):
            page = Page(self.shop, self)
            self.pages.append(page)

        for item, values in newItems.iteritems():
            pos = itemPos[itemIndex]
            page = self.pages[pageIndex]
            itemType = values.get('type')
            if itemType == ItemType.GAG:
                self.__makeGagEntry(pos, item, values, page)
            elif itemType == ItemType.UPGRADE:
                self.__makeUpgradeEntry(pos, item, values, page)
            elif itemType == ItemType.HEAL:
                self.__makeHealEntry(pos, item, values, page)
            if index % 4 == 0:
                index = 1
                pageIndex += 1
                itemIndex = 0
            else:
                itemIndex = itemIndex + 1
                index += 1

        if self.nPages == 1:
            self.backBtn.hide()
            self.nextBtn.hide()
        for page in self.pages:
            page.hide()
            page.update()

        self.isSetup = True

    def updatePages(self):
        for page in self.pages:
            page.update()

    def setPage(self, page):
        if self.nPage > -1:
            self.pages[self.nPage].hide()
        self.setBackBtn(True)
        self.setNextBtn(True)
        if page - 1 < 0:
            self.setBackBtn(False)
        elif page + 1 == self.nPages:
            self.setNextBtn(False)
        if page < 0 or page > self.nPages:
            return
        self.prevPage = page - 1
        self.nextPage = page + 1
        self.nPage = page
        self.pages[page].show()

    def setBackBtn(self, enabled):
        if self.backBtn:
            if enabled == False:
                self.backBtn.setColorScale(GRAYED_OUT_COLOR)
                self.backBtn['state'] = DGG.DISABLED
            else:
                self.backBtn.setColorScale(NORMAL_COLOR)
                self.backBtn['state'] = DGG.NORMAL

    def setNextBtn(self, enabled):
        if self.nextBtn:
            if enabled == False:
                self.nextBtn.setColorScale(GRAYED_OUT_COLOR)
                self.nextBtn['state'] = DGG.DISABLED
            else:
                self.nextBtn.setColorScale(NORMAL_COLOR)
                self.nextBtn['state'] = DGG.NORMAL

    def setOKCommand(self, command):
        if self.okBtn:
            self.okBtn['command'] = command

    def setCancelCommand(self, command):
        if self.clBtn:
            self.clBtn['command'] = command

    def showInfo(self, text, negative = 0, duration = -1):
        self.infoLbl.show()
        if negative:
            self.infoLbl['text_fg'] = (0.9, 0, 0, 1)
            self.infoLbl['text_shadow'] = (0, 0, 0, 1)
        else:
            self.infoLbl['text_fg'] = (0, 0, 0, 1)
            self.infoLbl['text_shadow'] = (0, 0, 0, 0)
        self.infoLbl['text'] = text
        if duration > -1:
            Sequence(Wait(duration), Func(self.hideInfo)).start()

    def hideInfo(self):
        if self.infoLbl:
            self.infoLbl.hide()

    def delete(self):
        elements = [self.title,
         self.okBtn,
         self.clBtn,
         self.infoLbl,
         self.backBtn,
         self.nextBtn]
        for element in elements:
            element.destroy()

        del elements
        for page in self.pages:
            page.destroy()
            self.pages.remove(page)

        self.title = None
        self.okBtn = None
        self.clBtn = None
        self.infoLbl = None
        self.backBtn = None
        self.nextBtn = None
        self.bgImage = None
        if self.window:
            self.window.destroy()
            self.window = None
        self.destroy()
        return
class VoteResultsPanel(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsPanel')

    def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs):
        opts = {'relief': None,
         'geom': DGG.getDefaultDialogGeom(),
         'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,),
         'geom_scale': (1.75, 1, 0.75),
         'pos': (0, 0, 0.525)}
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.2, 0, 0.0), text=TTLocalizer.TravelGameDirections[0], text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self.upDownFrame, relief=None, pos=(1.43, 0, 0.0), text=TTLocalizer.TravelGameDirections[1], text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers))
        self.totalText = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.0, 0, 0.0), text='Total', text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.2, 0, 0.0), text='', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.totalFrame, relief=None, pos=(1.43, 0, 0.0), text='', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel]
        self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(5))
        self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in range(self.numPlayers):
            frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        return

    def getRowPos(self, place):
        return Point3(-0.72, -0.01, 0.2 - place * 0.1)

    def setupResultLabel(self):
        reasonStr = ''
        if self.directionReason == TravelGameGlobals.ReasonVote:
            reasonStr = TTLocalizer.TravelGameReasonVotes % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
             'numVotes': self.directionTotals[self.directionToGo]}
        elif self.directionReason == TravelGameGlobals.ReasonRandom:
            reasonStr = TTLocalizer.TravelGameReasonRandom % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
             'numVotes': self.directionTotals[self.directionToGo]}
        elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider:
            reasonStr = TravelGameReasonPlace % {'name': 'TODO NAME',
             'dir': TTLocalizer.TravelGameDirections[self.directionToGo]}
        self.resultLabel['text'] = reasonStr
        self.resultLabel.hide()

    def createOnePlayerSequence(self, index, duration):
        numVotes = self.votes[index]
        direction = self.directions[index]

        def ticketTicker(t, label = self.entryList[index][direction + 1], startVotes = 0, endVotes = numVotes):
            label['text'] = str(int(t * endVotes + startVotes))

        track = Parallel()
        track.append(Func(self.entryList[index][0].show, name='showName %d' % index))
        track.append(LerpFunc(ticketTicker, duration=duration, name='countVotes %d' % index))
        startVotes = 0
        for prev in range(index):
            if self.directions[prev] == direction:
                startVotes += self.votes[prev]

        def totalTicker(t, label = self.totalVotesLabels[direction], startVotes = startVotes, additionalVotes = numVotes):
            label['text'] = str(int(t * additionalVotes + startVotes))

        track.append(LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index))
        return track

    def startMovie(self):
        self.movie = Sequence()
        for index in range(self.numPlayers):
            track = self.createOnePlayerSequence(index, 1.25)
            self.movie.append(track)
            self.movie.append(Wait(0.75))

        self.movie.append(Func(self.resultLabel.show))
        self.movie.append(Wait(2.0))
        self.movie.start()

    def destroy(self):
        self.movie.finish()
        DirectFrame.destroy(self)
    def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs):
        opts = {'relief': None,
         'geom': DGG.getDefaultDialogGeom(),
         'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,),
         'geom_scale': (1.75, 1, 0.25),
         'pos': (0, 0, 0.825)}
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsTrolleyPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers))
        self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel]
        self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5))
        self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in range(self.numPlayers):
            frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        self.avVotesLabel = {}
        self.avArrows = {}
        matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui')
        minnieArrow = matchingGameGui.find('**/minnieArrow')
        from toontown.minigame.DistributedTravelGame import map3dToAspect2d
        for index in range(self.numPlayers):
            avId = self.avIdList[index]
            av = base.cr.doId2do.get(avId)
            if av:
                height = av.getHeight()
                avPos = av.getPos(render)
                avPos.setZ(av.getZ() + 5)
                labelPos = map3dToAspect2d(render, avPos)
                if not labelPos:
                    continue
                labelPos.setZ(labelPos.getZ() + 0.3)
                arrow = None
                if self.votes[index] > 0:
                    arrow = aspect2d.attachNewNode('avArrow')
                    minnieArrow.copyTo(arrow)
                    arrow.setScale(1.1, 1, 1.15)
                    arrow.setPos(labelPos)
                    if self.directions[index] == 0:
                        arrow.setR(-90)
                        arrow.setColorScale(0, 0, 1, 1)
                    else:
                        arrow.setR(90)
                        arrow.setColorScale(1, 0, 0, 1)
                    arrow.wrtReparentTo(self.resultFrame)
                    arrow.hide()
                    self.avArrows[index] = arrow
                fgColor = Vec4(0, 0, 0, 1)
                if self.votes[index] > 0:
                    if self.directions[index] == 0:
                        fgColor = Vec4(0, 0, 1, 1)
                    else:
                        fgColor = Vec4(1, 0, 0, 1)
                if self.votes[index] > 0:
                    newLabel = DirectLabel(parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0))
                else:
                    newLabel = DirectLabel(parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0))
                newLabel.wrtReparentTo(self.resultFrame)
                newLabel.hide()
                self.avVotesLabel[index] = newLabel

        matchingGameGui.removeNode()
        self.curArrowSfxIndex = 0
        self.upArrowSfx = []
        self.downArrowSfx = []
        for i in range(5):
            self.upArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3'))
            self.downArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.mp3'))

        self.winVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_win_vote.mp3')
        self.noVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.mp3')
        self.loseVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.mp3')
        self.localAvatarWon = False
        self.localAvatarLost = False
        localIndex = self.avIdList.index(base.localAvatar.doId)
        localDirection = self.directions[localIndex]
        localVotes = self.votes[localIndex]
        if localVotes:
            if localDirection == self.directionToGo:
                if not TravelGameGlobals.ReverseWin:
                    self.localAvatarWon = True
                else:
                    self.localAvatarLost = True
            elif not TravelGameGlobals.ReverseWin:
                self.localAvatarLost = True
            else:
                self.localAvatarWon = True
        return
Esempio n. 6
0
class InventoryGui(DirectObject):
    directNotify = DirectNotify().newCategory('InventoryGui')

    def __init__(self):
        DirectObject.__init__(self)
        self.backpack = None
        self.threeSlotsPos = [(0, 0, 0.5), (0, 0, 0), (0, 0, -0.5)]
        self.fourSlotPos = [(0, 0, 0.45),
         (0, 0, 0.15),
         (0, 0, -0.15),
         (0, 0, -0.45)]
        self.availableSlot = 0
        self.slots = []
        self.activeSlot = None
        self.defaultSlots = 3
        self.prevSlot = None
        self.ammoLabel = None
        self.inventoryFrame = None
        self.switchSound = True
        self.switchSoundSfx = base.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.mp3')
        return

    def setWeapon(self, slot, playSound = True):
        if isinstance(slot, str):
            for iSlot in self.slots:
                if iSlot.getGag():
                    if iSlot.getGag().getName() == slot:
                        slot = iSlot

        if self.activeSlot:
            self.activeSlot.setOutlineImage('idle')
            self.prevSlot = self.activeSlot
        if self.backpack.getSupply(slot.getGag().getName()) > 0:
            if self.activeSlot != slot:
                base.localAvatar.b_equip(GagGlobals.getIDByName(slot.getGag().getName()))
                slot.setOutlineImage('selected')
                self.activeSlot = slot
            elif self.activeSlot == slot and slot.getGag().getState() == GagState.LOADED:
                base.localAvatar.b_unEquip()
                self.activeSlot = None
            self.update()
            if self.switchSound and playSound:
                SoundInterval(self.switchSoundSfx).start()
        else:
            return
        return

    def createGui(self):
        self.deleteGui()
        phase = 'phase_3.5/maps/'
        posGroup = self.threeSlotsPos
        self.inventoryFrame = DirectFrame(parent=base.a2dRightCenter, pos=(-0.2, 0, 0))
        if self.defaultSlots == 4:
            posGroup = self.fourSlotPos
        for slot in range(len(posGroup) + 1):
            if slot == 3:
                posGroup = self.fourSlotPos
            slotIdle = loader.loadTexture(phase + 'slot_%s_idle.png' % str(slot + 1))
            slotObj = Slot(slot + 1, posGroup[slot], self.inventoryFrame)
            slotOutline = OnscreenImage(image=slotIdle, color=(1, 1, 1, 0.5), parent=slotObj)
            slotOutline.setTransparency(TransparencyAttrib.MAlpha)
            slotObj.setOutline(slotOutline)
            self.slots.append(slotObj)
            if slot == 3:
                slotObj.hide()

        self.ammoLabel = DirectLabel(text='Ammo: 0', text_fg=(1, 1, 1, 1), relief=None, text_shadow=(0, 0, 0, 1), text_scale=0.08, pos=(0.2, 0, 0.35), parent=base.a2dBottomLeft)
        self.ammoLabel.hide()
        self.enableWeaponSwitch()
        self.resetScroll()
        self.update()
        return

    def deleteGui(self):
        self.disableWeaponSwitch()
        for slot in self.slots:
            self.slots.remove(slot)
            slot.destroy()

        if self.ammoLabel:
            self.ammoLabel.destroy()
            self.ammoLabel = None
        if self.inventoryFrame:
            self.inventoryFrame.destroy()
            self.inventoryFrame = None
        return

    def resetScroll(self):
        nextGag = 0
        prevGag = -1
        curGag = -1
        if self.prevSlot:
            prevGag = self.slots.index(self.prevSlot)
        if self.activeSlot:
            curGag = self.slots.index(self.activeSlot)
        if curGag == len(self.slots) - 1:
            nextGag = 0
            prevGag = curGag - 1
        elif curGag == 0:
            nextGag = 1
            prevGag = len(self.slots) - 1
        elif curGag == -1:
            prevGag = len(self.slots) - 1
        else:
            nextGag = curGag + 1
            prevGag = curGag - 1
        self.accept('wheel_down', self.setWeapon, extraArgs=[self.slots[prevGag]])
        self.accept('wheel_up', self.setWeapon, extraArgs=[self.slots[nextGag]])

    def update(self):
        if not self.backpack:
            return
        else:
            for element in [self.ammoLabel, self.inventoryFrame]:
                if not element:
                    return

            for slot in self.slots:
                gag = slot.getGag()
                if not gag:
                    continue
                supply = self.backpack.getSupply(gag.getName())
                index = self.slots.index(slot)
                if not gag and len(self.backpack.getGags()) - 1 >= index:
                    gag = self.backpack.getGagByIndex(index)
                    slot.setGag(gag)
                    if self.backpack.getSupply(gag.getName()) > 0:
                        slot.setOutlineImage('idle')
                    else:
                        slot.setOutlineImage('no_ammo')
                elif slot == self.activeSlot:
                    if supply > 0:
                        slot.setOutlineImage('selected')
                        self.ammoLabel['text_fg'] = (1, 1, 1, 1)
                    else:
                        slot.setOutlineImage('no_ammo')
                        self.ammoLabel['text_fg'] = (0.9, 0, 0, 1)
                        self.activeSlot = None
                    self.ammoLabel.show()
                    self.ammoLabel['text'] = 'Ammo: %s' % self.backpack.getSupply(slot.getGag().getName())
                elif self.backpack.getSupply(slot.getGag().getName()) > 0:
                    slot.setOutlineImage('idle')
                else:
                    slot.setOutlineImage('no_ammo')

            if self.activeSlot == None:
                self.ammoLabel.hide()
                self.ammoLabel['text'] = 'Ammo: 0'
            self.resetScroll()
            return

    def setBackpack(self, backpack):
        self.backpack = backpack

    def updateLoadout(self):
        if self.backpack:
            loadout = self.backpack.getLoadout()
            if len(loadout) <= 3:
                self.reseatSlots()
            elif len(loadout) == 4:
                self.reseatSlots(slots=4)
            for i in range(len(self.slots)):
                slot = self.slots[i]
                if i < len(loadout):
                    slot.setGag(loadout[i])
                else:
                    slot.setGag(None)

            self.update()
        return

    def reseatSlots(self, slots = 3):
        for slot in range(len(self.slots) - 1):
            if slots == 4:
                self.slots[slot].setPos(self.fourSlotPos[slot])
            else:
                self.slots[slot].setPos(self.threeSlotsPos[slot])

    def enableWeaponSwitch(self):
        for index in range(len(self.slots)):
            self.accept(str(index + 1), self.setWeapon, extraArgs=[self.slots[index]])

    def disableWeaponSwitch(self):
        for key in ['1',
         '2',
         '3',
         '4',
         'wheel_down',
         'wheel_up']:
            self.ignore(key)

    def getSlots(self):
        return self.slots
class DistributedIceGame(DistributedMinigame.DistributedMinigame,
                         DistributedIceWorld.DistributedIceWorld):
    notify = directNotify.newCategory('DistributedIceGame')
    MaxLocalForce = 100
    MaxPhysicsForce = 25000

    def __init__(self, cr):
        DistributedMinigame.DistributedMinigame.__init__(self, cr)
        DistributedIceWorld.DistributedIceWorld.__init__(self, cr)
        self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [
            State.State('off', self.enterOff, self.exitOff, ['inputChoice']),
            State.State(
                'inputChoice', self.enterInputChoice, self.exitInputChoice,
                ['waitServerChoices', 'moveTires', 'displayVotes', 'cleanup']),
            State.State('waitServerChoices', self.enterWaitServerChoices,
                        self.exitWaitServerChoices, ['moveTires', 'cleanup']),
            State.State('moveTires', self.enterMoveTires, self.exitMoveTires,
                        ['synch', 'cleanup']),
            State.State('synch', self.enterSynch, self.exitSynch,
                        ['inputChoice', 'scoring', 'cleanup']),
            State.State('scoring', self.enterScoring, self.exitScoring,
                        ['cleanup', 'finalResults', 'inputChoice']),
            State.State('finalResults', self.enterFinalResults,
                        self.exitFinalResults, ['cleanup']),
            State.State('cleanup', self.enterCleanup, self.exitCleanup, [])
        ], 'off', 'cleanup')
        self.addChildGameFSM(self.gameFSM)
        self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0)
        self.tireDict = {}
        self.forceArrowDict = {}
        self.canDrive = False
        self.timer = None
        self.timerStartTime = None
        self.curForce = 0
        self.curHeading = 0
        self.headingMomentum = 0.0
        self.forceMomentum = 0.0
        self.allTireInputs = None
        self.curRound = 0
        self.curMatch = 0
        self.controlKeyWarningLabel = DirectLabel(
            text=TTLocalizer.IceGameControlKeyWarning,
            text_fg=VBase4(1, 0, 0, 1),
            relief=None,
            pos=(0.0, 0, 0),
            scale=0.15)
        self.controlKeyWarningLabel.hide()
        self.waitingMoveLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForPlayersToFinishMove,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self.waitingMoveLabel.hide()
        self.waitingSyncLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForAISync,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self.waitingSyncLabel.hide()
        self.infoLabel = DirectLabel(text='',
                                     text_fg=VBase4(0, 0, 0, 1),
                                     relief=None,
                                     pos=(0.0, 0, 0.7),
                                     scale=0.075)
        self.updateInfoLabel()
        self.lastForceArrowUpdateTime = 0
        self.sendForceArrowUpdateAsap = False
        self.treasures = []
        self.penalties = []
        self.obstacles = []
        self.controlKeyPressed = False
        self.controlKeyWarningIval = None
        return

    def delete(self):
        DistributedIceWorld.DistributedIceWorld.delete(self)
        DistributedMinigame.DistributedMinigame.delete(self)
        if self.controlKeyWarningIval:
            self.controlKeyWarningIval.finish()
            self.controlKeyWarningIval = None
        self.controlKeyWarningLabel.destroy()
        del self.controlKeyWarningLabel
        self.waitingMoveLabel.destroy()
        del self.waitingMoveLabel
        self.waitingSyncLabel.destroy()
        del self.waitingSyncLabel
        self.infoLabel.destroy()
        del self.infoLabel
        for treasure in self.treasures:
            treasure.destroy()

        del self.treasures
        for penalty in self.penalties:
            penalty.destroy()

        del self.penalties
        for obstacle in self.obstacles:
            obstacle.removeNode()

        del self.obstacles
        del self.gameFSM
        return

    def announceGenerate(self):
        DistributedMinigame.DistributedMinigame.announceGenerate(self)
        DistributedIceWorld.DistributedIceWorld.announceGenerate(self)
        self.debugTaskName = self.uniqueName('debugTask')

    def getTitle(self):
        return TTLocalizer.IceGameTitle

    def getInstructions(self):
        szId = self.getSafezoneId()
        numPenalties = IceGameGlobals.NumPenalties[szId]
        result = TTLocalizer.IceGameInstructions
        if numPenalties == 0:
            result = TTLocalizer.IceGameInstructionsNoTnt
        return result

    def getMaxDuration(self):
        return 0

    def load(self):
        self.notify.debug('load')
        DistributedMinigame.DistributedMinigame.load(self)
        self.music = base.loadMusic('phase_4/audio/bgm/MG_IceGame.ogg')
        self.gameBoard = loader.loadModel(
            'phase_4/models/minigames/ice_game_icerink')
        background = loader.loadModel('phase_4/models/minigames/ice_game_2d')
        backgroundWide = loader.loadModel(
            'phase_4/models/minigames/iceslide_ground')
        background.reparentTo(self.gameBoard)
        backgroundWide.reparentTo(self.gameBoard)
        backgroundWide.setPos(0, -0.3, -0.5)
        self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
        self.gameBoard.setScale(1.0)
        self.setupSimulation()
        index = 0
        for avId in self.avIdList:
            self.setupTire(avId, index)
            self.setupForceArrow(avId)
            index += 1

        for index in xrange(len(self.avIdList), 4):
            self.setupTire(-index, index)
            self.setupForceArrow(-index)

        self.showForceArrows(realPlayersOnly=True)
        self.westWallModel = NodePath()
        if not self.westWallModel.isEmpty():
            self.westWallModel.reparentTo(self.gameBoard)
            self.westWallModel.setPos(IceGameGlobals.MinWall[0],
                                      IceGameGlobals.MinWall[1], 0)
            self.westWallModel.setScale(4)
        self.eastWallModel = NodePath()
        if not self.eastWallModel.isEmpty():
            self.eastWallModel.reparentTo(self.gameBoard)
            self.eastWallModel.setPos(IceGameGlobals.MaxWall[0],
                                      IceGameGlobals.MaxWall[1], 0)
            self.eastWallModel.setScale(4)
            self.eastWallModel.setH(180)
        self.arrowKeys = ArrowKeys.ArrowKeys()
        self.target = loader.loadModel('phase_3/models/misc/sphere')
        self.target.setScale(0.01)
        self.target.reparentTo(self.gameBoard)
        self.target.setPos(0, 0, 0)
        self.scoreCircle = loader.loadModel(
            'phase_4/models/minigames/ice_game_score_circle')
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.reparentTo(self.gameBoard)
        self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0)
        self.scoreCircle.setAlphaScale(0.5)
        self.scoreCircle.setTransparency(1)
        self.scoreCircle.hide()
        self.treasureModel = loader.loadModel(
            'phase_4/models/minigames/ice_game_barrel')
        self.penaltyModel = loader.loadModel(
            'phase_4/models/minigames/ice_game_tnt2')
        self.penaltyModel.setScale(0.75, 0.75, 0.7)
        szId = self.getSafezoneId()
        obstacles = IceGameGlobals.Obstacles[szId]
        index = 0
        cubicObstacle = IceGameGlobals.ObstacleShapes[szId]
        for pos in obstacles:
            newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius)
            newObstacle = self.createObstacle(newPos, index, cubicObstacle)
            self.obstacles.append(newObstacle)
            index += 1

        self.countSound = loader.loadSfx(
            'phase_3.5/audio/sfx/tick_counter.ogg')
        self.treasureGrabSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg')
        self.penaltyGrabSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
        self.tireSounds = []
        for tireIndex in xrange(4):
            tireHit = loader.loadSfx(
                'phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg')
            wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
            obstacleHit = loader.loadSfx(
                'phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg')
            self.tireSounds.append({
                'tireHit': tireHit,
                'wallHit': wallHit,
                'obstacleHit': obstacleHit
            })

        self.arrowRotateSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg')
        self.arrowUpSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg')
        self.arrowDownSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg')
        self.scoreCircleSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg')

    def unload(self):
        self.notify.debug('unload')
        DistributedMinigame.DistributedMinigame.unload(self)
        del self.music
        self.gameBoard.removeNode()
        del self.gameBoard
        for forceArrow in self.forceArrowDict.values():
            forceArrow.removeNode()

        del self.forceArrowDict
        self.scoreCircle.removeNode()
        del self.scoreCircle
        del self.countSound

    def onstage(self):
        self.notify.debug('onstage')
        DistributedMinigame.DistributedMinigame.onstage(self)
        self.gameBoard.reparentTo(render)
        self.__placeToon(self.localAvId)
        self.moveCameraToTop()
        self.scorePanels = []
        base.playMusic(self.music, looping=1, volume=0.8)

    def offstage(self):
        self.notify.debug('offstage')
        self.music.stop()
        self.gameBoard.hide()
        self.infoLabel.hide()
        for avId in self.tireDict:
            self.tireDict[avId]['tireNodePath'].hide()

        for panel in self.scorePanels:
            panel.cleanup()

        del self.scorePanels
        for obstacle in self.obstacles:
            obstacle.hide()

        for treasure in self.treasures:
            treasure.nodePath.hide()

        for penalty in self.penalties:
            penalty.nodePath.hide()

        for avId in self.avIdList:
            av = self.getAvatar(avId)
            if av:
                av.dropShadow.show()
                av.resetLOD()

        taskMgr.remove(self.uniqueName('aimtask'))
        self.arrowKeys.destroy()
        del self.arrowKeys
        DistributedMinigame.DistributedMinigame.offstage(self)

    def handleDisabledAvatar(self, avId):
        self.notify.debug('handleDisabledAvatar')
        self.notify.debug('avatar ' + str(avId) + ' disabled')
        DistributedMinigame.DistributedMinigame.handleDisabledAvatar(
            self, avId)

    def setGameReady(self):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameReady')
        if DistributedMinigame.DistributedMinigame.setGameReady(self):
            return
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            toon = self.getAvatar(avId)
            if toon:
                toon.reparentTo(render)
                self.__placeToon(avId)
                toon.forwardSpeed = 0
                toon.rotateSpeed = False
                toon.dropShadow.hide()
                toon.setAnimState('Sit')
                if avId in self.tireDict:
                    tireNp = self.tireDict[avId]['tireNodePath']
                    toon.reparentTo(tireNp)
                    toon.setY(1.0)
                    toon.setZ(-3)
                toon.startLookAround()

    def setGameStart(self, timestamp):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameStart')
        DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp)
        for avId in self.remoteAvIdList:
            toon = self.getAvatar(avId)
            if toon:
                toon.stopLookAround()

        self.scores = [0] * self.numPlayers
        spacing = 0.4
        for i in xrange(self.numPlayers):
            avId = self.avIdList[i]
            avName = self.getAvatarName(avId)
            scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(
                avId, avName)
            scorePanel.setScale(0.9)
            scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i),
                              0.0, -0.15)
            scorePanel.reparentTo(base.a2dTopRight)
            scorePanel.makeTransparent(0.75)
            self.scorePanels.append(scorePanel)

        self.arrowKeys.setPressHandlers([
            self.__upArrowPressed, self.__downArrowPressed,
            self.__leftArrowPressed, self.__rightArrowPressed,
            self.__controlPressed
        ])

    def isInPlayState(self):
        if not self.gameFSM.getCurrentState():
            return False
        if not self.gameFSM.getCurrentState().getName() == 'play':
            return False
        return True

    def enterOff(self):
        self.notify.debug('enterOff')

    def exitOff(self):
        pass

    def enterInputChoice(self):
        self.notify.debug('enterInputChoice')
        self.forceLocalToonToTire()
        self.controlKeyPressed = False
        if self.curRound == 0:
            self.setupStartOfMatch()
        else:
            self.notify.debug('self.curRound = %s' % self.curRound)
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.hide()
        if self.timerStartTime != None:
            self.startTimer()
        self.showForceArrows(realPlayersOnly=True)
        self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0)
        self.localForceArrow().reparentTo(self.localTireNp())
        self.localForceArrow().setY(IceGameGlobals.TireRadius)
        self.localTireNp().headsUp(self.target)
        self.notify.debug('self.localForceArrow() heading = %s' %
                          self.localForceArrow().getH())
        self.curHeading = self.localTireNp().getH()
        self.curForce = 25
        self.updateLocalForceArrow()
        for avId in self.forceArrowDict:
            forceArrow = self.forceArrowDict[avId]
            forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0)
            tireNp = self.tireDict[avId]['tireNodePath']
            forceArrow.reparentTo(tireNp)
            forceArrow.setY(IceGameGlobals.TireRadius)
            tireNp.headsUp(self.target)
            self.updateForceArrow(avId, tireNp.getH(), 25)

        taskMgr.add(self.__aimTask, self.uniqueName('aimtask'))
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.stop()
        self.sendForceArrowUpdateAsap = False
        return

    def exitInputChoice(self):
        if not self.controlKeyPressed:
            if self.controlKeyWarningIval:
                self.controlKeyWarningIval.finish()
                self.controlKeyWarningIval = None
            self.controlKeyWarningIval = Sequence(
                Func(self.controlKeyWarningLabel.show),
                self.controlKeyWarningLabel.colorScaleInterval(
                    10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1,
                                                                   1)),
                Func(self.controlKeyWarningLabel.hide))
            self.controlKeyWarningIval.start()
        if self.timer != None:
            self.timer.destroy()
            self.timer = None
        self.timerStartTime = None
        self.hideForceArrows()
        self.arrowRotateSound.stop()
        self.arrowUpSound.stop()
        self.arrowDownSound.stop()
        taskMgr.remove(self.uniqueName('aimtask'))
        return

    def enterWaitServerChoices(self):
        self.waitingMoveLabel.show()
        self.showForceArrows(True)

    def exitWaitServerChoices(self):
        self.waitingMoveLabel.hide()
        self.hideForceArrows()

    def enterMoveTires(self):
        for key in self.tireDict:
            body = self.tireDict[key]['tireBody']
            body.setAngularVel(0, 0, 0)
            body.setLinearVel(0, 0, 0)

        for index in xrange(len(self.allTireInputs)):
            input = self.allTireInputs[index]
            avId = self.avIdList[index]
            body = self.getTireBody(avId)
            degs = input[1] + 90
            tireNp = self.getTireNp(avId)
            tireH = tireNp.getH()
            self.notify.debug('tireH = %s' % tireH)
            radAngle = deg2Rad(degs)
            foo = NodePath('foo')
            dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
            self.notify.debug('dirVector is now=%s' % dirVector)
            inputForce = input[0]
            inputForce /= self.MaxLocalForce
            inputForce *= self.MaxPhysicsForce
            force = dirVector * inputForce
            self.notify.debug('adding force %s to %d' % (force, avId))
            body.addForce(force)

        self.enableAllTireBodies()
        self.totalPhysicsSteps = 0
        self.startSim()
        taskMgr.add(self.__moveTiresTask, self.uniqueName('moveTiresTtask'))

    def exitMoveTires(self):
        self.forceLocalToonToTire()
        self.disableAllTireBodies()
        self.stopSim()
        self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps)
        taskMgr.remove(self.uniqueName('moveTiresTtask'))

    def enterSynch(self):
        self.waitingSyncLabel.show()

    def exitSynch(self):
        self.waitingSyncLabel.hide()

    def enterScoring(self):
        sortedByDistance = []
        for avId in self.avIdList:
            np = self.getTireNp(avId)
            pos = np.getPos()
            pos.setZ(0)
            sortedByDistance.append((avId, pos.length()))

        def compareDistance(x, y):
            if x[1] - y[1] > 0:
                return 1
            elif x[1] - y[1] < 0:
                return -1
            else:
                return 0

        sortedByDistance.sort(cmp=compareDistance)
        self.scoreMovie = Sequence()
        curScale = 0.01
        curTime = 0
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.show()
        self.notify.debug('newScores = %s' % self.newScores)
        circleStartTime = 0
        for index in xrange(len(sortedByDistance)):
            distance = sortedByDistance[index][1]
            avId = sortedByDistance[index][0]
            scorePanelIndex = self.avIdList.index(avId)
            time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec
            if time < 0:
                time = 0.01
            scaleXY = distance + IceGameGlobals.TireRadius
            self.notify.debug('circleStartTime = %s' % circleStartTime)
            self.scoreMovie.append(
                Parallel(
                    LerpScaleInterval(self.scoreCircle, time,
                                      Point3(scaleXY, scaleXY, 1.0)),
                    SoundInterval(self.scoreCircleSound,
                                  duration=time,
                                  startTime=circleStartTime)))
            circleStartTime += time
            startScore = self.scorePanels[scorePanelIndex].getScore()
            destScore = self.newScores[scorePanelIndex]
            self.notify.debug('for avId %d, startScore=%d, newScores=%d' %
                              (avId, startScore, destScore))

            def increaseScores(t,
                               scorePanelIndex=scorePanelIndex,
                               startScore=startScore,
                               destScore=destScore):
                oldScore = self.scorePanels[scorePanelIndex].getScore()
                diff = destScore - startScore
                newScore = int(startScore + diff * t)
                if newScore > oldScore:
                    base.playSfx(self.countSound)
                self.scorePanels[scorePanelIndex].setScore(newScore)
                self.scores[scorePanelIndex] = newScore

            duration = (destScore -
                        startScore) * IceGameGlobals.ScoreCountUpRate
            tireNp = self.tireDict[avId]['tireNodePath']
            self.scoreMovie.append(
                Parallel(
                    LerpFunctionInterval(increaseScores, duration),
                    Sequence(
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)))))
            curScale += distance

        self.scoreMovie.append(
            Func(self.sendUpdate, 'reportScoringMovieDone', []))
        self.scoreMovie.start()

    def exitScoring(self):
        self.scoreMovie.finish()
        self.scoreMovie = None
        self.scoreCircle.hide()
        return

    def enterFinalResults(self):
        lerpTrack = Parallel()
        lerpDur = 0.5
        tY = 0.6
        bY = -0.05
        lX = -0.5
        cX = 0
        rX = 0.5
        scorePanelLocs = (((cX, bY), ), ((lX, bY), (rX, bY)),
                          ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY),
                                                           (lX, bY), (rX, bY)))
        scorePanelLocs = scorePanelLocs[self.numPlayers - 1]
        for i in xrange(self.numPlayers):
            panel = self.scorePanels[i]
            pos = scorePanelLocs[i]
            panel.wrtReparentTo(aspect2d)
            lerpTrack.append(
                Parallel(
                    LerpPosInterval(panel,
                                    lerpDur,
                                    Point3(pos[0], 0, pos[1]),
                                    blendType='easeInOut'),
                    LerpScaleInterval(panel,
                                      lerpDur,
                                      Vec3(panel.getScale()) * 2.0,
                                      blendType='easeInOut')))

        self.showScoreTrack = Parallel(
            lerpTrack,
            Sequence(Wait(IceGameGlobals.ShowScoresDuration),
                     Func(self.gameOver)))
        self.showScoreTrack.start()

    def exitFinalResults(self):
        self.showScoreTrack.pause()
        del self.showScoreTrack

    def enterCleanup(self):
        self.notify.debug('enterCleanup')
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.start()

    def exitCleanup(self):
        pass

    def __placeToon(self, avId):
        toon = self.getAvatar(avId)
        if toon:
            toon.setPos(0, 0, 0)
            toon.setHpr(0, 0, 0)

    def moveCameraToTop(self):
        camera.reparentTo(render)
        p = self.cameraThreeQuarterView
        camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])

    def setupTire(self, avId, index):
        tireNp, tireBody, tireOdeGeom = self.createTire(index)
        self.tireDict[avId] = {
            'tireNodePath': tireNp,
            'tireBody': tireBody,
            'tireOdeGeom': tireOdeGeom
        }
        if avId <= 0:
            tireBlocker = tireNp.find('**/tireblockermesh')
            if not tireBlocker.isEmpty():
                tireBlocker.hide()
        if avId == self.localAvId:
            tireNp = self.tireDict[avId]['tireNodePath']
            self.treasureSphereName = 'treasureCollider'
            self.treasureCollSphere = CollisionSphere(
                0, 0, 0, IceGameGlobals.TireRadius)
            self.treasureCollSphere.setTangible(0)
            self.treasureCollNode = CollisionNode(self.treasureSphereName)
            self.treasureCollNode.setFromCollideMask(
                ToontownGlobals.PieBitmask)
            self.treasureCollNode.addSolid(self.treasureCollSphere)
            self.treasureCollNodePath = tireNp.attachNewNode(
                self.treasureCollNode)
            self.treasureHandler = CollisionHandlerEvent()
            self.treasureHandler.addInPattern('%fn-intoTreasure')
            base.cTrav.addCollider(self.treasureCollNodePath,
                                   self.treasureHandler)
            eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName()
            self.notify.debug('eventName = %s' % eventName)
            self.accept(eventName, self.toonHitSomething)

    def setupForceArrow(self, avId):
        arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow')
        priority = 0
        if avId < 0:
            priority = -avId
        else:
            priority = self.avIdList.index(avId)
            if avId == self.localAvId:
                priority = 10
        self.forceArrowDict[avId] = arrow

    def hideForceArrows(self):
        for forceArrow in self.forceArrowDict.values():
            forceArrow.hide()

    def showForceArrows(self, realPlayersOnly=True):
        for avId in self.forceArrowDict:
            if realPlayersOnly:
                if avId > 0:
                    self.forceArrowDict[avId].show()
                else:
                    self.forceArrowDict[avId].hide()
            else:
                self.forceArrowDict[avId].show()

    def localForceArrow(self):
        if self.localAvId in self.forceArrowDict:
            return self.forceArrowDict[self.localAvId]
        else:
            return None
            return None

    def setChoices(self, input0, input1, input2, input3):
        pass

    def startDebugTask(self):
        taskMgr.add(self.debugTask, self.debugTaskName)

    def stopDebugTask(self):
        taskMgr.remove(self.debugTaskName)

    def debugTask(self, task):
        if self.canDrive and self.tireDict.has_key(localAvatar.doId):
            dt = globalClock.getDt()
            forceMove = 25000
            forceMoveDt = forceMove
            tireBody = self.tireDict[localAvatar.doId]['tireBody']
            if self.arrowKeys.upPressed() and not tireBody.isEnabled():
                x = 0
                y = 1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.downPressed() and not tireBody.isEnabled():
                x = 0
                y = -1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.leftPressed() and not tireBody.isEnabled():
                x = -1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.rightPressed() and not tireBody.isEnabled():
                x = 1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
        return task.cont

    def __upArrowPressed(self):
        pass

    def __downArrowPressed(self):
        pass

    def __leftArrowPressed(self):
        pass

    def __rightArrowPressed(self):
        pass

    def __controlPressed(self):
        if self.gameFSM.getCurrentState().getName() == 'inputChoice':
            self.sendForceArrowUpdateAsap = True
            self.updateLocalForceArrow()
            self.controlKeyPressed = True
            self.sendUpdate('setAvatarChoice',
                            [self.curForce, self.curHeading])
            self.gameFSM.request('waitServerChoices')

    def startTimer(self):
        now = globalClock.getFrameTime()
        elapsed = now - self.timerStartTime
        self.timer.posInTopRightCorner()
        self.timer.setTime(IceGameGlobals.InputTimeout)
        self.timer.countdown(IceGameGlobals.InputTimeout - elapsed,
                             self.handleChoiceTimeout)
        self.timer.show()

    def setTimerStartTime(self, timestamp):
        if not self.hasLocalToon:
            return
        else:
            self.timerStartTime = globalClockDelta.networkToLocalTime(
                timestamp)
            if self.timer != None:
                self.startTimer()
            return

    def handleChoiceTimeout(self):
        self.sendUpdate('setAvatarChoice', [0, 0])
        self.gameFSM.request('waitServerChoices')

    def localTireNp(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireNodePath']
        return ret

    def localTireBody(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireBody']
        return ret

    def getTireBody(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireBody']
        return ret

    def getTireNp(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireNodePath']
        return ret

    def updateForceArrow(self, avId, curHeading, curForce):
        forceArrow = self.forceArrowDict[avId]
        tireNp = self.tireDict[avId]['tireNodePath']
        tireNp.setH(curHeading)
        tireBody = self.tireDict[avId]['tireBody']
        tireBody.setQuaternion(tireNp.getQuat())
        self.notify.debug('curHeading = %s' % curHeading)
        yScale = curForce / 100.0
        yScale *= 1
        headY = yScale * 15
        xScale = (yScale - 1) / 2.0 + 1.0
        shaft = forceArrow.find('**/arrow_shaft')
        head = forceArrow.find('**/arrow_head')
        shaft.setScale(xScale, yScale, 1)
        head.setPos(0, headY, 0)
        head.setScale(xScale, xScale, 1)

    def updateLocalForceArrow(self):
        avId = self.localAvId
        self.b_setForceArrowInfo(avId, self.curHeading, self.curForce)

    def __aimTask(self, task):
        if not hasattr(self, 'arrowKeys'):
            return task.done
        dt = globalClock.getDt()
        headingMomentumChange = dt * 60.0
        forceMomentumChange = dt * 160.0
        arrowUpdate = False
        arrowRotating = False
        arrowUp = False
        arrowDown = False
        if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce += self.forceMomentum * dt
            arrowUpdate = True
            if oldForce < self.MaxLocalForce:
                arrowUp = True
        elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce -= self.forceMomentum * dt
            arrowUpdate = True
            if oldForce > 0.01:
                arrowDown = True
        else:
            self.forceMomentum = 0
        if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading += self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        elif self.arrowKeys.rightPressed(
        ) and not self.arrowKeys.leftPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading -= self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        else:
            self.headingMomentum = 0
        if arrowUpdate:
            self.normalizeHeadingAndForce()
            self.updateLocalForceArrow()
        if arrowRotating:
            if not self.arrowRotateSound.status(
            ) == self.arrowRotateSound.PLAYING:
                base.playSfx(self.arrowRotateSound, looping=True)
        else:
            self.arrowRotateSound.stop()
        if arrowUp:
            if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING:
                base.playSfx(self.arrowUpSound, looping=False)
        else:
            self.arrowUpSound.stop()
        if arrowDown:
            if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING:
                base.playSfx(self.arrowDownSound, looping=False)
        else:
            self.arrowDownSound.stop()
        return task.cont

    def normalizeHeadingAndForce(self):
        if self.curForce > self.MaxLocalForce:
            self.curForce = self.MaxLocalForce
        if self.curForce < 0.01:
            self.curForce = 0.01

    def setTireInputs(self, tireInputs):
        if not self.hasLocalToon:
            return
        self.allTireInputs = tireInputs
        self.gameFSM.request('moveTires')

    def enableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].enable()

    def disableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].disable()

    def areAllTiresDisabled(self):
        for avId in self.tireDict.keys():
            if self.tireDict[avId]['tireBody'].isEnabled():
                return False

        return True

    def __moveTiresTask(self, task):
        if self.areAllTiresDisabled():
            self.sendTirePositions()
            self.gameFSM.request('synch')
            return task.done
        return task.cont

    def sendTirePositions(self):
        tirePositions = []
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        self.sendUpdate('endingPositions', [tirePositions])

    def setFinalPositions(self, finalPos):
        if not self.hasLocalToon:
            return
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

    def updateInfoLabel(self):
        self.infoLabel['text'] = TTLocalizer.IceGameInfo % {
            'curMatch': self.curMatch + 1,
            'numMatch': IceGameGlobals.NumMatches,
            'curRound': self.curRound + 1,
            'numRound': IceGameGlobals.NumRounds
        }

    def setMatchAndRound(self, match, round):
        if not self.hasLocalToon:
            return
        self.curMatch = match
        self.curRound = round
        self.updateInfoLabel()

    def setScores(self, match, round, scores):
        if not self.hasLocalToon:
            return
        self.newMatch = match
        self.newRound = round
        self.newScores = scores

    def setNewState(self, state):
        if not self.hasLocalToon:
            return
        self.notify.debug('setNewState gameFSM=%s newState=%s' %
                          (self.gameFSM, state))
        self.gameFSM.request(state)

    def putAllTiresInStartingPositions(self):
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

    def b_setForceArrowInfo(self, avId, force, heading):
        self.setForceArrowInfo(avId, force, heading)
        self.d_setForceArrowInfo(avId, force, heading)

    def d_setForceArrowInfo(self, avId, force, heading):
        sendIt = False
        curTime = self.getCurrentGameTime()
        if self.sendForceArrowUpdateAsap:
            sendIt = True
        elif curTime - self.lastForceArrowUpdateTime > 0.2:
            sendIt = True
        if sendIt:
            self.sendUpdate('setForceArrowInfo', [avId, force, heading])
            self.sendForceArrowUpdateAsap = False
            self.lastForceArrowUpdateTime = self.getCurrentGameTime()

    def setForceArrowInfo(self, avId, force, heading):
        if not self.hasLocalToon:
            return
        self.updateForceArrow(avId, force, heading)

    def setupStartOfMatch(self):
        self.putAllTiresInStartingPositions()
        szId = self.getSafezoneId()
        self.numTreasures = IceGameGlobals.NumTreasures[szId]
        if self.treasures:
            for treasure in self.treasures:
                treasure.destroy()

            self.treasures = []
        index = 0
        treasureMargin = IceGameGlobals.TireRadius + 1.0
        while len(self.treasures) < self.numTreasures:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5,
                                               IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5,
                                               IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newTreasure = IceTreasure.IceTreasure(self.treasureModel,
                                                  pos,
                                                  index,
                                                  self.doId,
                                                  penalty=False)
            goodSpot = True
            for obstacle in self.obstacles:
                if newTreasure.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newTreasure.nodePath.getDistance(
                            treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.treasures.append(newTreasure)
                index += 1
            else:
                newTreasure.destroy()

        self.numPenalties = IceGameGlobals.NumPenalties[szId]
        if self.penalties:
            for penalty in self.penalties:
                penalty.destroy()

            self.penalties = []
        index = 0
        while len(self.penalties) < self.numPenalties:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5,
                                               IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5,
                                               IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newPenalty = IceTreasure.IceTreasure(self.penaltyModel,
                                                 pos,
                                                 index,
                                                 self.doId,
                                                 penalty=True)
            goodSpot = True
            for obstacle in self.obstacles:
                if newPenalty.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newPenalty.nodePath.getDistance(
                            treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                for penalty in self.penalties:
                    if newPenalty.nodePath.getDistance(
                            penalty.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.penalties.append(newPenalty)
                index += 1
            else:
                newPenalty.destroy()

    def toonHitSomething(self, entry):
        self.notify.debug('---- treasure Enter ---- ')
        self.notify.debug('%s' % entry)
        name = entry.getIntoNodePath().getName()
        parts = name.split('-')
        if len(parts) < 3:
            self.notify.debug('collided with %s, but returning' % name)
            return
        if not int(parts[1]) == self.doId:
            self.notify.debug("collided with %s, but doId doesn't match" %
                              name)
            return
        treasureNum = int(parts[2])
        if 'penalty' in parts[0]:
            self.__penaltyGrabbed(treasureNum)
        else:
            self.__treasureGrabbed(treasureNum)

    def __treasureGrabbed(self, treasureNum):
        self.treasures[treasureNum].showGrab()
        self.treasureGrabSound.play()
        self.sendUpdate('claimTreasure', [treasureNum])

    def setTreasureGrabbed(self, avId, treasureNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId))
        if avId != self.localAvId:
            self.treasures[treasureNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] += 1
        self.scorePanels[i].setScore(self.scores[i])

    def __penaltyGrabbed(self, penaltyNum):
        self.penalties[penaltyNum].showGrab()
        self.sendUpdate('claimPenalty', [penaltyNum])

    def setPenaltyGrabbed(self, avId, penaltyNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId))
        if avId != self.localAvId:
            self.penalties[penaltyNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] -= 1
        self.scorePanels[i].setScore(self.scores[i])

    def postStep(self):
        DistributedIceWorld.DistributedIceWorld.postStep(self)
        if self.colCount:
            for count in range(self.colCount):
                c0, c1 = self.getOrderedContacts(count)
                if c1 in self.tireCollideIds:
                    tireIndex = self.tireCollideIds.index(c1)
                    if c0 in self.tireCollideIds:
                        self.tireSounds[tireIndex]['tireHit'].play()
                    elif c0 == self.wallCollideId:
                        self.tireSounds[tireIndex]['wallHit'].play()
                    elif c0 == self.obstacleCollideId:
                        self.tireSounds[tireIndex]['obstacleHit'].play()

    def forceLocalToonToTire(self):
        toon = localAvatar
        if toon and self.localAvId in self.tireDict:
            tireNp = self.tireDict[self.localAvId]['tireNodePath']
            toon.reparentTo(tireNp)
            toon.setPosHpr(0, 0, 0, 0, 0, 0)
            toon.setY(1.0)
            toon.setZ(-3)
Esempio n. 8
0
class SimpleInteractive(DirectObject):
    
    def __init__(self, object, name, proximityText):
        DirectObject.__init__(self)
        self.object = object
        self.proximityText = proximityText
        self.proximityEvent = name
        self.enterProximityEvent = 'enter' + name
        self.exitProximityEvent = 'exit' + name
        self.useLabel = None
        self.fader = None
        self.size = 6
        self.disk = None
        proximitySphere = CollisionSphere(0, 0, 0, self.size)
        proximitySphere.setTangible(0)
        proximityNode = CollisionNode(self.proximityEvent)
        proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
        proximityNode.addSolid(proximitySphere)
        self.proximityNodePath = self.object.attachNewNode(proximityNode)
        self.accept(self.enterProximityEvent, self.approach)
        self.accept(self.exitProximityEvent, self.leave)

    
    def createInteractionDisk(self):
        self.disk = loader.loadModel('models/effects/selectionCursor')
        self.disk.setScale(self.size)
        self.disk.setColorScale(0, 1, 0, 1)
        self.disk.setP(-90)
        self.disk.setZ(0.025000000000000001)
        self.disk.setBillboardAxis(6)
        self.disk.reparentTo(self.object)
        self.disk.setBin('shadow', 0)
        self.disk.setTransparency(TransparencyAttrib.MAlpha)
        self.disk.setDepthWrite(0)
        self.disk.setDepthTest(0)

    
    def loadUseLabel(self, text):
        self.useLabel = DirectLabel(parent = aspect2d, frameColor = (0.10000000000000001, 0.10000000000000001, 0.25, 0.20000000000000001), text = text, text_align = TextNode.ACenter, text_scale = 0.059999999999999998, text_pos = (0.02, 0.02), text_fg = (1, 1, 1, 1), text_shadow = (0, 0, 0, 1), textMayChange = 1, text_font = PiratesGlobals.getPirateOutlineFont())
        self.useLabel.setPos(0, 0, -0.69999999999999996)
        self.useLabel.setAlphaScale(0)
        self.useLabel.hide()

    
    def fadeInText(self):
        if self.fader:
            self.fader.pause()
        

    
    def interactionAllowed(self, avId):
        return True

    
    def approach(self, collEntry):
        if not self.interactionAllowed(localAvatar.doId):
            return None
        
        if not self.disk:
            self.createInteractionDisk()
        
        if self.proximityText:
            if not self.useLabel:
                self.loadUseLabel(self.proximityText)
            
            if self.fader:
                self.fader.pause()
            
            fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale, fromData = 0, toData = 1, duration = 0.5)
            self.fader = Sequence(Func(self.useLabel.show), fadeIn)
            self.fader.start()
        
        self.disk.show()
        self.accept(USE_KEY_EVENT, self.handleUseKey)

    
    def requestInteraction(self, avId):
        pass

    
    def handleUseKey(self):
        self.requestInteraction(localAvatar.doId)

    
    def leave(self, collEntry):
        if self.disk:
            self.disk.hide()
        
        if self.proximityText:
            if self.fader:
                self.fader.pause()
                self.fader = None
            
            if self.useLabel:
                self.useLabel.hide()
            
        
        self.ignore(USE_KEY_EVENT)
class GroupTrackerPage(ShtikerPage.ShtikerPage):
    notify = directNotify.newCategory('GroupTrackerPage')

    def __init__(self):
        ShtikerPage.ShtikerPage.__init__(self)
        self.groupWidgets = []
        self.playerWidgets = []
        self.images = []                # image nodes: Possible images to apply on groups
        self.scrollList = None          # DirectScrolledList: Holds the GroupTrackerGroup widgets
        self.scrollTitle = None         # DirectLabel: Title of the list that holds the groups
        self.playerList = None          # DirectScrolledList: Holds players when showing a specific group details
        self.playerListTitle = None     # DirectLabel: Title of the playerList
        self.groupInfoTitle = None      # DirectLabel: holds the group detail title to show on the right
        self.groupInfoDistrict = None   # DirectLabel: shows group detail district on the right
        self.statusMessage = None       # DirectLabel: Shows important messages like Loading... or "No boarding groups available"
        self.groupIcon = None           # DirectButton: Icon to associate with the group ex. sellbot icon or cashbot icon depending on group info
        self.wantGroupToggle = None     # DirectButton: Allows the toon to toggle his listing

    def load(self):
        self.listXorigin = -0.02
        self.listFrameSizeX = 0.67
        self.listZorigin = -0.96
        self.listFrameSizeZ = 1.04
        self.arrowButtonScale = 1.3
        self.itemFrameXorigin = -0.237
        self.itemFrameZorigin = 0.365
        self.buttonXstart = self.itemFrameXorigin + 0.293
        self.gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui')
        guiButton = loader.loadModel('phase_3/models/gui/quit_button')
        self.scrollList = DirectScrolledList(parent=self, 
                                            relief=None, 
                                            pos=(-0.5, 0, 0), 
                                            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            incButton_relief=None, 
                                            incButton_scale=(self.arrowButtonScale, self.arrowButtonScale, -self.arrowButtonScale), 
                                            incButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin - 0.999), 
                                            incButton_image3_color=Vec4(1, 1, 1, 0.2), 
                                            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'), 
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            decButton_relief=None, 
                                            decButton_scale=(self.arrowButtonScale, self.arrowButtonScale, self.arrowButtonScale), 
                                            decButton_pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.227), 
                                            decButton_image3_color=Vec4(1, 1, 1, 0.2), 
                                            itemFrame_pos=(self.itemFrameXorigin, 0, self.itemFrameZorigin), 
                                            itemFrame_scale=1.0,
                                            itemFrame_relief=DGG.SUNKEN, 
                                            itemFrame_frameSize=(self.listXorigin, self.listXorigin + self.listFrameSizeX,
                                                                 self.listZorigin, self.listZorigin + self.listFrameSizeZ
                                                                 ), 
                                            itemFrame_frameColor=(0.85, 0.95, 1, 1), 
                                            itemFrame_borderWidth=(0.01, 0.01), 
                                            numItemsVisible=15, 
                                            forceHeight=0.065, 
                                            items=self.groupWidgets
                                            )
                                            
        self.scrollTitle = DirectFrame(parent=self.scrollList, 
                                       text=TTLocalizer.GroupTrackerListTitle, 
                                       text_scale=0.06, 
                                       text_align=TextNode.ACenter, 
                                       relief=None,
                                       pos=(self.buttonXstart, 0, self.itemFrameZorigin + 0.127)
                                       )
        
        self.playerList = DirectScrolledList(parent=self, 
                                            relief=None, 
                                            pos=(0.45, 0, 0.1), 
                                            
                                            incButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'),
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            incButton_relief=None, 
                                            incButton_scale=(1.0, 1.0, -1.0), 
                                            incButton_pos=(0, 0, -0.28), 
                                            incButton_image3_color=Vec4(1, 1, 1, 0.05),
                                            
                                            decButton_image=(self.gui.find('**/FndsLst_ScrollUp'), 
                                                             self.gui.find('**/FndsLst_ScrollDN'),
                                                             self.gui.find('**/FndsLst_ScrollUp_Rllvr'), 
                                                             self.gui.find('**/FndsLst_ScrollUp')
                                                             ), 
                                            decButton_relief=None, 
                                            decButton_scale=(1.0, 1.0, 1.0),
                                            decButton_pos=(0.0, 0, 0.04), 
                                            decButton_image3_color=Vec4(1, 1, 1, 0.25), 
                                            
                                            itemFrame_pos=(0, 0, -0.05), 
                                            itemFrame_scale=1.0,
                                            itemFrame_relief=DGG.SUNKEN, 
                                            itemFrame_frameSize=(-0.3, 0.3,  #x
                                                                 -0.2, 0.06),  #z
                                            itemFrame_frameColor=(0.85, 0.95, 1, 1), 
                                            itemFrame_borderWidth=(0.01, 0.01), 
                                            numItemsVisible=4,
                                            forceHeight=0.05, 
                                            items=self.playerWidgets
                                            )
                                            
        self.playerListTitle = DirectFrame(parent=self.playerList, 
                                       text='', 
                                       text_scale=0.05, 
                                       text_align=TextNode.ACenter, 
                                       relief=None,
                                       pos=(0, 0, 0.08)
                                       )
        self.groupInfoTitle = DirectLabel(parent=self, text='', 
                                          text_scale=0.080, text_align=TextNode.ACenter,
                                          text_wordwrap=15, relief=None, pos=(0.45, 0, 0.5))
        self.groupInfoDistrict = DirectLabel(parent=self,
                                     text='',
                                     text_scale=0.050,
                                     text_align=TextNode.ACenter, 
                                     text_wordwrap=15, 
                                     relief=None, 
                                     pos=(0.45, 0, 0.4)
                                     )
        
        self.statusMessage = DirectLabel(parent=self, text='', text_scale=0.060, text_align=TextNode.ACenter, text_wordwrap=5, relief=None, pos=(0.45,0,0.1))
                                     
        # Group Image:
        self.groupIcon = DirectButton(parent=self, relief=None, state=DGG.DISABLED, image=None, image_scale=(0.35, 1, 0.35), image_color=Vec4(1.0, 1.0, 1.0, 0.75), pos=(0.45, 10, -0.45), command=self.doNothing)
        
        # Group Toggle:
        self.wantGroupToggle = DirectButton(parent=self, relief=None, image=(guiButton.find('**/QuitBtn_UP'), guiButton.find('**/QuitBtn_DN'), guiButton.find('**/QuitBtn_RLVR')), image_scale=(0.7, 1, 1), text='', text_scale=0.052, text_pos=(0, -0.02), pos=(0.2, 0, -0.65), command=self.toggleWantGroup)
        self.updateWantGroupButton()
        
        
        # Loading possible group icons
        suitIcons = loader.loadModel('phase_3/models/gui/cog_icons')     
        bossbotIcon = suitIcons.find('**/CorpIcon')
        bossbotIcon.setColor(SUIT_ICON_COLORS[0])
        self.images.append(bossbotIcon)
        
        lawbotIcon = suitIcons.find('**/LegalIcon')
        lawbotIcon.setColor(SUIT_ICON_COLORS[1])
        self.images.append(lawbotIcon)
        
        cashbotIcon = suitIcons.find('**/MoneyIcon')
        cashbotIcon.setColor(SUIT_ICON_COLORS[2])
        self.images.append(cashbotIcon)
        
        sellbotIcon = suitIcons.find('**/SalesIcon')
        sellbotIcon.setColor(SUIT_ICON_COLORS[3])
        self.images.append(sellbotIcon)
        
        # Clean up
        self.clearGroupInfo()
        self.statusMessage.hide()
        
        suitIcons.removeNode()
        self.gui.removeNode()
        guiButton.removeNode()

        self.accept('GroupTrackerResponse', self.updatePage)

    def unload(self):
        self.scrollList.destroy()
        self.groupInfoDistrict.destroy()
        self.playerList.destroy()
        self.groupInfoTitle.destroy()
        self.groupIcon.destroy()
        self.wantGroupToggle.destroy()
        for widget in self.playerWidgets:
            widget.destroy()
        for widget in self.groupWidgets:
            widget.destroy()
        self.playerWidgets = []
        
        del self.scrollList
        del self.groupInfoDistrict
        del self.playerList
        del self.groupInfoTitle
        del self.groupIcon
        del self.wantGroupToggle
        ShtikerPage.ShtikerPage.unload(self)

    def enter(self):
        ShtikerPage.ShtikerPage.enter(self)
        self.setGroups([]) # CLEAR IT ALL
        self.setPlayers()  # CLEAR IT ALL
        if(self.scrollList['items'] == []):
            self.statusMessage['text'] = TTLocalizer.GroupTrackerLoading
            self.statusMessage.show()
        base.cr.globalGroupTracker.requestGroups()
        taskMgr.doMethodLater(3, self.displayNoGroupsTaskHandler, self.uniqueName('timeout'))

    def displayNoGroups(self):
        self.statusMessage['text'] = TTLocalizer.GroupTrackerEmpty
        self.statusMessage.show()
        self.clearGroupInfo()
    
    def displayNoGroupsTaskHandler(self, task):
        self.displayNoGroups()
        return task.done

    def updatePage(self):
        taskMgr.remove(self.uniqueName('timeout'))
        groups = base.cr.globalGroupTracker.getGroupInfo()
        self.setGroups(groups)
        
    def exit(self):
        self.clearGroupInfo()
        ShtikerPage.ShtikerPage.exit(self)
        base.cr.globalGroupTracker.doneRequesting()
    
    def updateGroupInfoEventHandle(self, groupWidget, mouseEvent):
        self.updateGroupInfo(groupWidget)
        
    def updateGroupInfo(self, groupWidget):
        ''' Updates the Right Page of the Group Tracker Page with new Info '''
        self.statusMessage.hide()

        # Update the Player List
        self.setPlayers(groupWidget)
        self.playerList.show()

        # Update the Player List Title
        self.playerListTitle['text'] = ('Players ' + str(groupWidget.getCurrentPlayers()) + '/' + str(groupWidget.getMaxPlayers()) + ':')
        self.playerListTitle.show()

        # Update the District
        self.groupInfoDistrict['text'] = TTLocalizer.BoardingGroupDistrictInformation % { 'district' : groupWidget.getDistrict() }
        self.groupInfoDistrict.show()

        # Update the Title
        self.groupInfoTitle['text'] = groupWidget.getTitle()
        self.groupInfoTitle.show()

        # Update the Image
        self.groupIcon['image'] = self.images[GroupTrackerGlobals.CATEGORY_TO_IMAGE_ID[groupWidget.getCategory()]]
        self.groupIcon['image_scale'] = (0.35, 1, 0.35)
        self.groupIcon.show()

    def clearGroupInfo(self):
        self.playerList.hide()
        self.playerListTitle.hide()
        self.groupInfoDistrict.hide()
        self.groupInfoTitle.hide()
        self.groupIcon.hide()

    def setPlayers(self, groupWidget=None):
        ''' Calls updatePlayerList '''

        # Clear the Widgets that were held in the listings
        for playerWidget in self.playerWidgets:
            playerWidget.destroy()
        self.playerWidgets = []

        # Make a player widget for each player
        # TODO: Edit this stuff when avIds come from players
        if groupWidget:
            leaderId = groupWidget.getLeaderId()
            playerNames = groupWidget.getMemberNames()
            playerIds = groupWidget.getMemberIds()
            for playerName in playerNames:
                playerId = playerIds[playerNames.index(playerName)]
                isLeader = playerId == leaderId
                self.playerWidgets.append(GroupTrackerPlayer(parent=self, avId=playerId, name=playerName, isLeader=isLeader))

        self.updatePlayerList()

    def reconsiderGroupInfo(self, groupWidget):
        ''' If someone is viewing this info and it was updated, we also want to update the info being viewed '''
        if self.playerWidgets is None or self.playerList['items'] == []:
            return # No Info is being viewed at the moment since you cant have an empty group
        
        # We have to update if this group's leader is the leader in the playerlist being viewed right now
        leaderId = groupWidget.getLeaderId()
        
        # Check all the players in the playerList being viewed for the same leader
        for playerWidget in self.playerWidgets:
            if playerWidget.getLeader():
                if leaderId == playerWidget.getId():
                    self.updateGroupInfo(groupWidget)
                    return False
        
        return True
                
    def setGroups(self, groups):
        ''' Calls updateGroupList '''
        
        # Clear our Group Widgets
        for group in self.groupWidgets:
            group.destroy()
        self.groupWidgets = []
        
        wantReconsiderInfo = True
    
        # Create a new group widget for each group
        for group in groups:
            if not group[GroupTrackerGlobals.SHOW] or len(group[GroupTrackerGlobals.MEMBER_IDS]) == 0:
                continue # We are using this to see if this group is dead or if someone doesnt want it up
            leaderId = 0
            for i, g in base.cr.globalGroupTracker.leader2Group.items():
                if g == group:
                    leaderId = i
            if not leaderId:
                continue
                
            leaderName = group[GroupTrackerGlobals.LEADER_NAME]
            shardName = group[GroupTrackerGlobals.SHARD_NAME]
            category = group[GroupTrackerGlobals.CATEGORY]
            memberIds = group[GroupTrackerGlobals.MEMBER_IDS]
            memberNames = group[GroupTrackerGlobals.MEMBER_NAMES]
            
            groupWidget = GroupTrackerGroup(parent=self, leaderId=leaderId, leaderName=leaderName, shardName=shardName, category=category, memberIds=memberIds, memberNames=memberNames)
            groupWidget.bind(DGG.WITHIN, self.updateGroupInfoEventHandle, extraArgs=[groupWidget])
            self.groupWidgets.append(groupWidget)
            if wantReconsiderInfo:
                wantReconsiderInfo = self.reconsiderGroupInfo(groupWidget)
        
        # Edge case where a group that was removed, info might remain on the screen if it didn't exist any more
        if wantReconsiderInfo:
            self.clearGroupInfo()
        
        # There are no groups, hide the information
        if len(self.groupWidgets) == 0:
            self.displayNoGroups()
        self.updateGroupList()

    def updateGroupList(self): 
        self.statusMessage.hide()
        if self.scrollList is None:
            return
            
        # Clear the Group Listing
        for item in self.scrollList['items']:
            if item:
                self.scrollList.removeItem(item, refresh=True)
        self.scrollList['items'] = []
        
        # Re-populate the Group Listing
        for groupWidget in self.groupWidgets:
            self.scrollList.addItem(groupWidget, refresh=True)
        
        if len(self.groupWidgets) == 0:
            self.displayNoGroups()

    def updatePlayerList(self):
        if self.playerList is None:
            return

        # Clear the Player Listing
        for item in self.playerList['items']:
            if item:
                self.playerList.removeItem(item)
        self.playerList['items'] = []

        # Re-Populate the List
        for playerWidget in self.playerWidgets:
            self.playerList.addItem(playerWidget)

    def toggleWantGroup(self):
        if settings.get('grouptracker', False):
            settings['grouptracker'] = False
            base.cr.globalGroupTracker.showMe(False)
        else:
            settings['grouptracker'] = True
            base.cr.globalGroupTracker.showMe(True)
            
        base.localAvatar.wantGroupTracker()
        
        base.localAvatar.wantGroupTracker() # Updates the ai toon so the boarding group AI could know what he wants
        self.updateWantGroupButton()
    
    def updateWantGroupButton(self):
        if settings.get('grouptracker', False):
            self.wantGroupToggle['text'] = 'Hide Me'
        else:
            self.wantGroupToggle['text'] = 'Show Me'
            
    def doNothing(self):
        pass
Esempio n. 10
0
class IsisAgent(kinematicCharacterController, DirectObject):
    @classmethod
    def setPhysics(cls, physics):
        """ This method is set in src.loader when the generators are loaded
        into the namespace.  This frees the environment definitions (in 
        scenario files) from having to pass around the physics parameter 
        that is required for all IsisObjects """
        cls.physics = physics

    def __init__(self, name, queueSize=100):

        # load the model and the different animations for the model into an Actor object.
        self.actor = Actor("media/models/boxman", {
            "walk": "media/models/boxman-walk",
            "idle": "media/models/boxman-idle"
        })
        self.actor.setScale(1.0)
        self.actor.setH(0)
        #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params
        self.actor.setColorScale(random.random(), random.random(),
                                 random.random(), 1.0)
        self.actorNodePath = NodePath('agent-%s' % name)
        self.activeModel = self.actorNodePath

        self.actorNodePath.reparentTo(render)

        self.actor.reparentTo(self.actorNodePath)
        self.name = name
        self.isMoving = False

        # initialize ODE controller
        kinematicCharacterController.__init__(self, IsisAgent.physics,
                                              self.actorNodePath)
        self.setGeomPos(self.actorNodePath.getPos(render))
        """
        Additional Direct Object that I use for convenience.
        """
        self.specialDirectObject = DirectObject()
        """
        How high above the center of the capsule you want the camera to be
        when walking and when crouching. It's related to the values in KCC.
        """
        self.walkCamH = 0.7
        self.crouchCamH = 0.2
        self.camH = self.walkCamH
        """
        This tells the Player Controller what we're aiming at.
        """
        self.aimed = None

        self.isSitting = False
        self.isDisabled = False
        """
        The special direct object is used for trigger messages and the like.
        """
        #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True])
        #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False])

        self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"])

        # Expose agent's right hand joint to attach objects to
        self.player_right_hand = self.actor.exposeJoint(
            None, 'modelRoot', 'Hand.R')
        self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot',
                                                       'Hand.L')

        self.right_hand_holding_object = None
        self.left_hand_holding_object = None

        # don't change the color of things you pick up
        self.player_right_hand.setColorScaleOff()
        self.player_left_hand.setColorScaleOff()

        self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head')
        self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head')

        self.controlMap = {
            "turn_left": 0,
            "turn_right": 0,
            "move_forward": 0,
            "move_backward": 0,
            "move_right": 0,
            "move_left": 0,
            "look_up": 0,
            "look_down": 0,
            "look_left": 0,
            "look_right": 0,
            "jump": 0
        }
        # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left]
        # turns are in degrees per second, moves are in units per second
        self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60]

        self.originalPos = self.actor.getPos()

        bubble = loader.loadTexture("media/textures/thought_bubble.png")
        #bubble.setTransparency(TransparencyAttrib.MAlpha)

        self.speech_bubble = DirectLabel(parent=self.actor,
                                         text="",
                                         text_wordwrap=10,
                                         pad=(3, 3),
                                         relief=None,
                                         text_scale=(.3, .3),
                                         pos=(0, 0, 3.6),
                                         frameColor=(.6, .2, .1, .5),
                                         textMayChange=1,
                                         text_frame=(0, 0, 0, 1),
                                         text_bg=(1, 1, 1, 1))
        #self.myImage=
        self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.speech_bubble.setColorScaleOff()
        self.speech_bubble.component('text0').textNode.setCardDecal(1)
        self.speech_bubble.setBillboardAxis()
        # hide the speech bubble from IsisAgent's own camera
        self.speech_bubble.hide(BitMask32.bit(1))

        self.thought_bubble = DirectLabel(parent=self.actor,
                                          text="",
                                          text_wordwrap=9,
                                          text_frame=(1, 0, -2, 1),
                                          text_pos=(0, .5),
                                          text_bg=(1, 1, 1, 0),
                                          relief=None,
                                          frameSize=(0, 1.5, -2, 3),
                                          text_scale=(.18, .18),
                                          pos=(0, 0.2, 3.6),
                                          textMayChange=1,
                                          image=bubble,
                                          image_pos=(0, 0.1, 0),
                                          sortOrder=5)
        self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.thought_bubble.setColorScaleOff()
        self.thought_bubble.component('text0').textNode.setFrameColor(
            1, 1, 1, 0)
        self.thought_bubble.component('text0').textNode.setFrameAsMargin(
            0.1, 0.1, 0.1, 0.1)
        self.thought_bubble.component('text0').textNode.setCardDecal(1)
        self.thought_bubble.setBillboardAxis()
        # hide the thought bubble from IsisAgent's own camera
        self.thought_bubble.hide(BitMask32.bit(1))
        # disable by default
        self.thought_bubble.hide()
        self.thought_filter = {}  # only show thoughts whose values are in here
        self.last_spoke = 0  # timers to keep track of last thought/speech and
        self.last_thought = 0  # hide visualizations

        # put a camera on ralph
        self.fov = NodePath(Camera('RaphViz'))
        self.fov.node().setCameraMask(BitMask32.bit(1))

        # position the camera to be infront of Boxman's face.
        self.fov.reparentTo(self.player_head)
        # x,y,z are not in standard orientation when parented to player-Head
        self.fov.setPos(0, 0.2, 0)
        # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face.
        self.fov.setHpr(0, -90, 0)

        lens = self.fov.node().getLens()
        lens.setFov(60)  #  degree field of view (expanded from 40)
        lens.setNear(0.2)
        #self.fov.node().showFrustum() # displays a box around his head
        #self.fov.place()

        self.prevtime = 0
        self.current_frame_count = 0

        self.isSitting = False
        self.isDisabled = False
        self.msg = None
        self.actorNodePath.setPythonTag("agent", self)

        # Initialize the action queue, with a maximum length of queueSize
        self.queue = []
        self.queueSize = queueSize
        self.lastSense = 0

    def setLayout(self, layout):
        """ Dummy method called by spatial methods for use with objects. 
        Doesn't make sense for an agent that can move around."""
        pass

    def setPos(self, pos):
        """ Wrapper to set the position of the ODE geometry, which in turn 
        sets the visual model's geometry the next time the update() method
        is called. """
        self.setGeomPos(pos)

    def setPosition(self, pos):
        self.setPos(pos)

    def reparentTo(self, parent):
        self.actorNodePath.reparentTo(parent)

    def setControl(self, control, value):
        """Set the state of one of the character's movement controls.  """
        self.controlMap[control] = value

    def get_objects_in_field_of_vision(self, exclude=['isisobject']):
        """ This works in an x-ray style. Fast. Works best if you listen to
        http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while
        you use it.
        
        needs to exclude isisobjects since they cannot be serialized  
        """
        objects = {}
        for obj in base.render.findAllMatches("**/IsisObject*"):
            if not obj.hasPythonTag("isisobj"):
                continue
            o = obj.getPythonTag("isisobj")
            bounds = o.activeModel.getBounds()
            bounds.xform(o.activeModel.getMat(self.fov))
            if self.fov.node().isInView(o.activeModel.getPos(self.fov)):
                pos = o.activeModel.getPos(render)
                pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2)
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d,
                                               Point3(p2[0], 0, p2[1]))
                object_dict = {}
                if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0]
                if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2]
                if 'distance' not in exclude:
                    object_dict['distance'] = o.activeModel.getDistance(
                        self.fov)
                if 'orientation' not in exclude:
                    object_dict['orientation'] = o.activeModel.getH(self.fov)
                if 'actions' not in exclude:
                    object_dict['actions'] = o.list_actions()
                if 'isisobject' not in exclude: object_dict['isisobject'] = o
                # add item to dinctionary
                objects[o] = object_dict
        return objects

    def get_agents_in_field_of_vision(self):
        """ This works in an x-ray vision style as well"""
        agents = {}
        for agent in base.render.findAllMatches("**/agent-*"):
            if not agent.hasPythonTag("agent"):
                continue
            a = agent.getPythonTag("agent")
            bounds = a.actorNodePath.getBounds()
            bounds.xform(a.actorNodePath.getMat(self.fov))
            pos = a.actorNodePath.getPos(self.fov)
            if self.fov.node().isInView(pos):
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d,
                                               Point3(p2[0], 0, p2[1]))
                agentDict = {'x_pos': p3[0],\
                             'y_pos': p3[2],\
                             'distance':a.actorNodePath.getDistance(self.fov),\
                             'orientation': a.actorNodePath.getH(self.fov)}
                agents[a] = agentDict
        return agents

    def in_view(self, isisobj):
        """ Returns true iff a particular isisobject is in view """
        return len(
            filter(lambda x: x['isisobject'] == isisobj,
                   self.get_objects_in_field_of_vision(exclude=[]).values()))

    def get_objects_in_view(self):
        """ Gets objects through ray tracing.  Slow"""
        return self.picker.get_objects_in_view()

    def control__turn_left__start(self, speed=None):
        self.setControl("turn_left", 1)
        self.setControl("turn_right", 0)
        if speed:
            self.speeds[0] = speed
        return "success"

    def control__turn_left__stop(self):
        self.setControl("turn_left", 0)
        return "success"

    def control__turn_right__start(self, speed=None):
        self.setControl("turn_left", 0)
        self.setControl("turn_right", 1)
        if speed:
            self.speeds[1] = speed
        return "success"

    def control__turn_right__stop(self):
        self.setControl("turn_right", 0)
        return "success"

    def control__move_forward__start(self, speed=None):
        self.setControl("move_forward", 1)
        self.setControl("move_backward", 0)
        if speed:
            self.speeds[2] = speed
        return "success"

    def control__move_forward__stop(self):
        self.setControl("move_forward", 0)
        return "success"

    def control__move_backward__start(self, speed=None):
        self.setControl("move_forward", 0)
        self.setControl("move_backward", 1)
        if speed:
            self.speeds[3] = speed
        return "success"

    def control__move_backward__stop(self):
        self.setControl("move_backward", 0)
        return "success"

    def control__move_left__start(self, speed=None):
        self.setControl("move_left", 1)
        self.setControl("move_right", 0)
        if speed:
            self.speeds[4] = speed
        return "success"

    def control__move_left__stop(self):
        self.setControl("move_left", 0)
        return "success"

    def control__move_right__start(self, speed=None):
        self.setControl("move_right", 1)
        self.setControl("move_left", 0)
        if speed:
            self.speeds[5] = speed
        return "success"

    def control__move_right__stop(self):
        self.setControl("move_right", 0)
        return "success"

    def control__look_left__start(self, speed=None):
        self.setControl("look_left", 1)
        self.setControl("look_right", 0)
        if speed:
            self.speeds[9] = speed
        return "success"

    def control__look_left__stop(self):
        self.setControl("look_left", 0)
        return "success"

    def control__look_right__start(self, speed=None):
        self.setControl("look_right", 1)
        self.setControl("look_left", 0)
        if speed:
            self.speeds[8] = speed
        return "success"

    def control__look_right__stop(self):
        self.setControl("look_right", 0)
        return "success"

    def control__look_up__start(self, speed=None):
        self.setControl("look_up", 1)
        self.setControl("look_down", 0)
        if speed:
            self.speeds[6] = speed
        return "success"

    def control__look_up__stop(self):
        self.setControl("look_up", 0)
        return "success"

    def control__look_down__start(self, speed=None):
        self.setControl("look_down", 1)
        self.setControl("look_up", 0)
        if speed:
            self.speeds[7] = speed
        return "success"

    def control__look_down__stop(self):
        self.setControl("look_down", 0)
        return "success"

    def control__jump(self):
        self.setControl("jump", 1)
        return "success"

    def control__view_objects(self):
        """ calls a raytrace to to all objects in view """
        objects = self.get_objects_in_field_of_vision()
        self.control__say(
            "If I were wearing x-ray glasses, I could see %i items" %
            len(objects))
        print "Objects in view:", objects
        return objects

    def control__sense(self):
        """ perceives the world, returns percepts dict """
        percepts = dict()
        # eyes: visual matricies
        #percepts['vision'] = self.sense__get_vision()
        # objects in purview (cheating object recognition)
        percepts['objects'] = self.sense__get_objects()
        # global position in environment - our robots can have GPS :)
        percepts['position'] = self.sense__get_position()
        # language: get last utterances that were typed
        percepts['language'] = self.sense__get_utterances()
        # agents: returns a map of agents to a list of actions that have been sensed
        percepts['agents'] = self.sense__get_agents()
        print percepts
        return percepts

    def control__think(self, message, layer=0):
        """ Changes the contents of an agent's thought bubble"""
        # only say things that are checked in the controller
        if self.thought_filter.has_key(layer):
            self.thought_bubble.show()
            self.thought_bubble['text'] = message
            #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05)
            #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer])
            self.last_thought = 0
        return "success"

    def control__say(self, message="Hello!"):
        self.speech_bubble['text'] = message
        self.last_spoke = 0
        return "success"

    """

    Methods explicitly for IsisScenario files 

    """

    def put_in_front_of(self, isisobj):
        # find open direction
        pos = isisobj.getGeomPos()
        direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0))
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
            'aimRay', 5, [pos, direction], [isisobj.geom])
        print "CLOSEST", closestEntry, closestObject
        if closestObject == None:
            self.setPosition(pos + Vec3(0, 2, 0))
        else:
            print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (
                isisobj, closestObject)
            direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0))
            closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                'aimRay', 5, [pos, direction], [isisobj.geom])
            if closestEntry == None:
                self.setPosition(pos + Vec3(0, -2, 0))
            else:
                print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (
                    isisobj, closestObject)
                direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0))
                closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                    'aimRay', 5, [pos, direction], [isisobj.geom])
                if closestEntry == None:
                    self.setPosition(pos + Vec3(2, 0, 0))
                else:
                    print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (
                        isisobj, closestObject)
                    # there's only one option left, do it anyway
                    self.setPosition(pos + Vec3(-2, 0, 0))
        # rotate agent to look at it
        self.actorNodePath.setPos(self.getGeomPos())
        self.actorNodePath.lookAt(pos)
        self.setH(self.actorNodePath.getH())

    def put_in_right_hand(self, target):
        return self.pick_object_up_with(target, self.right_hand_holding_object,
                                        self.player_right_hand)

    def put_in_left_hand(self, target):
        return self.pick_object_up_with(target, self.left_hand_holding_object,
                                        self.player_left_hand)

    def __get_object_in_center_of_view(self):
        direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
        pos = self.fov.getPos(render)
        exclude = [
        ]  #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom]
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
            'aimRay', 5, [pos, direction], exclude)
        return closestObject

    def pick_object_up_with(self, target, hand_slot, hand_joint):
        """ Attaches an IsisObject, target, to the hand joint.  Does not check anything first,
        other than the fact that the hand joint is not currently holding something else."""
        if hand_slot != None:
            print 'already holding ' + hand_slot.getName() + '.'
            return None
        else:
            if target.layout:
                target.layout.remove(target)
                target.layout = None
            # store original position
            target.originalHpr = target.getHpr(render)
            target.disable()  #turn off physics
            if target.body: target.body.setGravityMode(0)
            target.reparentTo(hand_joint)
            target.setPosition(hand_joint.getPos(render))
            target.setTag('heldBy', self.name)
            if hand_joint == self.player_right_hand:
                self.right_hand_holding_object = target
            elif hand_joint == self.player_left_hand:
                self.left_hand_holding_object = target
            hand_slot = target
            return target

    def control__pick_up_with_right_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return "error: no target in reach"
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with right hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target,
                                            self.right_hand_holding_object,
                                            self.player_right_hand)
        else:
            print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).'
            return 'error: object not graspable'

    def control__pick_up_with_left_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with left hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target,
                                            self.left_hand_holding_object,
                                            self.player_left_hand)
        else:
            print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).'
            return 'error: object not graspable'

    def control__drop_from_right_hand(self):
        print "attempting to drop object from right hand.\n"

        if self.right_hand_holding_object is None:
            print 'right hand is not holding an object.'
            return False
        if self.right_hand_holding_object.getNetTag('heldBy') == self.name:
            self.right_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_right_hand.getPos(render)
            heldPos = self.right_hand_holding_object.geom.getPosition()
            self.right_hand_holding_object.setPosition(pos)
            self.right_hand_holding_object.synchPosQuatToNode()
            self.right_hand_holding_object.setTag('heldBy', '')
            self.right_hand_holding_object.setRotation(
                self.right_hand_holding_object.originalHpr)
            self.right_hand_holding_object.enable()
            if self.right_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.right_hand_holding_object.body.setGravityMode(1)
                self.right_hand_holding_object.getBody().setForce(
                    quat.xform(Vec3(0, force, 0)))
            self.right_hand_holding_object = None
            return 'success'
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__drop_from_left_hand(self):
        print "attempting to drop object from left hand.\n"
        if self.left_hand_holding_object is None:
            return 'left hand is not holding an object.'
        if self.left_hand_holding_object.getNetTag('heldBy') == self.name:
            self.left_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_left_hand.getPos(render)
            heldPos = self.left_hand_holding_object.geom.getPosition()
            self.left_hand_holding_object.setPosition(pos)
            self.left_hand_holding_object.synchPosQuatToNode()
            self.left_hand_holding_object.setTag('heldBy', '')
            self.left_hand_holding_object.setRotation(
                self.left_hand_holding_object.originalHpr)
            self.left_hand_holding_object.enable()
            if self.left_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.left_hand_holding_object.body.setGravityMode(1)
                self.left_hand_holding_object.getBody().setForce(
                    quat.xform(Vec3(0, force, 0)))
            self.left_hand_holding_object = None
            return 'success'
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__use_right_hand(self, target=None, action=None):
        # TODO, rename this to use object with
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag('isisobj')
        print "Trying to use object", target
        if self.can_grasp(target):
            if (target.call(self, action, self.right_hand_holding_object) or
                (self.right_hand_holding_object and
                 self.right_hand_holding_object.call(self, action, target))):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def control__use_left_hand(self, target=None, action=None):
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag('isisobj')
        if self.can_grasp(target):
            if (target.call(self, action, self.left_hand_holding_object) or
                (self.left_hand_holding_object and
                 self.left_hand_holding_object.call(self, action, target))):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def can_grasp(self, isisobject):
        distance = isisobject.activeModel.getDistance(self.fov)
        print "distance = ", distance
        return distance < 5.0

    def is_holding(self, object_name):
        return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name  == object_name)) \
             or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name)))

    def empty_hand(self):
        if (self.left_hand_holding_object is None):
            return self.player_left_hand
        elif (self.right_hand_holding_object is None):
            return self.player_right_hand
        return False

    def has_empty_hand(self):
        return (self.empty_hand() is not False)

    def control__use_aimed(self):
        """
        Try to use the object that we aim at, by calling its callback method.
        """
        target = self.__get_object_in_center_of_view()
        if target.selectionCallback:
            target.selectionCallback(self, dir)
        return "success"

    def sense__get_position(self):
        x, y, z = self.actorNodePath.getPos()
        h, p, r = self.actorNodePath.getHpr()
        #FIXME
        # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr()
        left_hand_obj = ""
        right_hand_obj = ""
        if self.left_hand_holding_object:
            left_hand_obj = self.left_hand_holding_object.getName()
        if self.right_hand_holding_object:
            right_hand_obj = self.right_hand_holding_object.getName()
        return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\
                'body_p': p, 'body_r': r,  'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj}

    def sense__get_vision(self):
        self.fov.node().saveScreenshot("temp.jpg")
        image = Image.open("temp.jpg")
        os.remove("temp.jpg")
        return image

    def sense__get_objects(self):
        return dict([x.getName(), y]
                    for (x,
                         y) in self.get_objects_in_field_of_vision().items())

    def sense__get_agents(self):
        curSense = time()
        agents = {}
        for k, v in self.get_agents_in_field_of_vision().items():
            v['actions'] = k.get_other_agents_actions(self.lastSense, curSense)
            agents[k.name] = v
        self.lastSense = curSense
        return agents

    def sense__get_utterances(self):
        """ Clear out the buffer of things that the teacher has typed,
        FIXME: this doesn't work right now """
        return []
        utterances = self.teacher_utterances
        self.teacher_utterances = []
        return utterances

    def debug__print_objects(self):
        text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys())
        print text

    def add_action_to_history(self, action, args, result=0):
        self.queue.append((time(), action, args, result))
        if len(self.queue) > self.queueSize:
            self.queue.pop(0)

    def get_other_agents_actions(self, start=0, end=None):
        if not end:
            end = time()
        actions = []
        for act in self.queue:
            if act[0] >= start:
                if act[0] < end:
                    actions.append(act)
                else:
                    break
        return actions

    def update(self, stepSize=0.1):
        self.speed = [0.0, 0.0]
        self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70))
        self.actorNodePath.setQuat(self.getQuat())
        # the values in self.speeds are used as coefficientes for turns and movements
        if (self.controlMap["turn_left"] != 0):
            self.addToH(stepSize * self.speeds[0])
        if (self.controlMap["turn_right"] != 0):
            self.addToH(-stepSize * self.speeds[1])
        if self.verticalState == 'ground':
            # these actions require contact with the ground
            if (self.controlMap["move_forward"] != 0):
                self.speed[1] = self.speeds[2]
            if (self.controlMap["move_backward"] != 0):
                self.speed[1] = -self.speeds[3]
            if (self.controlMap["move_left"] != 0):
                self.speed[0] = -self.speeds[4]
            if (self.controlMap["move_right"] != 0):
                self.speed[0] = self.speeds[5]
            if (self.controlMap["jump"] != 0):
                kinematicCharacterController.jump(self)
                # one jump at a time!
                self.controlMap["jump"] = 0
        if (self.controlMap["look_left"] != 0):
            self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80)
        if (self.controlMap["look_right"] != 0):
            self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80)
        if (self.controlMap["look_up"] != 0):
            self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80)
        if (self.controlMap["look_down"] != 0):
            self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80)

        kinematicCharacterController.update(self, stepSize)
        """
        Update the held object position to be in the hands
        """
        if self.right_hand_holding_object != None:
            self.right_hand_holding_object.setPosition(
                self.player_right_hand.getPos(render))
        if self.left_hand_holding_object != None:
            self.left_hand_holding_object.setPosition(
                self.player_left_hand.getPos(render))

        #Update the dialog box and thought windows
        #This allows dialogue window to gradually decay (changing transparancy) and then disappear
        self.last_spoke += stepSize / 2
        self.last_thought += stepSize / 2
        self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01))
        self.speech_bubble['frameColor'] = (.6, .2, .1,
                                            .5 / (self.last_spoke + 0.01))
        if self.last_spoke > 2:
            self.speech_bubble['text'] = ""
        if self.last_thought > 1:
            self.thought_bubble.hide()

        # If the character is moving, loop the run animation.
        # If he is standing still, stop the animation.
        if (self.controlMap["move_forward"] !=
                0) or (self.controlMap["move_backward"] !=
                       0) or (self.controlMap["move_left"] !=
                              0) or (self.controlMap["move_right"] != 0):
            if self.isMoving is False:
                self.isMoving = True
        else:
            if self.isMoving:
                self.current_frame_count = 5.0
                self.isMoving = False

        total_frame_num = self.actor.getNumFrames('walk')
        if self.isMoving:
            self.current_frame_count = self.current_frame_count + (stepSize *
                                                                   250.0)
            if self.current_frame_count > total_frame_num:
                self.current_frame_count = self.current_frame_count % total_frame_num
            self.actor.pose('walk', self.current_frame_count)
        elif self.current_frame_count != 0:
            self.current_frame_count = 0
            self.actor.pose('idle', 0)
        return Task.cont

    def destroy(self):
        self.disable()
        self.specialDirectObject.ignoreAll()
        self.actorNodePath.removeNode()
        del self.specialDirectObject

        kinematicCharacterController.destroy(self)

    def disable(self):
        self.isDisabled = True
        self.geom.disable()
        self.footRay.disable()

    def enable(self):
        self.footRay.enable()
        self.geom.enable()
        self.isDisabled = False

    """
    Set camera to correct height above the center of the capsule
    when crouching and when standing up.
    """

    def crouch(self):
        kinematicCharacterController.crouch(self)
        self.camH = self.crouchCamH

    def crouchStop(self):
        """
        Only change the camera's placement when the KCC allows standing up.
        See the KCC to find out why it might not allow it.
        """
        if kinematicCharacterController.crouchStop(self):
            self.camH = self.walkCamH
Esempio n. 11
0
class Menu(DirectObject):
    def __init__(self):
        """Default constructor"""
        # load the default fonts
        #self.defaultFont = loader.loadFont("gui/fonts/UbuntuBold")
        #self.defaultFontRegular = loader.loadFont("gui/fonts/UbuntuRegular")
        # load the default button image map
        self.defaultBtnMaps = base.loader.loadModel(
            "gui/buttons/mainMenu/button_maps")

        # this button can be created with the createBackButton function
        self.btnBack = None

        self.frameMain = DirectFrame(
            # size of the frame
            frameSize = (base.a2dLeft, base.a2dRight,
                         base.a2dTop, base.a2dBottom),
            # position of the frame
            pos = (0, 0, 0),
            # tramsparent bg color
            frameColor = (0, 0, 0, 0))

        self.title = DirectLabel(
            scale = 0.25,
            pos = (0, 0, -0.25),
            frameColor = (0, 0, 0, 0),
            text = "Missing Title",
            text_align = TextNode.ACenter,
            text_fg = (1,1,1,1),
            #text_font = self.defaultFont
            )
        self.title.reparentTo(base.a2dTopCenter)

        self.clock = DirectLabel(
            scale = 0.1,
            pos = (-.1,0,.1),
            frameColor = (0, 0, 0, 0),
            text = "00:00",
            text_align = TextNode.ARight,
            text_fg = (1,1,1,1))
        self.clock.reparentTo(base.a2dBottomRight)


        self.hide()

    def showBase(self):
        """Show all GUI controls of the base menu"""
        self.accept("RatioChanged", self.recalcAspectRatio)
        self.frameMain.show()
        self.clock.show()
        self.title.show()
        if self.btnBack:
            self.btnBack.show()
        if not taskMgr.hasTaskNamed("clock"):
            taskMgr.add(self.clockTask, "clock")

    def hideBase(self):
        """Hide all GUI controls of the base menu"""
        self.ignore("RatioChanged")
        self.frameMain.hide()
        self.clock.hide()
        self.title.hide()
        if self.btnBack:
            self.btnBack.hide()
        if taskMgr.hasTaskNamed("clock"):
            taskMgr.remove("clock")

    def createBackButton(self, func):
        """Create the back button on the bottom left edge of the window"""
        self.btnBack = DirectButton(
            # size of the button
            scale = (0.25, 0.25, 0.25),
            # size of the text
            text_scale = (0.5*1.33, 0.5, 0.5),
            # the text on the button
            text = "ABC",
            # set the alignment to right
            text_align = TextNode.ARight,
            # put the text on the left side of the button
            text_pos = (4.1, -0.15),
            # set the text color to white
            text_fg = (1,1,1,1),
            # set the font of the text
            #text_font = self.defaultFont,
            # set the buttons images
            geom = (self.defaultBtnMaps.find("**/button_ready"),
                    self.defaultBtnMaps.find("**/button_click"),
                    self.defaultBtnMaps.find("**/button_rollover"),
                    self.defaultBtnMaps.find("**/button_disabled")),
            # set no relief
            relief = 1,
            # make it transparent
            frameColor = (0,0,0,0),
            # No sink in when press
            pressEffect = False,
            # position on the window
            pos = (0.0, 0, 0.2),
            # the event which is thrown on clickSound
            command = func,
            # sounds that should be played
            rolloverSound = None,
            clickSound = None)
        self.btnBack.reparentTo(base.a2dBottomLeft)

    def clockTask(self, task):
        self.clock["text"] = time.strftime("%H:%M")
        return task.cont

    def recalcAspectRatio(self):
        """get the new aspect ratio to resize the mainframe"""
        self.frameMain["frameSize"] = (
            base.a2dLeft, base.a2dRight,
            base.a2dTop, base.a2dBottom)
Esempio n. 12
0
class ShopWindow(DirectFrame):
    def __init__(self, shop, image, wantTurretCount):
        DirectFrame.__init__(self, sortOrder=1)
        self.shop = shop
        self.wantTurretCount = wantTurretCount
        self.bgImage = image
        self.title = None
        self.okBtn = None
        self.clBtn = None
        self.infoLbl = None
        self.turretLabel = None
        self.turretImg = None
        self.isSetup = False
        self.turretCount = 0

        # New variables for optimized shop.
        self.firstItemIndex = -1
        self.btnPositions = [(-0.45, 0, 0), (-0.15, 0, 0), (0.15, 0, 0),
                             (0.45, 0, 0)]
        self.page = Page(self.shop, self)
        self.itemButtons = []
        self.itemButtons.append(ItemButton(self.page, self.btnPositions[0]))
        self.itemButtons.append(ItemButton(self.page, self.btnPositions[1]))
        self.itemButtons.append(ItemButton(self.page, self.btnPositions[2]))
        self.itemButtons.append(ItemButton(self.page, self.btnPositions[3]))
        self.newItems = None

    def setup(self, title='CHOOSE WHAT YOU WANT TO BUY'):
        font = CIGlobals.getMickeyFont()
        txtFg = (0, 0, 0, 1)
        txtScale = 0.05
        txtPos = (0, -0.1)
        buttons = loader.loadModel('phase_3.5/models/gui/QT_buttons.bam')
        self.window = OnscreenImage(image=self.bgImage,
                                    scale=(0.9, 1, 0.7),
                                    parent=self)
        self.title = DirectLabel(text=title,
                                 relief=None,
                                 pos=(0, 0, 0.5),
                                 text_wordwrap=10,
                                 text_font=font,
                                 text_fg=(1, 1, 0, 1),
                                 scale=0.1,
                                 parent=self)

        # Let's update the turret count.
        self.updateTurretCount()

        self.infoLbl = DirectLabel(text='Welcome!',
                                   relief=None,
                                   text_scale=0.075,
                                   text_fg=txtFg,
                                   text_shadow=(0, 0, 0, 0),
                                   pos=(0, 0, 0.215))
        self.okBtn = DirectButton(geom=CIGlobals.getOkayBtnGeom(),
                                  relief=None,
                                  text='OK',
                                  text_fg=txtFg,
                                  text_scale=txtScale,
                                  text_pos=txtPos,
                                  pos=(-0.1, 0, -0.5),
                                  parent=self)
        self.clBtn = DirectButton(geom=CIGlobals.getCancelBtnGeom(),
                                  relief=None,
                                  text='Cancel',
                                  text_fg=txtFg,
                                  text_scale=txtScale,
                                  text_pos=txtPos,
                                  pos=(0.1, 0, -0.5),
                                  parent=self)
        buttonGeom = (buttons.find('**/QT_back'), buttons.find('**/QT_back'),
                      buttons.find('**/QT_back'), buttons.find('**/QT_back'))
        self.backBtn = DirectButton(geom=buttonGeom,
                                    relief=None,
                                    scale=0.05,
                                    pos=(-0.3, 0, -0.25),
                                    parent=self,
                                    command=self.changePage,
                                    extraArgs=[0])
        self.nextBtn = DirectButton(geom=buttonGeom,
                                    relief=None,
                                    scale=0.05,
                                    pos=(0.3, 0, -0.25),
                                    hpr=(0, 0, 180),
                                    command=self.changePage,
                                    extraArgs=[1],
                                    parent=self)
        self.hideInfo()

    def setTurrets(self, amount):
        if self.shop.upgradesPurchased:
            amount += 1
        self.turretCount = amount
        self.updatePage()

    def updateTurretCount(self):
        if self.turretLabel:
            self.turretLabel.destroy()

        if self.wantTurretCount:
            maxTurrets = CogBattleGlobals.MAX_TURRETS

            if not self.turretImg:
                self.turretImg = OnscreenImage(
                    image="phase_3.5/maps/cannon-icon.png",
                    scale=(0.05, 1, 0.05),
                    pos=(-0.22, 0, 0.275))
                self.turretImg.setTransparency(TransparencyAttrib.MAlpha)

            self.turretLabel = DirectLabel(
                text='Turrets: %s/%s' %
                (str(self.turretCount), str(maxTurrets)),
                relief=None,
                text_scale=0.07,
                text_fg=(0, 0, 0, 1),
                text_shadow=(0, 0, 0, 0),
                pos=(0, 0, 0.265))

    def changePage(self, direction):
        var = (self.firstItemIndex - 4)
        if direction == 1:
            var = (self.firstItemIndex + 4)

        self.setBackBtn(True)
        self.setNextBtn(True)
        if (var - 4) < 0:
            self.setBackBtn(False)
        elif (var + 4) >= len(self.newItems):
            self.setNextBtn(False)

        self.firstItemIndex = var
        self.setupItems(begin=self.firstItemIndex)

    def initializeShop(self, items):
        newItems = dict(items)
        loadout = base.localAvatar.backpack.loadout

        # Let's show the loadout gags first in a full shop.
        if self.shop.wantFullShop:
            crcGags = OrderedDict(newItems)
            for item, values in newItems.items():
                if values and values.get('type') == ItemType.GAG:
                    gagId = base.cr.attackMgr.getAttackIDByName(item)
                    hasGag = base.localAvatar.getBackpack().hasGag(gagId)
                    if gagId not in loadout or not hasGag:
                        del crcGags[item]
                        if not hasGag:
                            del newItems[item]
                    else:
                        del newItems[item]
            # Let's add back the other gags.
            crcGags.update(newItems)
            newItems = crcGags
        else:
            for item, values in newItems.items():
                if values and values.get('type') == ItemType.GAG:
                    gagId = base.localAvatar.getBackpack().hasGag(gagId)
                    if gagId not in loadout or not base.localAvatar.getBackpack(
                    ).hasGag(gagId):
                        del newItems[item]

        self.newItems = newItems
        self.firstItemIndex = 0
        self.setupItems()

        if len(newItems.keys()) <= 4:
            self.backBtn.hide()
            self.nextBtn.hide()
        self.setBackBtn(False)
        self.isSetup = True

    def setupItems(self, begin=0):
        for button in self.itemButtons:
            button.hide()
            button.label.hide()
        for i in xrange(4):
            item = self.newItems.keys()[begin + i] if (begin + i) < len(
                self.newItems.keys()) else None
            values = self.newItems.get(item) if item else None
            if item:
                button = self.itemButtons[i]
                button.setItem(item, values)
                button.update()

    def updatePage(self):
        battle = base.localAvatar.getBattleZone()

        if battle and self.wantTurretCount:
            self.shop.distShop.sendUpdate('requestTurretCount', [])
            self.updateTurretCount()

        for button in self.itemButtons:
            button.update()

    def setBackBtn(self, enabled):
        if self.backBtn:
            if enabled == False:
                self.backBtn.setColorScale(GRAYED_OUT_COLOR)
                self.backBtn['state'] = DGG.DISABLED
            else:
                self.backBtn.setColorScale(NORMAL_COLOR)
                self.backBtn['state'] = DGG.NORMAL

    def setNextBtn(self, enabled):
        if self.nextBtn:
            if enabled == False:
                self.nextBtn.setColorScale(GRAYED_OUT_COLOR)
                self.nextBtn['state'] = DGG.DISABLED
            else:
                self.nextBtn.setColorScale(NORMAL_COLOR)
                self.nextBtn['state'] = DGG.NORMAL

    def setOKCommand(self, command):
        if self.okBtn: self.okBtn['command'] = command

    def setCancelCommand(self, command):
        if self.clBtn: self.clBtn['command'] = command

    def showInfo(self, text, negative=0, duration=-1):
        self.infoLbl.show()
        if negative:
            self.infoLbl['text_fg'] = (0.9, 0, 0, 1)
            self.infoLbl['text_shadow'] = (0, 0, 0, 1)
        else:
            self.infoLbl['text_fg'] = (0, 0, 0, 1)
            self.infoLbl['text_shadow'] = (0, 0, 0, 0)
        self.infoLbl['text'] = text
        if duration > -1: Sequence(Wait(duration), Func(self.hideInfo)).start()

    def hideInfo(self):
        if self.infoLbl: self.infoLbl.hide()

    def delete(self):
        elements = [
            self.title, self.okBtn, self.clBtn, self.infoLbl, self.backBtn,
            self.nextBtn, self.turretLabel, self.turretImg, self.page
        ]
        for element in elements:
            if element:
                element.destroy()
        del elements
        del self.page
        for button in self.itemButtons:
            button.destroy()
        self.itemButtons = None
        del self.itemButtons
        self.title = None
        self.okBtn = None
        self.clBtn = None
        self.infoLbl = None
        self.backBtn = None
        self.nextBtn = None
        self.bgImage = None
        self.turretLabel = None
        self.turretCount = None
        if self.window:
            self.window.destroy()
            self.window = None
        self.destroy()
Esempio n. 13
0
class ItemButton(DirectButton):
    def __init__(self, page, pos):
        DirectButton.__init__(self,
                              parent=page,
                              relief=None,
                              command=self.handleClick,
                              pos=pos)
        self.window = page
        self.item = None
        self.values = None
        self.label = DirectLabel(text='',
                                 relief=None,
                                 parent=self,
                                 text_scale=0.05)
        self.label.initialiseoptions(DirectLabel)
        self.label.hide()
        self.hide()

    def setItem(self, item, values):
        if values:
            image = values.get('image')
            price = values.get('price')
            text = ''

            self.item = item
            self.values = values
            self['geom'] = image

            if values.get('type') == ItemType.GAG:
                gagId = base.cr.attackMgr.getAttackIDByName(item)
                supply = base.localAvatar.getBackpack().getSupply(gagId)
                maxSupply = base.localAvatar.getBackpack().getMaxSupply(gagId)
                self.setScale(1.3)
                self.label['text_scale'] = 0.05
                self.label.setPos(0, 0, -0.11)
                self.setTransparency(TransparencyAttrib.MNone)
            elif values.get('type') == ItemType.UPGRADE:
                upgradeID = values.get('upgradeID')
                avID = base.localAvatar.getPUInventory()[1]
                supply = 0
                maxSupply = values.get('maxUpgrades')

                battle = base.localAvatar.getBattleZone()
                if battle and battle.getTurretManager():
                    turret = battle.getTurretManager().getTurret()
                    if turret and turret.getGagID() == upgradeID:
                        supply = 1

                if avID == upgradeID:
                    dataSupply = base.localAvatar.getPUInventory()[0]
                    if dataSupply > 0:
                        supply = dataSupply

                self.setScale(0.15)
                self.label['text_scale'] = 0.3
                self.label.setPos(0, 0, -1.2)
                self.setTransparency(TransparencyAttrib.MNone)
            elif values.get('type') == ItemType.HEAL:
                text = '%s\n%s JBS' % (
                    item, price) if 'showTitle' in values else item
                self.setTransparency(TransparencyAttrib.MAlpha)
                self.setScale(0.105)
                self.label['text_scale'] = 0.55
                self.label.setPos(0, 0, -1.6)
            text = text if text else '%s/%s\n%s JBS' % (
                str(supply), str(maxSupply), str(price))
            self.label['text'] = text

            self.label.initialiseoptions(DirectLabel)
            self.initialiseoptions(ItemButton)

            self.label.show()
            self.show()

    def update(self):
        money = base.localAvatar.getMoney()
        if self.values:
            itemType = self.values.get('type')
            price = self.values.get('price')
            self.setColorScale(NORMAL_COLOR)
            if price > money:
                self.setColorScale(GRAYED_OUT_COLOR)
            if itemType == ItemType.GAG:
                backpack = base.localAvatar.getBackpack()
                gagId = base.cr.attackMgr.getAttackIDByName(self.item)
                supply = backpack.getSupply(gagId)
                maxSupply = backpack.getMaxSupply(gagId)
                inBackpack = backpack.hasGag(gagId)
                if not inBackpack or inBackpack and supply >= maxSupply:
                    self.setColorScale(GRAYED_OUT_COLOR)
                self.label['text'] = '%s/%s\n%s JBS' % (
                    str(supply), str(maxSupply), str(price))
            elif itemType == ItemType.UPGRADE:
                maxSupply = self.values.get('maxUpgrades')
                upgradeID = self.values.get('upgradeID')
                avID = base.localAvatar.getPUInventory()[1]
                supply = 0
                turretCount = 0
                hasTurret = False

                battle = base.localAvatar.getBattleZone()
                if battle and battle.getTurretManager():
                    turretCount = battle.getTurretCount()
                    turret = battle.getTurretManager().getTurret()
                    if turret:
                        hasTurret = True
                        if turret.getGagID() == upgradeID:
                            supply = 1

                if avID == upgradeID:
                    dataSupply = base.localAvatar.getPUInventory()[0]
                    if dataSupply > 0:
                        supply = dataSupply

                if supply > 0 or base.localAvatar.getPUInventory(
                )[0] > 0 or hasTurret or turretCount == CogBattleGlobals.MAX_TURRETS:
                    self.setColorScale(GRAYED_OUT_COLOR)

                self.label['text'] = '%s\n%s/%s\n%s JBS' % (
                    self.item, str(supply), str(maxSupply), str(price))
            elif itemType == ItemType.HEAL:
                if base.localAvatar.getHealth(
                ) == base.localAvatar.getMaxHealth() or self.shop.hasCooldown(
                        self.item):
                    self.setColorScale(GRAYED_OUT_COLOR)

    def handleClick(self):
        if self.item:
            self.window.shop.purchaseItem(self.item)

    def destroy(self):
        DirectFrame.destroy(self)
Esempio n. 14
0
class OutingsGUI:
    """Outing dialogs GUI."""
    def __init__(self):
        self.is_shown = False
        self._char_chooser = None
        self._outing_widgets = []
        self._assignees = []
        self._char_buttons = {}
        self._blink_step = 0

        self._outing_snd = loader.loadSfx(
            "sounds/outing_event.ogg")  # noqa: F821

        self._upcome_ico = DirectFrame(
            frameSize=(-0.1, 0.1, -0.1, 0.1),
            pos=(0, 0, 0.8),
            frameTexture="gui/tex/looting.png",
        )
        self._upcome_ico.setTransparency(TransparencyAttrib.MAlpha)
        self._upcome_ico.hide()

        self._upcome_text = DirectLabel(
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.04,
            text_fg=SILVER_COL,
            text_bg=(0, 0, 0, 0.5),
            pos=(0, 0, 0.65),
        )
        self._upcome_text.hide()

        self._list = DirectFrame(
            frameSize=(-0.73, 0.73, -0.9, 0.9),
            frameTexture="gui/tex/paper1.png",
            state=DGG.NORMAL,
        )
        self._list.setDepthTest(False)
        self._list.setTransparency(TransparencyAttrib.MAlpha)
        self._list.hide()

        self._name = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.047,
            pos=(-0.4, 0, 0.7),
        )
        self._type = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.032,
            pos=(-0.13, 0, 0.699),
        )
        self._desc = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.6, 0.6, 0.6, 0.6),
            text_scale=0.037,
            pos=(0, 0, 0.55),
        )

    def _assign_for_outing(self, to_send_wid, assignees):
        """Assign the chosen character for the outing.

        Args:
            to_send_wid (direct.gui.DirectLabel.DirectLabel):
                Widget with number of assigned characters.
            assignees (int): Assignees limit.
        """
        char = base.common_ctrl.chosen_char  # noqa: F821
        if char is None or char in self._assignees or len(
                self._assignees) == assignees:
            return

        self._assignees.append(char)
        self._char_buttons[char.id].setX(0.35)

        to_send_wid["text"] = base.labels.OUTINGS_GUI[0].format(  # noqa: F821
            cur_as=str(len(self._assignees)),
            max_as=str(assignees))

    def _unassign_for_outing(self, to_send_wid, assignees):
        """Exclude the chosen character from the outing.

        Args:
            to_send_wid (direct.gui.DirectLabel.DirectLabel):
                Widget with number of assigned characters.
            assignees (int): Assignees limit.
        """
        char = base.common_ctrl.chosen_char  # noqa: F821
        if char not in self._assignees:
            return

        self._assignees.remove(char)
        self._char_buttons[char.id].setX(-0.35)

        to_send_wid["text"] = base.labels.OUTINGS_GUI[0].format(  # noqa: F821
            cur_as=str(len(self._assignees)),
            max_as=str(assignees))

    def _blink_upcome_icon(self, task):
        """Blink upcoming outing icon to attract attention."""
        self._blink_step += 1
        if self._blink_step in (2, 4, 6):
            self._upcome_ico.show()
            if self._blink_step == 6:
                self._blink_step = 0
                return task.done

            return task.again

        self._upcome_ico.hide()
        return task.again

    def _animate_bars(self, bars, score, selected_effect, recruit_effect,
                      cohesion_inc, task):
        """Animate filling the bars.

        Args:
            bars (list): Widget to fill.
            score (int): Total outing score.
            selected_effect (dict):
                Effect which requires to choose a target.
            recruit_effect (int): Cost of a possible recruit
            cohesion_inc (float): Cohesion increase value.
        """
        all_filled = True
        for bar in bars:
            bar_wid = bar[0]
            if bar_wid["value"] >= bar[1]:
                continue

            bar_wid["value"] = bar_wid["value"] + bar_wid["range"] / 100
            all_filled = False

        if all_filled:
            shift = -0.07

            for num in range(4):
                self._outing_widgets.append(
                    DirectLabel(
                        parent=self._list,
                        text=str(bars[num][1]) + "/" + str(bars[num][2]),
                        frameSize=(0.6, 0.6, 0.6, 0.6),
                        text_scale=0.035,
                        pos=(0.168, 0, shift),
                    ))
                shift -= 0.12

            self._outing_widgets.append(
                DirectLabel(  # Total outing score:
                    parent=self._list,
                    text=base.labels.OUTINGS_GUI[1] + str(score) +
                    "/100",  # noqa: F821
                    text_font=base.main_font,  # noqa: F821
                    frameSize=(0.6, 0.6, 0.6, 0.6),
                    text_scale=0.042,
                    pos=(0, 0, -0.57),
                ))
            if round(cohesion_inc, 2) > 0.05:
                self._outing_widgets.append(
                    DirectLabel(  # Cohesion increased:
                        parent=self._list,
                        text=base.labels.OUTINGS_GUI[15].format(  # noqa: F821
                            value=round(cohesion_inc, 2)),
                        text_font=base.main_font,  # noqa: F821
                        frameSize=(0.6, 0.6, 0.6, 0.6),
                        text_scale=0.035,
                        pos=(0, 0, -0.69),
                    ))
            self._outing_widgets.append(
                DirectButton(  # Done
                    pos=(0, 0, -0.77),
                    text=base.labels.DISTINGUISHED[6],  # noqa: F821
                    text_font=base.main_font,  # noqa: F821
                    text_fg=RUST_COL,
                    text_shadow=(0, 0, 0, 1),
                    frameColor=(0, 0, 0, 0),
                    command=self._finish_outing,
                    extraArgs=[selected_effect, recruit_effect],
                    scale=(0.05, 0, 0.05),
                    clickSound=base.main_menu.click_snd,  # noqa: F821
                ))
            return task.done

        return task.again

    def _dont_hire_unit(self):
        """Finish an outing without recruiting."""
        self.hide_outing()
        base.common_ctrl.deselect()  # noqa: F821

    def _hire_unit(self, char, cost):
        """Hire unit from the outing.

        Args:
            char (units.crew.character.Character):
                Character to recruit.
            cost (int): Cost of the recruitement.
        """
        if not base.res_gui.check_enough_money(cost):  # noqa: F821
            return

        if not base.res_gui.check_has_cell():  # noqa: F821
            return

        base.dollars -= cost  # noqa: F821

        base.world.city_gui.write_snd.play()  # noqa: F821
        base.team.chars[char.id] = char  # noqa: F821

        char.prepare()
        base.train.place_recruit(char)  # noqa: F821
        base.res_gui.update_chars()  # noqa: F821

        self.hide_outing()
        base.common_ctrl.deselect()  # noqa: F821

    def _finish_outing(self, selected_effect, recruit_effect):
        """Show effect selector if needed and finish the outing.

        Args:
            selected_effect (dict):
                Effect which requires to choose a target.
            recruit_effect (int):
                Cost of a possible recruit.
        """
        clear_wids(self._outing_widgets)

        if not (selected_effect or recruit_effect):
            self.hide_outing()
            return

        if recruit_effect:
            char = base.team.generate_recruit()  # noqa: F821
            base.char_gui.show_char_info(char)  # noqa: F821

            self._outing_widgets.append(
                DirectLabel(  # You can recruit <name> for <cost>$
                    parent=self._list,
                    pos=(0, 0, 0),
                    text=base.labels.OUTINGS_GUI[12].format(  # noqa: F821
                        name=char.name, cost=recruit_effect),
                    text_font=base.main_font,  # noqa: F821
                    frameSize=(0.6, 0.6, 0.6, 0.6),
                    text_scale=0.045,
                ))
            self._outing_widgets.append(
                DirectButton(  # Recruit
                    pos=(-0.2, 0, -0.75),
                    text=base.labels.OUTINGS_GUI[10],  # noqa: F821
                    text_font=base.main_font,  # noqa: F821
                    text_fg=RUST_COL,
                    text_shadow=(0, 0, 0, 1),
                    frameColor=(0, 0, 0, 0),
                    command=self._hire_unit,
                    extraArgs=[char, recruit_effect],
                    scale=(0.05, 0, 0.05),
                    clickSound=base.main_menu.click_snd,  # noqa: F821
                ))
            self._outing_widgets.append(
                DirectButton(  # Don't recruit
                    pos=(0.2, 0, -0.75),
                    text=base.labels.OUTINGS_GUI[11],  # noqa: F821
                    text_font=base.main_font,  # noqa: F821
                    text_fg=RUST_COL,
                    text_shadow=(0, 0, 0, 1),
                    frameColor=(0, 0, 0, 0),
                    command=self._dont_hire_unit,
                    scale=(0.05, 0, 0.05),
                    clickSound=base.main_menu.click_snd,  # noqa: F821
                ))
            return

        # there are effects to select a target for
        effect_str = ""
        for key, value in selected_effect.items():
            if key == "add_trait":
                ind1, ind2 = value
                value = base.labels.TRAITS[ind1][ind2]  # noqa: F821
                effect_str = base.labels.OUTINGS_GUI[13].format(  # noqa: F821
                    trait=value,
                    desc=base.labels.TRAIT_DESC[value]  # noqa: F821
                )
            else:
                effect_str += (key + " " + ("+" if value > 0 else "-") +
                               str(value) + "\n")

        self._outing_widgets.append(
            DirectLabel(  # Select one character as a target for the effect:
                parent=self._list,
                text=base.labels.OUTINGS_GUI[14]  # noqa: F821
                + "\n{effect}".format(effect=effect_str),
                text_font=base.main_font,  # noqa: F821
                frameSize=(0.6, 0.6, 0.6, 0.6),
                text_scale=0.045,
            ))
        self._char_chooser = CharacterChooser(is_shadowed=True)
        self._char_chooser.prepare(
            self._list,
            (0, 0, -0.15),
            base.team.chars  # noqa: F821
        )
        self._outing_widgets.append(
            DirectButton(  # Done
                pos=(0, 0, -0.75),
                text=base.labels.DISTINGUISHED[6],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                text_fg=RUST_COL,
                text_shadow=(0, 0, 0, 1),
                frameColor=(0, 0, 0, 0),
                command=self._do_effect_and_finish,  # noqa: F821
                extraArgs=[selected_effect],
                scale=(0.05, 0, 0.05),
                clickSound=base.main_menu.click_snd,  # noqa: F821
            ))

    def _do_effect_and_finish(self, effect):
        """
        Do effects for the selected character
        and finish the outing.

        Args:
            effect (dict): The effect to do.
        """
        self._char_chooser.chosen_item.do_effects(effect)
        self._char_chooser.destroy()
        self.hide_outing()

    def show_upcoming(self, text, icon):
        """Show the upcoming event notification.

        Args:
            text (str): Event text.
            icon (str): Event icon.
        """
        self._upcome_text["text"] = text
        self._upcome_ico["frameTexture"] = icon

        self._upcome_text.show()
        self._upcome_ico.show()

        taskMgr.doMethodLater(  # noqa: F821
            0.3, self._blink_upcome_icon, "blink_outing_icon")

    def show_place_of_interest(self):
        """Show icon for a place of interest."""
        self.show_upcoming(
            base.labels.NOTIFIERS[0],
            OUTINGS_ICONS["Place Of Interest"],  # noqa: F821
        )

    def show_upcoming_outing(self, type_orig, type_):
        """Show upcoming outing notification.

        Args:
            type_orig (str): Original outing type.
            type_ (str): Translated outing type.
        """
        self._outing_snd.play()
        self.show_upcoming(
            base.labels.NOTIFIERS[1].format(type_.capitalize()),  # noqa: F821
            OUTINGS_ICONS[type_orig],
        )

    def show_city(self):
        """Show upcoming city notification."""
        self.show_upcoming(base.labels.TIPS[2],
                           "gui/tex/city.png")  # noqa: F821

    def show_upcoming_closer(self):
        """Show that 1 mile left until available outing."""
        self._upcome_text["text"] = self._upcome_text["text"].replace(
            base.labels.NOTIFIERS[2],  # noqa: F821
            base.labels.NOTIFIERS[3],  # noqa: F821
        )

    def show_can_start(self):
        """Show that outing can be started."""
        self._upcome_text["text"] = base.labels.NOTIFIERS[4]  # noqa: F821

    def hide_outing(self):
        """Hide all the outings gui."""
        self._upcome_text.hide()
        self._upcome_ico.hide()

        if self.is_shown:
            self._assignees.clear()

            self._list.hide()
            self.is_shown = False
            clear_wids(self._outing_widgets)

    def start(self, outing):
        """Start the outing scenario.

        Draw an interface with outing description.

        Args:
            outing (dict): Outing description.
        """
        self.hide_outing()
        base.traits_gui.hide()  # noqa: F821
        self.is_shown = True
        self._list.show()

        out_labels = base.labels.OUTINGS[outing["index"]]  # noqa: F821
        self._name["text"] = out_labels["name"]
        self._type["text"] = base.labels.OUTING_TYPES[
            outing["type"]]  # noqa: F821
        self._desc["text"] = out_labels["desc"]

        self._outing_widgets.append(
            DirectLabel(  # Crew:
                parent=self._list,
                text=base.labels.OUTINGS_GUI[9],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                frameSize=(0.6, 0.6, 0.6, 0.6),
                text_scale=0.035,
                pos=(-0.35, 0, 0),
            ))
        shift = -0.07
        for id_, char in base.team.chars.items():  # noqa: F821
            but = DirectButton(
                pos=(-0.35, 0, shift),
                text=char.name,
                text_fg=SILVER_COL,
                frameColor=(0, 0, 0, 0.3),
                command=base.common_ctrl.choose_char,  # noqa: F821
                extraArgs=[char.id],
                scale=(0.04, 0, 0.03),
            )
            self._char_buttons[id_] = but
            self._outing_widgets.append(but)

            shift -= 0.04

        to_send = DirectLabel(  # People to send
            parent=self._list,
            text=base.labels.OUTINGS_GUI[0].format(  # noqa: F821
                cur_as="0", max_as=outing["assignees"]),
            text_scale=0.035,
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.6, 0.6, 0.6, 0.6),
            pos=(0.35, 0, 0),
        )
        self._outing_widgets.append(to_send)

        self._outing_widgets.append(
            DirectButton(
                pos=(0, 0, -0.15),
                text=">",
                text_fg=SILVER_COL,
                frameColor=(0, 0, 0, 0.3),
                command=self._assign_for_outing,
                extraArgs=[to_send, outing["assignees"]],
                scale=(0.075, 0, 0.075),
            ))
        self._outing_widgets.append(
            DirectButton(
                pos=(0, 0, -0.21),
                text="<",
                text_fg=SILVER_COL,
                frameColor=(0, 0, 0, 0.3),
                command=self._unassign_for_outing,
                extraArgs=[to_send, outing["assignees"]],
                scale=(0.075, 0, 0.075),
            ))
        self._outing_widgets.append(
            DirectButton(  # Don't send
                pos=(-0.15, 0, -0.75),
                text=base.labels.OUTINGS_GUI[2],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                text_fg=RUST_COL,
                text_shadow=(0, 0, 0, 1),
                frameColor=(0, 0, 0, 0),
                command=self.hide_outing,
                scale=(0.05, 0, 0.05),
                clickSound=base.main_menu.click_snd,  # noqa: F821
            ))
        self._outing_widgets.append(
            DirectButton(  # Send
                pos=(0.15, 0, -0.75),
                text=base.labels.OUTINGS_GUI[3],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                text_fg=RUST_COL,
                text_shadow=(0, 0, 0, 1),
                frameColor=(0, 0, 0, 0),
                command=base.world.outings_mgr.go_for_outing,  # noqa: F821
                extraArgs=[outing, self._assignees],
                clickSound=base.main_menu.click_snd,  # noqa: F821
                scale=(0.05, 0, 0.05),
            ))

    def show_result(
        self,
        desc,
        score,
        cond_score,
        class_score,
        cohesion_score,
        day_part_score,
        selected_effect,
        recruit_effect,
        cohesion_inc,
    ):
        """Show outing results GUI.

        Args:
            desc (str): Result description.
            score (int): Total outing score.
            cond_score (float): Score from characters condition.
            class_score (int): Score from characters classes.
            cohesion_score (float): Characters cohesion score.
            day_part_score (int): Day part bonus and special skills score.
            selected_effect (dict): Effect which requires to choose a target.
            recruit_effect (int): Cost of a possible recruit.
            cohesion_inc (float): Cohesion increase value.
        """
        clear_wids(self._outing_widgets)

        self._desc["text"] = desc

        self._outing_widgets.append(
            DirectLabel(  # Outing score:
                parent=self._list,
                text=base.labels.OUTINGS_GUI[4],  # noqa: F821
                text_font=base.main_font,  # noqa: F821
                frameSize=(0.6, 0.6, 0.6, 0.6),
                text_scale=0.042,
            ))
        bars = []
        shift = -0.07
        for name, maximum, col, value in (
            (  # Character classes fit:
                base.labels.OUTINGS_GUI[5],  # noqa: F821
                40,
                (0.36, 0.6, 0.42, 1),
                class_score,
            ),
            (  # Characters condition:
                base.labels.OUTINGS_GUI[6],  # noqa: F821
                25,
                (0.65, 0.2, 0.2, 1),
                cond_score,
            ),
            (  # Characters cohesion:
                base.labels.OUTINGS_GUI[7],  # noqa: F821
                25,
                SILVER_COL,
                cohesion_score,
            ),
            (  # Day part:
                base.labels.OUTINGS_GUI[8],  # noqa: F821
                10,
                (0.42, 0.42, 0.8, 1),
                day_part_score,
            ),
        ):
            self._outing_widgets.append(
                DirectLabel(
                    parent=self._list,
                    text=name,
                    text_font=base.main_font,  # noqa: F821
                    frameSize=(0.6, 0.6, 0.6, 0.6),
                    text_scale=0.035,
                    pos=(-0.08, 0, shift),
                ))
            shift -= 0.04
            bar = DirectWaitBar(
                parent=self._list,
                frameSize=(-0.17, 0.17, -0.005, 0.005),
                frameColor=(0.3, 0.3, 0.3, 0.5),
                value=0,
                range=maximum,
                barColor=col,
                pos=(0, 0, shift),
            )
            bars.append((bar, value, maximum))
            self._outing_widgets.append(bar)

            shift -= 0.08

        taskMgr.doMethodLater(  # noqa: F821
            0.035,
            self._animate_bars,
            "animate_outing_bars",
            extraArgs=[
                bars, score, selected_effect, recruit_effect, cohesion_inc
            ],
            appendTask=True,
        )
Esempio n. 15
0
    def __init__(self, numPlayers, avIdList, votes, directions, namesList,
                 disconnectedList, directionToGo, directionReason,
                 directionTotals, *args, **kwargs):
        opts = {
            'relief': None,
            'geom': DGG.getDefaultDialogGeom(),
            'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ),
            'geom_scale': (1.75, 1, 0.25),
            'pos': (0, 0, 0.825)
        }
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsTrolleyPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self,
                                   relief=None,
                                   pos=(-0.5, 0, 0.06),
                                   text=TTLocalizer.TravelGameDirections[0] +
                                   ':',
                                   text_fg=(0.0, 0.0, 1.0, 1.0),
                                   text_scale=0.05,
                                   text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self,
                                     relief=None,
                                     pos=(0.5, 0, 0.06),
                                     text=TTLocalizer.TravelGameDirections[1] +
                                     ':',
                                     text_fg=(1.0, 0.0, 0.0, 1.0),
                                     text_scale=0.05,
                                     text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.upLabel,
                                             relief=None,
                                             pos=(0.2, 0, 0.0),
                                             text='0',
                                             text_fg=(0.0, 0.0, 1.0, 1.0),
                                             text_scale=0.05,
                                             text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.downLabel,
                                               relief=None,
                                               pos=(0.2, 0, 0.0),
                                               text='0',
                                               text_fg=(1.0, 0.0, 0.0, 1.0),
                                               text_scale=0.05,
                                               text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self,
                                      relief=None,
                                      pos=self.getRowPos(self.numPlayers))
        self.totalVotesLabels = [
            self.totalVotesUpLabel, self.totalVotesDownLabel
        ]
        self.resultFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(0.5))
        self.resultLabel = DirectLabel(parent=self.resultFrame,
                                       text='',
                                       text_scale=0.06,
                                       pos=(0.7, 0, 0.0),
                                       text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in xrange(self.numPlayers):
            frame = DirectFrame(parent=self,
                                relief=None,
                                pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame,
                                    relief=None,
                                    pos=(0.46, 0.0, 0.0),
                                    text=self.namesList[index],
                                    text_fg=(0.0, 0.0, 0.0, 1.0),
                                    text_scale=0.05,
                                    text_align=TextNode.ACenter,
                                    text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame,
                                       relief=None,
                                       pos=(1.2, 0.0, 0.0),
                                       text='',
                                       text_fg=(0, 0, 1, 1),
                                       text_scale=0.05,
                                       text_align=TextNode.ARight,
                                       text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame,
                                         relief=None,
                                         pos=(1.43, 0.0, 0.0),
                                         text='',
                                         text_fg=(1, 0, 0, 1),
                                         text_scale=0.05,
                                         text_align=TextNode.ARight,
                                         text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        self.avVotesLabel = {}
        self.avArrows = {}
        matchingGameGui = loader.loadModel(
            'phase_3.5/models/gui/matching_game_gui')
        minnieArrow = matchingGameGui.find('**/minnieArrow')
        from toontown.minigame.DistributedTravelGame import map3dToAspect2d
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            av = base.cr.doId2do.get(avId)
            if av:
                height = av.getHeight()
                avPos = av.getPos(render)
                avPos.setZ(av.getZ() + 5)
                labelPos = map3dToAspect2d(render, avPos)
                if not labelPos:
                    continue
                labelPos.setZ(labelPos.getZ() + 0.3)
                arrow = None
                if self.votes[index] > 0:
                    arrow = aspect2d.attachNewNode('avArrow')
                    minnieArrow.copyTo(arrow)
                    arrow.setScale(1.1, 1, 1.15)
                    arrow.setPos(labelPos)
                    if self.directions[index] == 0:
                        arrow.setR(-90)
                        arrow.setColorScale(0, 0, 1, 1)
                    else:
                        arrow.setR(90)
                        arrow.setColorScale(1, 0, 0, 1)
                    arrow.wrtReparentTo(self.resultFrame)
                    arrow.hide()
                    self.avArrows[index] = arrow
                fgColor = Vec4(0, 0, 0, 1)
                if self.votes[index] > 0:
                    if self.directions[index] == 0:
                        fgColor = Vec4(0, 0, 1, 1)
                    else:
                        fgColor = Vec4(1, 0, 0, 1)
                if self.votes[index] > 0:
                    newLabel = DirectLabel(
                        parent=aspect2d,
                        relief=None,
                        pos=labelPos,
                        text='test',
                        text_fg=(1, 1, 1, 1),
                        text_scale=0.1,
                        text_align=TextNode.ACenter,
                        text_font=ToontownGlobals.getSignFont(),
                        text_pos=(0, -0.01, 0))
                else:
                    newLabel = DirectLabel(
                        parent=aspect2d,
                        geom=DGG.getDefaultDialogGeom(),
                        geom_scale=(0.2, 1, 0.2),
                        relief=None,
                        pos=labelPos,
                        text='test',
                        text_fg=(0.5, 0.5, 0.5, 1),
                        text_scale=0.1,
                        text_align=TextNode.ACenter,
                        text_font=ToontownGlobals.getSignFont(),
                        text_pos=(0, -0.035, 0))
                newLabel.wrtReparentTo(self.resultFrame)
                newLabel.hide()
                self.avVotesLabel[index] = newLabel

        matchingGameGui.removeNode()
        self.curArrowSfxIndex = 0
        self.upArrowSfx = []
        self.downArrowSfx = []
        for i in xrange(5):
            self.upArrowSfx.append(
                base.loadSfx(
                    'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg'))
            self.downArrowSfx.append(
                base.loadSfx(
                    'phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.ogg'))

        self.winVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_win_vote.ogg')
        self.noVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.ogg')
        self.loseVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.ogg')
        self.localAvatarWon = False
        self.localAvatarLost = False
        localIndex = self.avIdList.index(base.localAvatar.doId)
        localDirection = self.directions[localIndex]
        localVotes = self.votes[localIndex]
        if localVotes:
            if localDirection == self.directionToGo:
                if not TravelGameGlobals.ReverseWin:
                    self.localAvatarWon = True
                else:
                    self.localAvatarLost = True
            elif not TravelGameGlobals.ReverseWin:
                self.localAvatarLost = True
            else:
                self.localAvatarWon = True
        return
Esempio n. 16
0
class QuestPoster(DirectFrame):
    notify = directNotify.newCategory('QuestPoster')

    # We need to declare and initialize these variables here
    # because some methods use them as default arguments.
    auxIcon = None

    # Requires one parameter, quest, this must be a Quest instance.
    # The next argument, parent, is where to reparent the DirectFrame to.
    # The next arguments are simply additional options when setting up the DirectFrame.
    def __init__(self, quest, parent=aspect2d, **kw):
        # The quest this poster is representing.
        self.quest = quest

        # Let's define our options for the DirectFrame.
        bookModel = loader.loadModel(
            'phase_3.5/models/gui/stickerbook_gui.bam')
        optiondefs = (('relief', None,
                       None), ('image', bookModel.find('**/questCard'),
                               None), ('image_scale', (0.8, 1.0, 0.58), None),
                      ('state', DGG.NORMAL, None))
        self.defineoptions(kw, optiondefs)

        # Finally, initialize the DirectFrame.
        DirectFrame.__init__(self, relief=None)
        self.initialiseoptions(QuestPoster)

        # Let's declare and initialize our barebone GUI element variables.
        self.titleLabel = DirectLabel(parent=self,
                                      relief=None,
                                      text=self.quest.getName(),
                                      text_font=CIGlobals.getMinnieFont(),
                                      text_fg=QuestGlobals.TEXT_COLOR,
                                      text_scale=0.05,
                                      text_align=TextNode.ACenter,
                                      text_wordwrap=25.0,
                                      textMayChange=1,
                                      pos=(0, 0, 0.23))

        ##########################################################################
        #           THE FOLLOWING ELEMENTS BELOW ARE GROUPED TOGETHER            #
        ##########################################################################

        # The background frame where the objective image is displayed.
        # This is the colored background frame.
        self.auxFrame = DirectFrame(
            parent=self,
            relief=None,
            image=bookModel.find('**/questPictureFrame'),
            image_scale=QuestGlobals.IMAGE_SCALE_SMALL,
            text='',
            text_pos=(0, -0.11),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=QuestGlobals.QPtextScale,
            text_align=TextNode.ACenter,
            text_wordwrap=11.0,
            pos=QuestGlobals.DEFAULT_LEFT_PICTURE_POS)

        # The icon that goes on top of the aux frame.
        self.auxIcon = DirectFrame(parent=self.auxFrame,
                                   relief=None,
                                   text=' ',
                                   text_font=CIGlobals.getSuitFont(),
                                   text_pos=(0, -0.03),
                                   text_fg=QuestGlobals.TEXT_COLOR,
                                   text_scale=0.13,
                                   text_align=TextNode.ACenter,
                                   text_wordwrap=13.0,
                                   textMayChange=1)
        self.auxIcon.setColorOff(-1)

        # The aux text saying: DEFEAT, RECOVER, etc.
        self.auxText = DirectLabel(parent=self,
                                   relief=None,
                                   text=QuestGlobals.RECOVER,
                                   text_font=CIGlobals.getToonFont(),
                                   text_scale=QuestGlobals.QPauxText,
                                   text_fg=QuestGlobals.TEXT_COLOR,
                                   text_align=TextNode.ACenter,
                                   textMayChange=1,
                                   pos=QuestGlobals.DEFAULT_AUX_POS)
        self.auxText.hide()

        ##########################################################################

        # Information displayed about the objective.
        self.objectiveInfo = DirectLabel(
            parent=self,
            relief=None,
            text='',
            text_font=CIGlobals.getToonFont(),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=0.04,
            text_align=TextNode.ACenter,
            text_wordwrap=QuestGlobals.QPtextWordwrap,
            textMayChange=1,
            pos=(QuestGlobals.DEFAULT_INFO_POS))
        self.objectiveInfo.hide()

        # Information displayed showing the location.
        self.locationInfo = DirectLabel(
            parent=self,
            relief=None,
            text='N/A',
            text_font=CIGlobals.getToonFont(),
            text_fg=QuestGlobals.TEXT_COLOR,
            text_scale=QuestGlobals.QPtextScale,
            text_align=TextNode.ACenter,
            text_wordwrap=QuestGlobals.QPtextWordwrap,
            textMayChange=1,
            pos=(0, 0, -0.115))
        self.locationInfo.hide()

        # The progress bar showing the objective's progress
        self.progressBar = DirectWaitBar(parent=self,
                                         relief=DGG.SUNKEN,
                                         frameSize=(-0.95, 0.95, -0.1, 0.12),
                                         borderWidth=(0.025, 0.025),
                                         scale=0.2,
                                         frameColor=(0.945, 0.875, 0.706, 1.0),
                                         barColor=(0.5, 0.7, 0.5, 1),
                                         text='0/0',
                                         text_font=CIGlobals.getToonFont(),
                                         text_scale=0.19,
                                         text_fg=(0.05, 0.14, 0.4, 1),
                                         text_align=TextNode.ACenter,
                                         text_pos=(0, -0.05),
                                         pos=(0, 0, -0.2425))
        self.progressBar.hide()

        # The wood panel at the bottom where rewards are displayed.
        rewardFrameGeom = loader.loadModel(
            'phase_4/models/gui/gag_shop_purchase_gui.bam')
        self.rewardFrame = DirectFrame(
            parent=self,
            relief=None,
            geom=rewardFrameGeom.find('**/Goofys_Sign'),
            geom_scale=(0.615, 0, 0.4),
            pos=(-0.01, 0, -0.25))

        # The text displayed on the right side of the frame with additional information, if necessary.
        self.sideInfo = DirectLabel(parent=self,
                                    relief=None,
                                    text=QuestGlobals.JUST_FOR_FUN,
                                    text_fg=(0.0, 0.439, 1.0, 1.0),
                                    text_shadow=(0, 0, 0, 1),
                                    pos=(-0.2825, 0, 0.2),
                                    scale=0.03)
        self.sideInfo.setR(-30)

        # This side information is usually not needed, let's hide it.
        self.sideInfo.hide()

        # Remove the nodes of the loaded models we no longer need.
        bookModel.removeNode()
        rewardFrameGeom.removeNode()

        # Let's hide this until it is needed.
        self.hide()
        return

    def setup(self):
        objective = self.quest.currentObjective
        objective.updateInfo()

        self.objectiveInfo.show()
        self.auxFrame.show()

        self.locationInfo['text'] = QuestGlobals.getLocationText(
            objective.location)
        self.locationInfo['text_pos'] = (0,
                                         0 if not QuestGlobals.isShopLocation(
                                             objective.location) else 0.025)
        self.locationInfo.show()

        # Let's setup the quest progress bar
        progress = objective.amount if hasattr(objective, 'amount') else None

        if progress and objective.neededAmount > 0:
            self.progressBar['range'] = objective.getNeededAmount()
            self.progressBar['value'] = progress & pow(2, 16) - 1

        if objective.__class__ in [
                DeliverItemObjective, CogObjective, RecoverItemObjective
        ]:
            self.progressBar.show()

        self.auxText.show()

        # Let's handle the objectives.
        if objective.__class__ == CogObjective:
            self.handleCogObjective()
        elif objective.__class__ == VisitNPCObjective:
            self.handleNPCObjective()

        self.titleLabel.initialiseoptions(DirectLabel)
        self.auxIcon.initialiseoptions(DirectFrame)
        self.auxText.initialiseoptions(DirectLabel)
        self.objectiveInfo.initialiseoptions(DirectLabel)
        self.locationInfo.initialiseoptions(DirectLabel)
        self.rewardFrame.initialiseoptions(DirectFrame)
        self.sideInfo.initialiseoptions(DirectLabel)

    # Changes geometry and scale of an icon.
    def handleSimpleIcon(self, geom, scale, icon):
        icon['geom'] = geom
        icon['geom_scale'] = scale

    def handleComplexIcon(self,
                          geom,
                          icon,
                          scale=QuestGlobals.IMAGE_SCALE_SMALL):
        isHead = True if type(geom) == ToonHead else geom.getName() == (
            '%sHead' % CIGlobals.Suit)

        if isHead:
            geom.setDepthWrite(1)
            geom.setDepthTest(1)
            self.fitGeometry(geom, fFlip=1)
            self.handleSimpleIcon(geom, scale, icon)

            # We have to rotate the head and set the scale of the icon.
            if CIGlobals.Suit in geom.getName():
                cogName = geom.getPythonTag('Settings')
                data = QuestGlobals.Suit2PosterZNDScale.get(cogName)
                zOffset = data[0]
                headScale = data[1]
                icon.setScale(headScale)
                icon.setZ(icon.getZ() + zOffset)
                geom.setH(180)
        else:
            raise ValueError(
                'Tried to use #handleComplexIcon() on a non-complex icon. Use this method for 3D geometry.'
            )

    def handleCogObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.DEFEAT,
                           frameColor=QuestGlobals.BLUE):
        objective = self.quest.currentObjective
        infoText = objective.getTaskInfo(speech=False)

        if objective.__class__ == RecoverItemObjective:
            infoText = QuestGlobals.makePlural(objective.name)
            print 'Yep'

        if not iconElement:
            iconElement = self.auxIcon

        # Let's make sure we have a current objective that is
        # an instance of the CogObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, CogObjective):
            return

        if objective.dept:
            icons = loader.loadModel('phase_3/models/gui/cog_icons.bam')
            deptIcon = None

            if objective.dept == Dept.BOSS:
                deptIcon = icons.find('**/CorpIcon')
            else:
                deptIcon = icons.find('**/%sIcon' %
                                      objective.dept.getTie().title())

            # Correct the medallion color.
            deptIcon.setColor(SuitGlobals.medallionColors[objective.dept])

            # Setup the icon and remove the icons node.
            self.handleSimpleIcon(deptIcon, 0.13, iconElement)
            icons.removeNode()
        elif not objective.name:
            # We aren't fighting a Cog in particular.
            cogIcon = QuestGlobals.getCogIcon()
            self.handleSimpleIcon(cogIcon, cogIcon.getScale(), iconElement)

        # We're fighting a Cog in particular.
        if objective.name:
            cogHeadInstance = SuitBank.getSuitByName(objective.name).getHead()
            cogHead = cogHeadInstance.generate()
            cogHead.setName('%sHead' % CIGlobals.Suit)
            cogHead.setPythonTag('Settings', cogHeadInstance.head)
            cogHeadInstance.setScale(2)
            self.handleComplexIcon(cogHead, iconElement)

        if not iconElement is self.auxIcon:
            if hasattr(self, 'goalInfo'):
                # We're working with the second frame, on the right.
                # Let's update the information pertaining to this side.
                self.goalInfo['text'] = infoText
                self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS)
                self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS)
            else:
                raise AttributeError(
                    'Attempted to setup DoubleFrame information for poster using default style.'
                )
        else:
            self.objectiveInfo['text'] = infoText
            self.auxText['text'] = auxText

        # Let's set the progress bar text
        pgBarText = '%d of %d %s' % (objective.amount, objective.neededAmount,
                                     QuestGlobals.makePastTense(auxText))
        self.progressBar['text'] = pgBarText

        # Let's set the color of the poster.
        frame = self.auxFrame if iconElement is self.auxIcon else self.goalFrame
        frame['image_color'] = Vec4(*frameColor)

    def handleNPCObjective(self,
                           iconElement=auxIcon,
                           auxText=QuestGlobals.VISIT,
                           frameColor=QuestGlobals.BROWN):
        objective = self.quest.currentObjective
        infoText = CIGlobals.NPCToonNames[objective.npcId]

        if not iconElement:
            iconElement = self.auxIcon

        # Let's make sure we have a current objective that is
        # an instance of the CogObjective class and this poster isn't destroyed.
        if not objective or not hasattr(self, 'titleLabel') or not isinstance(
                objective, VisitNPCObjective):
            return

        # Let's generate the head.
        dna = ToonDNA()
        dna.setDNAStrand(CIGlobals.NPCToonDict.get(objective.npcId)[2])
        head = ToonHead(base.cr)
        head.generateHead(dna.getGender(),
                          dna.getAnimal(),
                          dna.getHead(),
                          forGui=1)
        head.setHeadColor(dna.getHeadColor())
        self.handleComplexIcon(head, iconElement)

        self.auxText['text'] = auxText

        if not iconElement is self.auxIcon:
            if hasattr(self, 'goalInfo'):
                # We're working with the second frame, on the right.
                # Let's update the information pertaining to this side.
                self.goalInfo['text'] = infoText
                self.goalInfo.setPos(QuestGlobals.RECOVER_INFO2_POS)
                self.auxText.setPos(QuestGlobals.RECOVER_AUX_POS)
                self.goalFrame['image_color'] = frameColor
            else:
                raise AttributeError(
                    'Attempted to setup DoubleFrame information for poster using default style.'
                )
        else:
            self.objectiveInfo['text'] = infoText
            self.auxFrame['image_color'] = frameColor

    def fitGeometry(self, geom, fFlip=0, dimension=0.8):
        p1 = Point3()
        p2 = Point3()
        geom.calcTightBounds(p1, p2)
        if fFlip:
            t = p1[0]
            p1.setX(-p2[0])
            p2.setX(-t)
        d = p2 - p1
        biggest = max(d[0], d[2])
        s = dimension / biggest
        mid = (p1 + d / 2.0) * s
        geomXform = hidden.attachNewNode('geomXform')
        for child in geom.getChildren():
            child.reparentTo(geomXform)

        geomXform.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], 180, 0, 0, s,
                                 s, s)
        geomXform.reparentTo(geom)

    def destroy(self):
        if hasattr(self, 'titleLabel'):
            self.titleLabel.destroy()
            self.auxFrame.destroy()
            self.auxIcon.destroy()
            self.auxText.destroy()
            self.objectiveInfo.destroy()
            self.locationInfo.destroy()
            self.progressBar.destroy()
            self.rewardFrame.destroy()
            self.sideInfo.destroy()
            del self.titleLabel
            del self.auxFrame
            del self.auxIcon
            del self.auxText
            del self.objectiveInfo
            del self.locationInfo
            del self.progressBar
            del self.rewardFrame
            del self.sideInfo
            DirectFrame.destroy(self)
            self.notify.debug('Destroyed all elements.')
Esempio n. 17
0
class SimpleInteractive(DirectObject):
    __module__ = __name__

    def __init__(self, object, name, proximityText):
        DirectObject.__init__(self)
        self.object = object
        self.proximityText = proximityText
        self.proximityEvent = name
        self.enterProximityEvent = 'enter' + name
        self.exitProximityEvent = 'exit' + name
        self.useLabel = None
        self.fader = None
        self.size = 6
        self.disk = None
        proximitySphere = CollisionSphere(0, 0, 0, self.size)
        proximitySphere.setTangible(0)
        proximityNode = CollisionNode(self.proximityEvent)
        proximityNode.setIntoCollideMask(PiratesGlobals.WallBitmask)
        proximityNode.addSolid(proximitySphere)
        self.proximityNodePath = self.object.attachNewNode(proximityNode)
        self.accept(self.enterProximityEvent, self.approach)
        self.accept(self.exitProximityEvent, self.leave)
        return

    def createInteractionDisk(self):
        self.disk = loader.loadModel('models/effects/selectionCursor')
        self.disk.setScale(self.size)
        self.disk.setColorScale(0, 1, 0, 1)
        self.disk.setP(-90)
        self.disk.setZ(0.025)
        self.disk.setBillboardAxis(6)
        self.disk.reparentTo(self.object)
        self.disk.setBin('shadow', 0)
        self.disk.setTransparency(TransparencyAttrib.MAlpha)
        self.disk.setDepthWrite(0)
        self.disk.setDepthTest(0)

    def loadUseLabel(self, text):
        self.useLabel = DirectLabel(
            parent=aspect2d,
            frameColor=(0.1, 0.1, 0.25, 0.2),
            text=text,
            text_align=TextNode.ACenter,
            text_scale=0.06,
            text_pos=(0.02, 0.02),
            text_fg=(1, 1, 1, 1),
            text_shadow=(0, 0, 0, 1),
            textMayChange=1,
            text_font=PiratesGlobals.getPirateOutlineFont())
        self.useLabel.setPos(0, 0, -0.7)
        self.useLabel.setAlphaScale(0)
        self.useLabel.hide()

    def fadeInText(self):
        if self.fader:
            self.fader.pause()

    def interactionAllowed(self, avId):
        return True

    def approach(self, collEntry):
        if not self.interactionAllowed(localAvatar.doId):
            return
        if not self.disk:
            self.createInteractionDisk()
        if self.proximityText:
            if not self.useLabel:
                self.loadUseLabel(self.proximityText)
            if self.fader:
                self.fader.pause()
            fadeIn = LerpFunctionInterval(self.useLabel.setAlphaScale,
                                          fromData=0,
                                          toData=1,
                                          duration=0.5)
            self.fader = Sequence(Func(self.useLabel.show), fadeIn)
            self.fader.start()
        self.disk.show()
        self.accept(USE_KEY_EVENT, self.handleUseKey)

    def requestInteraction(self, avId):
        pass

    def handleUseKey(self):
        self.requestInteraction(localAvatar.doId)

    def leave(self, collEntry):
        if self.disk:
            self.disk.hide()
        if self.proximityText:
            if self.fader:
                self.fader.pause()
                self.fader = None
            if self.useLabel:
                self.useLabel.hide()
        self.ignore(USE_KEY_EVENT)
        return
Esempio n. 18
0
class DistCogdoGame(DistributedObject):
    notify = directNotify.newCategory("DistCogdoGame")

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)

        self._waitingStartLabel = DirectLabel(
            text=TTL.MinigameWaitingForOtherPlayers,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self._waitingStartLabel.hide()

        self.loadFSM = ClassicFSM.ClassicFSM(
            'DistCogdoGame.loaded',
            [
                State.State('NotLoaded', self.enterNotLoaded,
                            self.exitNotLoaded, ['Loaded']),
                State.State('Loaded', self.enterLoaded, self.exitLoaded,
                            ['NotLoaded'])
            ],
            # Initial state
            'NotLoaded',
            # Final state
            'NotLoaded')

        self.fsm = ClassicFSM.ClassicFSM(
            'DistCogdoGame',
            [
                State.State('Intro', self.enterIntro, self.exitIntro,
                            ['WaitServerStart']),
                State.State('WaitServerStart', self.enterWaitServerStart,
                            self.exitWaitServerStart, ['Game']),
                State.State('Game', self.enterGame, self.exitGame, ['Finish']),
                State.State('Finish', self.enterFinish, self.exitFinish,
                            ['Off']),
                State.State('Off', self.enterOff, self.exitOff, ['Intro'])
            ],
            # Initial state
            'Off',
            # Final state
            'Off')
        self.fsm.enterInitialState()

    def getTitle(self):
        pass  # override and return title

    def getInstructions(self):
        pass  # override and return instructions

    def setInteriorId(self, interiorId):
        self._interiorId = interiorId

    def getInterior(self):
        return self.cr.getDo(self._interiorId)

    def getToonIds(self):
        toonIds = []
        interior = self.getInterior()
        for toonId in interior.getToons()[0]:
            if toonId:
                toonIds.append(toonId)
        return toonIds

    def getNumPlayers(self):
        return len(self.getToonIds())

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        self.loadFSM.request('Loaded')

    def disable(self):
        self.fsm.requestFinalState()
        self.loadFSM.requestFinalState()
        self.fsm = None
        self.loadFSM = None
        DistributedObject.disable(self)

    def delete(self):
        self._waitingStartLabel.destroy()
        self._waitingStartLabel = None
        DistributedObject.delete(self)

    def enterNotLoaded(self):
        pass

    def exitNotLoaded(self):
        pass

    def enterLoaded(self):
        pass

    def exitLoaded(self):
        pass

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def setIntroStart(self):
        self.fsm.request('Intro')

    def enterIntro(self):
        assert self.notify.debugCall()
        base.cr.playGame.getPlace().fsm.request('Game')
        self._rulesDoneEvent = uniqueName('cogdoGameRulesDone')
        self.accept(self._rulesDoneEvent, self._handleRulesDone)
        self._rulesPanel = MinigameRulesPanel("MinigameRulesPanel",
                                              self.getTitle(),
                                              self.getInstructions(),
                                              self._rulesDoneEvent)
        self._rulesPanel.load()
        self._rulesPanel.enter()

    def exitIntro(self):
        self.ignore(self._rulesDoneEvent)
        if self._rulesPanel:
            self._rulesPanel.exit()
            self._rulesPanel.unload()
            self._rulesPanel = None

    def _handleRulesDone(self):
        self.ignore(self._rulesDoneEvent)
        self._rulesPanel.exit()
        self._rulesPanel.unload()
        self._rulesPanel = None
        self.sendUpdate('setAvatarReady', [])
        self.fsm.request('WaitServerStart')

    def enterWaitServerStart(self):
        numToons = 1
        interior = self.getInterior()
        if interior:
            numToons = len(interior.getToonIds())
        if numToons > 1:
            msg = TTL.MinigameWaitingForOtherPlayers
        else:
            msg = TTL.MinigamePleaseWait
        self._waitingStartLabel['text'] = msg
        self._waitingStartLabel.show()

    def exitWaitServerStart(self):
        self._waitingStartLabel.hide()

    def setGameStart(self, timestamp):
        self._startTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Game')

    def getStartTime(self):
        return self._startTime

    def enterGame(self):
        assert self.notify.debugCall()

    def exitGame(self):
        pass

    def setGameFinish(self, timestamp):
        self._finishTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Finish')

    def getFinishTime(self):
        return self._finishTime

    def enterFinish(self):
        assert self.notify.debugCall()

    def exitFinish(self):
        pass
class JellybeanRewardGui(DirectFrame):
    notify = directNotify.newCategory('JellybeanRewardGui')
    PreCountdownDelay = 1.0
    CountDownRate = 0.2
    JarLabelTextColor = (0.95, 0.95, 0.0, 1.0)
    JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0)

    def __init__(self, doneEvent):
        self.doneEvent = doneEvent
        DirectFrame.__init__(self)
        self.reparentTo(aspect2d)
        self.setPos(0.0, 0.0, 0.16)
        self.stash()
        publicPartyGui = loader.loadModel(
            'phase_4/models/parties/publicPartyGUI')
        self.frame = DirectFrame(
            parent=self,
            geom=publicPartyGui.find('**/activities_background'),
            geom_pos=(-0.8, 0.0, 0.2),
            geom_scale=2.0,
            relief=None)
        self.earnedLabel = DirectLabel(
            parent=self,
            relief=None,
            text=str(0),
            text_align=TextNode.ACenter,
            text_pos=(0.0, -0.07),
            text_scale=0.2,
            text_fg=(0.95, 0.95, 0.0, 1.0),
            text_font=ToontownGlobals.getSignFont(),
            textMayChange=True,
            image=DirectGuiGlobals.getDefaultDialogGeom(),
            image_scale=(0.33, 1.0, 0.33),
            pos=(-0.3, 0.0, 0.2),
            scale=0.9)
        purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui')
        jarImage = purchaseModels.find('**/Jar')
        self.jarLabel = DirectLabel(
            parent=self,
            relief=None,
            text=str(0),
            text_align=TextNode.ACenter,
            text_pos=(0.0, -0.07),
            text_scale=0.2,
            text_fg=JellybeanRewardGui.JarLabelTextColor,
            text_font=ToontownGlobals.getSignFont(),
            textMayChange=True,
            image=jarImage,
            scale=0.7,
            pos=(0.3, 0.0, 0.17))
        purchaseModels.removeNode()
        del purchaseModels
        jarImage.removeNode()
        del jarImage
        self.messageLabel = DirectLabel(parent=self,
                                        relief=None,
                                        text='',
                                        text_align=TextNode.ALeft,
                                        text_wordwrap=16.0,
                                        text_scale=0.07,
                                        pos=(-0.52, 0.0, -0.1),
                                        textMayChange=True)
        self.doubledJellybeanLabel = DirectLabel(
            parent=self,
            relief=None,
            text=TTLocalizer.PartyRewardDoubledJellybean,
            text_align=TextNode.ACenter,
            text_wordwrap=12.0,
            text_scale=0.09,
            text_fg=(1.0, 0.125, 0.125, 1.0),
            pos=(0.0, 0.0, -0.465),
            textMayChange=False)
        self.doubledJellybeanLabel.hide()
        self.closeButton = DirectButton(
            parent=self,
            relief=None,
            text=TTLocalizer.PartyJellybeanRewardOK,
            text_align=TextNode.ACenter,
            text_scale=0.065,
            text_pos=(0.0, -0.625),
            geom=(publicPartyGui.find('**/startButton_up'),
                  publicPartyGui.find('**/startButton_down'),
                  publicPartyGui.find('**/startButton_rollover'),
                  publicPartyGui.find('**/startButton_inactive')),
            geom_pos=(-0.39, 0.0, 0.125),
            command=self._close)
        publicPartyGui.removeNode()
        del publicPartyGui
        self.countSound = base.loadSfx(
            'phase_13/audio/sfx/tick_counter_short.ogg')
        self.overMaxSound = base.loadSfx(
            'phase_13/audio/sfx/tick_counter_overflow.ogg')
        return

    def showReward(self, earnedAmount, jarAmount, message):
        JellybeanRewardGui.notify.debug(
            'showReward( earnedAmount=%d, jarAmount=%d, ...)' %
            (earnedAmount, jarAmount))
        self.earnedCount = earnedAmount
        self.earnedLabel['text'] = str(self.earnedCount)
        self.jarCount = jarAmount
        self.jarMax = base.localAvatar.getMaxMoney()
        self.jarLabel['text'] = str(self.jarCount)
        self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelTextColor
        self.messageLabel['text'] = message
        if base.cr.newsManager.isHolidayRunning(
                ToontownGlobals.JELLYBEAN_DAY
        ) or base.cr.newsManager.isHolidayRunning(
                ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY
        ) or base.cr.newsManager.isHolidayRunning(
                ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY_MONTH):
            self.doubledJellybeanLabel.show()
        else:
            self.doubledJellybeanLabel.hide()
        self.unstash()
        taskMgr.doMethodLater(JellybeanRewardGui.PreCountdownDelay,
                              self.transferOneJellybean,
                              'JellybeanRewardGuiTransferOneJellybean',
                              extraArgs=[])

    def transferOneJellybean(self):
        if self.earnedCount == 0:
            return
        self.earnedCount -= 1
        self.earnedLabel['text'] = str(self.earnedCount)
        self.jarCount += 1
        if self.jarCount <= self.jarMax:
            self.jarLabel['text'] = str(self.jarCount)
        elif self.jarCount > self.jarMax:
            self.jarLabel[
                'text_fg'] = JellybeanRewardGui.JarLabelMaxedTextColor
        if self.jarCount <= self.jarMax:
            base.playSfx(self.countSound)
        else:
            base.playSfx(self.overMaxSound)
        taskMgr.doMethodLater(JellybeanRewardGui.CountDownRate,
                              self.transferOneJellybean,
                              'JellybeanRewardGuiTransferOneJellybean',
                              extraArgs=[])

    def _close(self):
        taskMgr.remove('JellybeanRewardGuiTransferOneJellybean')
        self.stash()
        messenger.send(self.doneEvent)

    def destroy(self):
        taskMgr.remove('JellybeanRewardGuiTransferOneJellybean')
        del self.countSound
        del self.overMaxSound
        self.frame.destroy()
        self.earnedLabel.destroy()
        self.jarLabel.destroy()
        self.messageLabel.destroy()
        self.closeButton.destroy()
        DirectFrame.destroy(self)
Esempio n. 20
0
class IsisAgent(kinematicCharacterController, DirectObject):
    @classmethod
    def setPhysics(cls, physics):
        """ This method is set in src.loader when the generators are loaded
        into the namespace.  This frees the environment definitions (in 
        scenario files) from having to pass around the physics parameter 
        that is required for all IsisObjects """
        cls.physics = physics

    def __init__(self, name, queueSize=100):

        # load the model and the different animations for the model into an Actor object.
        self.actor = Actor(
            "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"}
        )
        self.actor.setScale(1.0)
        self.actor.setH(0)
        # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params
        self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0)
        self.actorNodePath = NodePath("agent-%s" % name)
        self.activeModel = self.actorNodePath

        self.actorNodePath.reparentTo(render)

        self.actor.reparentTo(self.actorNodePath)
        self.name = name
        self.isMoving = False

        # initialize ODE controller
        kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath)
        self.setGeomPos(self.actorNodePath.getPos(render))
        """
        Additional Direct Object that I use for convenience.
        """
        self.specialDirectObject = DirectObject()

        """
        How high above the center of the capsule you want the camera to be
        when walking and when crouching. It's related to the values in KCC.
        """
        self.walkCamH = 0.7
        self.crouchCamH = 0.2
        self.camH = self.walkCamH

        """
        This tells the Player Controller what we're aiming at.
        """
        self.aimed = None

        self.isSitting = False
        self.isDisabled = False

        """
        The special direct object is used for trigger messages and the like.
        """
        # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True])
        # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False])

        self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"])

        # Expose agent's right hand joint to attach objects to
        self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R")
        self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L")

        self.right_hand_holding_object = None
        self.left_hand_holding_object = None

        # don't change the color of things you pick up
        self.player_right_hand.setColorScaleOff()
        self.player_left_hand.setColorScaleOff()

        self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head")
        self.neck = self.actor.controlJoint(None, "modelRoot", "Head")

        self.controlMap = {
            "turn_left": 0,
            "turn_right": 0,
            "move_forward": 0,
            "move_backward": 0,
            "move_right": 0,
            "move_left": 0,
            "look_up": 0,
            "look_down": 0,
            "look_left": 0,
            "look_right": 0,
            "jump": 0,
        }
        # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left]
        # turns are in degrees per second, moves are in units per second
        self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60]

        self.originalPos = self.actor.getPos()

        bubble = loader.loadTexture("media/textures/thought_bubble.png")
        # bubble.setTransparency(TransparencyAttrib.MAlpha)

        self.speech_bubble = DirectLabel(
            parent=self.actor,
            text="",
            text_wordwrap=10,
            pad=(3, 3),
            relief=None,
            text_scale=(0.3, 0.3),
            pos=(0, 0, 3.6),
            frameColor=(0.6, 0.2, 0.1, 0.5),
            textMayChange=1,
            text_frame=(0, 0, 0, 1),
            text_bg=(1, 1, 1, 1),
        )
        # self.myImage=
        self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.speech_bubble.setColorScaleOff()
        self.speech_bubble.component("text0").textNode.setCardDecal(1)
        self.speech_bubble.setBillboardAxis()
        # hide the speech bubble from IsisAgent's own camera
        self.speech_bubble.hide(BitMask32.bit(1))

        self.thought_bubble = DirectLabel(
            parent=self.actor,
            text="",
            text_wordwrap=9,
            text_frame=(1, 0, -2, 1),
            text_pos=(0, 0.5),
            text_bg=(1, 1, 1, 0),
            relief=None,
            frameSize=(0, 1.5, -2, 3),
            text_scale=(0.18, 0.18),
            pos=(0, 0.2, 3.6),
            textMayChange=1,
            image=bubble,
            image_pos=(0, 0.1, 0),
            sortOrder=5,
        )
        self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.thought_bubble.setColorScaleOff()
        self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0)
        self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1)
        self.thought_bubble.component("text0").textNode.setCardDecal(1)
        self.thought_bubble.setBillboardAxis()
        # hide the thought bubble from IsisAgent's own camera
        self.thought_bubble.hide(BitMask32.bit(1))
        # disable by default
        self.thought_bubble.hide()
        self.thought_filter = {}  # only show thoughts whose values are in here
        self.last_spoke = 0  # timers to keep track of last thought/speech and
        self.last_thought = 0  # hide visualizations

        # put a camera on ralph
        self.fov = NodePath(Camera("RaphViz"))
        self.fov.node().setCameraMask(BitMask32.bit(1))

        # position the camera to be infront of Boxman's face.
        self.fov.reparentTo(self.player_head)
        # x,y,z are not in standard orientation when parented to player-Head
        self.fov.setPos(0, 0.2, 0)
        # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face.
        self.fov.setHpr(0, -90, 0)

        lens = self.fov.node().getLens()
        lens.setFov(60)  #  degree field of view (expanded from 40)
        lens.setNear(0.2)
        # self.fov.node().showFrustum() # displays a box around his head
        # self.fov.place()

        self.prevtime = 0
        self.current_frame_count = 0

        self.isSitting = False
        self.isDisabled = False
        self.msg = None
        self.actorNodePath.setPythonTag("agent", self)

        # Initialize the action queue, with a maximum length of queueSize
        self.queue = []
        self.queueSize = queueSize
        self.lastSense = 0

    def setLayout(self, layout):
        """ Dummy method called by spatial methods for use with objects. 
        Doesn't make sense for an agent that can move around."""
        pass

    def setPos(self, pos):
        """ Wrapper to set the position of the ODE geometry, which in turn 
        sets the visual model's geometry the next time the update() method
        is called. """
        self.setGeomPos(pos)

    def setPosition(self, pos):
        self.setPos(pos)

    def reparentTo(self, parent):
        self.actorNodePath.reparentTo(parent)

    def setControl(self, control, value):
        """Set the state of one of the character's movement controls.  """
        self.controlMap[control] = value

    def get_objects_in_field_of_vision(self, exclude=["isisobject"]):
        """ This works in an x-ray style. Fast. Works best if you listen to
        http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while
        you use it.
        
        needs to exclude isisobjects since they cannot be serialized  
        """
        objects = {}
        for obj in base.render.findAllMatches("**/IsisObject*"):
            if not obj.hasPythonTag("isisobj"):
                continue
            o = obj.getPythonTag("isisobj")
            bounds = o.activeModel.getBounds()
            bounds.xform(o.activeModel.getMat(self.fov))
            if self.fov.node().isInView(o.activeModel.getPos(self.fov)):
                pos = o.activeModel.getPos(render)
                pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2)
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1]))
                object_dict = {}
                if "x_pos" not in exclude:
                    object_dict["x_pos"] = p3[0]
                if "y_pos" not in exclude:
                    object_dict["y_pos"] = p3[2]
                if "distance" not in exclude:
                    object_dict["distance"] = o.activeModel.getDistance(self.fov)
                if "orientation" not in exclude:
                    object_dict["orientation"] = o.activeModel.getH(self.fov)
                if "actions" not in exclude:
                    object_dict["actions"] = o.list_actions()
                if "isisobject" not in exclude:
                    object_dict["isisobject"] = o
                # add item to dinctionary
                objects[o] = object_dict
        return objects

    def get_agents_in_field_of_vision(self):
        """ This works in an x-ray vision style as well"""
        agents = {}
        for agent in base.render.findAllMatches("**/agent-*"):
            if not agent.hasPythonTag("agent"):
                continue
            a = agent.getPythonTag("agent")
            bounds = a.actorNodePath.getBounds()
            bounds.xform(a.actorNodePath.getMat(self.fov))
            pos = a.actorNodePath.getPos(self.fov)
            if self.fov.node().isInView(pos):
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1]))
                agentDict = {
                    "x_pos": p3[0],
                    "y_pos": p3[2],
                    "distance": a.actorNodePath.getDistance(self.fov),
                    "orientation": a.actorNodePath.getH(self.fov),
                }
                agents[a] = agentDict
        return agents

    def in_view(self, isisobj):
        """ Returns true iff a particular isisobject is in view """
        return len(
            filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())
        )

    def get_objects_in_view(self):
        """ Gets objects through ray tracing.  Slow"""
        return self.picker.get_objects_in_view()

    def control__turn_left__start(self, speed=None):
        self.setControl("turn_left", 1)
        self.setControl("turn_right", 0)
        if speed:
            self.speeds[0] = speed
        return "success"

    def control__turn_left__stop(self):
        self.setControl("turn_left", 0)
        return "success"

    def control__turn_right__start(self, speed=None):
        self.setControl("turn_left", 0)
        self.setControl("turn_right", 1)
        if speed:
            self.speeds[1] = speed
        return "success"

    def control__turn_right__stop(self):
        self.setControl("turn_right", 0)
        return "success"

    def control__move_forward__start(self, speed=None):
        self.setControl("move_forward", 1)
        self.setControl("move_backward", 0)
        if speed:
            self.speeds[2] = speed
        return "success"

    def control__move_forward__stop(self):
        self.setControl("move_forward", 0)
        return "success"

    def control__move_backward__start(self, speed=None):
        self.setControl("move_forward", 0)
        self.setControl("move_backward", 1)
        if speed:
            self.speeds[3] = speed
        return "success"

    def control__move_backward__stop(self):
        self.setControl("move_backward", 0)
        return "success"

    def control__move_left__start(self, speed=None):
        self.setControl("move_left", 1)
        self.setControl("move_right", 0)
        if speed:
            self.speeds[4] = speed
        return "success"

    def control__move_left__stop(self):
        self.setControl("move_left", 0)
        return "success"

    def control__move_right__start(self, speed=None):
        self.setControl("move_right", 1)
        self.setControl("move_left", 0)
        if speed:
            self.speeds[5] = speed
        return "success"

    def control__move_right__stop(self):
        self.setControl("move_right", 0)
        return "success"

    def control__look_left__start(self, speed=None):
        self.setControl("look_left", 1)
        self.setControl("look_right", 0)
        if speed:
            self.speeds[9] = speed
        return "success"

    def control__look_left__stop(self):
        self.setControl("look_left", 0)
        return "success"

    def control__look_right__start(self, speed=None):
        self.setControl("look_right", 1)
        self.setControl("look_left", 0)
        if speed:
            self.speeds[8] = speed
        return "success"

    def control__look_right__stop(self):
        self.setControl("look_right", 0)
        return "success"

    def control__look_up__start(self, speed=None):
        self.setControl("look_up", 1)
        self.setControl("look_down", 0)
        if speed:
            self.speeds[6] = speed
        return "success"

    def control__look_up__stop(self):
        self.setControl("look_up", 0)
        return "success"

    def control__look_down__start(self, speed=None):
        self.setControl("look_down", 1)
        self.setControl("look_up", 0)
        if speed:
            self.speeds[7] = speed
        return "success"

    def control__look_down__stop(self):
        self.setControl("look_down", 0)
        return "success"

    def control__jump(self):
        self.setControl("jump", 1)
        return "success"

    def control__view_objects(self):
        """ calls a raytrace to to all objects in view """
        objects = self.get_objects_in_field_of_vision()
        self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects))
        print "Objects in view:", objects
        return objects

    def control__sense(self):
        """ perceives the world, returns percepts dict """
        percepts = dict()
        # eyes: visual matricies
        # percepts['vision'] = self.sense__get_vision()
        # objects in purview (cheating object recognition)
        percepts["objects"] = self.sense__get_objects()
        # global position in environment - our robots can have GPS :)
        percepts["position"] = self.sense__get_position()
        # language: get last utterances that were typed
        percepts["language"] = self.sense__get_utterances()
        # agents: returns a map of agents to a list of actions that have been sensed
        percepts["agents"] = self.sense__get_agents()
        print percepts
        return percepts

    def control__think(self, message, layer=0):
        """ Changes the contents of an agent's thought bubble"""
        # only say things that are checked in the controller
        if self.thought_filter.has_key(layer):
            self.thought_bubble.show()
            self.thought_bubble["text"] = message
            # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05)
            # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer])
            self.last_thought = 0
        return "success"

    def control__say(self, message="Hello!"):
        self.speech_bubble["text"] = message
        self.last_spoke = 0
        return "success"

    """

    Methods explicitly for IsisScenario files 

    """

    def put_in_front_of(self, isisobj):
        # find open direction
        pos = isisobj.getGeomPos()
        direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0))
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom])
        print "CLOSEST", closestEntry, closestObject
        if closestObject == None:
            self.setPosition(pos + Vec3(0, 2, 0))
        else:
            print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject)
            direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0))
            closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom])
            if closestEntry == None:
                self.setPosition(pos + Vec3(0, -2, 0))
            else:
                print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject)
                direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0))
                closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                    "aimRay", 5, [pos, direction], [isisobj.geom]
                )
                if closestEntry == None:
                    self.setPosition(pos + Vec3(2, 0, 0))
                else:
                    print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject)
                    # there's only one option left, do it anyway
                    self.setPosition(pos + Vec3(-2, 0, 0))
        # rotate agent to look at it
        self.actorNodePath.setPos(self.getGeomPos())
        self.actorNodePath.lookAt(pos)
        self.setH(self.actorNodePath.getH())

    def put_in_right_hand(self, target):
        return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand)

    def put_in_left_hand(self, target):
        return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand)

    def __get_object_in_center_of_view(self):
        direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
        pos = self.fov.getPos(render)
        exclude = []  # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom]
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude)
        return closestObject

    def pick_object_up_with(self, target, hand_slot, hand_joint):
        """ Attaches an IsisObject, target, to the hand joint.  Does not check anything first,
        other than the fact that the hand joint is not currently holding something else."""
        if hand_slot != None:
            print "already holding " + hand_slot.getName() + "."
            return None
        else:
            if target.layout:
                target.layout.remove(target)
                target.layout = None
            # store original position
            target.originalHpr = target.getHpr(render)
            target.disable()  # turn off physics
            if target.body:
                target.body.setGravityMode(0)
            target.reparentTo(hand_joint)
            target.setPosition(hand_joint.getPos(render))
            target.setTag("heldBy", self.name)
            if hand_joint == self.player_right_hand:
                self.right_hand_holding_object = target
            elif hand_joint == self.player_left_hand:
                self.left_hand_holding_object = target
            hand_slot = target
            return target

    def control__pick_up_with_right_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return "error: no target in reach"
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with right hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand)
        else:
            print "object (" + target.name + ") is not graspable (i.e. in view and close enough)."
            return "error: object not graspable"

    def control__pick_up_with_left_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with left hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand)
        else:
            print "object (" + target.name + ") is not graspable (i.e. in view and close enough)."
            return "error: object not graspable"

    def control__drop_from_right_hand(self):
        print "attempting to drop object from right hand.\n"

        if self.right_hand_holding_object is None:
            print "right hand is not holding an object."
            return False
        if self.right_hand_holding_object.getNetTag("heldBy") == self.name:
            self.right_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_right_hand.getPos(render)
            heldPos = self.right_hand_holding_object.geom.getPosition()
            self.right_hand_holding_object.setPosition(pos)
            self.right_hand_holding_object.synchPosQuatToNode()
            self.right_hand_holding_object.setTag("heldBy", "")
            self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr)
            self.right_hand_holding_object.enable()
            if self.right_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.right_hand_holding_object.body.setGravityMode(1)
                self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0)))
            self.right_hand_holding_object = None
            return "success"
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__drop_from_left_hand(self):
        print "attempting to drop object from left hand.\n"
        if self.left_hand_holding_object is None:
            return "left hand is not holding an object."
        if self.left_hand_holding_object.getNetTag("heldBy") == self.name:
            self.left_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_left_hand.getPos(render)
            heldPos = self.left_hand_holding_object.geom.getPosition()
            self.left_hand_holding_object.setPosition(pos)
            self.left_hand_holding_object.synchPosQuatToNode()
            self.left_hand_holding_object.setTag("heldBy", "")
            self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr)
            self.left_hand_holding_object.enable()
            if self.left_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.left_hand_holding_object.body.setGravityMode(1)
                self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0)))
            self.left_hand_holding_object = None
            return "success"
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__use_right_hand(self, target=None, action=None):
        # TODO, rename this to use object with
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "Trying to use object", target
        if self.can_grasp(target):
            if target.call(self, action, self.right_hand_holding_object) or (
                self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target)
            ):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def control__use_left_hand(self, target=None, action=None):
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        if self.can_grasp(target):
            if target.call(self, action, self.left_hand_holding_object) or (
                self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target)
            ):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def can_grasp(self, isisobject):
        distance = isisobject.activeModel.getDistance(self.fov)
        print "distance = ", distance
        return distance < 5.0

    def is_holding(self, object_name):
        return (
            self.left_hand_holding_object
            and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name)
        ) or (
            self.right_hand_holding_object
            and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name)
        )

    def empty_hand(self):
        if self.left_hand_holding_object is None:
            return self.player_left_hand
        elif self.right_hand_holding_object is None:
            return self.player_right_hand
        return False

    def has_empty_hand(self):
        return self.empty_hand() is not False

    def control__use_aimed(self):
        """
        Try to use the object that we aim at, by calling its callback method.
        """
        target = self.__get_object_in_center_of_view()
        if target.selectionCallback:
            target.selectionCallback(self, dir)
        return "success"

    def sense__get_position(self):
        x, y, z = self.actorNodePath.getPos()
        h, p, r = self.actorNodePath.getHpr()
        # FIXME
        # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr()
        left_hand_obj = ""
        right_hand_obj = ""
        if self.left_hand_holding_object:
            left_hand_obj = self.left_hand_holding_object.getName()
        if self.right_hand_holding_object:
            right_hand_obj = self.right_hand_holding_object.getName()
        return {
            "body_x": x,
            "body_y": y,
            "body_z": z,
            "body_h": h,
            "body_p": p,
            "body_r": r,
            "in_left_hand": left_hand_obj,
            "in_right_hand": right_hand_obj,
        }

    def sense__get_vision(self):
        self.fov.node().saveScreenshot("temp.jpg")
        image = Image.open("temp.jpg")
        os.remove("temp.jpg")
        return image

    def sense__get_objects(self):
        return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items())

    def sense__get_agents(self):
        curSense = time()
        agents = {}
        for k, v in self.get_agents_in_field_of_vision().items():
            v["actions"] = k.get_other_agents_actions(self.lastSense, curSense)
            agents[k.name] = v
        self.lastSense = curSense
        return agents

    def sense__get_utterances(self):
        """ Clear out the buffer of things that the teacher has typed,
        FIXME: this doesn't work right now """
        return []
        utterances = self.teacher_utterances
        self.teacher_utterances = []
        return utterances

    def debug__print_objects(self):
        text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys())
        print text

    def add_action_to_history(self, action, args, result=0):
        self.queue.append((time(), action, args, result))
        if len(self.queue) > self.queueSize:
            self.queue.pop(0)

    def get_other_agents_actions(self, start=0, end=None):
        if not end:
            end = time()
        actions = []
        for act in self.queue:
            if act[0] >= start:
                if act[0] < end:
                    actions.append(act)
                else:
                    break
        return actions

    def update(self, stepSize=0.1):
        self.speed = [0.0, 0.0]
        self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70))
        self.actorNodePath.setQuat(self.getQuat())
        # the values in self.speeds are used as coefficientes for turns and movements
        if self.controlMap["turn_left"] != 0:
            self.addToH(stepSize * self.speeds[0])
        if self.controlMap["turn_right"] != 0:
            self.addToH(-stepSize * self.speeds[1])
        if self.verticalState == "ground":
            # these actions require contact with the ground
            if self.controlMap["move_forward"] != 0:
                self.speed[1] = self.speeds[2]
            if self.controlMap["move_backward"] != 0:
                self.speed[1] = -self.speeds[3]
            if self.controlMap["move_left"] != 0:
                self.speed[0] = -self.speeds[4]
            if self.controlMap["move_right"] != 0:
                self.speed[0] = self.speeds[5]
            if self.controlMap["jump"] != 0:
                kinematicCharacterController.jump(self)
                # one jump at a time!
                self.controlMap["jump"] = 0
        if self.controlMap["look_left"] != 0:
            self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80)
        if self.controlMap["look_right"] != 0:
            self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80)
        if self.controlMap["look_up"] != 0:
            self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80)
        if self.controlMap["look_down"] != 0:
            self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80)

        kinematicCharacterController.update(self, stepSize)

        """
        Update the held object position to be in the hands
        """
        if self.right_hand_holding_object != None:
            self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render))
        if self.left_hand_holding_object != None:
            self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render))

        # Update the dialog box and thought windows
        # This allows dialogue window to gradually decay (changing transparancy) and then disappear
        self.last_spoke += stepSize / 2
        self.last_thought += stepSize / 2
        self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01))
        self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01))
        if self.last_spoke > 2:
            self.speech_bubble["text"] = ""
        if self.last_thought > 1:
            self.thought_bubble.hide()

        # If the character is moving, loop the run animation.
        # If he is standing still, stop the animation.
        if (
            (self.controlMap["move_forward"] != 0)
            or (self.controlMap["move_backward"] != 0)
            or (self.controlMap["move_left"] != 0)
            or (self.controlMap["move_right"] != 0)
        ):
            if self.isMoving is False:
                self.isMoving = True
        else:
            if self.isMoving:
                self.current_frame_count = 5.0
                self.isMoving = False

        total_frame_num = self.actor.getNumFrames("walk")
        if self.isMoving:
            self.current_frame_count = self.current_frame_count + (stepSize * 250.0)
            if self.current_frame_count > total_frame_num:
                self.current_frame_count = self.current_frame_count % total_frame_num
            self.actor.pose("walk", self.current_frame_count)
        elif self.current_frame_count != 0:
            self.current_frame_count = 0
            self.actor.pose("idle", 0)
        return Task.cont

    def destroy(self):
        self.disable()
        self.specialDirectObject.ignoreAll()
        self.actorNodePath.removeNode()
        del self.specialDirectObject

        kinematicCharacterController.destroy(self)

    def disable(self):
        self.isDisabled = True
        self.geom.disable()
        self.footRay.disable()

    def enable(self):
        self.footRay.enable()
        self.geom.enable()
        self.isDisabled = False

    """
    Set camera to correct height above the center of the capsule
    when crouching and when standing up.
    """

    def crouch(self):
        kinematicCharacterController.crouch(self)
        self.camH = self.crouchCamH

    def crouchStop(self):
        """
        Only change the camera's placement when the KCC allows standing up.
        See the KCC to find out why it might not allow it.
        """
        if kinematicCharacterController.crouchStop(self):
            self.camH = self.walkCamH
class JellybeanRewardGui(DirectFrame):
    notify = directNotify.newCategory('JellybeanRewardGui')
    PreCountdownDelay = 1.0
    CountDownRate = 0.2
    JarLabelTextColor = (0.95, 0.95, 0.0, 1.0)
    JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0)

    def __init__(self, doneEvent):
        self.doneEvent = doneEvent
        DirectFrame.__init__(self)
        self.reparentTo(aspect2d)
        self.setPos(0.0, 0.0, 0.16)
        self.stash()
        publicPartyGui = loader.loadModel('phase_4/models/parties/publicPartyGUI')
        self.frame = DirectFrame(parent=self, geom=publicPartyGui.find('**/activities_background'), geom_pos=(-0.8, 0.0, 0.2), geom_scale=2.0, relief=None)
        self.earnedLabel = DirectLabel(parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=(0.95, 0.95, 0.0, 1.0), text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=DirectGuiGlobals.getDefaultDialogGeom(), image_scale=(0.33, 1.0, 0.33), pos=(-0.3, 0.0, 0.2), scale=0.9)
        purchaseModels = loader.loadModel('phase_4/models/gui/purchase_gui')
        jarImage = purchaseModels.find('**/Jar')
        self.jarLabel = DirectLabel(parent=self, relief=None, text=str(0), text_align=TextNode.ACenter, text_pos=(0.0, -0.07), text_scale=0.2, text_fg=JellybeanRewardGui.JarLabelTextColor, text_font=ToontownGlobals.getSignFont(), textMayChange=True, image=jarImage, scale=0.7, pos=(0.3, 0.0, 0.17))
        purchaseModels.removeNode()
        del purchaseModels
        jarImage.removeNode()
        del jarImage
        self.messageLabel = DirectLabel(parent=self, relief=None, text='', text_align=TextNode.ALeft, text_wordwrap=16.0, text_scale=0.07, pos=(-0.52, 0.0, -0.1), textMayChange=True)
        self.doubledJellybeanLabel = DirectLabel(parent=self, relief=None, text=TTLocalizer.PartyRewardDoubledJellybean, text_align=TextNode.ACenter, text_wordwrap=12.0, text_scale=0.09, text_fg=(1.0, 0.125, 0.125, 1.0), pos=(0.0, 0.0, -0.465), textMayChange=False)
        self.doubledJellybeanLabel.hide()
        self.closeButton = DirectButton(parent=self, relief=None, text=TTLocalizer.PartyJellybeanRewardOK, text_align=TextNode.ACenter, text_scale=0.065, text_pos=(0.0, -0.625), geom=(publicPartyGui.find('**/startButton_up'),
         publicPartyGui.find('**/startButton_down'),
         publicPartyGui.find('**/startButton_rollover'),
         publicPartyGui.find('**/startButton_inactive')), geom_pos=(-0.39, 0.0, 0.125), command=self._close)
        publicPartyGui.removeNode()
        del publicPartyGui
        self.countSound = base.loadSfx('phase_13/audio/sfx/tick_counter_short.mp3')
        self.overMaxSound = base.loadSfx('phase_13/audio/sfx/tick_counter_overflow.mp3')
        return

    def showReward(self, earnedAmount, jarAmount, message):
        JellybeanRewardGui.notify.debug('showReward( earnedAmount=%d, jarAmount=%d, ...)' % (earnedAmount, jarAmount))
        self.earnedCount = earnedAmount
        self.earnedLabel['text'] = str(self.earnedCount)
        self.jarCount = jarAmount
        self.jarMax = base.localAvatar.getMaxMoney()
        self.jarLabel['text'] = str(self.jarCount)
        self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelTextColor
        self.messageLabel['text'] = message
        if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_DAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY) or base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_PARTIES_HOLIDAY_MONTH):
            self.doubledJellybeanLabel.show()
        else:
            self.doubledJellybeanLabel.hide()
        self.unstash()
        taskMgr.doMethodLater(JellybeanRewardGui.PreCountdownDelay, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[])

    def transferOneJellybean(self):
        if self.earnedCount == 0:
            return
        self.earnedCount -= 1
        self.earnedLabel['text'] = str(self.earnedCount)
        self.jarCount += 1
        if self.jarCount <= self.jarMax:
            self.jarLabel['text'] = str(self.jarCount)
        elif self.jarCount > self.jarMax:
            self.jarLabel['text_fg'] = JellybeanRewardGui.JarLabelMaxedTextColor
        if self.jarCount <= self.jarMax:
            base.playSfx(self.countSound)
        else:
            base.playSfx(self.overMaxSound)
        taskMgr.doMethodLater(JellybeanRewardGui.CountDownRate, self.transferOneJellybean, 'JellybeanRewardGuiTransferOneJellybean', extraArgs=[])

    def _close(self):
        taskMgr.remove('JellybeanRewardGuiTransferOneJellybean')
        self.stash()
        messenger.send(self.doneEvent)

    def destroy(self):
        taskMgr.remove('JellybeanRewardGuiTransferOneJellybean')
        del self.countSound
        del self.overMaxSound
        self.frame.destroy()
        self.earnedLabel.destroy()
        self.jarLabel.destroy()
        self.messageLabel.destroy()
        self.closeButton.destroy()
        DirectFrame.destroy(self)
Esempio n. 22
0
class DistributedCannonDefenseShip(DistributedNPCSimpleShip):
    specialHitSfx = {}
    coldShotHitSfx = None
    sharkChompSfx = {}

    def __init__(self, cr):
        DistributedNPCSimpleShip.__init__(self, cr)
        self.goldStolenlbl = None
        self.hasGoldlbl = None
        self.hasBNote = None
        self.textureCard = None
        self.goldIcon = None
        self.flameEffects = []
        self.isSinkingWhileOnFire = False
        self.healthModifier = 0
        self.modifierSet = False
        self.shipStatsSet = False
        self.shipStatIndex = None
        self.initHealthBar()
        self.initIndicatorIcons()
        self.sinkTimeScale = CannonDefenseGlobals.SHIP_SINK_DURATION_SCALE
        self.sharkActor = Actor(
            'models/char/pir_r_gam_fsh_lgComTshark.bam',
            {'attack': 'models/char/pir_a_gam_fsh_lgComTshark_attack.bam'})
        self.sharkParallel = None
        self.fader = None
        if not self.coldShotHitSfx:
            DistributedCannonDefenseShip.specialHitSfx = {
                InventoryType.DefenseCannonMineInWater:
                loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_MINE_HIT),
                InventoryType.DefenseCannonBomb:
                loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_BOMB_HIT),
                InventoryType.DefenseCannonHotShot:
                loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_HOTSHOT_HIT),
                InventoryType.DefenseCannonFireStorm:
                loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_FIRESTORM_HIT),
                InventoryType.DefenseCannonChumShot:
                loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_SHARK)
            }
            DistributedCannonDefenseShip.coldShotHitSfx = loadSfx(
                SoundGlobals.SFX_MINIGAME_CANNON_ICE_HIT)
            DistributedCannonDefenseShip.sharkChompSfxs = [
                loadSfx(SoundGlobals.SFX_MONSTER_SMASH_01),
                loadSfx(SoundGlobals.SFX_MONSTER_SMASH_02),
                loadSfx(SoundGlobals.SFX_MONSTER_SMASH_03)
            ]

    def buildShip(self):
        DistributedNPCSimpleShip.buildShip(self)
        self.model.sfxAlternativeStyle = True

    def setupLocalStats(self):
        DistributedNPCSimpleShip.setupLocalStats(self)

    def setShipStatIndex(self, statIndex):
        self.shipStatsSet = True
        self.shipStatIndex = statIndex
        self.maxHp = CannonDefenseGlobals.shipStats[
            self.shipStatIndex]['shipHp']
        self.maxMastHealth = CannonDefenseGlobals.shipStats[
            self.shipStatIndex]['mastHp']
        self.healthBar.setPos(
            0.0, 0.0, CannonDefenseGlobals.shipStats[self.shipStatIndex]
            ['healthBarHeight'])
        if self.modifierSet:
            self.calcModifiedHealth()

    def setHealthModifier(self, modifier):
        self.modifierSet = True
        self.healthModifier = modifier
        if self.shipStatsSet:
            self.calcModifiedHealth()

    def calcModifiedHealth(self):
        if self.healthModifier == 0:
            return None

        self.maxHp += self.healthModifier * self.maxHp * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE
        mastList = CannonDefenseGlobals.shipStats[self.shipStatIndex]['mastHp']
        mastFinalHp = []
        for mastHealth in mastList:
            hp = mastHealth
            hp += self.healthModifier * mastHealth * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE
            mastFinalHp.append(hp)

        self.maxMastHealth = mastFinalHp

    def setLogo(self, logo):
        self.logo = logo

    def setStyle(self, style):
        self.style = style

    def announceGenerate(self):
        DistributedNPCSimpleShip.announceGenerate(self)
        rad = (self.model.dimensions / 2.0).length()
        cn = NodePath(CollisionNode('c'))
        cs = CollisionSphere(0, 0, 0, rad)
        cn.node().addSolid(cs)
        cn.reparentTo(self.model.modelCollisions)
        cn.setTransform(self.model.center.getTransform(self))
        cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask)
        self.model.defendSphere = cn
        self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE)
        self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN)
        self.smoother.setExpectedBroadcastPeriod(0.29999999999999999)
        self.smoother.setDelay(2)
        self.healthBar.reparentTo(self.model.modelRoot)

    def initHealthBar(self):
        self.healthBar = DirectWaitBar(
            frameSize=(-0.34999999999999998, 0.34999999999999998,
                       -0.040000000000000001, 0.040000000000000001),
            relief=DGG.FLAT,
            frameColor=(0.0, 0.0, 0.0, 0.0),
            borderWidth=(0.0, 0.0),
            barColor=(0.0, 1.0, 0.0, 1.0),
            scale=100)
        self.healthBar.setBillboardPointEye()
        self.healthBar['value'] = 100
        self.healthBar.hide(OTPRender.ReflectionCameraBitmask)
        self.healthBar.setLightOff()

    def initIndicatorIcons(self):
        self.textureCard = loader.loadModel(
            'models/textureCards/pir_m_gam_can_ship_icons')
        if self.textureCard:
            self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*')

        self.goldStolenlbl = DirectLabel(
            parent=self.healthBar,
            relief=None,
            pos=(0, 0, 0.20000000000000001),
            text_align=TextNode.ACenter,
            text_scale=0.5,
            textMayChange=0,
            text='!',
            text_fg=PiratesGuiGlobals.TextFG23,
            text_shadow=PiratesGuiGlobals.TextShadow,
            text_font=PiratesGlobals.getPirateBoldOutlineFont(),
            sortOrder=2)
        self.goldStolenlbl.setTransparency(1)
        self.goldStolenlbl.hide()
        self.hasGoldlbl = DirectLabel(parent=self.healthBar,
                                      relief=None,
                                      pos=(0, 0, 0.34999999999999998),
                                      image=self.goldIcon,
                                      image_scale=0.5,
                                      image_pos=(0, 0, 0),
                                      sortOrder=2)
        self.hasGoldlbl.setTransparency(1)
        self.hasGoldlbl.hide()
        self.hasBNote = self.healthBar.attachNewNode('noteIndicator')
        self.bnoteBack = loader.loadModel(
            'models/textureCards/skillIcons').find(
                '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote)
        self.hasBNote.setZ(0.34999999999999998)
        self.hasBNote.setScale(0.59999999999999998)
        self.hasBNote.hide()

    def getHealthBarColor(self, health):
        return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int(
            (health / 100.0) *
            (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))]

    def setHealthState(self, health):
        DistributedNPCSimpleShip.setHealthState(self, health)
        self.healthBar['value'] = health
        self.healthBar['barColor'] = self.getHealthBarColor(health)

    def setCurrentState(self, state):
        if state == CannonDefenseGlobals.SHIP_STATE_STEALING:
            self.goldStolenlbl.show()
        elif state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE:
            self.hasGoldlbl.show()
            self.goldStolenlbl.hide()
        elif state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES:
            self.hasBNote.show()
            self.goldStolenlbl.hide()
        else:
            self.hasGoldlbl.hide()
            self.hasBNote.hide()
            self.goldStolenlbl.hide()
        rad = (self.model.dimensions / 2.0).length()
        cn = NodePath(CollisionNode('c'))
        cs = CollisionSphere(0, 0, 0, rad)
        cn.node().addSolid(cs)
        cn.reparentTo(self.model.modelCollisions)
        cn.setTransform(self.model.center.getTransform(self))
        cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask)
        self.model.defendSphere = cn
        self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE)
        self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN)
        self.smoother.setExpectedBroadcastPeriod(0.29999999999999999)
        self.smoother.setDelay(2)
        self.healthBar.reparentTo(self.model.modelRoot)

    def initHealthBar(self):
        self.healthBar = DirectWaitBar(
            frameSize=(-0.34999999999999998, 0.34999999999999998,
                       -0.040000000000000001, 0.040000000000000001),
            relief=DGG.FLAT,
            frameColor=(0.0, 0.0, 0.0, 0.0),
            borderWidth=(0.0, 0.0),
            barColor=(0.0, 1.0, 0.0, 1.0),
            scale=100)
        self.healthBar.setBillboardPointEye()
        self.healthBar['value'] = 100
        self.healthBar.hide(OTPRender.ReflectionCameraBitmask)
        self.healthBar.setLightOff()

    def initIndicatorIcons(self):
        self.textureCard = loader.loadModel(
            'models/textureCards/pir_m_gam_can_ship_icons')
        if self.textureCard:
            self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*')

        self.goldStolenlbl = DirectLabel(
            parent=self.healthBar,
            relief=None,
            pos=(0, 0, 0.20000000000000001),
            text_align=TextNode.ACenter,
            text_scale=0.5,
            textMayChange=0,
            text='!',
            text_fg=PiratesGuiGlobals.TextFG23,
            text_shadow=PiratesGuiGlobals.TextShadow,
            text_font=PiratesGlobals.getPirateBoldOutlineFont(),
            sortOrder=2)
        self.goldStolenlbl.setTransparency(1)
        self.goldStolenlbl.hide()
        self.hasGoldlbl = DirectLabel(parent=self.healthBar,
                                      relief=None,
                                      pos=(0, 0, 0.34999999999999998),
                                      image=self.goldIcon,
                                      image_scale=0.5,
                                      image_pos=(0, 0, 0),
                                      sortOrder=2)
        self.hasGoldlbl.setTransparency(1)
        self.hasGoldlbl.hide()
        self.hasBNote = self.healthBar.attachNewNode('noteIndicator')
        self.bnoteBack = loader.loadModel(
            'models/textureCards/skillIcons').find(
                '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote)
        self.hasBNote.setZ(0.34999999999999998)
        self.hasBNote.setScale(0.59999999999999998)
        self.hasBNote.hide()

    def getHealthBarColor(self, health):
        return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int(
            (health / 100.0) *
            (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))]

    def setHealthState(self, health):
        DistributedNPCSimpleShip.setHealthState(self, health)
        self.healthBar['value'] = health
        self.healthBar['barColor'] = self.getHealthBarColor(health)

    def setCurrentState(self, state):
        if state == CannonDefenseGlobals.SHIP_STATE_STEALING:
            self.goldStolenlbl.show()
        elif state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE:
            self.hasGoldlbl.show()
            self.goldStolenlbl.hide()
        elif state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES:
            self.hasBNote.show()
            self.goldStolenlbl.hide()
        else:
            self.hasGoldlbl.hide()
            self.hasBNote.hide()
            self.goldStolenlbl.hide()

    def calculateLook(self):
        pass

    def playProjectileHitSfx(self, ammoSkillId, hitSail):
        if ammoSkillId in [
                InventoryType.DefenseCannonColdShotInWater,
                InventoryType.DefenseCannonSmokePowder
        ]:
            return None

        if ammoSkillId in self.specialHitSfx:
            sfx = self.specialHitSfx[ammoSkillId]
            base.playSfx(sfx, node=self, cutoff=2000)
            return None

        DistributedNPCSimpleShip.playProjectileHitSfx(self, ammoSkillId,
                                                      hitSail)

    def projectileWeaponHit(self,
                            skillId,
                            ammoSkillId,
                            skillResult,
                            targetEffects,
                            pos,
                            normal,
                            codes,
                            attacker,
                            itemEffects=[]):
        DistributedNPCSimpleShip.projectileWeaponHit(self, skillId,
                                                     ammoSkillId, skillResult,
                                                     targetEffects, pos,
                                                     normal, codes, attacker,
                                                     itemEffects)

    def sinkingBegin(self):
        self.healthBar.reparentTo(hidden)
        if len(self.flameEffects) > 0:
            self.isSinkingWhileOnFire = True

        DistributedNPCSimpleShip.sinkingBegin(self)

    def sinkingEnd(self):
        while len(self.flameEffects) > 0:
            effect = self.flameEffects.pop()
            effect.stopLoop()
        DistributedNPCSimpleShip.sinkingEnd(self)

    def addStatusEffect(self,
                        effectId,
                        attackerId,
                        duration=0,
                        timeLeft=0,
                        timestamp=0,
                        buffData=[0]):
        if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE:
            self.addFireEffect(self.getModelRoot().getPos())

        if effectId == WeaponGlobals.C_CANNON_DEFENSE_ICE:
            base.playSfx(self.coldShotHitSfx, node=self, cutoff=2000)

        DistributedNPCSimpleShip.addStatusEffect(self, effectId, attackerId,
                                                 duration, timeLeft, timestamp,
                                                 buffData)

    def removeStatusEffect(self, effectId, attackerId):
        DistributedNPCSimpleShip.removeStatusEffect(self, effectId, attackerId)
        if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE:
            if not self.isSinkingWhileOnFire:
                while len(self.flameEffects) > 0:
                    effect = self.flameEffects.pop()
                    effect.stopLoop()

    def addFireEffect(self, pos):
        fireEffect = ShipFire.getEffect()
        if fireEffect:
            fireEffect.reparentTo(self.getModelRoot())
            fireEffect.setPos(pos)
            fireEffect.setHpr(90, -15, 0)
            fireEffect.startLoop()
            fireEffect.setEffectScale(20.0)
            self.flameEffects.append(fireEffect)

    def playSharkAttack(self, pos):
        if self.sharkActor.getCurrentAnim() == None:
            self.sharkActor.wrtReparentTo(self.getModelRoot())
            self.sharkActor.setPos(self, pos)
            self.sharkActor.setScale(20)
            self.sharkActor.play('attack')
            sharkAttackEffect = None
            if base.options.getSpecialEffectsSetting(
            ) >= base.options.SpecialEffectsLow:
                effect = CannonSplash.getEffect()
                if effect:
                    effect.reparentTo(base.effectsRoot)
                    effect.setPos(self, pos)
                    effect.setZ(1)
                    effect.play()

                sharkAttackEffect = Func(self.playAttackEffect, pos)

            hprIvalShip = LerpHprInterval(self.getModelRoot(),
                                          duration=3,
                                          hpr=(0, 0, -180))
            s1 = Sequence(Wait(0.75), hprIvalShip,
                          Func(self.getModelRoot().stash))
            s2 = Sequence(Wait(0.75), sharkAttackEffect, Wait(0.5),
                          sharkAttackEffect)
            self.sharkParallel = Parallel(s1, s2)
            self.sharkParallel.start()
            taskMgr.doMethodLater(self.sharkActor.getDuration('attack'),
                                  self.detachShark,
                                  self.uniqueName('playSharkAttack'),
                                  extraArgs=[])

    def playAttackEffect(self, pos):
        effect = BulletEffect.getEffect()
        if effect:
            effect.reparentTo(base.effectsRoot)
            effect.setPos(self, pos)
            effect.loadObjects(6)
            effect.play()

        sfx = random.choice(self.sharkChompSfxs)
        base.playSfx(sfx, node=self.getModelRoot(), cutoff=2000)

    def detachShark(self):
        self.sharkActor.detachNode()

    def delete(self):
        if self.fader:
            self.fader.pause()
            self.fader = None

        DistributedNPCSimpleShip.delete(self)

    def destroy(self):
        if self.goldStolenlbl:
            self.goldStolenlbl.destroy()
            self.goldStolenlbl = None

        if self.hasGoldlbl:
            self.hasGoldlbl.destroy()
            self.hasGoldlbl = None

        if self.textureCard:
            self.textureCard.removeNode()
            self.textureCard = None
            self.goldIcon = None

        if self.healthBar:
            self.healthBar.destroy()

        if self.sharkActor:
            self.sharkActor.cleanUp()
            self.sharkActor.removeNode()

        if self.sharkParallel:
            self.sharkParallel.pause()
            self.sharkParallel = None

        DistributedNPCSimpleShip.destroy(self)

    def fadeIn(self, length):
        if self.fader:
            self.fader.finish()
            self.fader = None

        self.setTransparency(1)
        self.fader = Sequence(
            self.colorScaleInterval(length, Vec4(1, 1, 1, 1), Vec4(1, 1, 1,
                                                                   0)),
            Func(self.clearTransparency))
        self.fader.start()

    def fadeOut(self, length):
        if self.fader:
            self.fader.finish()
            self.fader = None

        self.setTransparency(1)
        self.fader = Sequence(
            self.colorScaleInterval(length, Vec4(1, 1, 1, 0), Vec4(1, 1, 1,
                                                                   1)),
            Func(self.hide), Func(self.clearTransparency))
        self.fader.start()
class VoteResultsTrolleyPanel(DirectFrame):
    __module__ = __name__
    notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsTrolleyPanel')

    def __init__(self, numPlayers, avIdList, votes, directions, namesList, disconnectedList, directionToGo, directionReason, directionTotals, *args, **kwargs):
        opts = {'relief': None,
         'geom': DGG.getDefaultDialogGeom(),
         'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8,),
         'geom_scale': (1.75, 1, 0.25),
         'pos': (0, 0, 0.825)}
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsTrolleyPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self, relief=None, pos=(-0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[0] + ':', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self, relief=None, pos=(0.5, 0, 0.06), text=TTLocalizer.TravelGameDirections[1] + ':', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.upLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(0.0, 0.0, 1.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.downLabel, relief=None, pos=(0.2, 0, 0.0), text='0', text_fg=(1.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(self.numPlayers))
        self.totalVotesLabels = [self.totalVotesUpLabel, self.totalVotesDownLabel]
        self.resultFrame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(0.5))
        self.resultLabel = DirectLabel(parent=self.resultFrame, text='', text_scale=0.06, pos=(0.7, 0, 0.0), text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in range(self.numPlayers):
            frame = DirectFrame(parent=self, relief=None, pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame, relief=None, pos=(0.46, 0.0, 0.0), text=self.namesList[index], text_fg=(0.0, 0.0, 0.0, 1.0), text_scale=0.05, text_align=TextNode.ACenter, text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame, relief=None, pos=(1.2, 0.0, 0.0), text='', text_fg=(0, 0, 1, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame, relief=None, pos=(1.43, 0.0, 0.0), text='', text_fg=(1, 0, 0, 1), text_scale=0.05, text_align=TextNode.ARight, text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        self.avVotesLabel = {}
        self.avArrows = {}
        matchingGameGui = loader.loadModel('phase_3.5/models/gui/matching_game_gui')
        minnieArrow = matchingGameGui.find('**/minnieArrow')
        from toontown.minigame.DistributedTravelGame import map3dToAspect2d
        for index in range(self.numPlayers):
            avId = self.avIdList[index]
            av = base.cr.doId2do.get(avId)
            if av:
                height = av.getHeight()
                avPos = av.getPos(render)
                avPos.setZ(av.getZ() + 5)
                labelPos = map3dToAspect2d(render, avPos)
                if not labelPos:
                    continue
                labelPos.setZ(labelPos.getZ() + 0.3)
                arrow = None
                if self.votes[index] > 0:
                    arrow = aspect2d.attachNewNode('avArrow')
                    minnieArrow.copyTo(arrow)
                    arrow.setScale(1.1, 1, 1.15)
                    arrow.setPos(labelPos)
                    if self.directions[index] == 0:
                        arrow.setR(-90)
                        arrow.setColorScale(0, 0, 1, 1)
                    else:
                        arrow.setR(90)
                        arrow.setColorScale(1, 0, 0, 1)
                    arrow.wrtReparentTo(self.resultFrame)
                    arrow.hide()
                    self.avArrows[index] = arrow
                fgColor = Vec4(0, 0, 0, 1)
                if self.votes[index] > 0:
                    if self.directions[index] == 0:
                        fgColor = Vec4(0, 0, 1, 1)
                    else:
                        fgColor = Vec4(1, 0, 0, 1)
                if self.votes[index] > 0:
                    newLabel = DirectLabel(parent=aspect2d, relief=None, pos=labelPos, text='test', text_fg=(1, 1, 1, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.01, 0))
                else:
                    newLabel = DirectLabel(parent=aspect2d, geom=DGG.getDefaultDialogGeom(), geom_scale=(0.2, 1, 0.2), relief=None, pos=labelPos, text='test', text_fg=(0.5, 0.5, 0.5, 1), text_scale=0.1, text_align=TextNode.ACenter, text_font=ToontownGlobals.getSignFont(), text_pos=(0, -0.035, 0))
                newLabel.wrtReparentTo(self.resultFrame)
                newLabel.hide()
                self.avVotesLabel[index] = newLabel

        matchingGameGui.removeNode()
        self.curArrowSfxIndex = 0
        self.upArrowSfx = []
        self.downArrowSfx = []
        for i in range(5):
            self.upArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3'))
            self.downArrowSfx.append(base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.mp3'))

        self.winVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_win_vote.mp3')
        self.noVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.mp3')
        self.loseVoteSfx = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.mp3')
        self.localAvatarWon = False
        self.localAvatarLost = False
        localIndex = self.avIdList.index(base.localAvatar.doId)
        localDirection = self.directions[localIndex]
        localVotes = self.votes[localIndex]
        if localVotes:
            if localDirection == self.directionToGo:
                if not TravelGameGlobals.ReverseWin:
                    self.localAvatarWon = True
                else:
                    self.localAvatarLost = True
            elif not TravelGameGlobals.ReverseWin:
                self.localAvatarLost = True
            else:
                self.localAvatarWon = True
        return

    def getRowPos(self, place):
        return Point3(-0.72, -0.01, 0.0 - place * 0.1)

    def setupResultLabel(self):
        reasonStr = ''
        if self.directionReason == TravelGameGlobals.ReasonVote:
            if self.directionToGo == 0:
                losingDirection = 1
            else:
                losingDirection = 0
            diffVotes = self.directionTotals[self.directionToGo] - self.directionTotals[losingDirection]
            if diffVotes > 1:
                reasonStr = TTLocalizer.TravelGameReasonVotesPlural % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
                 'numVotes': diffVotes}
            else:
                reasonStr = TTLocalizer.TravelGameReasonVotesSingular % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
                 'numVotes': diffVotes}
        elif self.directionReason == TravelGameGlobals.ReasonRandom:
            reasonStr = TTLocalizer.TravelGameReasonRandom % {'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
             'numVotes': self.directionTotals[self.directionToGo]}
        elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider:
            reasonStr = TravelGameReasonPlace % {'name': 'TODO NAME',
             'dir': TTLocalizer.TravelGameDirections[self.directionToGo]}
        self.resultLabel['text'] = reasonStr
        self.resultLabel.hide()

    def createOnePlayerSequence(self, index, duration):
        numVotes = self.votes[index]
        direction = self.directions[index]

        def ticketTicker(t, label = self.entryList[index][direction + 1], startVotes = 0, endVotes = numVotes):
            label['text'] = str(int(t * endVotes + startVotes))

        track = Parallel()
        startVotes = 0
        for prev in range(index):
            if self.directions[prev] == direction:
                startVotes += self.votes[prev]

        def totalTicker(t, label = self.totalVotesLabels[direction], startVotes = startVotes, additionalVotes = numVotes):
            label['text'] = str(int(t * additionalVotes + startVotes))

        track.append(LerpFunc(totalTicker, duration=duration, name='countTotal %d' % index))
        if self.avVotesLabel.has_key(index):

            def avVotesTicker(t, label = self.avVotesLabel[index], startVotes = 0, endVotes = numVotes, direction = direction):
                oldValue = label['text']
                newValue = int(t * endVotes + startVotes)
                label['text'] = str(newValue)
                if not oldValue == label['text']:
                    if newValue:
                        if direction == 0:
                            self.upArrowSfx[self.curArrowSfxIndex].play()
                        else:
                            self.downArrowSfx[self.curArrowSfxIndex].play()
                            self.curArrowSfxIndex += 1
                        if self.curArrowSfxIndex >= len(self.upArrowSfx):
                            self.curArrowSfxIndex = 0

            label = self.avVotesLabel[index]
            track.append(Func(self.avVotesLabel[index].show, name='showName %d' % index))
            if self.avArrows.has_key(index):
                track.append(Func(self.avArrows[index].show, name='showArrow %d' % index))
            if direction == 0 and numVotes:
                pass
            elif direction == 1 and numVotes:
                pass
            else:
                track.append(SoundInterval(self.noVoteSfx))
            track.append(LerpFunc(avVotesTicker, duration=duration, name='countAvVotes %d' % index))
        return track

    def startMovie(self):
        self.movie = Sequence()
        for index in range(self.numPlayers):
            track = self.createOnePlayerSequence(index, 1.25)
            self.movie.append(track)
            self.movie.append(Wait(0.75))

        self.movie.append(Func(self.resultLabel.show))
        soundAndWait = Parallel()
        soundAndWait.append(Wait(2.0))
        if self.localAvatarWon:
            soundAndWait.append(SoundInterval(self.winVoteSfx))
        elif self.localAvatarLost:
            soundAndWait.append(SoundInterval(self.loseVoteSfx, duration=0.43))
        self.movie.append(soundAndWait)
        self.movie.start()

    def destroy(self):
        self.movie.finish()
        del self.movie
        del self.winVoteSfx
        del self.noVoteSfx
        del self.upArrowSfx
        del self.loseVoteSfx
        del self.downArrowSfx
        DirectFrame.destroy(self)
class DistCogdoGame(DistCogdoGameBase, DistributedObject):
    notify = directNotify.newCategory('DistCogdoGame')

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        base.cogdoGame = self
        cr.cogdoGame = self
        self._waitingStartLabel = DirectLabel(
            text=TTL.MinigameWaitingForOtherPlayers,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self._waitingStartLabel.hide()
        self.loadFSM = ClassicFSM.ClassicFSM('DistCogdoGame.loaded', [
            State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded,
                        ['Loaded']),
            State.State('Loaded', self.enterLoaded, self.exitLoaded,
                        ['NotLoaded'])
        ], 'NotLoaded', 'NotLoaded')
        self.loadFSM.enterInitialState()
        self.fsm = ClassicFSM.ClassicFSM('DistCogdoGame', [
            State.State('Visible', self.enterVisible, self.exitVisible,
                        ['Intro']),
            State.State('Intro', self.enterIntro, self.exitIntro,
                        ['WaitServerStart']),
            State.State('WaitServerStart', self.enterWaitServerStart,
                        self.exitWaitServerStart, ['Game']),
            State.State('Game', self.enterGame, self.exitGame, ['Finish']),
            State.State('Finish', self.enterFinish, self.exitFinish, ['Off']),
            State.State('Off', self.enterOff, self.exitOff, ['Visible'])
        ], 'Off', 'Off')
        self.fsm.enterInitialState()
        self.difficultyOverride = None
        self.exteriorZoneOverride = None
        self._gotInterior = StateVar(False)
        self._toonsInEntranceElev = StateVar(False)
        self._wantStashElevator = StateVar(False)
        self._stashElevatorFC = FunctionCall(self._doStashElevator,
                                             self._toonsInEntranceElev,
                                             self._gotInterior,
                                             self._wantStashElevator)

    def getTitle(self):
        pass

    def getInstructions(self):
        pass

    def setInteriorId(self, interiorId):
        self._interiorId = interiorId

    def setExteriorZone(self, exteriorZone):
        self.exteriorZone = exteriorZone

    def setDifficultyOverrides(self, difficultyOverride, exteriorZoneOverride):
        if difficultyOverride != CogdoGameConsts.NoDifficultyOverride:
            self.difficultyOverride = difficultyOverride / float(
                CogdoGameConsts.DifficultyOverrideMult)
        if exteriorZoneOverride != CogdoGameConsts.NoExteriorZoneOverride:
            self.exteriorZoneOverride = exteriorZoneOverride

    def getInterior(self):
        return self.cr.getDo(self._interiorId)

    def getEntranceElevator(self, callback):
        return self.getInterior().getEntranceElevator(callback)

    def getToonIds(self):
        interior = self.getInterior()
        if interior is not None:
            return interior.getToonIds()

        return []

    def getToon(self, toonId):
        if toonId in self.cr.doId2do:
            return self.cr.doId2do[toonId]

        return None

    def getNumPlayers(self):
        return len(self.getToonIds())

    def isSinglePlayer(self):
        if self.getNumPlayers() == 1:
            return 1

        return 0

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        self.loadFSM.request('Loaded')
        self._requestInterior()
        self.notify.info('difficulty: %s, safezoneId: %s' %
                         (self.getDifficulty(), self.getSafezoneId()))

    def _requestInterior(self):
        self.cr.relatedObjectMgr.requestObjects(
            [self._interiorId], allCallback=self._handleGotInterior)

    def _handleGotInterior(self, objs):
        self._gotInterior.set(True)
        self.getEntranceElevator(self.placeEntranceElev)

    def stashEntranceElevator(self):
        self._wantStashElevator.set(True)

    def placeEntranceElev(self, elev):
        pass

    def _doStashElevator(self, toonsInEntranceElev, gotInterior,
                         wantStashElevator):
        if gotInterior:
            interior = self.getInterior()
            if interior:
                if not toonsInEntranceElev and wantStashElevator:
                    interior.stashElevatorIn()
                else:
                    interior.stashElevatorIn(False)

    def disable(self):
        base.cogdoGame = None
        self.cr.cogdoGame = None
        self.fsm.requestFinalState()
        self.loadFSM.requestFinalState()
        self.fsm = None
        self.loadFSM = None
        DistributedObject.disable(self)

    def delete(self):
        self._stashElevatorFC.destroy()
        self._wantStashElevator.destroy()
        self._toonsInEntranceElev.destroy()
        self._gotInterior.destroy()
        self._waitingStartLabel.destroy()
        self._waitingStartLabel = None
        DistributedObject.delete(self)

    def getDifficulty(self):
        if self.difficultyOverride is not None:
            return self.difficultyOverride

        if hasattr(base, 'cogdoGameDifficulty'):
            return float(base.cogdoGameDifficulty)

        return CogdoGameConsts.getDifficulty(self.getSafezoneId())

    def getSafezoneId(self):
        if self.exteriorZoneOverride is not None:
            return self.exteriorZoneOverride

        if hasattr(base, 'cogdoGameSafezoneId'):
            return CogdoGameConsts.getSafezoneId(base.cogdoGameSafezoneId)

        return CogdoGameConsts.getSafezoneId(self.exteriorZone)

    def enterNotLoaded(self):
        pass

    def exitNotLoaded(self):
        pass

    def enterLoaded(self):
        pass

    def exitLoaded(self):
        pass

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def setVisible(self):
        self.fsm.request('Visible')

    def setIntroStart(self):
        self.fsm.request('Intro')

    def enterVisible(self):
        self._toonsInEntranceElev.set(True)

    def exitVisible(self):
        pass

    def enterIntro(self, duration=MinigameGlobals.rulesDuration):
        base.cr.playGame.getPlace().fsm.request('Game')
        self._rulesDoneEvent = self.uniqueName('cogdoGameRulesDone')
        self.accept(self._rulesDoneEvent, self._handleRulesDone)
        self._rulesPanel = CogdoGameRulesPanel('CogdoGameRulesPanel',
                                               self.getTitle(),
                                               '',
                                               self._rulesDoneEvent,
                                               timeout=duration)
        self._rulesPanel.load()
        self._rulesPanel.enter()

    def exitIntro(self):
        self._toonsInEntranceElev.set(False)
        self.ignore(self._rulesDoneEvent)
        if self._rulesPanel:
            self._rulesPanel.exit()
            self._rulesPanel.unload()
            self._rulesPanel = None

    def _handleRulesDone(self):
        self.ignore(self._rulesDoneEvent)
        self._rulesPanel.exit()
        self._rulesPanel.unload()
        self._rulesPanel = None
        self.fsm.request('WaitServerStart')
        self.d_setAvatarReady()

    def d_setAvatarReady(self):
        self.sendUpdate('setAvatarReady', [])

    def enterWaitServerStart(self):
        numToons = 1
        interior = self.getInterior()
        if interior:
            numToons = len(interior.getToonIds())

        if numToons > 1:
            msg = TTL.MinigameWaitingForOtherPlayers
        else:
            msg = TTL.MinigamePleaseWait

        self._waitingStartLabel['text'] = msg
        self._waitingStartLabel.show()

    def exitWaitServerStart(self):
        self._waitingStartLabel.hide()

    def setGameStart(self, timestamp):
        self._startTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Game')

    def getStartTime(self):
        return self._startTime

    def enterGame(self):
        pass

    def exitGame(self):
        pass

    def setGameFinish(self, timestamp):
        self._finishTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Finish')

    def getFinishTime(self):
        return self._finishTime

    def enterFinish(self):
        pass

    def exitFinish(self):
        pass

    def setToonSad(self, toonId):
        pass

    def setToonDisconnect(self, toonId):
        pass
Esempio n. 25
0
class GameOverScreen():
    def __init__(self):
        # a fill panel so the player doesn't see how everything
        # gets loaded in the background
        self.frameMain = DirectFrame(
            # size of the frame
            frameSize = (base.a2dLeft, base.a2dRight,
                         base.a2dTop, base.a2dBottom),
            image = "Logo.png",
            image_scale = (0.612/2.0, 1, 0.495/2.0),
            image_pos = (0, 0, 0.7),
            # tramsparent bg color
            frameColor = (0, 0, 0, 1))
        self.frameMain.setTransparency(1)

        self.lblWin = DirectLabel(
            scale = 0.25,
            pos = (0, 0, 0.25),
            frameColor = (0, 0, 0, 0),
            text = _("You Succeeded"),
            text_align = TextNode.ACenter,
            text_fg = (1,1,1,1))
        self.lblWin.reparentTo(self.frameMain)

        self.lblTime = DirectLabel(
            scale = 0.07,
            pos = (0, 0, 0.00),
            frameColor = (0, 0, 0, 0),
            text = "your time",
            text_align = TextNode.ACenter,
            text_fg = (1,1,1,1))
        self.lblTime.reparentTo(self.frameMain)

        self.lblResult = DirectLabel(
            scale = 0.40,
            pos = (0, 0, -0.25),
            frameColor = (0, 0, 0, 0),
            text = "00:00",
            text_align = TextNode.ACenter,
            text_fg = (1,1,1,1))
        self.lblResult.reparentTo(self.frameMain)

        self.btnContinue = DirectButton(
            scale = (0.25, 0.25, 0.25),
            # some temp text
            text = _("Continue..."),
            text_scale = (0.5, 0.5, 0.5),
            # set the alignment to right
            text_align = TextNode.ACenter,
            # put the text on the right side of the button
            text_pos = (0, 0),
            # set the text color to black
            text_fg = (1,1,1,1),
            text_shadow = (0.3, 0.3, 0.1, 1),
            text_shadowOffset = (0.05, 0.05),
            relief = 1,
            frameColor = (0,0,0,0),
            pressEffect = False,
            pos = (0, 0, -0.65),
            command = lambda: base.messenger.send("Exit"),
            rolloverSound = None,
            clickSound = None)
        self.btnContinue.setTransparency(1)
        self.btnContinue.reparentTo(self.frameMain)
        self.hide()

    def show(self, winLoose, resulttime):
        if winLoose == "win":
            timestring = "%d:%02d" % (resulttime/60, resulttime%60)
            self.lblResult["text"] = timestring
            self.lblTime.show()
            self.lblResult.show()
        else:
            self.lblWin["text"] = _("You Loose")
            self.lblTime.hide()
            self.lblResult.hide()
        self.frameMain.show()

    def hide(self):
        self.frameMain.hide()
Esempio n. 26
0
class VoteResultsPanel(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory('VoteResultsPanel')

    def __init__(self, numPlayers, avIdList, votes, directions, namesList,
                 disconnectedList, directionToGo, directionReason,
                 directionTotals, *args, **kwargs):
        opts = {
            'relief': None,
            'geom': DGG.getDefaultDialogGeom(),
            'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ),
            'geom_scale': (1.75, 1, 0.75),
            'pos': (0, 0, 0.525)
        }
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self.upDownFrame,
                                   relief=None,
                                   pos=(1.2, 0, 0.0),
                                   text=TTLocalizer.TravelGameDirections[0],
                                   text_fg=(0.0, 0.0, 1.0, 1.0),
                                   text_scale=0.05,
                                   text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self.upDownFrame,
                                     relief=None,
                                     pos=(1.43, 0, 0.0),
                                     text=TTLocalizer.TravelGameDirections[1],
                                     text_fg=(1.0, 0.0, 0.0, 1.0),
                                     text_scale=0.05,
                                     text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self,
                                      relief=None,
                                      pos=self.getRowPos(self.numPlayers))
        self.totalText = DirectLabel(parent=self.totalFrame,
                                     relief=None,
                                     pos=(1.0, 0, 0.0),
                                     text='Total',
                                     text_fg=(0.0, 0.0, 0.0, 1.0),
                                     text_scale=0.05,
                                     text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.totalFrame,
                                             relief=None,
                                             pos=(1.2, 0, 0.0),
                                             text='',
                                             text_fg=(0.0, 0.0, 1.0, 1.0),
                                             text_scale=0.05,
                                             text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.totalFrame,
                                               relief=None,
                                               pos=(1.43, 0, 0.0),
                                               text='',
                                               text_fg=(1.0, 0.0, 0.0, 1.0),
                                               text_scale=0.05,
                                               text_align=TextNode.ARight)
        self.totalVotesLabels = [
            self.totalVotesUpLabel, self.totalVotesDownLabel
        ]
        self.resultFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(5))
        self.resultLabel = DirectLabel(parent=self.resultFrame,
                                       text='',
                                       text_scale=0.06,
                                       pos=(0.7, 0, 0.0),
                                       text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in xrange(self.numPlayers):
            frame = DirectFrame(parent=self,
                                relief=None,
                                pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame,
                                    relief=None,
                                    pos=(0.46, 0.0, 0.0),
                                    text=self.namesList[index],
                                    text_fg=(0.0, 0.0, 0.0, 1.0),
                                    text_scale=0.05,
                                    text_align=TextNode.ACenter,
                                    text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame,
                                       relief=None,
                                       pos=(1.2, 0.0, 0.0),
                                       text='',
                                       text_fg=(0, 0, 1, 1),
                                       text_scale=0.05,
                                       text_align=TextNode.ARight,
                                       text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame,
                                         relief=None,
                                         pos=(1.43, 0.0, 0.0),
                                         text='',
                                         text_fg=(1, 0, 0, 1),
                                         text_scale=0.05,
                                         text_align=TextNode.ARight,
                                         text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        return

    def getRowPos(self, place):
        return Point3(-0.72, -0.01, 0.2 - place * 0.1)

    def setupResultLabel(self):
        reasonStr = ''
        if self.directionReason == TravelGameGlobals.ReasonVote:
            reasonStr = TTLocalizer.TravelGameReasonVotes % {
                'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
                'numVotes': self.directionTotals[self.directionToGo]
            }
        elif self.directionReason == TravelGameGlobals.ReasonRandom:
            reasonStr = TTLocalizer.TravelGameReasonRandom % {
                'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
                'numVotes': self.directionTotals[self.directionToGo]
            }
        elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider:
            reasonStr = TravelGameReasonPlace % {
                'name': 'TODO NAME',
                'dir': TTLocalizer.TravelGameDirections[self.directionToGo]
            }
        self.resultLabel['text'] = reasonStr
        self.resultLabel.hide()

    def createOnePlayerSequence(self, index, duration):
        numVotes = self.votes[index]
        direction = self.directions[index]

        def ticketTicker(t,
                         label=self.entryList[index][(direction + 1)],
                         startVotes=0,
                         endVotes=numVotes):
            label['text'] = str(int(t * endVotes + startVotes))

        track = Parallel()
        track.append(
            Func(self.entryList[index][0].show, name='showName %d' % index))
        track.append(
            LerpFunc(ticketTicker,
                     duration=duration,
                     name='countVotes %d' % index))
        startVotes = 0
        for prev in xrange(index):
            if self.directions[prev] == direction:
                startVotes += self.votes[prev]

        def totalTicker(t,
                        label=self.totalVotesLabels[direction],
                        startVotes=startVotes,
                        additionalVotes=numVotes):
            label['text'] = str(int(t * additionalVotes + startVotes))

        track.append(
            LerpFunc(totalTicker,
                     duration=duration,
                     name='countTotal %d' % index))
        return track

    def startMovie(self):
        self.movie = Sequence()
        for index in xrange(self.numPlayers):
            track = self.createOnePlayerSequence(index, 1.25)
            self.movie.append(track)
            self.movie.append(Wait(0.75))

        self.movie.append(Func(self.resultLabel.show))
        self.movie.append(Wait(2.0))
        self.movie.start()

    def destroy(self):
        self.movie.finish()
        DirectFrame.destroy(self)
class DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld):
    notify = directNotify.newCategory("DistributedIceGame")
    MaxLocalForce = 100
    MaxPhysicsForce = 25000

    def __init__(self, cr):
        DistributedMinigame.DistributedMinigame.__init__(self, cr)
        DistributedIceWorld.DistributedIceWorld.__init__(self, cr)
        self.gameFSM = ClassicFSM.ClassicFSM(
            "DistributedIceGame",
            [
                State.State("off", self.enterOff, self.exitOff, ["inputChoice"]),
                State.State(
                    "inputChoice",
                    self.enterInputChoice,
                    self.exitInputChoice,
                    ["waitServerChoices", "moveTires", "displayVotes", "cleanup"],
                ),
                State.State(
                    "waitServerChoices",
                    self.enterWaitServerChoices,
                    self.exitWaitServerChoices,
                    ["moveTires", "cleanup"],
                ),
                State.State("moveTires", self.enterMoveTires, self.exitMoveTires, ["synch", "cleanup"]),
                State.State("synch", self.enterSynch, self.exitSynch, ["inputChoice", "scoring", "cleanup"]),
                State.State("scoring", self.enterScoring, self.exitScoring, ["cleanup", "finalResults", "inputChoice"]),
                State.State("finalResults", self.enterFinalResults, self.exitFinalResults, ["cleanup"]),
                State.State("cleanup", self.enterCleanup, self.exitCleanup, []),
            ],
            "off",
            "cleanup",
        )
        self.addChildGameFSM(self.gameFSM)
        self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0)
        self.tireDict = {}
        self.forceArrowDict = {}
        self.canDrive = False
        self.timer = None
        self.timerStartTime = None
        self.curForce = 0
        self.curHeading = 0
        self.headingMomentum = 0.0
        self.forceMomentum = 0.0
        self.allTireInputs = None
        self.curRound = 0
        self.curMatch = 0
        self.controlKeyWarningLabel = DirectLabel(
            text=TTLocalizer.IceGameControlKeyWarning,
            text_fg=VBase4(1, 0, 0, 1),
            relief=None,
            pos=(0.0, 0, 0),
            scale=0.15,
        )
        self.controlKeyWarningLabel.hide()
        self.waitingMoveLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForPlayersToFinishMove,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075,
        )
        self.waitingMoveLabel.hide()
        self.waitingSyncLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForAISync,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075,
        )
        self.waitingSyncLabel.hide()
        self.infoLabel = DirectLabel(text="", text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075)
        self.updateInfoLabel()
        self.lastForceArrowUpdateTime = 0
        self.sendForceArrowUpdateAsap = False
        self.treasures = []
        self.penalties = []
        self.obstacles = []
        self.controlKeyPressed = False
        self.controlKeyWarningIval = None
        return

    def delete(self):
        DistributedIceWorld.DistributedIceWorld.delete(self)
        DistributedMinigame.DistributedMinigame.delete(self)
        if self.controlKeyWarningIval:
            self.controlKeyWarningIval.finish()
            self.controlKeyWarningIval = None
        self.controlKeyWarningLabel.destroy()
        del self.controlKeyWarningLabel
        self.waitingMoveLabel.destroy()
        del self.waitingMoveLabel
        self.waitingSyncLabel.destroy()
        del self.waitingSyncLabel
        self.infoLabel.destroy()
        del self.infoLabel
        for treasure in self.treasures:
            treasure.destroy()

        del self.treasures
        for penalty in self.penalties:
            penalty.destroy()

        del self.penalties
        for obstacle in self.obstacles:
            obstacle.removeNode()

        del self.obstacles
        del self.gameFSM
        return

    def announceGenerate(self):
        DistributedMinigame.DistributedMinigame.announceGenerate(self)
        DistributedIceWorld.DistributedIceWorld.announceGenerate(self)
        self.debugTaskName = self.uniqueName("debugTask")

    def getTitle(self):
        return TTLocalizer.IceGameTitle

    def getInstructions(self):
        szId = self.getSafezoneId()
        numPenalties = IceGameGlobals.NumPenalties[szId]
        result = TTLocalizer.IceGameInstructions
        if numPenalties == 0:
            result = TTLocalizer.IceGameInstructionsNoTnt
        return result

    def getMaxDuration(self):
        return 0

    def load(self):
        self.notify.debug("load")
        DistributedMinigame.DistributedMinigame.load(self)
        self.music = base.loadMusic("phase_4/audio/bgm/MG_IceGame.ogg")
        self.gameBoard = loader.loadModel("phase_4/models/minigames/ice_game_icerink")
        background = loader.loadModel("phase_4/models/minigames/ice_game_2d")
        backgroundWide = loader.loadModel("phase_4/models/minigames/iceslide_ground")
        background.reparentTo(self.gameBoard)
        backgroundWide.reparentTo(self.gameBoard)
        backgroundWide.setPos(0, -0.3, -0.5)
        self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
        self.gameBoard.setScale(1.0)
        self.setupSimulation()
        index = 0
        for avId in self.avIdList:
            self.setupTire(avId, index)
            self.setupForceArrow(avId)
            index += 1

        for index in xrange(len(self.avIdList), 4):
            self.setupTire(-index, index)
            self.setupForceArrow(-index)

        self.showForceArrows(realPlayersOnly=True)
        self.westWallModel = NodePath()
        if not self.westWallModel.isEmpty():
            self.westWallModel.reparentTo(self.gameBoard)
            self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0)
            self.westWallModel.setScale(4)
        self.eastWallModel = NodePath()
        if not self.eastWallModel.isEmpty():
            self.eastWallModel.reparentTo(self.gameBoard)
            self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0)
            self.eastWallModel.setScale(4)
            self.eastWallModel.setH(180)
        self.arrowKeys = ArrowKeys.ArrowKeys()
        self.target = loader.loadModel("phase_3/models/misc/sphere")
        self.target.setScale(0.01)
        self.target.reparentTo(self.gameBoard)
        self.target.setPos(0, 0, 0)
        self.scoreCircle = loader.loadModel("phase_4/models/minigames/ice_game_score_circle")
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.reparentTo(self.gameBoard)
        self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0)
        self.scoreCircle.setAlphaScale(0.5)
        self.scoreCircle.setTransparency(1)
        self.scoreCircle.hide()
        self.treasureModel = loader.loadModel("phase_4/models/minigames/ice_game_barrel")
        self.penaltyModel = loader.loadModel("phase_4/models/minigames/ice_game_tnt2")
        self.penaltyModel.setScale(0.75, 0.75, 0.7)
        szId = self.getSafezoneId()
        obstacles = IceGameGlobals.Obstacles[szId]
        index = 0
        cubicObstacle = IceGameGlobals.ObstacleShapes[szId]
        for pos in obstacles:
            newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius)
            newObstacle = self.createObstacle(newPos, index, cubicObstacle)
            self.obstacles.append(newObstacle)
            index += 1

        self.countSound = loader.loadSfx("phase_3.5/audio/sfx/tick_counter.ogg")
        self.treasureGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg")
        self.penaltyGrabSound = loader.loadSfx("phase_4/audio/sfx/MG_cannon_fire_alt.ogg")
        self.tireSounds = []
        for tireIndex in xrange(4):
            tireHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg")
            wallHit = loader.loadSfx("phase_4/audio/sfx/MG_maze_pickup.ogg")
            obstacleHit = loader.loadSfx("phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg")
            self.tireSounds.append({"tireHit": tireHit, "wallHit": wallHit, "obstacleHit": obstacleHit})

        self.arrowRotateSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg")
        self.arrowUpSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg")
        self.arrowDownSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg")
        self.scoreCircleSound = loader.loadSfx("phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg")

    def unload(self):
        self.notify.debug("unload")
        DistributedMinigame.DistributedMinigame.unload(self)
        del self.music
        self.gameBoard.removeNode()
        del self.gameBoard
        for forceArrow in self.forceArrowDict.values():
            forceArrow.removeNode()

        del self.forceArrowDict
        self.scoreCircle.removeNode()
        del self.scoreCircle
        del self.countSound

    def onstage(self):
        self.notify.debug("onstage")
        DistributedMinigame.DistributedMinigame.onstage(self)
        self.gameBoard.reparentTo(render)
        self.__placeToon(self.localAvId)
        self.moveCameraToTop()
        self.scorePanels = []
        base.playMusic(self.music, looping=1, volume=0.8)

    def offstage(self):
        self.notify.debug("offstage")
        self.music.stop()
        self.gameBoard.hide()
        self.infoLabel.hide()
        for avId in self.tireDict:
            self.tireDict[avId]["tireNodePath"].hide()

        for panel in self.scorePanels:
            panel.cleanup()

        del self.scorePanels
        for obstacle in self.obstacles:
            obstacle.hide()

        for treasure in self.treasures:
            treasure.nodePath.hide()

        for penalty in self.penalties:
            penalty.nodePath.hide()

        for avId in self.avIdList:
            av = self.getAvatar(avId)
            if av:
                av.dropShadow.show()
                av.resetLOD()

        taskMgr.remove(self.uniqueName("aimtask"))
        self.arrowKeys.destroy()
        del self.arrowKeys
        DistributedMinigame.DistributedMinigame.offstage(self)

    def handleDisabledAvatar(self, avId):
        self.notify.debug("handleDisabledAvatar")
        self.notify.debug("avatar " + str(avId) + " disabled")
        DistributedMinigame.DistributedMinigame.handleDisabledAvatar(self, avId)

    def setGameReady(self):
        if not self.hasLocalToon:
            return
        self.notify.debug("setGameReady")
        if DistributedMinigame.DistributedMinigame.setGameReady(self):
            return
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            toon = self.getAvatar(avId)
            if toon:
                toon.reparentTo(render)
                self.__placeToon(avId)
                toon.forwardSpeed = 0
                toon.rotateSpeed = False
                toon.dropShadow.hide()
                toon.setAnimState("Sit")
                if avId in self.tireDict:
                    tireNp = self.tireDict[avId]["tireNodePath"]
                    toon.reparentTo(tireNp)
                    toon.setY(1.0)
                    toon.setZ(-3)
                toon.startLookAround()

    def setGameStart(self, timestamp):
        if not self.hasLocalToon:
            return
        self.notify.debug("setGameStart")
        DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp)
        for avId in self.remoteAvIdList:
            toon = self.getAvatar(avId)
            if toon:
                toon.stopLookAround()

        self.scores = [0] * self.numPlayers
        spacing = 0.4
        for i in xrange(self.numPlayers):
            avId = self.avIdList[i]
            avName = self.getAvatarName(avId)
            scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName)
            scorePanel.setScale(0.9)
            scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15)
            scorePanel.reparentTo(base.a2dTopRight)
            scorePanel.makeTransparent(0.75)
            self.scorePanels.append(scorePanel)

        self.arrowKeys.setPressHandlers(
            [
                self.__upArrowPressed,
                self.__downArrowPressed,
                self.__leftArrowPressed,
                self.__rightArrowPressed,
                self.__controlPressed,
            ]
        )

    def isInPlayState(self):
        if not self.gameFSM.getCurrentState():
            return False
        if not self.gameFSM.getCurrentState().getName() == "play":
            return False
        return True

    def enterOff(self):
        self.notify.debug("enterOff")

    def exitOff(self):
        pass

    def enterInputChoice(self):
        self.notify.debug("enterInputChoice")
        self.forceLocalToonToTire()
        self.controlKeyPressed = False
        if self.curRound == 0:
            self.setupStartOfMatch()
        else:
            self.notify.debug("self.curRound = %s" % self.curRound)
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.hide()
        if self.timerStartTime != None:
            self.startTimer()
        self.showForceArrows(realPlayersOnly=True)
        self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0)
        self.localForceArrow().reparentTo(self.localTireNp())
        self.localForceArrow().setY(IceGameGlobals.TireRadius)
        self.localTireNp().headsUp(self.target)
        self.notify.debug("self.localForceArrow() heading = %s" % self.localForceArrow().getH())
        self.curHeading = self.localTireNp().getH()
        self.curForce = 25
        self.updateLocalForceArrow()
        for avId in self.forceArrowDict:
            forceArrow = self.forceArrowDict[avId]
            forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0)
            tireNp = self.tireDict[avId]["tireNodePath"]
            forceArrow.reparentTo(tireNp)
            forceArrow.setY(IceGameGlobals.TireRadius)
            tireNp.headsUp(self.target)
            self.updateForceArrow(avId, tireNp.getH(), 25)

        taskMgr.add(self.__aimTask, self.uniqueName("aimtask"))
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.stop()
        self.sendForceArrowUpdateAsap = False
        return

    def exitInputChoice(self):
        if not self.controlKeyPressed:
            if self.controlKeyWarningIval:
                self.controlKeyWarningIval.finish()
                self.controlKeyWarningIval = None
            self.controlKeyWarningIval = Sequence(
                Func(self.controlKeyWarningLabel.show),
                self.controlKeyWarningLabel.colorScaleInterval(
                    10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)
                ),
                Func(self.controlKeyWarningLabel.hide),
            )
            self.controlKeyWarningIval.start()
        if self.timer != None:
            self.timer.destroy()
            self.timer = None
        self.timerStartTime = None
        self.hideForceArrows()
        self.arrowRotateSound.stop()
        self.arrowUpSound.stop()
        self.arrowDownSound.stop()
        taskMgr.remove(self.uniqueName("aimtask"))
        return

    def enterWaitServerChoices(self):
        self.waitingMoveLabel.show()
        self.showForceArrows(True)

    def exitWaitServerChoices(self):
        self.waitingMoveLabel.hide()
        self.hideForceArrows()

    def enterMoveTires(self):
        for key in self.tireDict:
            body = self.tireDict[key]["tireBody"]
            body.setAngularVel(0, 0, 0)
            body.setLinearVel(0, 0, 0)

        for index in xrange(len(self.allTireInputs)):
            input = self.allTireInputs[index]
            avId = self.avIdList[index]
            body = self.getTireBody(avId)
            degs = input[1] + 90
            tireNp = self.getTireNp(avId)
            tireH = tireNp.getH()
            self.notify.debug("tireH = %s" % tireH)
            radAngle = deg2Rad(degs)
            foo = NodePath("foo")
            dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
            self.notify.debug("dirVector is now=%s" % dirVector)
            inputForce = input[0]
            inputForce /= self.MaxLocalForce
            inputForce *= self.MaxPhysicsForce
            force = dirVector * inputForce
            self.notify.debug("adding force %s to %d" % (force, avId))
            body.addForce(force)

        self.enableAllTireBodies()
        self.totalPhysicsSteps = 0
        self.startSim()
        taskMgr.add(self.__moveTiresTask, self.uniqueName("moveTiresTtask"))

    def exitMoveTires(self):
        self.forceLocalToonToTire()
        self.disableAllTireBodies()
        self.stopSim()
        self.notify.debug("total Physics steps = %d" % self.totalPhysicsSteps)
        taskMgr.remove(self.uniqueName("moveTiresTtask"))

    def enterSynch(self):
        self.waitingSyncLabel.show()

    def exitSynch(self):
        self.waitingSyncLabel.hide()

    def enterScoring(self):
        sortedByDistance = []
        for avId in self.avIdList:
            np = self.getTireNp(avId)
            pos = np.getPos()
            pos.setZ(0)
            sortedByDistance.append((avId, pos.length()))

        def compareDistance(x, y):
            if x[1] - y[1] > 0:
                return 1
            elif x[1] - y[1] < 0:
                return -1
            else:
                return 0

        sortedByDistance.sort(cmp=compareDistance)
        self.scoreMovie = Sequence()
        curScale = 0.01
        curTime = 0
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.show()
        self.notify.debug("newScores = %s" % self.newScores)
        circleStartTime = 0
        for index in xrange(len(sortedByDistance)):
            distance = sortedByDistance[index][1]
            avId = sortedByDistance[index][0]
            scorePanelIndex = self.avIdList.index(avId)
            time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec
            if time < 0:
                time = 0.01
            scaleXY = distance + IceGameGlobals.TireRadius
            self.notify.debug("circleStartTime = %s" % circleStartTime)
            self.scoreMovie.append(
                Parallel(
                    LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)),
                    SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime),
                )
            )
            circleStartTime += time
            startScore = self.scorePanels[scorePanelIndex].getScore()
            destScore = self.newScores[scorePanelIndex]
            self.notify.debug("for avId %d, startScore=%d, newScores=%d" % (avId, startScore, destScore))

            def increaseScores(t, scorePanelIndex=scorePanelIndex, startScore=startScore, destScore=destScore):
                oldScore = self.scorePanels[scorePanelIndex].getScore()
                diff = destScore - startScore
                newScore = int(startScore + diff * t)
                if newScore > oldScore:
                    base.playSfx(self.countSound)
                self.scorePanels[scorePanelIndex].setScore(newScore)
                self.scores[scorePanelIndex] = newScore

            duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate
            tireNp = self.tireDict[avId]["tireNodePath"]
            self.scoreMovie.append(
                Parallel(
                    LerpFunctionInterval(increaseScores, duration),
                    Sequence(
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)),
                    ),
                )
            )
            curScale += distance

        self.scoreMovie.append(Func(self.sendUpdate, "reportScoringMovieDone", []))
        self.scoreMovie.start()

    def exitScoring(self):
        self.scoreMovie.finish()
        self.scoreMovie = None
        self.scoreCircle.hide()
        return

    def enterFinalResults(self):
        lerpTrack = Parallel()
        lerpDur = 0.5
        tY = 0.6
        bY = -0.05
        lX = -0.5
        cX = 0
        rX = 0.5
        scorePanelLocs = (
            ((cX, bY),),
            ((lX, bY), (rX, bY)),
            ((cX, tY), (lX, bY), (rX, bY)),
            ((lX, tY), (rX, tY), (lX, bY), (rX, bY)),
        )
        scorePanelLocs = scorePanelLocs[self.numPlayers - 1]
        for i in xrange(self.numPlayers):
            panel = self.scorePanels[i]
            pos = scorePanelLocs[i]
            panel.wrtReparentTo(aspect2d)
            lerpTrack.append(
                Parallel(
                    LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType="easeInOut"),
                    LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType="easeInOut"),
                )
            )

        self.showScoreTrack = Parallel(
            lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver))
        )
        self.showScoreTrack.start()

    def exitFinalResults(self):
        self.showScoreTrack.pause()
        del self.showScoreTrack

    def enterCleanup(self):
        self.notify.debug("enterCleanup")
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.start()

    def exitCleanup(self):
        pass

    def __placeToon(self, avId):
        toon = self.getAvatar(avId)
        if toon:
            toon.setPos(0, 0, 0)
            toon.setHpr(0, 0, 0)

    def moveCameraToTop(self):
        camera.reparentTo(render)
        p = self.cameraThreeQuarterView
        camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])

    def setupTire(self, avId, index):
        tireNp, tireBody, tireOdeGeom = self.createTire(index)
        self.tireDict[avId] = {"tireNodePath": tireNp, "tireBody": tireBody, "tireOdeGeom": tireOdeGeom}
        if avId <= 0:
            tireBlocker = tireNp.find("**/tireblockermesh")
            if not tireBlocker.isEmpty():
                tireBlocker.hide()
        if avId == self.localAvId:
            tireNp = self.tireDict[avId]["tireNodePath"]
            self.treasureSphereName = "treasureCollider"
            self.treasureCollSphere = CollisionSphere(0, 0, 0, IceGameGlobals.TireRadius)
            self.treasureCollSphere.setTangible(0)
            self.treasureCollNode = CollisionNode(self.treasureSphereName)
            self.treasureCollNode.setFromCollideMask(ToontownGlobals.PieBitmask)
            self.treasureCollNode.addSolid(self.treasureCollSphere)
            self.treasureCollNodePath = tireNp.attachNewNode(self.treasureCollNode)
            self.treasureHandler = CollisionHandlerEvent()
            self.treasureHandler.addInPattern("%fn-intoTreasure")
            base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler)
            eventName = "%s-intoTreasure" % self.treasureCollNodePath.getName()
            self.notify.debug("eventName = %s" % eventName)
            self.accept(eventName, self.toonHitSomething)

    def setupForceArrow(self, avId):
        arrow = loader.loadModel("phase_4/models/minigames/ice_game_arrow")
        priority = 0
        if avId < 0:
            priority = -avId
        else:
            priority = self.avIdList.index(avId)
            if avId == self.localAvId:
                priority = 10
        self.forceArrowDict[avId] = arrow

    def hideForceArrows(self):
        for forceArrow in self.forceArrowDict.values():
            forceArrow.hide()

    def showForceArrows(self, realPlayersOnly=True):
        for avId in self.forceArrowDict:
            if realPlayersOnly:
                if avId > 0:
                    self.forceArrowDict[avId].show()
                else:
                    self.forceArrowDict[avId].hide()
            else:
                self.forceArrowDict[avId].show()

    def localForceArrow(self):
        if self.localAvId in self.forceArrowDict:
            return self.forceArrowDict[self.localAvId]
        else:
            return None
        return None

    def setChoices(self, input0, input1, input2, input3):
        pass

    def startDebugTask(self):
        taskMgr.add(self.debugTask, self.debugTaskName)

    def stopDebugTask(self):
        taskMgr.remove(self.debugTaskName)

    def debugTask(self, task):
        if self.canDrive and self.tireDict.has_key(localAvatar.doId):
            dt = globalClock.getDt()
            forceMove = 25000
            forceMoveDt = forceMove
            tireBody = self.tireDict[localAvatar.doId]["tireBody"]
            if self.arrowKeys.upPressed() and not tireBody.isEnabled():
                x = 0
                y = 1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.downPressed() and not tireBody.isEnabled():
                x = 0
                y = -1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.leftPressed() and not tireBody.isEnabled():
                x = -1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.rightPressed() and not tireBody.isEnabled():
                x = 1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
        return task.cont

    def __upArrowPressed(self):
        pass

    def __downArrowPressed(self):
        pass

    def __leftArrowPressed(self):
        pass

    def __rightArrowPressed(self):
        pass

    def __controlPressed(self):
        if self.gameFSM.getCurrentState().getName() == "inputChoice":
            self.sendForceArrowUpdateAsap = True
            self.updateLocalForceArrow()
            self.controlKeyPressed = True
            self.sendUpdate("setAvatarChoice", [self.curForce, self.curHeading])
            self.gameFSM.request("waitServerChoices")

    def startTimer(self):
        now = globalClock.getFrameTime()
        elapsed = now - self.timerStartTime
        self.timer.posInTopRightCorner()
        self.timer.setTime(IceGameGlobals.InputTimeout)
        self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout)
        self.timer.show()

    def setTimerStartTime(self, timestamp):
        if not self.hasLocalToon:
            return
        self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp)
        if self.timer != None:
            self.startTimer()
        return

    def handleChoiceTimeout(self):
        self.sendUpdate("setAvatarChoice", [0, 0])
        self.gameFSM.request("waitServerChoices")

    def localTireNp(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]["tireNodePath"]
        return ret

    def localTireBody(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]["tireBody"]
        return ret

    def getTireBody(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]["tireBody"]
        return ret

    def getTireNp(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]["tireNodePath"]
        return ret

    def updateForceArrow(self, avId, curHeading, curForce):
        forceArrow = self.forceArrowDict[avId]
        tireNp = self.tireDict[avId]["tireNodePath"]
        tireNp.setH(curHeading)
        tireBody = self.tireDict[avId]["tireBody"]
        tireBody.setQuaternion(tireNp.getQuat())
        self.notify.debug("curHeading = %s" % curHeading)
        yScale = curForce / 100.0
        yScale *= 1
        headY = yScale * 15
        xScale = (yScale - 1) / 2.0 + 1.0
        shaft = forceArrow.find("**/arrow_shaft")
        head = forceArrow.find("**/arrow_head")
        shaft.setScale(xScale, yScale, 1)
        head.setPos(0, headY, 0)
        head.setScale(xScale, xScale, 1)

    def updateLocalForceArrow(self):
        avId = self.localAvId
        self.b_setForceArrowInfo(avId, self.curHeading, self.curForce)

    def __aimTask(self, task):
        if not hasattr(self, "arrowKeys"):
            return task.done
        dt = globalClock.getDt()
        headingMomentumChange = dt * 60.0
        forceMomentumChange = dt * 160.0
        arrowUpdate = False
        arrowRotating = False
        arrowUp = False
        arrowDown = False
        if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce += self.forceMomentum * dt
            arrowUpdate = True
            if oldForce < self.MaxLocalForce:
                arrowUp = True
        elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce -= self.forceMomentum * dt
            arrowUpdate = True
            if oldForce > 0.01:
                arrowDown = True
        else:
            self.forceMomentum = 0
        if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading += self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        elif self.arrowKeys.rightPressed() and not self.arrowKeys.leftPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading -= self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        else:
            self.headingMomentum = 0
        if arrowUpdate:
            self.normalizeHeadingAndForce()
            self.updateLocalForceArrow()
        if arrowRotating:
            if not self.arrowRotateSound.status() == self.arrowRotateSound.PLAYING:
                base.playSfx(self.arrowRotateSound, looping=True)
        else:
            self.arrowRotateSound.stop()
        if arrowUp:
            if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING:
                base.playSfx(self.arrowUpSound, looping=False)
        else:
            self.arrowUpSound.stop()
        if arrowDown:
            if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING:
                base.playSfx(self.arrowDownSound, looping=False)
        else:
            self.arrowDownSound.stop()
        return task.cont

    def normalizeHeadingAndForce(self):
        if self.curForce > self.MaxLocalForce:
            self.curForce = self.MaxLocalForce
        if self.curForce < 0.01:
            self.curForce = 0.01

    def setTireInputs(self, tireInputs):
        if not self.hasLocalToon:
            return
        self.allTireInputs = tireInputs
        self.gameFSM.request("moveTires")

    def enableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]["tireBody"].enable()

    def disableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]["tireBody"].disable()

    def areAllTiresDisabled(self):
        for avId in self.tireDict.keys():
            if self.tireDict[avId]["tireBody"].isEnabled():
                return False

        return True

    def __moveTiresTask(self, task):
        if self.areAllTiresDisabled():
            self.sendTirePositions()
            self.gameFSM.request("synch")
            return task.done
        return task.cont

    def sendTirePositions(self):
        tirePositions = []
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        self.sendUpdate("endingPositions", [tirePositions])

    def setFinalPositions(self, finalPos):
        if not self.hasLocalToon:
            return
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

    def updateInfoLabel(self):
        self.infoLabel["text"] = TTLocalizer.IceGameInfo % {
            "curMatch": self.curMatch + 1,
            "numMatch": IceGameGlobals.NumMatches,
            "curRound": self.curRound + 1,
            "numRound": IceGameGlobals.NumRounds,
        }

    def setMatchAndRound(self, match, round):
        if not self.hasLocalToon:
            return
        self.curMatch = match
        self.curRound = round
        self.updateInfoLabel()

    def setScores(self, match, round, scores):
        if not self.hasLocalToon:
            return
        self.newMatch = match
        self.newRound = round
        self.newScores = scores

    def setNewState(self, state):
        if not self.hasLocalToon:
            return
        self.notify.debug("setNewState gameFSM=%s newState=%s" % (self.gameFSM, state))
        self.gameFSM.request(state)

    def putAllTiresInStartingPositions(self):
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            np = self.tireDict[avId]["tireNodePath"]
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]["tireBody"]
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            np = self.tireDict[avId]["tireNodePath"]
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug("avId=%s newPos=%s" % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]["tireBody"]
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

    def b_setForceArrowInfo(self, avId, force, heading):
        self.setForceArrowInfo(avId, force, heading)
        self.d_setForceArrowInfo(avId, force, heading)

    def d_setForceArrowInfo(self, avId, force, heading):
        sendIt = False
        curTime = self.getCurrentGameTime()
        if self.sendForceArrowUpdateAsap:
            sendIt = True
        elif curTime - self.lastForceArrowUpdateTime > 0.2:
            sendIt = True
        if sendIt:
            self.sendUpdate("setForceArrowInfo", [avId, force, heading])
            self.sendForceArrowUpdateAsap = False
            self.lastForceArrowUpdateTime = self.getCurrentGameTime()

    def setForceArrowInfo(self, avId, force, heading):
        if not self.hasLocalToon:
            return
        self.updateForceArrow(avId, force, heading)

    def setupStartOfMatch(self):
        self.putAllTiresInStartingPositions()
        szId = self.getSafezoneId()
        self.numTreasures = IceGameGlobals.NumTreasures[szId]
        if self.treasures:
            for treasure in self.treasures:
                treasure.destroy()

            self.treasures = []
        index = 0
        treasureMargin = IceGameGlobals.TireRadius + 1.0
        while len(self.treasures) < self.numTreasures:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug("yPos=%s" % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False)
            goodSpot = True
            for obstacle in self.obstacles:
                if newTreasure.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newTreasure.nodePath.getDistance(treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.treasures.append(newTreasure)
                index += 1
            else:
                newTreasure.destroy()

        self.numPenalties = IceGameGlobals.NumPenalties[szId]
        if self.penalties:
            for penalty in self.penalties:
                penalty.destroy()

            self.penalties = []
        index = 0
        while len(self.penalties) < self.numPenalties:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug("yPos=%s" % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True)
            goodSpot = True
            for obstacle in self.obstacles:
                if newPenalty.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newPenalty.nodePath.getDistance(treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                for penalty in self.penalties:
                    if newPenalty.nodePath.getDistance(penalty.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.penalties.append(newPenalty)
                index += 1
            else:
                newPenalty.destroy()

    def toonHitSomething(self, entry):
        self.notify.debug("---- treasure Enter ---- ")
        self.notify.debug("%s" % entry)
        name = entry.getIntoNodePath().getName()
        parts = name.split("-")
        if len(parts) < 3:
            self.notify.debug("collided with %s, but returning" % name)
            return
        if not int(parts[1]) == self.doId:
            self.notify.debug("collided with %s, but doId doesn't match" % name)
            return
        treasureNum = int(parts[2])
        if "penalty" in parts[0]:
            self.__penaltyGrabbed(treasureNum)
        else:
            self.__treasureGrabbed(treasureNum)

    def __treasureGrabbed(self, treasureNum):
        self.treasures[treasureNum].showGrab()
        self.treasureGrabSound.play()
        self.sendUpdate("claimTreasure", [treasureNum])

    def setTreasureGrabbed(self, avId, treasureNum):
        if not self.hasLocalToon:
            return
        self.notify.debug("treasure %s grabbed by %s" % (treasureNum, avId))
        if avId != self.localAvId:
            self.treasures[treasureNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] += 1
        self.scorePanels[i].setScore(self.scores[i])

    def __penaltyGrabbed(self, penaltyNum):
        self.penalties[penaltyNum].showGrab()
        self.sendUpdate("claimPenalty", [penaltyNum])

    def setPenaltyGrabbed(self, avId, penaltyNum):
        if not self.hasLocalToon:
            return
        self.notify.debug("penalty %s grabbed by %s" % (penaltyNum, avId))
        if avId != self.localAvId:
            self.penalties[penaltyNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] -= 1
        self.scorePanels[i].setScore(self.scores[i])

    def postStep(self):
        DistributedIceWorld.DistributedIceWorld.postStep(self)
        if not self.colCount:
            return
        for count in xrange(self.colCount):
            c0, c1 = self.getOrderedContacts(count)
            if c1 in self.tireCollideIds:
                tireIndex = self.tireCollideIds.index(c1)
                if c0 in self.tireCollideIds:
                    self.tireSounds[tireIndex]["tireHit"].play()
                elif c0 == self.wallCollideId:
                    self.tireSounds[tireIndex]["wallHit"].play()
                elif c0 == self.obstacleCollideId:
                    self.tireSounds[tireIndex]["obstacleHit"].play()

    def forceLocalToonToTire(self):
        toon = localAvatar
        if toon and self.localAvId in self.tireDict:
            tireNp = self.tireDict[self.localAvId]["tireNodePath"]
            toon.reparentTo(tireNp)
            toon.setPosHpr(0, 0, 0, 0, 0, 0)
            toon.setY(1.0)
            toon.setZ(-3)
Esempio n. 28
0
class VoteResultsTrolleyPanel(DirectFrame):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'VoteResultsTrolleyPanel')

    def __init__(self, numPlayers, avIdList, votes, directions, namesList,
                 disconnectedList, directionToGo, directionReason,
                 directionTotals, *args, **kwargs):
        opts = {
            'relief': None,
            'geom': DGG.getDefaultDialogGeom(),
            'geom_color': ToontownGlobals.GlobalDialogColor[:3] + (0.8, ),
            'geom_scale': (1.75, 1, 0.25),
            'pos': (0, 0, 0.825)
        }
        opts.update(kwargs)
        DirectFrame.__init__(self, *args, **opts)
        self.initialiseoptions(VoteResultsTrolleyPanel)
        listMultiplier = 1
        if TravelGameGlobals.SpoofFour:
            listMultiplier = 4
        self.avIdList = avIdList * listMultiplier
        self.numPlayers = numPlayers * listMultiplier
        self.votes = votes * listMultiplier
        self.directions = directions * listMultiplier
        self.namesList = namesList * listMultiplier
        self.disconnectedList = disconnectedList * listMultiplier
        self.directionToGo = directionToGo
        self.directionReason = directionReason
        self.directionTotals = directionTotals
        self.entryList = []
        self.rowFrame = []
        self.upDownFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(-1))
        self.upLabel = DirectLabel(parent=self,
                                   relief=None,
                                   pos=(-0.5, 0, 0.06),
                                   text=TTLocalizer.TravelGameDirections[0] +
                                   ':',
                                   text_fg=(0.0, 0.0, 1.0, 1.0),
                                   text_scale=0.05,
                                   text_align=TextNode.ARight)
        self.downLabel = DirectLabel(parent=self,
                                     relief=None,
                                     pos=(0.5, 0, 0.06),
                                     text=TTLocalizer.TravelGameDirections[1] +
                                     ':',
                                     text_fg=(1.0, 0.0, 0.0, 1.0),
                                     text_scale=0.05,
                                     text_align=TextNode.ARight)
        self.totalVotesUpLabel = DirectLabel(parent=self.upLabel,
                                             relief=None,
                                             pos=(0.2, 0, 0.0),
                                             text='0',
                                             text_fg=(0.0, 0.0, 1.0, 1.0),
                                             text_scale=0.05,
                                             text_align=TextNode.ARight)
        self.totalVotesDownLabel = DirectLabel(parent=self.downLabel,
                                               relief=None,
                                               pos=(0.2, 0, 0.0),
                                               text='0',
                                               text_fg=(1.0, 0.0, 0.0, 1.0),
                                               text_scale=0.05,
                                               text_align=TextNode.ARight)
        self.totalFrame = DirectFrame(parent=self,
                                      relief=None,
                                      pos=self.getRowPos(self.numPlayers))
        self.totalVotesLabels = [
            self.totalVotesUpLabel, self.totalVotesDownLabel
        ]
        self.resultFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=self.getRowPos(0.5))
        self.resultLabel = DirectLabel(parent=self.resultFrame,
                                       text='',
                                       text_scale=0.06,
                                       pos=(0.7, 0, 0.0),
                                       text_align=TextNode.ACenter)
        self.setupResultLabel()
        for index in xrange(self.numPlayers):
            frame = DirectFrame(parent=self,
                                relief=None,
                                pos=self.getRowPos(index))
            self.rowFrame.append(frame)
            nameLabel = DirectFrame(parent=frame,
                                    relief=None,
                                    pos=(0.46, 0.0, 0.0),
                                    text=self.namesList[index],
                                    text_fg=(0.0, 0.0, 0.0, 1.0),
                                    text_scale=0.05,
                                    text_align=TextNode.ACenter,
                                    text_font=DGG.getDefaultFont())
            votesUpLabel = DirectLabel(parent=frame,
                                       relief=None,
                                       pos=(1.2, 0.0, 0.0),
                                       text='',
                                       text_fg=(0, 0, 1, 1),
                                       text_scale=0.05,
                                       text_align=TextNode.ARight,
                                       text_font=DGG.getDefaultFont())
            votesDownLabel = DirectLabel(parent=frame,
                                         relief=None,
                                         pos=(1.43, 0.0, 0.0),
                                         text='',
                                         text_fg=(1, 0, 0, 1),
                                         text_scale=0.05,
                                         text_align=TextNode.ARight,
                                         text_font=DGG.getDefaultFont())
            nameLabel.hide()
            self.entryList.append((nameLabel, votesUpLabel, votesDownLabel))

        self.avVotesLabel = {}
        self.avArrows = {}
        matchingGameGui = loader.loadModel(
            'phase_3.5/models/gui/matching_game_gui')
        minnieArrow = matchingGameGui.find('**/minnieArrow')
        from toontown.minigame.DistributedTravelGame import map3dToAspect2d
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            av = base.cr.doId2do.get(avId)
            if av:
                height = av.getHeight()
                avPos = av.getPos(render)
                avPos.setZ(av.getZ() + 5)
                labelPos = map3dToAspect2d(render, avPos)
                if not labelPos:
                    continue
                labelPos.setZ(labelPos.getZ() + 0.3)
                arrow = None
                if self.votes[index] > 0:
                    arrow = aspect2d.attachNewNode('avArrow')
                    minnieArrow.copyTo(arrow)
                    arrow.setScale(1.1, 1, 1.15)
                    arrow.setPos(labelPos)
                    if self.directions[index] == 0:
                        arrow.setR(-90)
                        arrow.setColorScale(0, 0, 1, 1)
                    else:
                        arrow.setR(90)
                        arrow.setColorScale(1, 0, 0, 1)
                    arrow.wrtReparentTo(self.resultFrame)
                    arrow.hide()
                    self.avArrows[index] = arrow
                fgColor = Vec4(0, 0, 0, 1)
                if self.votes[index] > 0:
                    if self.directions[index] == 0:
                        fgColor = Vec4(0, 0, 1, 1)
                    else:
                        fgColor = Vec4(1, 0, 0, 1)
                if self.votes[index] > 0:
                    newLabel = DirectLabel(
                        parent=aspect2d,
                        relief=None,
                        pos=labelPos,
                        text='test',
                        text_fg=(1, 1, 1, 1),
                        text_scale=0.1,
                        text_align=TextNode.ACenter,
                        text_font=ToontownGlobals.getSignFont(),
                        text_pos=(0, -0.01, 0))
                else:
                    newLabel = DirectLabel(
                        parent=aspect2d,
                        geom=DGG.getDefaultDialogGeom(),
                        geom_scale=(0.2, 1, 0.2),
                        relief=None,
                        pos=labelPos,
                        text='test',
                        text_fg=(0.5, 0.5, 0.5, 1),
                        text_scale=0.1,
                        text_align=TextNode.ACenter,
                        text_font=ToontownGlobals.getSignFont(),
                        text_pos=(0, -0.035, 0))
                newLabel.wrtReparentTo(self.resultFrame)
                newLabel.hide()
                self.avVotesLabel[index] = newLabel

        matchingGameGui.removeNode()
        self.curArrowSfxIndex = 0
        self.upArrowSfx = []
        self.downArrowSfx = []
        for i in xrange(5):
            self.upArrowSfx.append(
                base.loadSfx(
                    'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg'))
            self.downArrowSfx.append(
                base.loadSfx(
                    'phase_4/audio/sfx/MG_sfx_travel_game_red_arrow.ogg'))

        self.winVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_win_vote.ogg')
        self.noVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_square_no_vote_1.ogg')
        self.loseVoteSfx = base.loadSfx(
            'phase_4/audio/sfx/MG_sfx_travel_game_lose_vote.ogg')
        self.localAvatarWon = False
        self.localAvatarLost = False
        localIndex = self.avIdList.index(base.localAvatar.doId)
        localDirection = self.directions[localIndex]
        localVotes = self.votes[localIndex]
        if localVotes:
            if localDirection == self.directionToGo:
                if not TravelGameGlobals.ReverseWin:
                    self.localAvatarWon = True
                else:
                    self.localAvatarLost = True
            elif not TravelGameGlobals.ReverseWin:
                self.localAvatarLost = True
            else:
                self.localAvatarWon = True
        return

    def getRowPos(self, place):
        return Point3(-0.72, -0.01, 0.0 - place * 0.1)

    def setupResultLabel(self):
        reasonStr = ''
        if self.directionReason == TravelGameGlobals.ReasonVote:
            if self.directionToGo == 0:
                losingDirection = 1
            else:
                losingDirection = 0
            diffVotes = self.directionTotals[
                self.directionToGo] - self.directionTotals[losingDirection]
            if diffVotes > 1:
                reasonStr = TTLocalizer.TravelGameReasonVotesPlural % {
                    'dir':
                    TTLocalizer.TravelGameDirections[self.directionToGo],
                    'numVotes': diffVotes
                }
            else:
                reasonStr = TTLocalizer.TravelGameReasonVotesSingular % {
                    'dir':
                    TTLocalizer.TravelGameDirections[self.directionToGo],
                    'numVotes': diffVotes
                }
        elif self.directionReason == TravelGameGlobals.ReasonRandom:
            reasonStr = TTLocalizer.TravelGameReasonRandom % {
                'dir': TTLocalizer.TravelGameDirections[self.directionToGo],
                'numVotes': self.directionTotals[self.directionToGo]
            }
        elif self.directionReason == TravelGameGlobals.ReasonPlaceDecider:
            reasonStr = TravelGameReasonPlace % {
                'name': 'TODO NAME',
                'dir': TTLocalizer.TravelGameDirections[self.directionToGo]
            }
        self.resultLabel['text'] = reasonStr
        self.resultLabel.hide()

    def createOnePlayerSequence(self, index, duration):
        numVotes = self.votes[index]
        direction = self.directions[index]

        def ticketTicker(t,
                         label=self.entryList[index][direction + 1],
                         startVotes=0,
                         endVotes=numVotes):
            label['text'] = str(int(t * endVotes + startVotes))

        track = Parallel()
        startVotes = 0
        for prev in xrange(index):
            if self.directions[prev] == direction:
                startVotes += self.votes[prev]

        def totalTicker(t,
                        label=self.totalVotesLabels[direction],
                        startVotes=startVotes,
                        additionalVotes=numVotes):
            label['text'] = str(int(t * additionalVotes + startVotes))

        track.append(
            LerpFunc(totalTicker,
                     duration=duration,
                     name='countTotal %d' % index))
        if self.avVotesLabel.has_key(index):

            def avVotesTicker(t,
                              label=self.avVotesLabel[index],
                              startVotes=0,
                              endVotes=numVotes,
                              direction=direction):
                oldValue = label['text']
                newValue = int(t * endVotes + startVotes)
                label['text'] = str(newValue)
                if not oldValue == label['text']:
                    if newValue:
                        if direction == 0:
                            self.upArrowSfx[self.curArrowSfxIndex].play()
                        else:
                            self.downArrowSfx[self.curArrowSfxIndex].play()
                            self.curArrowSfxIndex += 1
                        if self.curArrowSfxIndex >= len(self.upArrowSfx):
                            self.curArrowSfxIndex = 0

            label = self.avVotesLabel[index]
            track.append(
                Func(self.avVotesLabel[index].show,
                     name='showName %d' % index))
            if self.avArrows.has_key(index):
                track.append(
                    Func(self.avArrows[index].show,
                         name='showArrow %d' % index))
            if direction == 0 and numVotes:
                pass
            elif direction == 1 and numVotes:
                pass
            else:
                track.append(SoundInterval(self.noVoteSfx))
            track.append(
                LerpFunc(avVotesTicker,
                         duration=duration,
                         name='countAvVotes %d' % index))
        return track

    def startMovie(self):
        self.movie = Sequence()
        for index in xrange(self.numPlayers):
            track = self.createOnePlayerSequence(index, 1.25)
            self.movie.append(track)
            self.movie.append(Wait(0.75))

        self.movie.append(Func(self.resultLabel.show))
        soundAndWait = Parallel()
        soundAndWait.append(Wait(2.0))
        if self.localAvatarWon:
            soundAndWait.append(SoundInterval(self.winVoteSfx))
        elif self.localAvatarLost:
            soundAndWait.append(SoundInterval(self.loseVoteSfx, duration=0.43))
        self.movie.append(soundAndWait)
        self.movie.start()

    def destroy(self):
        self.movie.finish()
        del self.movie
        del self.winVoteSfx
        del self.noVoteSfx
        del self.upArrowSfx
        del self.loseVoteSfx
        del self.downArrowSfx
        DirectFrame.destroy(self)
class DistCogdoGame(DistCogdoGameBase, DistributedObject):
    notify = directNotify.newCategory('DistCogdoGame')

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        base.cogdoGame = self
        cr.cogdoGame = self
        self._waitingStartLabel = DirectLabel(text=TTL.MinigameWaitingForOtherPlayers, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075)
        self._waitingStartLabel.hide()
        self.loadFSM = ClassicFSM.ClassicFSM('DistCogdoGame.loaded', [State.State('NotLoaded', self.enterNotLoaded, self.exitNotLoaded, ['Loaded']), State.State('Loaded', self.enterLoaded, self.exitLoaded, ['NotLoaded'])], 'NotLoaded', 'NotLoaded')
        self.loadFSM.enterInitialState()
        self.fsm = ClassicFSM.ClassicFSM('DistCogdoGame', [State.State('Visible', self.enterVisible, self.exitVisible, ['Intro']),
         State.State('Intro', self.enterIntro, self.exitIntro, ['WaitServerStart']),
         State.State('WaitServerStart', self.enterWaitServerStart, self.exitWaitServerStart, ['Game']),
         State.State('Game', self.enterGame, self.exitGame, ['Finish']),
         State.State('Finish', self.enterFinish, self.exitFinish, ['Off']),
         State.State('Off', self.enterOff, self.exitOff, ['Visible'])], 'Off', 'Off')
        self.fsm.enterInitialState()
        self.difficultyOverride = None
        self.exteriorZoneOverride = None
        self._gotInterior = StateVar(False)
        self._toonsInEntranceElev = StateVar(False)
        self._wantStashElevator = StateVar(False)
        self._stashElevatorFC = FunctionCall(self._doStashElevator, self._toonsInEntranceElev, self._gotInterior, self._wantStashElevator)

    def getTitle(self):
        pass

    def getInstructions(self):
        pass

    def setInteriorId(self, interiorId):
        self._interiorId = interiorId

    def setExteriorZone(self, exteriorZone):
        self.exteriorZone = exteriorZone

    def setDifficultyOverrides(self, difficultyOverride, exteriorZoneOverride):
        if difficultyOverride != CogdoGameConsts.NoDifficultyOverride:
            self.difficultyOverride = difficultyOverride / float(CogdoGameConsts.DifficultyOverrideMult)
        if exteriorZoneOverride != CogdoGameConsts.NoExteriorZoneOverride:
            self.exteriorZoneOverride = exteriorZoneOverride

    def getInterior(self):
        return self.cr.getDo(self._interiorId)

    def getEntranceElevator(self, callback):
        return self.getInterior().getEntranceElevator(callback)

    def getToonIds(self):
        interior = self.getInterior()
        if interior is not None:
            return interior.getToonIds()
        else:
            return []

    def getToon(self, toonId):
        if self.cr.doId2do.has_key(toonId):
            return self.cr.doId2do[toonId]
        else:
            return None

    def getNumPlayers(self):
        return len(self.getToonIds())

    def isSinglePlayer(self):
        if self.getNumPlayers() == 1:
            return 1
        else:
            return 0

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        self.loadFSM.request('Loaded')
        self._requestInterior()
        self.notify.info('difficulty: %s, safezoneId: %s' % (self.getDifficulty(), self.getSafezoneId()))

    def _requestInterior(self):
        self.cr.relatedObjectMgr.requestObjects([self._interiorId], allCallback=self._handleGotInterior)

    def _handleGotInterior(self, objs):
        self._gotInterior.set(True)
        self.getEntranceElevator(self.placeEntranceElev)

    def stashEntranceElevator(self):
        self._wantStashElevator.set(True)

    def placeEntranceElev(self, elev):
        pass

    def _doStashElevator(self, toonsInEntranceElev, gotInterior, wantStashElevator):
        if gotInterior:
            interior = self.getInterior()
            if interior:
                if not toonsInEntranceElev and wantStashElevator:
                    interior.stashElevatorIn()
                else:
                    interior.stashElevatorIn(False)

    def disable(self):
        base.cogdoGame = None
        self.cr.cogdoGame = None
        self.fsm.requestFinalState()
        self.loadFSM.requestFinalState()
        self.fsm = None
        self.loadFSM = None
        DistributedObject.disable(self)

    def delete(self):
        self._stashElevatorFC.destroy()
        self._wantStashElevator.destroy()
        self._toonsInEntranceElev.destroy()
        self._gotInterior.destroy()
        self._waitingStartLabel.destroy()
        self._waitingStartLabel = None
        DistributedObject.delete(self)

    def getDifficulty(self):
        if self.difficultyOverride is not None:
            return self.difficultyOverride
        if hasattr(base, 'cogdoGameDifficulty'):
            return float(base.cogdoGameDifficulty)
        return CogdoGameConsts.getDifficulty(self.getSafezoneId())

    def getSafezoneId(self):
        if self.exteriorZoneOverride is not None:
            return self.exteriorZoneOverride
        if hasattr(base, 'cogdoGameSafezoneId'):
            return CogdoGameConsts.getSafezoneId(base.cogdoGameSafezoneId)
        return CogdoGameConsts.getSafezoneId(self.exteriorZone)

    def enterNotLoaded(self):
        pass

    def exitNotLoaded(self):
        pass

    def enterLoaded(self):
        pass

    def exitLoaded(self):
        pass

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def setVisible(self):
        self.fsm.request('Visible')

    def setIntroStart(self):
        self.fsm.request('Intro')

    def enterVisible(self):
        self._toonsInEntranceElev.set(True)

    def exitVisible(self):
        pass

    def enterIntro(self, duration = MinigameGlobals.rulesDuration):
        base.cr.playGame.getPlace().fsm.request('Game')
        self._rulesDoneEvent = self.uniqueName('cogdoGameRulesDone')
        self.accept(self._rulesDoneEvent, self._handleRulesDone)
        self._rulesPanel = CogdoGameRulesPanel('CogdoGameRulesPanel', self.getTitle(), '', self._rulesDoneEvent, timeout=duration)
        self._rulesPanel.load()
        self._rulesPanel.enter()

    def exitIntro(self):
        self._toonsInEntranceElev.set(False)
        self.ignore(self._rulesDoneEvent)
        if self._rulesPanel:
            self._rulesPanel.exit()
            self._rulesPanel.unload()
            self._rulesPanel = None

    def _handleRulesDone(self):
        self.ignore(self._rulesDoneEvent)
        self._rulesPanel.exit()
        self._rulesPanel.unload()
        self._rulesPanel = None
        self.fsm.request('WaitServerStart')
        self.d_setAvatarReady()

    def d_setAvatarReady(self):
        self.sendUpdate('setAvatarReady', [])

    def enterWaitServerStart(self):
        numToons = 1
        interior = self.getInterior()
        if interior:
            numToons = len(interior.getToonIds())
        if numToons > 1:
            msg = TTL.MinigameWaitingForOtherPlayers
        else:
            msg = TTL.MinigamePleaseWait
        self._waitingStartLabel['text'] = msg
        self._waitingStartLabel.show()

    def exitWaitServerStart(self):
        self._waitingStartLabel.hide()

    def setGameStart(self, timestamp):
        self._startTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Game')

    def getStartTime(self):
        return self._startTime

    def enterGame(self):
        if SCHELLGAMES_DEV:
            self.acceptOnce('escape', messenger.send, ['magicWord', ['~endMaze']])

    def exitGame(self):
        if SCHELLGAMES_DEV:
            self.ignore('escape')

    def setGameFinish(self, timestamp):
        self._finishTime = globalClockDelta.networkToLocalTime(timestamp)
        self.fsm.request('Finish')

    def getFinishTime(self):
        return self._finishTime

    def enterFinish(self):
        pass

    def exitFinish(self):
        pass

    def setToonSad(self, toonId):
        pass

    def setToonDisconnect(self, toonId):
        pass
Esempio n. 30
0
class JellybeanRewardGui(DirectFrame):
    """
    This class does not load a gui model specifically created for this purpose.
    Instead, it loads sub-parts of other models and cobbles them together into
    a frankenstein gui. As such, changing any of those models could
    inadvertently change how this gui looks. Ideally this class would be 
    refactored to use a gui model specific to this class.
    """
    notify = directNotify.newCategory("JellybeanRewardGui")

    PreCountdownDelay = 1.0
    CountDownRate = 0.2  # how quickly we transfer beans from reward box to your jar
    JarLabelTextColor = (0.95, 0.95, 0.0, 1.0)
    JarLabelMaxedTextColor = (1.0, 0.0, 0.0, 1.0)

    def __init__(self, doneEvent):
        self.doneEvent = doneEvent
        DirectFrame.__init__(self)
        self.reparentTo(aspect2d)
        self.setPos(0.0, 0.0, 0.16)
        self.stash()
        # load the public party gui and extract the sub-chunk of the model that
        # we will use as the background for this gui
        publicPartyGui = loader.loadModel(
            "phase_4/models/parties/publicPartyGUI")
        # create a top level DirectFrame to hold everything else
        self.frame = DirectFrame(
            parent=self,
            geom=publicPartyGui.find("**/activities_background"),
            geom_pos=(-0.8, 0.0, 0.2),
            geom_scale=2.0,
            relief=None,
        )

        # counter for beans won in the activity
        self.earnedLabel = DirectLabel(
            parent=self,
            relief=None,
            text=str(0),
            text_align=TextNode.ACenter,
            text_pos=(0.0, -0.07),
            text_scale=0.2,
            text_fg=(0.95, 0.95, 0.0, 1.0),
            text_font=ToontownGlobals.getSignFont(),
            textMayChange=True,
            image=DirectGuiGlobals.getDefaultDialogGeom(),
            image_scale=(0.33, 1.0, 0.33),
            pos=(-0.3, 0.0, 0.2),
            scale=0.9,
        )

        # counter with jellybean jar in the background for beans in the
        # "pocketbook" (the beans you carry around with you that are not in your
        # home bank)
        purchaseModels = loader.loadModel("phase_4/models/gui/purchase_gui")
        jarImage = purchaseModels.find("**/Jar")
        self.jarLabel = DirectLabel(
            parent=self,
            relief=None,
            text=str(0),
            text_align=TextNode.ACenter,
            text_pos=(0.0, -0.07),
            text_scale=0.2,
            text_fg=JellybeanRewardGui.JarLabelTextColor,
            text_font=ToontownGlobals.getSignFont(),
            textMayChange=True,
            image=jarImage,
            scale=0.7,
            pos=(0.3, 0.0, 0.17),
        )
        purchaseModels.removeNode()
        del purchaseModels
        jarImage.removeNode()
        del jarImage

        # message text
        self.messageLabel = DirectLabel(
            parent=self,
            relief=None,
            text="",
            text_align=TextNode.ALeft,
            text_wordwrap=16.0,
            text_scale=0.07,
            pos=(-0.52, 0.0, -0.1),
            textMayChange=True,
        )

        self.doubledJellybeanLabel = DirectLabel(
            parent=self,
            relief=None,
            text=TTLocalizer.PartyRewardDoubledJellybean,
            text_align=TextNode.ACenter,
            text_wordwrap=12.0,
            text_scale=0.09,
            text_fg=(1.0, 0.125, 0.125, 1.0),
            pos=(0.0, 0.0, -0.465),
            textMayChange=False,
        )
        self.doubledJellybeanLabel.hide()

        # button to close the gui when the player is done reading it
        self.closeButton = DirectButton(
            parent=self,
            relief=None,
            text=TTLocalizer.PartyJellybeanRewardOK,
            text_align=TextNode.ACenter,
            text_scale=0.065,
            text_pos=(0.0, -0.625),
            geom=(
                publicPartyGui.find("**/startButton_up"),
                publicPartyGui.find("**/startButton_down"),
                publicPartyGui.find("**/startButton_rollover"),
                publicPartyGui.find("**/startButton_inactive"),
            ),
            geom_pos=(-0.39, 0.0,
                      0.125),  # place the geom to line up with the text
            command=self._close,
        )

        publicPartyGui.removeNode()
        del publicPartyGui

        self.countSound = base.loadSfx(
            "phase_13/audio/sfx/tick_counter_short.mp3")
        self.overMaxSound = base.loadSfx(
            "phase_13/audio/sfx/tick_counter_overflow.mp3")

    def showReward(self, earnedAmount, jarAmount, message):
        """
        This function assumes that the amount earned has already been updated
        for the toon. 
        
        Parameters:
          earnedAmount- How many jellybeans the toon gets
          jarAmount- Amount in their pocketbook jar 
          message- Activity-specific information to display while showing the
                   jellybean reward animation.
        """
        JellybeanRewardGui.notify.debug(
            "showReward( earnedAmount=%d, jarAmount=%d, ...)" %
            (earnedAmount, jarAmount))
        # set parameters
        self.earnedCount = earnedAmount
        self.earnedLabel["text"] = str(self.earnedCount)
        self.jarCount = jarAmount
        self.jarMax = base.localAvatar.getMaxMoney()
        self.jarLabel["text"] = str(self.jarCount)
        self.jarLabel["text_fg"] = JellybeanRewardGui.JarLabelTextColor
        self.messageLabel["text"] = message
        if base.cr.newsManager.isHolidayRunning(ToontownGlobals.JELLYBEAN_DAY):
            self.doubledJellybeanLabel.show()
        else:
            self.doubledJellybeanLabel.hide()
        # show the gui
        self.unstash()
        taskMgr.doMethodLater(
            JellybeanRewardGui.PreCountdownDelay,
            self.transferOneJellybean,
            "JellybeanRewardGuiTransferOneJellybean",
            extraArgs=[],
        )

    def transferOneJellybean(self):
        if self.earnedCount == 0:
            return
        # count the beans won counter down and the total counter up
        self.earnedCount -= 1
        self.earnedLabel["text"] = str(self.earnedCount)
        self.jarCount += 1
        # only update the total display if under max
        if self.jarCount <= self.jarMax:
            self.jarLabel['text'] = str(self.jarCount)
        # if we have reached the max, color the jar text accordingly
        elif self.jarCount > self.jarMax:
            self.jarLabel[
                "text_fg"] = JellybeanRewardGui.JarLabelMaxedTextColor

        # play the counting sound
        if self.jarCount <= self.jarMax:
            base.playSfx(self.countSound)
        # or the over max sound
        else:
            base.playSfx(self.overMaxSound)
        taskMgr.doMethodLater(
            JellybeanRewardGui.CountDownRate,
            self.transferOneJellybean,
            "JellybeanRewardGuiTransferOneJellybean",
            extraArgs=[],
        )

    def _close(self):
        taskMgr.remove("JellybeanRewardGuiTransferOneJellybean")
        self.stash()
        messenger.send(self.doneEvent)

    def destroy(self):
        taskMgr.remove("JellybeanRewardGuiTransferOneJellybean")
        del self.countSound
        del self.overMaxSound
        self.frame.destroy()
        self.earnedLabel.destroy()
        self.jarLabel.destroy()
        self.messageLabel.destroy()
        self.closeButton.destroy()
        DirectFrame.destroy(self)