Esempio n. 1
0
    def generateMenu(self):

        for i in self.info_texts:
            item = OnscreenText(
                text=i,
                style=1,
                fg=(1, 1, 1, 1),
                font=self.font,
                pos=(0, ((len(self.info_texts) + len(self.item_texts) -
                          self.info_texts.index(i)) * 0.1) + self.offset),
                align=TextNode.ACenter,
                drawOrder=1,
                parent=render2d,
                scale=0.1 * self.scale_factor)
            item.hide()
            self.info_table.append(item)

        for j in self.item_texts:
            item = OnscreenText(
                text=j,
                style=1,
                fg=(1, 1, 1, 1),
                font=self.font,
                pos=(0, (
                    (len(self.item_texts) - self.item_texts.index(j)) * 0.1) +
                     self.offset),
                align=TextNode.ACenter,
                drawOrder=1,
                parent=render2d,
                scale=0.06 * self.scale_factor)
            item.hide()
            self.menu_items.append(item)
        self.selectionDown()
class CogInvasionClientRepository(AstronClientRepository):
    notify = directNotify.newCategory("CIClientRepository")
    GameGlobalsId = DO_ID_COGINVASION
    SetZoneDoneEvent = 'CICRSetZoneDone'
    EmuSetZoneDoneEvent = 'CICREmuSetZoneDone'
    SetInterest = 'Set'
    ClearInterest = 'Clear'
    ClearInterestDoneEvent = 'CICRClearInterestDone'
    ITAG_PERM = 'perm'
    ITAG_AVATAR = 'avatar'
    ITAG_SHARD = 'shard'
    ITAG_WORLD = 'world'
    ITAG_GAME = 'game'

    def __init__(self, serverVersion):
        self.serverVersion = serverVersion
        AstronClientRepository.__init__(
            self, ['phase_3/etc/direct.dc', 'phase_3/etc/toon.dc'])
        self.loginFSM = ClassicFSM('login', [
            State('off', self.enterOff, self.exitOff),
            State('connect', self.enterConnect, self.exitConnect),
            State('disconnect', self.enterDisconnect, self.exitDisconnect),
            State('avChoose', self.enterAvChoose, self.exitAvChoose),
            State('playingGame', self.enterPlayingGame, self.exitPlayingGame),
            State('serverUnavailable', self.enterServerUnavailable,
                  self.exitServerUnavailable),
            State('makeAToon', self.enterMakeAToon, self.exitMakeAToon),
            State('submitNewToon', self.enterSubmitNewToon,
                  self.exitSubmitNewToon),
            State('noShards', self.enterNoShards, self.exitNoShards),
            State('waitForSetAvatarResponse',
                  self.enterWaitForSetAvatarResponse,
                  self.exitWaitForSetAvatarResponse),
            State('waitForShardList', self.enterWaitForShardList,
                  self.exitWaitForShardList),
            State('ejected', self.enterEjected, self.exitEjected),
            State('districtReset', self.enterDistrictReset,
                  self.exitDistrictReset),
            State('died', self.enterDied, self.exitDied),
            State('betaInform', self.enterBetaInform, self.exitBetaInform)
        ], 'off', 'off')
        self.loginFSM.enterInitialState()
        self.gameFSM = ClassicFSM('game', [
            State('off', self.enterGameOff, self.exitGameOff),
            State('waitForGameEnterResponse',
                  self.enterWaitForGameEnterResponse,
                  self.exitWaitForGameEnterResponse),
            State('playGame', self.enterPlayGame, self.exitPlayGame),
            State('closeShard', self.enterCloseShard, self.exitCloseShard),
            State('switchShards', self.enterSwitchShards,
                  self.exitSwitchShards)
        ], 'off', 'off')
        self.gameFSM.enterInitialState()
        #self.taskNameAllocator = UniqueIdAllocator(0, 1000000000)
        self.avChooser = AvChooser(self.loginFSM)
        self.playGame = PlayGame(self.gameFSM, "playGameDone")
        self.hoodMgr = HoodMgr()
        self.makeAToon = MakeAToon()
        self.loginToken = os.environ.get("LOGIN_TOKEN")
        self.serverAddress = os.environ.get("GAME_SERVER")
        self.serverURL = URLSpec("http://%s" % self.serverAddress)
        self.parentMgr.registerParent(CIGlobals.SPRender, render)
        self.parentMgr.registerParent(CIGlobals.SPHidden, hidden)
        self.adminAccess = False
        self.localAvChoice = None
        self.SuitsActive = 0
        self.BossActive = 0
        self.accServerTimesNA = 0
        self.maxAccServerTimesNA = 10
        self.setZonesEmulated = 0
        self.old_setzone_interest_handle = None
        self.setZoneQueue = Queue()
        self.accept(self.SetZoneDoneEvent, self._handleEmuSetZoneDone)
        self.handler = None
        self.__currentAvId = 0
        self.myDistrict = None
        self.activeDistricts = {}
        self.shardListHandle = None
        self.uberZoneInterest = None
        self.isShowingPlayerIds = False
        self.doBetaInform = False
        self.dTutorial = None
        self.requestedName = None
        self.whisperNoise = base.loadSfx(
            'phase_3.5/audio/sfx/GUI_whisper_3.ogg')
        self.checkHttp()
        #self.http.addPreapprovedServerCertificateFilename(self.serverURL, Filename('phase_3/etc/gameserver.crt'))
        #self.tournamentMusicChunks = {}
        #self.threadedTaskChain = taskMgr.setupTaskChain("threadedTaskChainForSoundIntervals", numThreads = 2)

        self.attackMgr = base.cl_attackMgr

        base.minigame = None

        self.newToonSlot = None

        base.finalExitCallbacks.insert(0, self.__handleExit)

        self.accountName = os.environ.get('ACCOUNT_NAME', '')
        self.csm = self.generateGlobalObject(DO_ID_CLIENT_SERVICES_MANAGER,
                                             'ClientServicesManager')
        self.friendsManager = self.generateGlobalObject(
            DO_ID_FRIENDS_MANAGER, 'FriendsManager')
        self.uin = self.generateGlobalObject(DO_ID_UNIQUE_INTEREST_NOTIFIER,
                                             'UniqueInterestNotifier')
        self.statsManager = self.generateGlobalObject(DO_ID_STATS_MANAGER,
                                                      'StatsManager')

        self.pingToggle = False
        self.currentPing = None

        self.pingText = OnscreenText("",
                                     align=TextNode.ALeft,
                                     parent=base.a2dBottomLeft,
                                     fg=(1, 1, 1, 1),
                                     shadow=(0, 0, 0, 0.5),
                                     pos=(0.3, 0.09))
        self.pingText.setBin('gsg-popup', 1000)
        self.pingText.hide()

        SpeedHackChecker.startChecking()
        self.loginFSM.request('connect')
        return

    def readerPollUntilEmpty(self, task):
        while self.readerPollOnce():
            pass

        if not metadata.IS_PRODUCTION:
            if ConfigVariableBool('simulated-latency', False).getValue():
                latency = random.uniform(
                    ConfigVariableDouble('simulated-latency-min',
                                         0.125).getValue(),
                    ConfigVariableDouble('simulated-latency-max',
                                         0.15).getValue())
                task.delayTime = latency
                return task.again

        return task.cont

    def togglePing(self):
        self.pingToggle = not self.pingToggle

        if self.pingToggle:
            taskMgr.add(self.__districtPingTask, "CICR.districtPingTask")
            self.showPing()
        else:
            self.hidePing()
            taskMgr.remove("CICR.districtPingTask")

    def showPing(self):
        self.pingText.show()

    def hidePing(self):
        self.pingText.hide()

    def handleNewPing(self):
        if self.currentPing is None:
            display = "?"
        else:
            display = int(round(self.currentPing))

        self.pingText.setText("Ping: {0} ms".format(display))

    def __districtPingTask(self, task):
        if self.myDistrict:
            # Figure out how much network latency there is.
            self.myDistrict.d_ping()

        task.delayTime = 1.0
        return task.again

    def deleteObject(self, doId):
        """
        implementation copied from AstronClientRepository.py

        Brian: modified to also delete owner views

        Removes the object from the client's view of the world.  This
        should normally not be called directly except in the case of
        error recovery, since the server will normally be responsible
        for deleting and disabling objects as they go out of scope.

        After this is called, future updates by server on this object
        will be ignored (with a warning message).  The object will
        become valid again the next time the server sends a generate
        message for this doId.

        This is not a distributed message and does not delete the
        object on the server or on any other client.
        """

        if doId in self.doId2do:
            # If it is in the dictionary, remove it.
            obj = self.doId2do[doId]
            # Remove it from the dictionary
            del self.doId2do[doId]
            # Disable, announce, and delete the object itself...
            # unless delayDelete is on...
            obj.deleteOrDelay()
            if self.isLocalId(doId):
                self.freeDoId(doId)
        elif doId in self.doId2ownerView:
            # If it is in the owner dictionary, remove it.
            obj = self.doId2ownerView[doId]
            # Remove it from the dictionary
            del self.doId2ownerView[doId]
            # Disable, announce, and delete the object itself...
            # unless delayDelete is on...
            obj.deleteOrDelay()
            if self.isLocalId(doId):
                self.freeDoId(doId)
        elif self.cache.contains(doId):
            # If it is in the cache, remove it.
            self.cache.delete(doId)
            if self.isLocalId(doId):
                self.freeDoId(doId)
        elif self.cacheOwner.contains(doId):
            # If it is in the owner cache, remove it.
            self.cacheOwner.delete(doId)
            if self.isLocalId(doId):
                self.freeDoId(doId)
        else:
            # Otherwise, ignore it
            self.notify.warning("Asked to delete non-existent DistObj " +
                                str(doId))

    #def uniqueName(self, idString):
    #	return "%s-%s" % (idString, self.taskNameAllocator.allocate())

    #def removeTask(self, taskName):
    #	div = taskName.split('-')
    #	self.taskNameAllocator.free(div[1])
    #	taskMgr.remove(taskName)

    def __handleExit(self):
        try:
            base.localAvatar.b_setAnimState('teleportOut')
        except:
            pass

        ccoginvasion.CTMusicData.stop_am_update_task()

        self.gameFSM.request('closeShard', ['off'])

    def isChristmas(self):
        return self.holidayManager.getHoliday() == HolidayType.CHRISTMAS

    def showPlayerIds(self):
        print "Showing player ids..."
        self.isShowingPlayerIds = True
        for av in self.doId2do.values():
            if av.__class__.__name__ in [
                    "DistributedPlayerToon", "LocalToon", "DistributedSuit"
            ]:
                av.showAvId()

    def hidePlayerIds(self):
        print "Hiding player ids..."
        self.isShowingPlayerIds = False
        for av in self.doId2do.values():
            if av.__class__.__name__ in [
                    "DistributedPlayerToon", "LocalToon", 'DistributedSuit'
            ]:
                av.showName()

    def sendSetLocation(self, doId, parentId, zoneId):
        dg = PyDatagram()
        dg.addUint16(CLIENT_OBJECT_LOCATION)
        dg.addUint32(doId)
        dg.addUint32(parentId)
        dg.addUint32(zoneId)
        self.send(dg)

    def getNextSetZoneDoneEvent(self):
        return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated + 1)

    def getLastSetZoneDoneEvent(self):
        return '%s-%s' % (self.EmuSetZoneDoneEvent, self.setZonesEmulated)

    def getQuietZoneLeftEvent(self):
        return 'leftQuietZone-%s' % (id(self), )

    def b_setLocation(self, do, parentId, zoneId):
        self.sendSetLocation(do.doId, parentId, zoneId)
        do.setLocation(parentId, zoneId)

    def sendSetZoneMsg(self, zoneId, visibleZoneList=None):
        event = self.getNextSetZoneDoneEvent()
        self.setZonesEmulated += 1
        parentId = base.localAvatar.defaultShard
        self.sendSetLocation(base.localAvatar.doId, parentId, zoneId)
        localAvatar.setLocation(parentId, zoneId)
        interestZones = zoneId
        if visibleZoneList is not None:
            interestZones = visibleZoneList
        self._addInterestOpToQueue(
            self.SetInterest, [parentId, interestZones, 'OldSetZoneEmulator'],
            event)
        return

    def resetInterestStateForConnectionLoss(self):
        self.old_setzone_interest_handle = None
        self.setZoneQueue.clear()
        return

    def _removeEmulatedSetZone(self, doneEvent):
        self._addInterestOpToQueue(self.ClearInterest, None, doneEvent)
        return

    def _addInterestOpToQueue(self, op, args, event):
        self.setZoneQueue.push([op, args, event])
        if len(self.setZoneQueue) == 1:
            self._sendNextSetZone()

    def _sendNextSetZone(self):
        op, args, event = self.setZoneQueue.top()
        if op == self.SetInterest:
            parentId, interestZones, name = args
            if self.old_setzone_interest_handle is None:
                self.old_setzone_interest_handle = self.addInterest(
                    parentId, interestZones, name, self.SetZoneDoneEvent)
            else:
                self.alterInterest(self.old_setzone_interest_handle, parentId,
                                   interestZones, name, self.SetZoneDoneEvent)
        elif op == self.ClearInterest:
            self.removeInterest(self.old_setzone_interest_handle,
                                self.SetZoneDoneEvent)
            self.old_setzone_interest_handle = None
        else:
            self.notify.error('unknown setZone op: %s' % op)
        return

    def _handleEmuSetZoneDone(self):
        op, args, event = self.setZoneQueue.pop()
        queueIsEmpty = self.setZoneQueue.isEmpty()
        if event is not None:
            messenger.send(event)
        if not queueIsEmpty:
            self._sendNextSetZone()
        return

    def enterSwitchShards(self, shardId, hoodId, zoneId, avId):
        self._switchShardParams = [shardId, hoodId, zoneId, avId]
        self.removeShardInterest(self._handleOldShardGone)

    def _handleOldShardGone(self):
        status = {}
        status['hoodId'] = self._switchShardParams[1]
        status['zoneId'] = self._switchShardParams[2]
        status['avId'] = self._switchShardParams[3]
        self.gameFSM.request('waitForGameEnterResponse',
                             [status, self._switchShardParams[0]])

    def exitSwitchShards(self):
        del self._switchShardParams

    def enterBetaInform(self):
        msg = (
            "Welcome to Cog Invasion Online!\n\nBefore playing, please remember that the game is in Alpha, "
            "and that you may encounter bugs and incomplete features.\n\nIf you happen to encounter any bugs, "
            "please report them to us by using the Contact Us Page at coginvasion.com.\n\nHave fun!"
        )
        self.dialog = GlobalDialog(message=msg,
                                   style=3,
                                   doneEvent="gameEnterChoice")
        self.dialog.show()
        self.acceptOnce("gameEnterChoice", self.handleGameEnterChoice)

    def handleGameEnterChoice(self):
        self.loginFSM.request('avChoose')

    def exitBetaInform(self):
        self.ignore("gameEnterChoice")
        self.dialog.cleanup()
        del self.dialog

    def enterCloseShard(self, nextState='avChoose'):
        self.setNoNewInterests(True)
        self._removeLocalAvFromStateServer(nextState)

    def exitCloseShard(self):
        self.setNoNewInterests(False)
        self.ignore(self.ClearInterestDoneEvent)
        return

    def _removeLocalAvFromStateServer(self, nextState):
        self.sendSetAvatarIdMsg(0)
        self._removeAllOV()
        callback = Functor(self.loginFSM.request, nextState)
        self.removeShardInterest(callback)

    def removeShardInterest(self, callback):
        self._removeCurrentShardInterest(
            Functor(self._removeShardInterestComplete, callback))

    def _removeShardInterestComplete(self, callback):
        self.cache.flush()
        self.doDataCache.flush()

        callback()
        return

    def _removeCurrentShardInterest(self, callback):
        if self.old_setzone_interest_handle is None:
            callback()
            return
        self.acceptOnce(self.ClearInterestDoneEvent,
                        Functor(self._removeCurrentUberZoneInterest, callback))
        self._removeEmulatedSetZone(self.ClearInterestDoneEvent)
        return

    def _removeCurrentUberZoneInterest(self, callback):
        self.acceptOnce(self.ClearInterestDoneEvent,
                        Functor(self._removeShardInterestDone, callback))
        self.removeInterest(self.uberZoneInterest, self.ClearInterestDoneEvent)

    def _removeShardInterestDone(self, callback):
        self.uberZoneInterest = None
        callback()
        return

    def _removeAllOV(self):
        owners = self.doId2ownerView.keys()
        for doId in owners:
            self.disableDoId(doId, ownerView=True)

    def enterDied(self):
        self.deathDialog = GlobalDialog(message=CIGlobals.SuitDefeatMsg,
                                        style=2,
                                        doneEvent="deathChoice")
        self.deathDialog.show()
        self.acceptOnce("deathChoice", self.handleDeathChoice)

    def handleDeathChoice(self):
        value = self.deathDialog.getValue()
        if value:
            self.loginFSM.request('avChoose')
        else:
            sys.exit()

    def exitDied(self):
        self.deathDialog.cleanup()
        del self.deathDialog
        self.ignore("deathChoice")

    def enterConnect(self):
        self.connectingDialog = GlobalDialog(message=CIGlobals.ConnectingMsg)
        self.connectingDialog.show()
        self.connect([self.serverURL],
                     successCallback=self.handleConnected,
                     failureCallback=self.handleConnectFail)

    def handleConnected(self):
        self.notify.info("Sending CLIENT_HELLO...")
        self.acceptOnce("CLIENT_HELLO_RESP", self.handleClientHelloResp)
        self.acceptOnce("CLIENT_EJECT", self.handleEjected)
        self.acceptOnce("LOST_CONNECTION", self.handleLostConnection)
        AstronClientRepository.sendHello(self, self.serverVersion)

    def handleLostConnection(self):
        self.deleteAllObjects()
        self.loginFSM.request('disconnect', [1])

    def deleteAllObjects(self):
        for doId in self.doId2do.keys():
            obj = self.doId2do[doId]

            if not isinstance(obj, DistributedObjectGlobal) and not hasattr(
                    obj, 'isDistrict'):
                if hasattr(base,
                           'localAvatar') and doId != base.localAvatar.doId:
                    self.deleteObject(doId)

    def handleEjected(self, errorCode, reason):
        self.notify.info("OMG I WAS EJECTED!")
        self.ignore("LOST_CONNECTION")
        errorMsg = ErrorCode2ErrorMsg.get(errorCode,
                                          None) or UnknownErrorMsg % errorCode
        self.loginFSM.request('ejected', [errorMsg])

    def handleClientHelloResp(self):
        self.notify.info("Got CLIENT_HELLO_RESP!")
        self.acceptOnce(self.csm.getLoginAcceptedEvent(),
                        self.handleLoginAccepted)
        self.csm.d_requestLogin(self.loginToken, self.accountName)

    def handleLoginAccepted(self):
        self.notify.info("Woo-hoo, I am authenticated!")
        base.cr.holidayManager = self.generateGlobalObject(
            DO_ID_HOLIDAY_MANAGER, 'HolidayManager')
        base.cr.nameServicesManager = self.generateGlobalObject(
            DO_ID_NAME_SERVICES_MANAGER, 'NameServicesManager')
        self.loginFSM.request('waitForShardList')

    def handleConnectFail(self, _, __):
        self.notify.info("Could not connect to gameserver, notifying user.")
        self.connectingDialog.cleanup()
        self.connectingDialog = GlobalDialog(
            message=CIGlobals.NoConnectionMsg % self.serverAddress + " " +
            CIGlobals.TryAgain,
            style=2,
            doneEvent="connectFail")
        self.connectingDialog.show()
        self.acceptOnce("connectFail", self.handleConnectFailButton)

    def handleConnectFailButton(self):
        value = self.connectingDialog.getValue()
        if value:
            self.loginFSM.request('connect')
        else:
            sys.exit()

    def exitConnect(self):
        self.ignore("connectFail")
        self.ignore("CLIENT_HELLO_RESP")
        self.ignore(self.csm.getLoginAcceptedEvent())
        self.connectingDialog.cleanup()
        del self.connectingDialog

    def enterEjected(self, errorMsg):
        self.ejectDialog = GlobalDialog(message=errorMsg,
                                        style=3,
                                        doneEvent='ejectDone')
        self.ejectDialog.show()
        self.acceptOnce('ejectDone', sys.exit)

    def exitEjected(self):
        self.ignore('ejectDone')
        self.ejectDialog.cleanup()
        del self.ejectDialog

    def enterServerUnavailable(self):
        self.notify.info(CIGlobals.ServerUnavailable)
        self.serverNA = GlobalDialog(message=CIGlobals.ServerUnavailable,
                                     style=4,
                                     doneEvent="serverNAEvent")
        self.serverNA.show()
        self.acceptOnce("serverNAEvent", sys.exit)
        self.startServerNAPoll()

    def startServerNAPoll(self):
        self.notify.info("Starting server poll...")
        self.accServerTimesNA = 1
        taskMgr.add(self.serverNAPoll, "serverNAPoll")

    def serverNAPoll(self, task):
        dg = PyDatagram()
        dg.addUint16(ACC_IS_SERVER_UP)
        self.send(dg)
        task.delayTime = 3.0
        return Task.again

    def __handleServerNAResp(self, resp):
        if resp == ACC_SERVER_UP:
            taskMgr.remove("serverNAPoll")
            # Enter the previous state that we were in, which should have
            # been some state where we communicate with the acc server.
            self.loginFSM.request(self.loginFSM.getLastState().getName())
        else:
            self.accServerTimesNA += 1
            if self.accServerTimesNA >= self.maxAccServerTimesNA:
                taskMgr.remove("serverNAPoll")
                self.notify.info(
                    "Giving up on polling account server after %s times." %
                    self.accServerTimesNA)
                self.loginFSM.request("disconnect", enterArgList=[1])
                self.accServerTimesNA = 0

    def exitServerUnavailable(self):
        self.ignore("serverNAEvent")
        self.serverNA.cleanup()
        del self.serverNA

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def playTheme(self):
        base.playMusic(CIGlobals.getThemeSong(), looping=1)

    def enterAvChoose(self, newToonSlot=None):
        ModelPool.garbageCollect()
        TexturePool.garbageCollect()
        self.avChooser.load()
        self.avChooser.enter(newToonSlot)
        if newToonSlot is None:
            self.playTheme()
        self.accept("enterMakeAToon", self.__handleMakeAToonReq)
        self.accept("avChooseDone", self.__handleAvChooseDone)

    def __handleMakeAToonReq(self, slot):
        self.loginFSM.request('makeAToon', [slot])

    def __handleAvChooseDone(self, avChoice):
        print "------- AvChooseDone -------"
        print "Toon name: %s" % avChoice.getName()
        print "Slot:      %s" % avChoice.getSlot()
        print "DNA:       %s" % avChoice.getDNA()
        self.loginFSM.request("waitForSetAvatarResponse", [avChoice])

    def exitAvChoose(self):
        self.avChooser.exit()
        self.avChooser.unload()
        self.ignore("enterMakeAToon")
        self.ignore("avChooseDone")

    def handlePlayGame(self, msgType, di):
        if msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER:
            self.handleGenerateWithRequiredOtherOwner(msgType, di)
        else:
            AstronClientRepository.handleDatagram(self, di)

    def enterPlayingGame(self):
        zoneId = localAvatar.getLastHood()
        hoodId = ZoneUtil.getHoodId(zoneId)
        status = {"hoodId": hoodId, "zoneId": zoneId, "avId": self.localAvId}
        shardId = self.myDistrict.doId
        self.gameFSM.request('waitForGameEnterResponse', [status, shardId])

    def exitPlayingGame(self):
        self.deleteAllObjects()
        self.handler = None
        self.gameFSM.request('off')
        camera.reparentTo(render)
        camera.setPos(0, 0, 0)
        camera.setHpr(0, 0, 0)
        self.localAvChoice = None
        if loader.inBulkBlock:
            loader.endBulkLoad(loader.blockName)

    def enterNoShards(self):
        self.noShardDialog = GlobalDialog(message=CIGlobals.NoShardsMsg + " " +
                                          CIGlobals.TryAgain,
                                          style=2,
                                          doneEvent='noShardsDone')
        self.noShardDialog.show()
        self.acceptOnce('noShardsDone', self.handleNoShardsDone)

    def handleNoShardsDone(self):
        value = self.noShardDialog.getValue()
        if value:
            self.loginFSM.request('waitForShardList')
        else:
            sys.exit()

    def exitNoShards(self):
        self.noShardDialog.cleanup()
        del self.noShardDialog
        self.ignore('noShardsDone')

    def enterWaitForShardList(self):
        self.shardListHandle = self.addTaggedInterest(
            self.GameGlobalsId,
            ZoneUtil.DistrictZone,
            self.ITAG_PERM,
            'localShardList',
            event='shardList_complete')
        self.acceptOnce('shardList_complete', self._handleShardListComplete)

    def _handleShardListComplete(self):
        if self._shardsAreAvailable():
            self.myDistrict = self._chooseAShard()
            if self.doBetaInform:
                self.loginFSM.request('betaInform')
            else:
                self.loginFSM.request('avChoose')
            taskMgr.add(self.monitorDistrict, "monitorMyDistrict")
        else:
            self.loginFSM.request('noShards')

    def monitorDistrict(self, task):
        if self.myDistrict is None and self.isConnected():
            self.loginFSM.request('districtReset')
            return task.done
        return task.cont

    def _shardsAreAvailable(self):
        for shard in self.activeDistricts.values():
            if shard.available:
                return True
        return False

    def _chooseAShard(self):
        choices = []
        for shard in self.activeDistricts.values():
            choices.append(shard)
        return random.choice(choices)

    def exitWaitForShardList(self):
        self.ignore('shardList_complete')

    def enterDistrictReset(self):
        self.districtResetDialog = GlobalDialog(
            message=CIGlobals.DistrictResetMsg,
            style=3,
            doneEvent='distresetdone')
        self.districtResetDialog.show()
        self.acceptOnce('distresetdone', sys.exit)

    def exitDistrictReset(self):
        self.districtResetDialog.cleanup()
        del self.districtResetDialog

    def enterWaitForSetAvatarResponse(self, choice):
        #self.acceptOnce(self.csm.getSetAvatarEvent(), self.__handleSetAvatarResponse)
        self.sendSetAvatarMsg(choice)

    def enterLoadDone(self):
        self.loginFSM.request("playingGame")

    def __handleSetAvatarResponse(self, avId, di):
        print "Entering game..."
        enterLoad = EnterLoad(self.enterLoadDone)
        dclass = self.dclassesByName['DistributedPlayerToon']
        localAvatar = LocalToon.LocalToon(base.cr)
        localAvatar.dclass = dclass
        base.localAvatar = localAvatar
        __builtins__['localAvatar'] = base.localAvatar
        localAvatar.doId = avId
        self.localAvId = avId
        parentId = None
        zoneId = None
        localAvatar.setLocation(parentId, zoneId)
        localAvatar.generateInit()
        localAvatar.generate()
        dclass.receiveUpdateBroadcastRequiredOwner(localAvatar, di)
        localAvatar.announceGenerate()
        localAvatar.postGenerateMessage()
        self.doId2do[avId] = localAvatar

        # TEMPORARY:
        #localAvatar.hoodsDiscovered = [1000, 2000, 3000, 4000, 5000, 9000]
        #localAvatar.teleportAccess = [1000, 2000, 3000, 4000, 5000, 9000]

        enterLoad.load()
        del enterLoad

    def exitWaitForSetAvatarResponse(self):
        self.ignore(self.csm.getSetAvatarEvent())

    def enterWaitForGameEnterResponse(self, status, shardId):
        if shardId is not None:
            district = self.activeDistricts[shardId]
        else:
            district = None
        if not district:
            self.loginFSM.request('noShards')
            return
        else:
            self.myDistrict = district
        self.notify.info("Entering shard %s" % shardId)
        localAvatar.setLocation(shardId, status['zoneId'])
        localAvatar.defaultShard = shardId
        self.handleEnteredShard(status)
        return

    def handleEnteredShard(self, status):
        self.uberZoneInterest = self.addInterest(localAvatar.defaultShard,
                                                 ZoneUtil.UberZone, 'uberZone',
                                                 'uberZoneInterestComplete')
        self.acceptOnce('uberZoneInterestComplete',
                        self.uberZoneInterestComplete, [status])

    def uberZoneInterestComplete(self, status):
        self.__gotTimeSync = 0
        if self.timeManager is None:
            print "No time manager"
            DistributedSmoothNode.globalActivateSmoothing(0, 0)
            self.gotTimeSync(status)
        else:
            print "Time manager found"
            DistributedSmoothNode.globalActivateSmoothing(1, 0)
            #h = HashVal()
            #hashPrcVariables(h)
            #pyc = HashVal()
            #if not __dev__:
            #	self.hashFiles(pyc)
            #self.timeManager.d_setSignature(self.userSignature, h.asBin(), pyc.asBin())
            #self.timeManager.sendCpuInfo()

            self.timeManager.lastAttempt = -self.timeManager.minWait * 2
            if self.timeManager.synchronize('startup'):
                self.accept('gotTimeSync', self.gotTimeSync, [status])
            else:
                self.gotTimeSync(status)
        return

    def getPing(self):
        if self.myDistrict:
            return self.myDistrict.currentPing
        return 0

    def exitWaitForGameEnterResponse(self):
        self.ignore('uberZoneInterestComplete')
        return

    def gotTimeSync(self, status):
        self.notify.info('gotTimeSync')
        self.ignore('gotTimeSync')
        self.__gotTimeSync = 1
        self.prepareToEnter(status)

    def prepareToEnter(self, status):
        if not self.__gotTimeSync:
            self.notify.info("still waiting for time sync")
            return
        self.gameFSM.request('playGame', [status])

    def enterMakeAToon(self, slot):
        base.stopMusic()
        self.makeAToon.setSlot(slot)
        self.makeAToon.loadEnviron()
        self.makeAToon.load()
        self.makeAToon.matFSM.request('genderShop')
        self.acceptOnce("quitCreateAToon", self.__handleMakeAToonQuit)
        self.acceptOnce("createAToonFinished", self.__handleMakeAToonDone)

    def __handleMakeAToonQuit(self):
        self.loginFSM.request("avChoose")

    def __handleMakeAToonDone(self, dnaStrand, slot, name):
        self.loginFSM.request('submitNewToon',
                              enterArgList=[dnaStrand, slot, name])

    def exitMakeAToon(self):
        self.makeAToon.setSlot(-1)
        self.makeAToon.enterExit(None)
        self.ignore("quitCreateAToon")
        self.ignore("createAToonFinished")

    def enterSubmitNewToon(self, dnaStrand, slot, name, skipTutorial=0):
        self.newToonSlot = slot
        self.submittingDialog = GlobalDialog(message=CIGlobals.Submitting)
        self.submittingDialog.show()
        self.acceptOnce(self.csm.getToonCreatedEvent(),
                        self.__handleSubmitNewToonResp)
        self.csm.sendSubmitNewToon(dnaStrand, slot, name, skipTutorial)

    def __handleSubmitNewToonResp(self, avId):
        # Now that our toon exists in the database, we can add send over the name we wanted to NameServicesManagerUD.
        if self.requestedName is not None:
            self.nameServicesManager.d_requestName(self.requestedName, avId)
            self.requestedName = None

        self.loginFSM.request('avChoose', [self.newToonSlot])

    def exitSubmitNewToon(self):
        self.newToonSlot = None
        self.ignore(self.csm.getToonCreatedEvent())
        self.submittingDialog.cleanup()
        del self.submittingDialog

    def enterGameOff(self):
        pass

    def exitGameOff(self):
        pass

    def enterPlayGame(self, status):
        base.stopMusic()
        base.transitions.noFade()
        if self.localAvChoice is None:
            self.notify.error(
                "called enterPlayGame() without self.localAvChoice being set!")
            return
        if localAvatar.getTutorialCompleted() == 1:
            zoneId = status['zoneId']
            hoodId = status['hoodId']
            avId = status['avId']
            self.playGame.load()
            self.playGame.enter(hoodId, zoneId, avId)
        else:
            self.sendQuietZoneRequest()
            localAvatar.sendUpdate('createTutorial')
        self.myDistrict.d_joining()

    def tutorialCreated(self, zoneId):
        # zoneId = the zone the tutorial resides in
        # tutId = the doId of the tutorial
        requestStatus = {'zoneId': zoneId}
        self.tutQuietZoneState = QuietZoneState('tutQuietZoneDone')
        self.tutQuietZoneState.load()
        self.tutQuietZoneState.enter(requestStatus)
        self.acceptOnce('tutQuietZoneDone', self.__handleTutQuietZoneDone)

    def __handleTutQuietZoneDone(self):
        # We've entered the zone that the tutorial is in.
        self.tutQuietZoneState.exit()
        self.tutQuietZoneState.unload()
        del self.tutQuietZoneState

    def exitPlayGame(self):
        self.ignore('tutQuietZoneDone')
        if hasattr(self, 'tutQuietZoneDone'):
            self.tutQuietZoneState.exit()
            self.tutQuietZoneState.unload()
            del self.tutQuietZoneState
        base.stopMusic()
        self.playGame.exit()
        self.playGame.unload()

    def enterDisconnect(self, isPlaying, booted=0, bootReason=None):
        self.notify.info(
            "Disconnect details: isPlaying = %s, booted = %s, bootReason = %s"
            % (isPlaying, booted, bootReason))
        style = 3
        if isPlaying == 1:
            if not booted:
                msg = CIGlobals.DisconnectionMsg
        else:
            if not booted:
                msg = CIGlobals.JoinFailureMsg
        if self.isConnected():
            self.sendDisconnect()
        self.disconnectDialog = GlobalDialog(message=msg,
                                             style=style,
                                             doneEvent="disconnectDone")
        self.disconnectDialog.show()
        if style == 3:
            self.acceptOnce("disconnectDone", sys.exit)
        else:
            self.acceptOnce("disconnectDone", self.handleDisconnectDone)

    def handleDisconnectDone(self):
        value = self.disconnectDialog.getValue()
        if value:
            self.loginFSM.request('connect')
        else:
            sys.exit()

    def exitDisconnect(self):
        self.ignore("disconnectDone")
        self.disconnectDialog.cleanup()
        del self.disconnectDialog

    def renderFrame(self):
        gsg = base.win.getGsg()
        if gsg:
            render2d.prepareScene(gsg)
        base.graphicsEngine.renderFrame()

    def renderFrames(self):
        base.graphicsEngine.renderFrame()
        base.graphicsEngine.renderFrame()

    def handleDatagram(self, di):
        if self.notify.getDebug():
            print "ClientRepository received datagram:"
            #di.getDatagram().dumpHex(ostream)
        msgType = self.getMsgType()
        self.currentSenderId = None
        if self.handler is None:
            self.astronHandle(di)
        else:
            self.handler(msgType, di)
        self.considerHeartbeat()

    def astronHandle(self, di):
        AstronClientRepository.handleDatagram(self, di)

    def handleQuietZoneGenerateWithRequired(self, di):
        doId = di.getUint32()
        parentId = di.getUint32()
        zoneId = di.getUint32()
        classId = di.getUint16()
        dclass = self.dclassesByNumber[classId]
        if dclass.getClassDef().neverDisable:
            dclass.startGenerate()
            distObj = self.generateWithRequiredFields(dclass, doId, di,
                                                      parentId, zoneId)
            dclass.stopGenerate()

    def handleQuietZoneGenerateWithRequiredOther(self, di):
        doId = di.getUint32()
        parentId = di.getUint32()
        zoneId = di.getUint32()
        classId = di.getUint16()
        dclass = self.dclassesByNumber[classId]
        if dclass.getClassDef().neverDisable:
            dclass.startGenerate()
            distObj = self.generateWithRequiredOtherFields(
                dclass, doId, di, parentId, zoneId)
            dclass.stopGenerate()

    def handleQuietZoneUpdateField(self, di):
        di2 = DatagramIterator(di)
        doId = di2.getUint32()
        if doId in self.deferredDoIds:
            args, deferrable, dg0, updates = self.deferredDoIds[doId]
            dclass = args[2]
            if not dclass.getClassDef().neverDisable:
                return
        else:
            do = self.getDo(doId)
            if do:
                if not do.neverDisable:
                    return
        AstronClientRepository.handleUpdateField(self, di)

    def handleDelete(self, di):
        doId = di.getUint32()
        self.deleteObject(doId)

    def _abandonShard(self):
        for doId, obj in self.doId2do.items():
            if obj.parentId == localAvatar.defaultShard and obj is not localAvatar:
                self.deleteObject(doId)

    def handleEnterObjectRequiredOwner(self, di):
        if self.loginFSM.getCurrentState().getName(
        ) == 'waitForSetAvatarResponse':
            doId = di.getUint32()
            parentId = di.getUint32()
            zoneId = di.getUint32()
            dclassId = di.getUint16()
            self.__handleSetAvatarResponse(doId, di)
        else:
            AstronClientRepository.handleEnterObjectRequiredOwner(self, di)

    def addTaggedInterest(self,
                          parentId,
                          zoneId,
                          mainTag,
                          desc,
                          otherTags=[],
                          event=None):
        return self.addInterest(parentId, zoneId, desc, event)

    def sendSetAvatarMsg(self, choice):
        avId = choice.getAvId()
        self.sendSetAvatarIdMsg(avId)
        self.localAvChoice = choice

    def sendSetAvatarIdMsg(self, avId):
        if avId != self.__currentAvId:
            self.__currentAvId = avId
            self.csm.sendSetAvatar(avId)

    def sendQuietZoneRequest(self):
        self.sendSetZoneMsg(ZoneUtil.QuietZone)
Esempio n. 3
0
class DistributedMinigame(DistributedObject.DistributedObject, Timer.Timer):
    def __init__(self, cr):
        try:
            self.DistributedMinigame_initialized
            return
        except:
            self.DistributedMinigame_initialized = 1

        DistributedObject.DistributedObject.__init__(self, cr)
        Timer.Timer.__init__(self)
        self.headPanels = HeadPanels()
        self.finalScoreUI = FinalScoreGUI()
        self.fsm = ClassicFSM('DistributedMinigame', [
            State('start', self.enterStart, self.exitStart, ['waitForOthers']),
            State('waitForOthers', self.enterWaitForOthers,
                  self.exitWaitForOthers, ['play']),
            State('play', self.enterPlay, self.exitPlay, ['gameOver']),
            State('gameOver', self.enterGameOver, self.exitGameOver, ['off']),
            State('off', self.enterOff, self.exitOff)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.cr = cr
        self.localAv = base.localAvatar
        self.localAvId = self.localAv.doId
        self.musicPath = 'phase_4/audio/bgm/trolley_song.mid'
        self.winSfx = base.loadSfx('phase_4/audio/sfx/MG_win.ogg')
        self.loseSfx = base.loadSfx('phase_4/audio/sfx/MG_lose.ogg')
        self.prizeHigh = base.loadSfx('phase_6/audio/sfx/KART_Applause_1.ogg')
        self.prizeLow = base.loadSfx('phase_6/audio/sfx/KART_Applause_4.ogg')
        self.music = None
        self.description = ''
        self.descDialog = None
        self.winnerPrize = 0
        self.loserPrize = 0
        self.winnerMsg = 'Winner!\nYou have earned: %s Jellybeans'
        self.loserMsg = 'Loser!\nYou have earned: %s Jellybeans'
        self.allWinnerMsgs = [
            'Nice try!\nYou have earned: %s', 'Good job!\nYou have earned: %s',
            'Way to go!\nYou have earned: %s', 'Awesome!\nYou have earned: %s'
        ]
        self.timer = None
        self.timeLbl = None
        self.alertText = None
        self.alertPulse = None
        self.popupSound = None
        self.gameOverLbl = OnscreenText(text="TIME'S\nUP!",
                                        scale=0.25,
                                        font=CIGlobals.getMickeyFont(),
                                        fg=(1, 0, 0, 1))
        self.gameOverLbl.setBin('gui-popup', 60)
        self.gameOverLbl.hide()
        return

    def getTeamDNAColor(self, team):
        pass

    def showAlert(self, text):
        self.stopPulse()
        base.playSfx(self.popupSound)
        self.alertText.setText(text)
        self.alertPulse = getAlertPulse(self.alertText)
        self.alertPulse.start()

    def stopPulse(self):
        if self.alertPulse:
            self.alertPulse.finish()
            self.alertPulse = None
        return

    def enterFinalScores(self):
        self.finalScoreUI.load()
        self.finalScoreUI.showFinalScores()

    def exitFinalScores(self):
        self.finalScoreUI.hideFinalScores()
        self.finalScoreUI.unload()

    def finalScores(self, avIdList, scoreList):
        self.finalScoreUI.handleFinalScores(avIdList, scoreList)

    def generateHeadPanel(self, gender, head, headtype, color, doId, name):
        self.headPanels.generate(gender, head, headtype, color, doId, name)

    def updateHeadPanelValue(self, doId, direction):
        self.headPanels.updateValue(doId, direction)

    def setTimerTime(self, time):
        self.setTime(time)

    def createTimer(self):
        Timer.Timer.load(self)

    def deleteTimer(self):
        Timer.Timer.unload(self)

    def setDescription(self, desc):
        self.description = desc

    def getDescription(self):
        return self.description

    def enterStart(self):
        self.descDialog = GlobalDialog(style=3,
                                       message=self.getDescription(),
                                       doneEvent='gameDescAck')
        self.acceptOnce('gameDescAck', self.handleDescAck)

    def handleDescAck(self):
        self.d_ready()
        self.fsm.request('waitForOthers')

    def exitStart(self):
        self.ignore('gameDescAck')
        self.descDialog.cleanup()
        del self.descDialog

    def enterWaitForOthers(self):
        self.waitLbl = DirectLabel(text='Waiting for other players...',
                                   relief=None,
                                   text_fg=(1, 1, 1, 1),
                                   text_scale=0.08,
                                   text_shadow=(0, 0, 0, 1))
        return

    def exitWaitForOthers(self):
        self.waitLbl.destroy()
        del self.waitLbl

    def setLoserPrize(self, prize):
        self.loserPrize = prize

    def setWinnerPrize(self, prize):
        self.winnerPrize = prize

    def getLoserPrize(self):
        return self.loserPrize

    def getWinnerPrize(self):
        return self.winnerPrize

    def winner(self):
        self.winSfx.play()
        self.localAv.b_setAnimState('happy')
        Sequence(Wait(3.5), Func(self.displayGameOver, 'winner')).start()

    def showPrize(self, amt):
        self.winSfx.play()
        self.localAv.b_setAnimState('happy')
        Sequence(Wait(3.5), Func(self.displayGameOver, 'showPrize',
                                 amt)).start()

    def loser(self):
        self.loseSfx.play()
        self.localAv.b_setAnimState('neutral')
        Sequence(Wait(3.5), Func(self.displayGameOver, 'loser')).start()

    def displayGameOver(self, scenario, amt=None):
        if scenario == 'winner':
            msg = self.winnerMsg % self.winnerPrize
            self.prizeHigh.play()
        else:
            if scenario == 'loser':
                msg = self.loserMsg % self.loserPrize
                self.prizeLow.play()
            else:
                if scenario == 'showPrize':
                    msg = random.choice(self.allWinnerMsgs) % amt
                    self.prizeHigh.play()
        self.gameOverDialog = GlobalDialog(message=msg,
                                           style=3,
                                           doneEvent='gameOverAck')
        self.acceptOnce('gameOverAck', self.__handleGameOverAck)
        self.gameOverDialog.show()

    def deleteGameOverDialog(self):
        self.ignore('gameOverAck')
        if hasattr(self, 'gameOverDialog'):
            self.gameOverDialog.cleanup()
            del self.gameOverDialog

    def __handleGameOverAck(self):
        self.fsm.requestFinalState()
        Sequence(Func(base.transitions.irisOut, 1.0), Wait(1.2),
                 Func(self.d_leaving),
                 Func(self.headBackToMinigameArea)).start()

    def headBackToMinigameArea(self):
        whereName = ZoneUtil.getWhereName(CIGlobals.MinigameAreaId)
        loaderName = ZoneUtil.getLoaderName(CIGlobals.MinigameAreaId)
        requestStatus = {
            'zoneId': CIGlobals.MinigameAreaId,
            'hoodId': CIGlobals.MinigameArea,
            'where': whereName,
            'how': 'teleportIn',
            'avId': base.localAvatar.doId,
            'shardId': None,
            'loader': loaderName
        }
        self.cr.playGame.hood.fsm.request('quietZone', [requestStatus])
        return

    def abort(self):
        self.headBackToMinigameArea()

    def load(self, showDesc=True):
        if showDesc:
            self.fsm.request('start')
        base.transitions.irisIn()

    def d_leaving(self):
        self.sendUpdate('leaving', [])

    def allPlayersReady(self):
        self.fsm.request('play')

    def enterPlay(self):
        self.playMinigameMusic()

    def exitPlay(self):
        self.stopMinigameMusic()

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterGameOver(self, winner, winnerDoId, allPrize):
        if winner:
            if self.localAvId in winnerDoId:
                self.winner()
            else:
                self.loser()
        else:
            self.showPrize(allPrize)

    def exitGameOver(self):
        self.deleteGameOverDialog()

    def gameOver(self, winner=0, winnerDoId=[], allPrize=0):
        self.fsm.request('gameOver', [winner, winnerDoId, allPrize])

    def setMinigameMusic(self, path):
        self.musicPath = path

    def getMinigameMusic(self):
        return self.musicPath

    def playMinigameMusic(self):
        self.stopMinigameMusic()
        self.music = base.loadMusic(self.musicPath)
        self.music.setLoop(True)
        self.music.setVolume(0.8)
        self.music.play()

    def stopMinigameMusic(self):
        if self.music:
            self.music.stop()
            self.music = None
        return

    def d_ready(self):
        self.sendUpdate('ready', [])

    def announceGenerate(self):
        DistributedObject.DistributedObject.announceGenerate(self)
        base.minigame = self
        self.alertText = getAlertText()
        self.popupSound = base.loadSfx(
            'phase_3/audio/sfx/GUI_balloon_popup.ogg')
        NametagGlobals.setWant2dNametags(False)

    def disable(self):
        base.localAvatar.getGeomNode().setColorScale(VBase4(1, 1, 1, 1))
        if hasattr(self, 'gameOverLbl') and self.gameOverLbl:
            self.gameOverLbl.destroy()
        self.gameOverLbl = None
        NametagGlobals.setWant2dNametags(True)
        base.localAvatar.setPosHpr(0, 0, 0, 0, 0, 0)
        self.fsm.requestFinalState()
        del self.fsm
        self.winSfx = None
        self.loseSfx = None
        self.prizeHigh = None
        self.prizeLow = None
        self.headPanels.delete()
        self.headPanels = None
        self.finalScoreUI.unload()
        self.finalScoreUI = None
        base.minigame = None
        DistributedObject.DistributedObject.disable(self)
        return
class Slot(DirectFrame):
    def __init__(self, baseGui, index, pos, parent):
        DirectFrame.__init__(
            self,
            pos=pos,
            parent=parent,
            image=loader.loadTexture('phase_3.5/maps/slot_%s_%s.png' %
                                     (str(index), 'idle')),
            scale=0.15,
            frameSize=(-1, 1, -1, 1),
            frameColor=(0, 0, 0, 0),
            sortOrder=0)
        self.initialiseoptions(Slot)
        self.gui = baseGui
        self.index = index
        self.hoverObj = None
        self.gagImage = None
        self.gag = None
        self.mouseRlvrSfx = base.loadSfx('phase_3/audio/sfx/GUI_rollover.ogg')
        self.soundRecharged = base.loadSfx(
            'phase_3.5/audio/sfx/tt_s_gui_sbk_cdrSuccess.ogg')
        self.infoText = OnscreenText(text='No\nAmmo',
                                     fg=(1, 0, 0, 1),
                                     parent=self,
                                     scale=0.5,
                                     shadow=(0, 0, 0, 1),
                                     align=TextNode.ACenter,
                                     pos=(0, 0.1))
        self.infoText.setBin('unsorted', 100)
        self.infoText.hide()
        self.rechargeBar = DirectWaitBar(value=0,
                                         range=100,
                                         frameColor=(1, 1, 1, 1),
                                         barColor=(0.286, 0.901, 1, 1),
                                         relief=DGG.RAISED,
                                         borderWidth=(0.04, 0.04),
                                         pos=(-1.25, 0, 0),
                                         hpr=(0, 0, -90),
                                         parent=self,
                                         frameSize=(-0.85, 0.85, -0.12, 0.12))
        self.rechargeBar.setBin('fixed', 60)
        self.rechargeBar.hide()
        self.gagLabel = OnscreenText(text='Birthday Cake',
                                     fg=(1, 1, 1, 1),
                                     parent=self,
                                     scale=0.25,
                                     shadow=(0, 0, 0, 1),
                                     align=TextNode.ACenter,
                                     pos=(0, -0.9),
                                     mayChange=1)
        self.gagLabel.setBin('fixed', 50)
        self.gagLabel.hide()
        battleGui = loader.loadModel('phase_3.5/models/gui/battle_gui.bam')
        arrow = battleGui.find('**/PckMn_BackBtn')
        arrowRlvr = battleGui.find('**/PckMn_BackBtn_Rlvr')
        arrowDn = battleGui.find('**/PckMn_BackBtn_Dn')
        self.leftArrow = DirectButton(geom=(arrow, arrowDn, arrowRlvr, arrow),
                                      parent=self,
                                      pos=(-0.925, -2.0, -1.02),
                                      relief=None,
                                      scale=2,
                                      command=self.updateLoadout,
                                      extraArgs=[0],
                                      geom3_color=(0.5, 0.5, 0.5, 1.0))
        self.leftArrow.setBin('fixed', 60)
        self.rightArrow = DirectButton(geom=(arrow, arrowDn, arrowRlvr, arrow),
                                       parent=self,
                                       pos=(0.925, -2.0, -1.02),
                                       hpr=(180, 0, 0),
                                       relief=None,
                                       scale=2,
                                       command=self.updateLoadout,
                                       extraArgs=[1],
                                       geom3_color=(0.5, 0.5, 0.5, 1.0))
        self.rightArrow.setBin('fixed', 60)
        self.hoverObj = DirectButton(relief=None,
                                     parent=self,
                                     frameSize=self['frameSize'])
        self.setBin('transparent', 30)
        self.setOutlineImage('idle')
        self.hoverObj.guiItem.setActive(True)
        self.hoverObj.bind(DGG.WITHIN, self.mouseEntered)
        self.hoverObj.bind(DGG.WITHOUT, self.mouseExited)
        self.hoverObj.bind(DGG.B1CLICK, self.gui.click_setWeapon, [self])
        return

    def toggleArrows(self, left, right):
        if left:
            self.leftArrow['state'] = DGG.NORMAL
        else:
            self.leftArrow['state'] = DGG.DISABLED
        if right:
            self.rightArrow['state'] = DGG.NORMAL
        else:
            self.rightArrow['state'] = DGG.DISABLED

    def updateArrows(self):
        if not self.gag:
            self.toggleArrows(False, False)
        else:
            track = GagGlobals.TrackGagNamesByTrackName.get(
                GagGlobals.getTrackOfGag(self.gag.getID()))
            index = None
            useTrack = []
            for name in track:
                gag = self.gui.backpack.getGagByID(
                    GagGlobals.getIDByName(name))
                if gag == self.gag or gag not in self.gui.backpack.getLoadout(
                ):
                    useTrack.append(name)

            index = useTrack.index(self.gag.getName())
            if index == 0:
                self.toggleArrows(False, True)
            else:
                if index > 0 and index < len(useTrack) - 1:
                    gagId = GagGlobals.getIDByName(useTrack[index + 1])
                    if not self.gui.backpack.hasGag(gagId):
                        self.toggleArrows(True, False)
                else:
                    if index == len(useTrack) - 1:
                        self.toggleArrows(True, False)
                    else:
                        self.toggleArrows(True, True)
        return

    def updateLoadout(self, forward):
        if self.gag and self.gag.getState() in [
                GagState.RECHARGING, GagState.LOADED
        ]:
            track = GagGlobals.TrackGagNamesByTrackName.get(
                GagGlobals.getTrackOfGag(self.gag.getID()))
            index = None
            useTrack = []
            for name in track:
                gag = self.gui.backpack.getGagByID(
                    GagGlobals.getIDByName(name))
                if gag == self.gag or gag not in self.gui.backpack.getLoadout(
                ):
                    useTrack.append(name)

            index = useTrack.index(self.gag.getName())
            if forward == 1:
                nextGagIndex = index + 1
            else:
                nextGagIndex = index - 1
            if nextGagIndex < 0 or nextGagIndex >= len(useTrack):
                return
            gagId = GagGlobals.getIDByName(useTrack[nextGagIndex])
            loadout = self.gui.backpack.getLoadout()
            if self.gui.backpack.hasGag(gagId) and self.gag in loadout:
                self.hideInfoText()
                if self.gag not in loadout:
                    return
                loadout[loadout.index(
                    self.gag)] = self.gui.backpack.getGagByID(gagId)
                self.gui.backpack.setLoadout(loadout)
        return

    def showNoAmmo(self):
        self.infoText['text'] = 'No\nAmmo'
        self.infoText['scale'] = 0.5
        self.infoText['fg'] = (1, 0, 0, 1)
        self.infoText['pos'] = (0, 0.1)
        self.infoText.show()
        if self.gag and self.gag.getState() == GagState.RECHARGING:
            self.rechargeBar.show()

    def showRecharging(self):
        self.infoText['text'] = 'Recharging...'
        self.infoText['scale'] = 0.315
        self.infoText['fg'] = (0.286, 0.901, 1, 1)
        self.infoText['pos'] = (0, 0)
        self.infoText.show()
        self.rechargeBar.show()

    def __tickRecharge(self):
        if not self.gag:
            self.ignoreAll()
        else:
            elapsedTime = float(self.gag.getRechargeElapsedTime())
            totalTime = float(self.gag.getRechargeTime())
            barValue = int(
                float(elapsedTime / totalTime) * self.rechargeBar['range'])
            self.rechargeBar['value'] = barValue
            if barValue == 0:
                self.gui.setWeapon(self, playSound=False)
                self.setOutlineImage('no_ammo')
                self.showRecharging()
            else:
                if barValue >= 100:
                    base.playSfx(self.soundRecharged)
                    slotImage = 'idle'
                    if base.localAvatar.getBackpack().getSupply(
                            self.gag.getID()) <= 0:
                        slotImage = 'no_ammo'
                    else:
                        if self.gui.getActiveSlot() == self:
                            slotImage = 'selected'
                    Sequence(Wait(0.5), Func(self.setOutlineImage,
                                             slotImage)).start()

    def hideInfoText(self):
        self.infoText.hide()
        self.rechargeBar.hide()

    def setSlotImage(self, gagImage):
        if self.gagImage:
            self.gagImage.destroy()
            self.gagImage = None
        self.gagImage = OnscreenImage(image=gagImage, parent=self)
        self.gagImage.setTransparency(TransparencyAttrib.MAlpha)
        return

    def setOutline(self):
        self.setTransparency(TransparencyAttrib.MAlpha)

    def setOutlineImage(self, image):
        phase = 'phase_3.5/maps/'
        if hasattr(self, '_optionInfo'):
            self['image'] = loader.loadTexture(phase + 'slot_%s_%s.png' %
                                               (str(self.index), image))
            self.setOutline()
            if image != 'no_ammo':
                if self.gag and base.localAvatar.getBackpack().getSupply(
                        self.gag.getID(
                        )) == 0 or self.gag and self.gag.getState(
                        ) == GagState.RECHARGING:
                    image = 'no_ammo'
            if image == 'no_ammo':
                if self.gag and self.gag.getState() == GagState.RECHARGING:
                    self.showRecharging()
                else:
                    self.showNoAmmo()
                    self.rechargeBar.hide()
                self.setBin('fixed', 40)
                if self.gagImage:
                    self.gagImage.setBin('transparent', 30)
            else:
                self.hideInfoText()
                if self.gagImage:
                    self.gagImage.setBin('fixed', 40)
                self.setBin('transparent', 30)

    def getOutline(self):
        return self.outline

    def mouseEntered(self, cmd):
        if self.gag:
            self.gagLabel.show()
            self.mouseRlvrSfx.play()

    def mouseExited(self, cmd):
        self.gagLabel.hide()

    def setGag(self, gag):
        if type(gag) == types.IntType:
            gag = self.gui.backpack.getGagByID(gag)
        self.ignoreAll()
        self.gag = gag
        if gag:
            self.show()
            self.setSlotImage(self.gag.getImage())
            self.gagLabel['text'] = self.gag.getName()
            self.accept('%s-Recharge-Tick' % str(self.gag.getID()),
                        self.__tickRecharge)
        else:
            self.hide()
            self.gagLabel['text'] = ''
        self.updateArrows()

    def getGag(self):
        return self.gag
class KOTHGui(DirectFrame):
    notify = directNotify.newCategory('KOTHGui')

    pointsSfx = None
    points = None

    def __init__(self):
        # Let's load up the DirectFrame
        DirectFrame.__init__(self,
                             parent=base.a2dTopLeft,
                             relief=None,
                             pos=(0.275, 1, -0.7),
                             sortOrder=0)

        # The variables we're going to be using.
        self.pointsSfx = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
        self.points = 0

        # Background because it won't work for whatever reason.
        gui = loader.loadModel('phase_4/models/gui/purchase_gui.bam')
        panel = gui.find('**/yellowPanel')
        self.bg = OnscreenImage(image=panel, parent=self)

        # Let's setup the header text.
        self.title = OnscreenText(text='Capture Points',
                                  font=CIGlobals.getMinnieFont(),
                                  parent=self,
                                  scale=0.0475,
                                  pos=(0, 0.18),
                                  fg=(1, 0, 0, 1),
                                  shadow=(0.2, 0.2, 0.2, 1))

        # Let's setup the amount text.
        self.amt_label = OnscreenText(text=str(self.points),
                                      font=CIGlobals.getToonFont(),
                                      parent=self,
                                      scale=0.15,
                                      pos=(0, 0.03525),
                                      shadow=(0.5, 0.5, 0.5, 0.6))

        # Let's setup the info text.
        self.info = OnscreenText(
            text=
            'First Toon to 100 points wins!\nEarn points by standing on the\nhill after capturing it.',
            parent=self,
            font=CIGlobals.getToonFont(),
            scale=0.035,
            pos=(0, -0.05),
            fg=(1.5, 0, 0, 1),
            shadow=(0.2, 0.2, 0.2, 1))

        # We're not ready to show the GUI yet.
        self.hide()

    def show(self):
        self.title.show()
        self.amt_label.show()
        self.info.show()
        self.bg.show()

    def hide(self):
        self.title.hide()
        self.amt_label.hide()
        self.info.hide()
        self.bg.hide()

    def destroy(self):
        self.title.destroy()
        self.amt_label.destroy()
        self.info.destroy()
        self.bg.destroy()
        self.title = None
        self.amt_label = None
        self.info = None
        self.bg = None

        # Let's get rid of the sound.
        self.pointsSfx.stop()
        self.pointsSfx = None

        self.points = None
        DirectFrame.destroy(self)

    def setPoints(self, points):
        self.points = points
        self.amt_label.setText(str(self.points))
        self.pointsSfx.play()

    def getPoints(self):
        return self.points
class KOTHGui(DirectFrame):
    notify = directNotify.newCategory('KOTHGui')
    pointsSfx = None
    points = None

    def __init__(self):
        DirectFrame.__init__(self,
                             parent=base.a2dTopLeft,
                             relief=None,
                             pos=(0.275, 1, -0.7),
                             sortOrder=0)
        self.pointsSfx = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
        self.points = 0
        gui = loader.loadModel('phase_4/models/gui/purchase_gui.bam')
        panel = gui.find('**/yellowPanel')
        self.bg = OnscreenImage(image=panel, parent=self)
        self.title = OnscreenText(text='Capture Points',
                                  font=CIGlobals.getMinnieFont(),
                                  parent=self,
                                  scale=0.0475,
                                  pos=(0, 0.18),
                                  fg=(1, 0, 0, 1),
                                  shadow=(0.2, 0.2, 0.2, 1))
        self.amt_label = OnscreenText(text=str(self.points),
                                      font=CIGlobals.getToonFont(),
                                      parent=self,
                                      scale=0.15,
                                      pos=(0, 0.03525),
                                      shadow=(0.5, 0.5, 0.5, 0.6))
        self.info = OnscreenText(
            text=
            'First Toon to 100 points wins!\nEarn points by standing on the\nhill after capturing it.',
            parent=self,
            font=CIGlobals.getToonFont(),
            scale=0.035,
            pos=(0, -0.05),
            fg=(1.5, 0, 0, 1),
            shadow=(0.2, 0.2, 0.2, 1))
        self.hide()
        return

    def show(self):
        self.title.show()
        self.amt_label.show()
        self.info.show()
        self.bg.show()

    def hide(self):
        self.title.hide()
        self.amt_label.hide()
        self.info.hide()
        self.bg.hide()

    def destroy(self):
        self.title.destroy()
        self.amt_label.destroy()
        self.info.destroy()
        self.bg.destroy()
        self.title = None
        self.amt_label = None
        self.info = None
        self.bg = None
        self.pointsSfx.stop()
        self.pointsSfx = None
        self.points = None
        DirectFrame.destroy(self)
        return

    def setPoints(self, points):
        self.points = points
        self.amt_label.setText(str(self.points))
        self.pointsSfx.play()

    def getPoints(self):
        return self.points
Esempio n. 7
0
class LocationGag(Precacheable):

    buttonSoundPath = 'phase_5/audio/sfx/AA_drop_trigger_box.ogg'
    buttonPath = 'phase_3.5/models/props/button.bam'

    def __init__(self, minDistance, maxDistance, shadowScale=1):
        self.button = None
        self.buttonSfx = loader.loadSfx(self.buttonSoundPath)
        self.buttonAnim = 'push-button'
        self.chooseLocFrame = 34
        self.hitStartFrame = 45
        self.completeFrame = 77
        self.dropLoc = None
        self.minDistance = minDistance
        self.maxDistance = maxDistance
        self.locationSeeker = None
        self.buttonHold = 0.15
        self.actorTrack = None
        self.soundTrack = None
        self.isCircle = False
        self.shadowScale = 1
        self.helpInfo = None

    @classmethod
    def doPrecache(cls):
        precacheSound(cls.buttonSoundPath)
        precacheModel(cls.buttonPath)

    def setShadowData(self, isCircle, shadowScale):
        self.isCircle = isCircle
        self.shadowScale = shadowScale

    def getShadowScale(self):
        return self.shadowScale

    def equip(self):
        print "equip again"
        self.cleanupLocationSeeker()
        self.buildButton()
        self.button.reparentTo(self.avatar.find('**/def_joint_left_hold'))

        if self.isLocal():
            fpsCam = base.localAvatar.getFPSCam()
            vm = fpsCam.viewModel
            fpsCam.setVMGag(self.button,
                            pos=(-0.04, 0.05, -0.01),
                            hpr=(328.39, 268.95, 359.48),
                            scale=0.559,
                            hand=1)
            fpsCam.setVMAnimTrack(
                Sequence(ActorInterval(vm, 'button_draw'),
                         Func(vm.loop, 'button_idle')))

            self.locationSeeker = LocationSeeker(self.avatar, self,
                                                 self.minDistance,
                                                 self.maxDistance)
            self.locationSeeker.setShadowType(self.isCircle, self.shadowScale)
            self.avatar.acceptOnce(
                self.locationSeeker.getLocationSelectedName(),
                base.localAvatar.releaseGag)

            self.helpInfo = OnscreenText(
                text='Move the shadow with your mouse\nClick to release',
                pos=(0, -0.75),
                font=CIGlobals.getToonFont(),
                fg=(1, 1, 1, 1),
                shadow=(0, 0, 0, 1))
            self.helpInfo.hide()  # yeet

        self.doDrawAndHold(self.buttonAnim,
                           0,
                           self.chooseLocFrame,
                           bobStart=self.chooseLocFrame,
                           bobEnd=self.chooseLocFrame,
                           holdCallback=self.locationSeeker.startSeeking
                           if self.isLocal() else None)

    def release(self):
        if self.avatar:
            self.buildTracks()
            if self.isLocal():
                self.getFPSCam().setVMAnimTrack(
                    Sequence(
                        ActorInterval(self.getViewModel(), 'button_press'),
                        Func(self.getViewModel().loop, 'button_idle')))

    def complete(self):
        if self.button:
            numFrames = base.localAvatar.getNumFrames(self.buttonAnim)
            self.getAnimationTrack(self.buttonAnim,
                                   startFrame=self.completeFrame,
                                   playRate=self.playRate).start()

        self.cleanupButton()

    def buildTracks(self, mode=0):
        if not self.avatar:
            return
        self.cleanupTracks()
        if mode == 0:
            self.actorTrack = Sequence(
                self.getAnimationTrack(self.buttonAnim,
                                       startFrame=self.hitStartFrame,
                                       endFrame=self.completeFrame,
                                       playRate=self.playRate))
            self.soundTrack = Sequence(
                Wait(self.buttonHold),
                SoundInterval(self.buttonSfx, node=self.avatar))

    def cleanupTracks(self):
        if self.actorTrack:
            self.actorTrack.pause()
            self.actorTrack = None
        if self.soundTrack:
            self.soundTrack.pause()
            self.soundTrack = None

    def getActorTrack(self):
        return self.actorTrack

    def getSoundTrack(self):
        return self.soundTrack

    def setDropLoc(self, x, y, z):
        self.dropLoc = Point3(x, y, z)

    def buildButton(self):
        self.cleanupButton()
        self.button = loader.loadModel(self.buttonPath)

    def setLocation(self, value):
        self.dropLoc = value

    def getLocation(self):
        return self.dropLoc

    def getLocationSeeker(self):
        return self.locationSeeker

    def cleanupButton(self):
        if self.button:
            self.button.removeNode()
            self.button = None

    def cleanupLocationSeeker(self):
        if self.locationSeeker:
            self.dropLoc = self.locationSeeker.getLocation()
            self.locationSeeker.cleanup()
            self.locationSeeker = None
        if self.helpInfo:
            self.helpInfo.destroy()

    def cleanup(self):
        self.cleanupButton()
        self.cleanupLocationSeeker()
        self.cleanupTracks()
        self.dropLoc = None
        self.buttonSfx.stop()
        self.buttonSoundPath = None
        self.buttonAnim = None
class DistributedInspectionSite(DistributedNode):
    
    def __init__(self, cr):
        DistributedNode.__init__(self, cr)
        
        #######################################################
        # The below attributes are required at generation time.
        #######################################################
        # The site id is the unique id associated with the data
        # for the inspection site.
        #######################################################
        self.siteId = -1
        self.zoneId = -1
        #######################################################
        self.siteData = None
        
        self.distanceTask = None
        self.interactCollSphereNP = None
        self.interactCollSphere = None
        self.identifierIcon = None
        self.floorMarker = None
        
        self.iconSequence = None
        self.fadeSequence = None
        self.text = None
        
    def setSiteId(self, _id):
        self.siteId = _id
    
    def getSiteId(self):
        return self.siteId
    
    def setZoneId(self, _id):
        self.zoneId = _id
        
    def getZoneId(self):
        return self.zoneId
        
    def announceGenerate(self):
        DistributedNode.announceGenerate(self)
        self.setName('InspectionSite-%d' % self.siteId)
        self.notify = directNotify.newCategory('DistributedInspectionSite[%d]' % self.siteId)
        self.siteData = InspectionSites.getSiteById(self.zoneId, self.siteId)
        
        if self.siteData:
            interactKey = base.inputStore.Interact.upper()
            self.text = OnscreenText(
                text = 'Press \'%s\' to %s' % (interactKey, self.siteData.type),
                pos = (0, -0.75), font = CIGlobals.getToonFont(), fg = (1, 1, 1, 1),
                shadow = (0, 0, 0, 1)
            )
            self.text.hide()
            self.distanceTask = base.taskMgr.add(self.__calculateDistance, self.uniqueName('calculateAvDistance'))
            self.generateCollision()
            self.generateIconAndMarker()
            self.accept('enter' + self.interactCollSphereNP.getName(), self.onEnter)
            self.accept('exit' + self.interactCollSphereNP.getName(), self.onExit)
        self.reparentTo(render)
        
    def __calculateDistance(self, task):
        dist = float(base.localAvatar.getPos(self).length())
        fullAlphaDist = 15.0
        noAlphaDist = 105.0
        alpha = 1.0
        
        if 10 < dist < noAlphaDist:
            alpha = float(fullAlphaDist / dist)
            if alpha < 0.0:
                alpha = 0.0
        elif dist >= noAlphaDist:
            alpha = 0.0
            
        self.identifierIcon.setColorScale(1.0, 1.0, 1.0, alpha)
        self.floorMarker.setColorScale(1.0, 1.0, 1.0, alpha)
        return task.cont
        
    def generateCollision(self):
        self.interactCollSphere = CollisionSphere(0, 0, 0, 4)
        self.interactCollSphere.setTangible(0)
        ss = CollisionNode('inspectionSensor')
        ss.addSolid(self.interactCollSphere)
        
        self.interactCollSphereNP = self.attachNewNode(ss)
        self.interactCollSphereNP.setCollideMask(CIGlobals.EventBitmask)

    def generateIconAndMarker(self):
        icon = 'phase_5/maps/inspect_location.mat'
        self.identifierIcon = DirectFrame(parent = self, image = icon, frameColor = (0, 0, 0, 0))
        self.identifierIcon.setTransparency(TransparencyAttrib.MAlpha)
        self.identifierIcon.setTwoSided(1)
        self.identifierIcon.setBillboardPointEye()
        self.identifierIcon.setZ(2.0)
        
        self.iconSequence = Sequence(
            LerpPosInterval(self.identifierIcon, 1.0, pos = (0, 0, 6.0), startPos = (0, 0, 3.0),
                blendType = 'easeInOut', name = ('inspSite%d-in' % self.siteId)),
            LerpPosInterval(self.identifierIcon, 1.0, pos = (0, 0, 3.0), startPos = (0, 0, 6.0),
                blendType = 'easeInOut', name = ('inspSite%d-out' % self.siteId))
        )
        
        self.iconSequence.loop()
        
        cm = CardMaker('marker')
        self.floorMarker = self.attachNewNode(cm.generate())
        self.floorMarker.setBSPMaterial(icon, 1)
        self.floorMarker.setTransparency(TransparencyAttrib.MAlpha)
        self.floorMarker.setTwoSided(1)
        self.floorMarker.setPosHpr(-2.50, 2.53, -0.01, 0.0, 90.0, 0.0)
        self.floorMarker.setScale(5.0)
        
    def requestEnter(self):
        pass
    
    def canEnter(self):
        place = base.cr.playGame.getPlace()
        return place and place.fsm.getCurrentState().getName() == 'walk'
        
    def onEnter(self, _):
        self.text.show()
        self.acceptOnce(base.inputStore.Interact, self.requestEnter)
        
    def onExit(self, _):
        self.text.hide()
        self.ignore(base.inputStore.Interact)

    def disable(self):
        DistributedNode.disable(self)
        base.taskMgr.remove(self.distanceTask)
        if self.iconSequence:
            self.iconSequence.finish()
            self.iconSequence = None
        if self.fadeSequence:
            self.fadeSequence.finish()
            self.fadeSequence = None
        if self.text:
            self.text.hide()

        self.ignoreAll()
        
    def delete(self):
        if self.siteData:
            self.siteData = None
        if self.identifierIcon:
            self.identifierIcon.destroy()
            self.identifierIcon = None
        if self.distanceTask:
            self.distanceTask = None
        if self.interactCollSphereNP:
            self.interactCollSphereNP.removeNode()
            self.interactCollSphereNP = None
            self.interactCollSphere = None
        if self.floorMarker:
            self.floorMarker.removeNode()
            self.floorMarker = None
        if self.text:
            self.text.hide()
            self.text.destroy()
            self.text = None
        del self.siteData
        del self.identifierIcon
        del self.distanceTask
        del self.interactCollSphereNP
        del self.interactCollSphere
        del self.floorMarker
        del self.text
        DistributedNode.delete(self)
class DistributedCogBattle(DistributedObject):
    notify = directNotify.newCategory("DistributedCogBattle")
    DNCData = {
        0: [[(-50, 98.73, 0.40), (351.31, 0.00, 0.00), 1.25],
            [(-41.07, 97.20, 0.40), (350.34, 0.00, 0.00), 1.25],
            [(-152.73, -0.58, 0.40), (90.00, 0, 0), 1.25],
            [(-152.73, 8.81, 0.40), (85.30, 0, 0), 1.25],
            [(34.34, -157.19, 2.95), (150.75, 0, 0), 1.25],
            [(26.21, -152.66, 2.95), (147.09, 0, 0), 1.25]],
        1: [],
        2: [],
        5: []
    }

    def __init__(self, cr):
        try:
            self.DistributedCogBattle_initialized
            return
        except:
            self.DistributedCogBattle_initialized = 1
        DistributedObject.__init__(self, cr)
        self.hoodIndex = None
        self.totalCogs = None
        self.cogsRemaining = None
        self.cogProgressBar = None
        self.DNCSigns = []
        self.introMessageSeq = None
        self.victorySeq = None
        self.turretManager = None
        self.isGettingBeans = False
        self.getBeansLabel = OnscreenText(
            text="Hurry and pick up all of the jellybeans!",
            fg=(1, 1, 1, 1),
            shadow=(0, 0, 0, 1),
            pos=(0, 0.7),
            font=CIGlobals.getMinnieFont())
        self.getBeansLabel.hide()
        self.timer = Timer()
        self.timer.setZeroCommand(self.getBeansTimeUp)
        # Give toons 30 seconds to get the beans at the end.
        self.timer.setInitialTime(60)
        self.endMusic = base.loadMusic(
            'phase_7/audio/bgm/encntr_toon_winning_indoor.mid')
        self.balloonSound = base.loadSfx(
            'phase_3/audio/sfx/GUI_balloon_popup.ogg')

    def d_left(self):
        self.sendUpdate('iLeft')

    def monitorHP(self, task):
        if base.localAvatar.getHealth() < 1:
            taskMgr.doMethodLater(7.0, self.diedTask,
                                  self.uniqueName('diedTask'))
            return task.done
        return task.cont

    def diedTask(self, task):
        self.d_left()
        return task.done

    def setTurretManager(self, tmgr):
        self.turretManager = tmgr

    def getTurretManager(self):
        return self.turretManager

    def getTurretCount(self):
        avatars = self.cr.doFindAll('DistributedToon')
        turrets = 0

        if self.turretManager:
            if self.turretManager.getTurret():
                turrets += 1

        if base.localAvatar.getPUInventory()[0] > 0:
            turrets += 1

        for avatar in avatars:
            if avatar.zoneId == base.localAvatar.zoneId:
                battle = avatar.getMyBattle()
                if avatar.getPUInventory()[0] > 0:
                    turrets += 1

                if battle:
                    if battle.getTurretManager():
                        if battle.getTurretManager().getTurret():
                            turrets += 1
        return turrets

    def victory(self):
        self.cr.playGame.getPlace().fsm.request('stop')
        base.localAvatar.b_setAnimState('win')
        self.victorySeq = Sequence(Wait(5.0), Func(self.finishVictory))
        self.victorySeq.start()

    def finishVictory(self):
        # Give the players some time to pick up jellybeans before they leave.
        self.cr.playGame.getPlace().fsm.request('walk')
        self.cr.playGame.hood.loader.music.stop()
        base.playMusic(self.endMusic, volume=0.8, looping=1)
        self.timer.load()
        self.timer.startTiming()
        self.getBeansLabel.show()
        base.playSfx(self.balloonSound)

    def getBeansTimeUp(self):
        self.timer.unload()
        self.getBeansLabel.hide()
        hoodId = self.cr.playGame.hood.hoodId
        zoneId = CogBattleGlobals.HoodIndex2HoodId[self.getHoodIndex()]
        requestStatus = {
            'zoneId': zoneId,
            'hoodId': hoodId,
            'where': 'playground',
            'avId': base.localAvatar.doId,
            'loader': 'safeZoneLoader',
            'shardId': None,
            'how': 'teleportIn'
        }
        self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus])

    def setTotalCogs(self, num):
        self.totalCogs = num

    def getTotalCogs(self):
        return self.totalCogs

    def setCogsRemaining(self, num):
        self.cogsRemaining = num
        if self.cogProgressBar:
            self.__updateProgressBar()

    def getCogsRemaining(self):
        return self.cogsRemaining

    def setHoodIndex(self, index):
        self.hoodIndex = index

    def getHoodIndex(self):
        return self.hoodIndex

    def startPlacePoll(self):
        taskMgr.add(self.__placePoll, "DistributedCogBattle-placePoll")

    def __placePoll(self, task):
        # Wait for the place to come out of None
        if self.cr.playGame.getPlace() != None:
            self.sendUpdate("arrived", [])
            self.constructArea()
            self.createInterface()
            self.__doIntroMessages()
            return task.done
        else:
            return task.cont

    def stopPlacePoll(self):
        taskMgr.remove("DistributedCogBattle-placePoll")

    def createInterface(self):
        self.cogProgressBar = DirectWaitBar(pos=(0, 0, -0.9),
                                            relief=DGG.RAISED,
                                            scale=0.6,
                                            frameColor=(1, 0.5, 0.3, 0.75),
                                            barColor=(1, 0.25, 0.25, 0.5),
                                            value=0,
                                            range=self.getTotalCogs(),
                                            text="",
                                            text_scale=0.08)
        self.__updateProgressBar()

    def __updateProgressBar(self):
        self.cogProgressBar.update(self.getCogsRemaining())
        self.cogProgressBar['text'] = "{0}/{1} {2} Remaining".format(
            self.getCogsRemaining(), self.getTotalCogs(), CIGlobals.Suits)

    def destroyInterface(self):
        if self.cogProgressBar:
            self.cogProgressBar.destroy()
            self.cogProgressBar = None

    def createBossGui(self):
        self.destroyInterface()
        backgroundGui = loader.loadModel(
            'phase_5/models/cogdominium/tt_m_gui_csa_flyThru.bam')
        backgroundGui.find('**/chatBubble').removeNode()
        bg = backgroundGui.find('**/background')
        bg.setScale(5.2)
        bg.setPos(0.14, 0, -0.6667)
        bg.reparentTo(aspect2d)
        self.frame = DirectFrame(geom=bg, relief=None, pos=(0.2, 0, -0.6667))

    def constructArea(self):
        for data in self.DNCData[self.hoodIndex]:
            dnc = loader.loadModel("phase_3.5/models/props/do_not_cross.egg")
            dnc.setPos(*data[0])
            dnc.setHpr(*data[1])
            dnc.setScale(data[2])
            dnc.reparentTo(render)
            self.DNCSigns.append(dnc)

    def deconstructArea(self):
        for dnc in self.DNCSigns:
            dnc.removeNode()

    def createWhisper(self, msg):
        whisper = WhisperPopup('Toon HQ: ' + msg, CIGlobals.getToonFont(),
                               ChatGlobals.WTSystem)
        whisper.manage(base.marginManager)

    def __doIntroMessages(self):
        self.introMessageSeq = Sequence(
            name="DistributedCogBattle-introMessageSeq")
        self.introMessageSeq.append(
            Func(
                self.createWhisper,
                "Welcome, Toons! The Cogs will be here soon, so get prepared!")
        )
        self.introMessageSeq.append(Wait(7.5))
        self.introMessageSeq.append(
            Func(
                self.createWhisper,
                "The pink bar at the bottom of the screen shows the amount of Cogs remaining to defeat."
            ))
        self.introMessageSeq.append(Wait(8.5))
        self.introMessageSeq.append(
            Func(
                self.createWhisper,
                "Purchase gags from Goofy at the Gag Shop to restock your used gags."
            ))
        self.introMessageSeq.append(Wait(7.5))
        self.introMessageSeq.append(
            Func(
                self.createWhisper,
                "Purchase battle tools from Coach at Coach's Battle Shop in between invasions."
            ))
        self.introMessageSeq.setDoneEvent(self.introMessageSeq.getName())
        self.acceptOnce(self.introMessageSeq.getDoneEvent(),
                        self.__introMessagesDone)
        self.introMessageSeq.start()

    def __introMessagesDone(self):
        if self.introMessageSeq:
            self.introMessageSeq.finish()
            self.introMessageSeq = None

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        base.localAvatar.setMyBattle(self)
        self.startPlacePoll()
        taskMgr.add(self.monitorHP, "DCB.monitorHP")

    def disable(self):
        taskMgr.remove("DCB.monitorHP")
        taskMgr.remove(self.uniqueName('diedTask'))
        self.endMusic.stop()
        self.endMusic = None
        self.getBeansLabel.destroy()
        self.getBeansLabel = None
        self.timer.unload()
        self.timer.cleanup()
        self.timer = None
        self.balloonSound = None
        self.turretManager = None
        base.localAvatar.setMyBattle(None)
        self.stopPlacePoll()
        self.deconstructArea()
        self.destroyInterface()
        if self.victorySeq:
            self.victorySeq.pause()
            self.victorySeq = None
        self.hoodIndex = None
        self.DNCSigns = None
        self.totalCogs = None
        self.cogsRemaining = None
        if self.introMessageSeq:
            self.introMessageSeq.pause()
            self.introMessageSeq = None
        DistributedObject.disable(self)
Esempio n. 10
0
class KOTHKingGui(DirectFrame):
    notify = directNotify.newCategory('KOTHKingGui')
    
    def __init__(self, mg, king, points):
        DirectFrame.__init__(self, parent = aspect2d)
        self.setBin('gui-popup', 60)
        self.mg = mg
        
        # Let's create the background
        box = DGG.getDefaultDialogGeom()
        self.bg = OnscreenImage(image = box, color = (1, 1, 0.75, 1), scale = (1.9, 1.4, 1.4), parent = self)
        
        # Let's create the header
        toonFont = CIGlobals.getToonFont()
        minnieFont = CIGlobals.getMinnieFont()
        
        name = 'Nobody'
        
        if king:
            name = king.getName()
            self.kingId = king.doId
        else:
            king = base.localAvatar
            self.kingId = 0
        
        self.title = OnscreenText(text = '%s is King!' % name, pos = (0, 0.5, 0), font = toonFont, 
            scale = 0.12, parent = self, shadow = (0.5, 0.5, 0.5, 0.6))
        
        # Let's create the Toon head
        headFrame = self.attachNewNode('head')
        headFrame.setPosHprScale(0, 0, -0.1, 180, 0, 0, 0.3, 0.3, 0.3)
        head = ToonGlobals.generateGuiHead(king)
        head.reparentTo(headFrame)
        
        # Let's create the points text
        self.amt_label = OnscreenText(text = 'Your Points: 0', pos = (-0.012, -0.4, 0), font = toonFont,
            scale = 0.12, parent = self, shadow = (0.5, 0.5, 0.5, 0.6))
        self.amt_label.hide()
        
        # Let's create the bad news text
        self.motivator = OnscreenText(text = 'Better luck next time!', pos = (0, -0.6, 0), font = minnieFont,
            scale = 0.125, parent = self, fg = (1, 0, 0, 1), shadow = (0.2, 0.2, 0.2, 1))
        self.motivator.hide()
        
        self.easterEgg = False
        
        if 50 < points != 100:
            self.motivator['fg'] = (0, 1, 0, 1)
            self.motivator.setText('Great job!')
        elif points == 100:
            self.motivator['fg'] = (0, 1, 0, 1)
            if random.randint(0, 100) <= 10:
                self.motivator.setText('YOU THE REAL MVP!')
                self.easterEgg = True
            else:
                self.motivator.setText('AMAZING!')
        
        # Let's create the sound effects
        self.zeroPointsSfx = loader.loadSfx('phase_4/audio/sfx/MG_neg_buzzer.ogg')
        self.poorScoreSfx = loader.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_no_bonus.ogg')
        self.goodScoreSfx = loader.loadSfx('phase_4/audio/sfx/MG_pairing_match_bonus_both.ogg')
        self.stomperSfx = loader.loadSfx('phase_4/audio/sfx/CHQ_FACT_stomper_small.ogg')
        self.fireworkSfx = loader.loadSfx('phase_4/audio/sfx/firework_explosion_02.ogg')
        self.perfectSfx = loader.loadSfx('phase_5/audio/sfx/SZ_MM_fanfare.ogg')
        self.tick_fastSfx = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
        self.tick_slowSfx = loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
        self.easterEggSfx = loader.loadSfx('phase_4/audio/sfx/avatar_emotion_very_sad.ogg')
        
        # Let's create the basic sequence
        self.pointsSeq = Sequence(Func(self.amt_label.show),
            Wait(0.25))
        
        self.seqLevel = 0
        self.fakeNumber = 0
        self.points = points
    
    def start(self):
        base.transitions.fadeScreen(0.5)
        if self.points == 0:
            self.__doZero()
        else:
            self.__doRegular()
            
    def destroy(self):
        # Let's stop the sequence.
        if self.pointsSeq:
            self.pointsSeq.finish()
        self.pointsSeq = None
        
        # Let's stop and destroy all the sounds.
        if self.zeroPointsSfx:
            self.zeroPointsSfx.stop()
            self.poorScoreSfx.stop()
            self.goodScoreSfx.stop()
            self.stomperSfx.stop()
            self.fireworkSfx.stop()
            self.perfectSfx.stop()
            self.tick_fastSfx.stop()
            self.tick_slowSfx.stop()
            self.easterEggSfx.stop()
        self.zeroPointsSfx = None
        self.poorScoreSfx = None
        self.goodScoreSfx = None
        self.stomperSfx = None
        self.fireworkSfx = None
        self.perfectSfx = None
        self.tick_fastSfx = None
        self.tick_slowSfx = None
        self.easterEggSfx = None
        
        # Let's destroy all the variables.
        self.points = None
        self.easterEgg = None
        self.seqLevel = None
        self.fakeNumber = None
        self.kingId = None
        self.mg = None
        
        # Let's destroy all the frames.
        if self.bg:
            self.bg.destroy()
            self.title.destroy()
            self.amt_label.destroy()
            self.motivator.destroy()
        self.bg = None
        self.title = None
        self.amt_label = None
        self.motivator = None
        
        DirectFrame.destroy(self)
        
    def unload(self):
        pass
    
    def hideFinalScores(self):
        base.transitions.noTransitions()
        self.hide()
        
    def handleExit(self):
        winner = 0
        if self.kingId != 0:
            winner = 1
        self.pointsSeq.append(Sequence(Wait(5), Func(self.mg.gameOver, winner, [self.kingId])))
        return
        
    def __doZeroEffect(self, task):
        if self.seqLevel == 0:
            task.delayTime = 0.2
            self.tick_fastSfx.play()
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.fakeNumber += 1
            
            if self.fakeNumber == 3:
                self.seqLevel = 1
        elif self.seqLevel == 1:
            task.delayTime = 0.35
            self.tick_slowSfx.play()
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.fakeNumber += 1
            
            if self.fakeNumber == 6:
                self.seqLevel = 2
                task.delayTime = 0.35
                
        elif self.seqLevel == 2:
            task.delayTime = 0.10
            self.tick_fastSfx.play()
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.fakeNumber -= 1
            
            if self.fakeNumber == -1:
                self.stomperSfx.play()
                ToontownIntervals.start(ToontownIntervals.getPulseLargerIval(self.amt_label, 'effect'))
                self.pointsSeq = Sequence(Wait(0.25), Func(self.zeroPointsSfx.play), Func(self.motivator.show))
                self.handleExit()
                self.pointsSeq.start()
                return task.done
        return task.again
    
    def __doRegularEffect(self, task):
        if self.points <= 5 and self.seqLevel == 0:
            self.seqLevel = 2
            
        if self.seqLevel == 0:
            task.delayTime = 0.35
            self.fakeNumber += 1
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.tick_slowSfx.play()
            
            if self.fakeNumber == 2:
                task.delayTime = 0.25
                self.seqLevel = 1
        
        elif self.seqLevel == 1:
            if self.points <= 50:
                task.delayTime = 0.12
            elif 50 < self.points != 100:
                task.delayTime = 0.075
            else:
                task.delayTime = 0.065
            self.fakeNumber += 1
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.tick_fastSfx.play()
            
            if self.fakeNumber == self.points - 5:
                task.delayTime = 0.25
                self.seqLevel = 2
        
        elif self.seqLevel == 2:
            task.delayTime = 0.35
            self.fakeNumber += 1
            self.amt_label.setText('Your Points: %s' % str(self.fakeNumber))
            self.tick_slowSfx.play()
            
            if self.fakeNumber == self.points:
                if self.points <= 50:
                    self.pointsSeq = Sequence(Wait(0.25), Func(self.poorScoreSfx.play), Func(self.motivator.show))
                elif 50 < self.points != 100:
                    pulse = ToontownIntervals.getPulseLargerIval(self.amt_label, 'effect')
                    self.pointsSeq = Sequence(Wait(0.25), Func(self.goodScoreSfx.play),
                        Func(ToontownIntervals.start, pulse), Func(self.motivator.show))
                elif self.points == 100:
                    pulse = ToontownIntervals.getPulseLargerIval(self.amt_label, 'effect')
                    self.pointsSeq = Sequence(Wait(0.25), Func(ToontownIntervals.start, pulse), 
                        Func(self.fireworkSfx.play), Wait(0.25), Func(self.perfectSfx.play), Func(self.motivator.show))
                    
                    if self.easterEgg:
                        self.pointsSeq.append(Sequence(Wait(0.30), Func(self.easterEggSfx.play)))
                self.handleExit()
                self.pointsSeq.start()
                return task.done
        return task.again
        
    def __doZero(self):
        self.pointsSeq.append(Sequence(
            Func(taskMgr.add, self.__doZeroEffect, 'Point Effect')
        ))
        self.pointsSeq.start()
        
    def __doRegular(self):
        self.pointsSeq.append(Sequence(
            Func(taskMgr.add, self.__doRegularEffect, 'Point Effect')
        ))
        self.pointsSeq.start()
Esempio n. 11
0
class ChoiceWidget(DirectFrame):
    notify = directNotify.newCategory("ChoiceWidget")

    def __init__(self,
                 parent,
                 options,
                 pos=(0, 0, 0),
                 command=None,
                 widgetName="",
                 choiceTextScale=0.08,
                 desc="",
                 settingKeyName=None,
                 mode=AUTO,
                 requirement=None):
        """ 
        Generates an ordered choice widget with the specified parameters.
        
        Parameters:
        
        parent: Pretty much self-explanatory, this is the parent of the widget.
        If an object with a `book` attribute is passed in, it will use that instead.
        
        options: A list of options that the user can select with the GUI.
        
        pos: Pretty much self-explanatory.
        
        command: Function that should be executed whenever a game setting is updated.
        The newly saved choice is passed to the specified function.
        
        widgetName: The label shown to the left of the widget identifying what the widget
        is for.
        
        choiceTextScale: The scale of the text which displays which option the user has
        currently selected.
        
        desc: Optional description of what the choices displayed by this widget are for.
        
        settingKeyName: The name of the key inside of the game settings map that this choice
        widget works with. This MUST be set if trying to simulate a game setting changer widget.
        
        mode: This is the kind of widget this is going to be. Use one of the following:
            - AUTO:
                - The system will attempt to figure out what the type of choices are available.
                    * 2 options automatically looks like a true/false widget *
            - MULTICHOICE:
                - This overrides the system in case there are two options but true/false functionality
                isn't wanted.
            - DEGREE:
                - This means that the choice widget deals with x in front of some sort of degree value that should
                - be stripped away when selecting choices. This is used for the antialiasing choice widget.
        
        """
        self.requirement = requirement
        self.options = options
        self.command = command
        self.currentChoiceIndex = 0
        self.origChoice = None
        self.userChoice = None
        self.settingKeyName = settingKeyName
        self.mode = mode

        # Let's update the options if we specified a setting key name.
        if self.settingKeyName and len(self.settingKeyName) > 0:
            settingsMgr = CIGlobals.getSettingsMgr()
            settingInst = settingsMgr.getSetting(self.settingKeyName)

            if not settingInst:
                raise ValueError("Setting \"{0}\" could not be found!".format(
                    self.settingKeyName))
            else:
                self.options = settingInst.getOptions()
                desc = settingInst.getDescription()

        widgetParent = parent
        if hasattr(parent, 'book'):
            widgetParent = parent.book

        DirectFrame.__init__(self, parent=widgetParent, pos=pos)

        bg = loader.loadModel('phase_3/models/gui/ChatPanel.bam')

        self.selFrame = DirectFrame(pos=(0.4, 0, 0),
                                    frameColor=(1.0, 1.0, 1.0, 1.0),
                                    image=bg,
                                    relief=None,
                                    image_scale=(0.22, 0.11, 0.11),
                                    image_pos=(-0.107, 0.062, 0.062),
                                    parent=self)

        self.choiceText = OnscreenText(text="Hello!",
                                       align=TextNode.ACenter,
                                       parent=self.selFrame,
                                       pos=(0, -0.01),
                                       scale=choiceTextScale)
        self.fwdBtn = CIGlobals.makeDirectionalBtn(1,
                                                   self.selFrame,
                                                   pos=(0.2, 0, 0),
                                                   command=self.__goFwd)
        self.bckBtn = CIGlobals.makeDirectionalBtn(0,
                                                   self.selFrame,
                                                   pos=(-0.2, 0, 0),
                                                   command=self.__goBck)

        self.lbl = OnscreenText(text=widgetName + ":",
                                pos=(-0.7, 0, 0),
                                align=TextNode.ALeft,
                                parent=self)

        if len(desc) > 0:
            self.desc = OnscreenText(text=desc,
                                     pos=(0.0, -0.1, 0.0),
                                     parent=self.selFrame,
                                     scale=0.05,
                                     bg=DESC_BACKGROUND_COLOR,
                                     mayChange=False)
            self.desc.setBin('gui-popup', 40)
            self.desc.hide()

            # Let's bind our events on the selection frame for the description.
            self.selFrame['state'] = DGG.NORMAL
            self.selFrame.bind(DGG.ENTER,
                               self.__setDescVisible,
                               extraArgs=[True])
            self.selFrame.bind(DGG.EXIT,
                               self.__setDescVisible,
                               extraArgs=[False])

        self.initialiseoptions(ChoiceWidget)

        self.reset()

        bg.detachNode()
        del bg

    def reset(self):
        """ Resets the selected choice to the very first option, or, if representing choices for a game setting,
        resets the widget to the currently saved setting. """

        # The index of the original display choice.
        destIndex = 0

        if self.settingKeyName:
            # This widget is supposed to be used to change game settings. Let's lookup the currently saved game setting.
            self.origChoice = self.__getCurrentSetting().getValue()

            try:
                if self.mode == DEGREE and not self.origChoice == 0:
                    destIndex = self.options.index('x{0}'.format(
                        str(self.origChoice)))
                elif (self.mode == AUTO
                      and len(self.options) == 2) or isinstance(
                          self.origChoice, (int, long)):
                    destIndex = int(self.origChoice)
                elif isinstance(self.origChoice, (list, tuple)):
                    destIndex = self.options.index('{0}x{1}'.format(
                        str(self.origChoice[0]), str(self.origChoice[1])))
                elif self.origChoice in self.options:
                    destIndex = self.options.index(self.origChoice)
                elif self.origChoice.title() in self.options:
                    destIndex = self.options.index(self.origChoice.title())
            except:
                # We couldn't determine the right index for the original choice. Let's ignore any errors and default
                # to the very first choice when we reset.
                pass
        else:
            # If this widget is not being used to simulate changing game settings, let's use the first value in options as the original choice.
            self.origChoice = self.options[0]
        self.userChoice = self.origChoice
        self.goto(destIndex)

    def saveSetting(self):
        """ If `settingKeyName` was set, this updates the game setting key with the choice selected with the widget. However, 
        if `settingKeyName` was not set, it will send the command specified with the current user choice. """
        willUpdateChoice = (self.userChoice != self.origChoice)
        if self.settingKeyName and willUpdateChoice:
            settingInst = CIGlobals.getSettingsMgr().getSetting(
                self.settingKeyName)

            if settingInst:
                settingInst.setValue(self.userChoice)

            self.reset()

        if self.command and willUpdateChoice:
            # Let's send the command with the newly saved choice.
            self.command(self.userChoice)

    def __getCurrentSetting(self):
        return CIGlobals.getSettingsMgr().getSetting(self.settingKeyName)

    def __setDescVisible(self, visible, _):
        if visible:
            CIGlobals.getRolloverSound().play()
            self.desc.show()
        else:
            self.desc.hide()

    def cleanup(self):
        if hasattr(self, 'choiceText'):
            self.choiceText.destroy()
            del self.choiceText
        if hasattr(self, 'fwdBtn'):
            self.fwdBtn.destroy()
            del self.fwdBtn
        if hasattr(self, 'bckBtn'):
            self.bckBtn.destroy()
            del self.bckBtn
        if hasattr(self, 'lbl'):
            self.lbl.destroy()
            del self.lbl
        if hasattr(self, 'selFrame'):
            self.selFrame.destroy()
            del self.selFrame
        if hasattr(self, 'desc'):
            self.desc.destroy()
            del self.desc
        del self.options
        del self.command
        del self.currentChoiceIndex
        del self.settingKeyName
        del self.origChoice
        del self.userChoice
        del self.mode
        del self.requirement
        self.destroy()

    def goto(self, index):
        self.currentChoiceIndex = index
        self.updateDirectionalBtns()
        self.__setCurrentData(False)

    def __setCurrentData(self, doCmd=True):
        self.choiceText.setText(self.options[self.currentChoiceIndex])
        if (doCmd):

            # Let's update the internal user choice.
            if self.mode == AUTO and len(self.options) == 2:
                # If we only have two options, we must be working with on/off choices.
                self.userChoice = bool(self.currentChoiceIndex)
            elif self.mode == INDEX:
                self.userChoice = self.currentChoiceIndex
            elif self.mode == DEGREE or self.mode == RESOLUTION:
                # We're working with either a degree based option or a resolution option.
                data = self.options[self.currentChoiceIndex].split('x')

                if CIGlobals.isEmptyString(data[0]):
                    # This is a degree-based option.
                    if self.currentChoiceIndex != 0:
                        self.userChoice = int(data[1])
                    else:
                        self.userChoice = 0
                else:
                    # This is a screen resolution option.
                    self.userChoice = [int(data[0]), int(data[1])]
            else:
                self.userChoice = self.options[self.currentChoiceIndex]

    def updateDirectionalBtns(self):
        if self.requirement and callable(self.requirement):
            if not self.requirement():
                # The requirement to modify this choice widget was not met.
                for btn in [self.fwdBtn, self.bckBtn]:
                    btn['state'] = DGG.DISABLED
                    btn.setColorScale(DISABLED_COLOR)
                return

        self.fwdBtn['state'] = DGG.NORMAL
        self.bckBtn['state'] = DGG.NORMAL
        self.fwdBtn.setColorScale(1, 1, 1, 1)
        self.bckBtn.setColorScale(1, 1, 1, 1)
        if self.currentChoiceIndex == 0:
            self.bckBtn['state'] = DGG.DISABLED
            self.bckBtn.setColorScale(DISABLED_COLOR)
        elif self.currentChoiceIndex == len(self.options) - 1:
            self.fwdBtn['state'] = DGG.DISABLED
            self.fwdBtn.setColorScale(DISABLED_COLOR)

    def __goFwd(self):
        if self.currentChoiceIndex < len(self.options) - 1:
            self.currentChoiceIndex += 1
            self.__setCurrentData()
        self.updateDirectionalBtns()

    def __goBck(self):
        if self.currentChoiceIndex > 0:
            self.currentChoiceIndex -= 1
            self.__setCurrentData()
        self.updateDirectionalBtns()
class Credits(DirectObject):

    developers = {'Game Development': ['DuckyDuck1553', 'DecodedLogic']}
    webDevelopers = {
        'Web Development': ['totok', 'DuckyDuck1553', 'DecodedLogic']
    }
    artists = {
        'Artists': [
            'John L. (supertricky)', 'DuckyDuck1553', 'DecodedLogic',
            'Baru (fatigue)', 'Isabel (allyjean)', 'Colorblind', 'loonatic'
        ]
    }
    composers = {'Composers': ['Dylan J.', 'Doc. Dynamite', 'CBiard']}
    communityManager = {'Community Manager': ['Leo (Bradley)']}
    moderators = {
        'Moderation Team':
        ['Mark (Black & White)', 'Jackson M.', 'Gabriel A.', 'Davon M.']
    }
    specialThanks = {
        'Special Thanks': [
            'Jesse Schell', 'rdb', 'Baribal', 'ThomasEgi', 'tobspr',
            'jjkoletar', 'mmavipc', 'CFSWorks', 'loblao', 'HarvTarv',
            'Hawkheart', 'TheRandomDog', 'Joey Z. (joey19982)',
            'Disney Interactive', 'Microsoft', 'YorkeTheMouse', 'Disyer',
            '\n\n\nAnd of course, YOU!\n\n\n'
        ]
    }

    def __init__(self):
        DirectObject.__init__(self)

        base.setBackgroundColor(0, 0, 0)

        self.textParent = base.credits2d.attachNewNode('textParent')
        self.textParent.setBin("gui-popup", 61)
        self.textParent.setDepthWrite(False)
        self.textParent.setTransparency(True)

        self.logoImage = OnscreenImage('phase_3/maps/CogInvasion_Logo.png',
                                       parent=self.textParent,
                                       scale=(0.685, 1.0, 0.325))
        self.logoImage.setTransparency(1)

        text = self.buildCreditsText()
        self.creditsText = OnscreenText(parent=self.textParent,
                                        font=CIGlobals.getToonFont(),
                                        fg=(1, 1, 1, 1),
                                        scale=0.065,
                                        pos=(0, -0.5, 0),
                                        text=text,
                                        shadow=(0, 0, 0, 1))

        self.posInterval = None

        self.backgroundImg = OnscreenImage('phase_3/maps/credits_fade.png',
                                           parent=render2d)
        self.backgroundImg.setTransparency(True)
        self.backgroundImg.setColor(0, 0, 0, 1.0)
        self.backgroundImg.setBin("gui-popup", 62)
        self.backgroundImg.setDepthWrite(False)

        self.exitText = OnscreenText(parent=base.credits2d,
                                     font=CIGlobals.getToonFont(),
                                     fg=(1.0, 0, 0, 1.0),
                                     shadow=(0, 0, 0, 1),
                                     scale=0.085,
                                     pos=(0, -0.96, 0),
                                     text='Press any key to exit')
        self.exitText.hide()
        self.exitText.setBin("gui-popup", 63)
        self.exitText.setDepthWrite(False)
        self.exitText.setTransparency(True)

        self.creditsAudioMgr = AudioManager.createAudioManager()
        self.creditsAudioMgr.setVolume(0.65)
        self.bgm = self.creditsAudioMgr.getSound(
            'phase_4/audio/bgm/new_years_fireworks_music.ogg')

    def buildCreditsText(self):
        def writeNames(message, namesList):
            for name in namesList:
                message = '%s%s\n' % (message, name)
            return message

        message = 'Cog Invasion Online\n{0}\n'.format(
            metadata.getBuildInformation())
        message += '\nCREDITS\n\n'

        # Write the game developers' names
        message += 'Programming\n\n'
        message += '%s\n' % self.developers.keys()[0]
        message = writeNames(message, self.developers.values()[0])
        message += '\n\n'

        # Write the web developers' names
        message += '%s\n' % self.webDevelopers.keys()[0]
        message = writeNames(message, self.webDevelopers.values()[0])

        # Let's begin the art section
        message += '\n\nArt\n\n'

        # Write the artists' names
        message += '%s\n' % self.artists.keys()[0]
        message = writeNames(message, self.artists.values()[0])

        message += '\n\n'

        # Write the composers' names
        message += '%s\n' % self.composers.keys()[0]
        message = writeNames(message, self.composers.values()[0])

        ##########################################
        # Let's begin the community section.
        message += '\n\nCommunity\n\n'

        # Write the community manager names
        message += '%s\n' % self.communityManager.keys()[0]
        message = writeNames(message, self.communityManager.values()[0])
        message += '\n\n'

        # Write the moderators' names
        message += '%s\n' % self.moderators.keys()[0]
        message = writeNames(message, self.moderators.values()[0])

        # Let's begin the Special Thanks section.
        message += '\n\n'

        # Write the special thanks' names
        message += '%s\n' % self.specialThanks.keys()[0]
        message = writeNames(message, self.specialThanks.values()[0])
        message += '\nWe thank the original Toontown Online team.\nNot only for the game, but for the memories.'
        message += "\n\n\n\n\"Don't cry because it's over.\nSmile because it happened.\"\n  - Dr. Seuss"

        return message

    def exit(self, key):
        self.__fadeOut()
        base.taskMgr.doMethodLater(1.1, self.__exitTask, "exitTask")

    def __exitTask(self, task):
        messenger.send('credits-Complete')
        self.ignoreAll()
        self.destroy()
        base.unMuteMusic()
        base.unMuteSfx()
        base.setBackgroundColor(0.05, 0.15, 0.4)
        base.transitions.fadeIn(1.0)
        return task.done

    def watchTextPosition(self, task):
        if self.textParent.getZ() >= 5.187:
            self.exitText.show()
            self.acceptOnce('button', self.exit)
            return task.done
        return task.cont

    def __fadeIn(self):
        Parallel(
            LerpColorScaleInterval(self.textParent, 1.0, (1, 1, 1, 1),
                                   (1, 1, 1, 0)),
            LerpColorScaleInterval(self.backgroundImg, 1.0, (1, 1, 1, 1),
                                   (1, 1, 1, 0)),
            LerpColorScaleInterval(self.exitText, 1.0, (1, 1, 1, 1),
                                   (1, 1, 1, 0))).start()

    def __fadeOut(self):
        Parallel(
            LerpColorScaleInterval(self.textParent, 1.0, (1, 1, 1, 0),
                                   (1, 1, 1, 1)),
            LerpColorScaleInterval(self.backgroundImg, 1.0, (1, 1, 1, 0),
                                   (1, 1, 1, 1)),
            LerpColorScaleInterval(self.exitText, 1.0, (1, 1, 1, 0),
                                   (1, 1, 1, 1))).start()

    def setup(self):
        self.__fadeIn()

        b3 = self.textParent.getTightBounds()
        dimensions = b3[1] - b3[0]
        self.posInterval = self.textParent.posInterval(
            50, Point3(0, 0, dimensions[2] + 2), Point3(0, 0, 0))
        self.posInterval.start()

        self.bgm.setLoop(1)
        self.bgm.play()

        base.buttonThrowers[0].node().setButtonDownEvent('button')
        taskMgr.add(self.watchTextPosition, 'Watch Text Position')

    def destroy(self):
        if self.posInterval:
            self.posInterval.pause()
            self.posInterval = None
        if self.bgm:
            self.bgm.stop()
            self.bgm = None
        if self.backgroundImg:
            self.backgroundImg.destroy()
            self.backgroundImg = None
        if self.creditsText:
            self.creditsText.destroy()
            self.creditsText = None
        if self.exitText:
            self.exitText.destroy()
            self.exitText = None
        if self.logoImage:
            self.logoImage.destroy()
            self.logoImage = None
        if self.textParent:
            self.textParent.removeNode()
            self.textParent = None
        if self.creditsAudioMgr:
            self.creditsAudioMgr.stopAllSounds()
            self.creditsAudioMgr = None
        self.developers = None
        self.webDevelopers = None
        self.artists = None
        self.specialThanks = None
        self.composers = None
        self.communityManager = None
        self.moderators = None
        self.prevMusic = None
Esempio n. 13
0
class RewardPanel(DirectFrame):
    notify = directNotify.newCategory('RewardPanel')

    def __init__(self, panelData):
        dialogBox = loader.loadModel('phase_3/models/gui/dialog_box_gui.bam')
        DirectFrame.__init__(self,
                             relief=None,
                             geom=dialogBox,
                             geom_color=CIGlobals.DialogColor,
                             geom_scale=(1.75, 1, 0.75 * 1.1),
                             geom_pos=Point3(0, 0, -0.05),
                             pos=(0, 0, 0.661))
        self.initialiseoptions(RewardPanel)
        self.setScale(0.8)

        # The data for the reward panel inside of a RPToonData object.
        self.panelData = panelData

        # Top wood panel saying Reward Panel
        gagShopNodes = loader.loadModel(
            'phase_4/models/gui/gag_shop_purchase_gui.bam')
        # Original pos: (-0.02, 0, 0.3) scale = (1.55, 1, 1)
        self.titlePanel = OnscreenImage(
            parent=self,
            image=gagShopNodes.find('**/Goofys_Sign'),
            pos=(0, 0, 0.3),
            hpr=(1, 0, 0),
            scale=(1.3, 1, 0.9))

        self.avatarNamePanel = DirectFrame(parent=self.titlePanel,
                                           pos=(0, 0.005, 0))
        self.avatarText = OnscreenText(parent=self.avatarNamePanel,
                                       text='',
                                       font=CIGlobals.getMickeyFont(),
                                       fg=(0.698, 0.13, 0.13, 1),
                                       mayChange=1,
                                       scale=(0.1, 0.13, 0.1))

        self.panelContentsTitle = OnscreenText(parent=self,
                                               text=GagPanelName,
                                               font=CIGlobals.getMickeyFont(),
                                               pos=(0, 0.24, 0),
                                               fg=(0.3725, 0.619, 0.627, 1),
                                               mayChange=1)

        self.playerInfo = DirectFrame(parent=self,
                                      relief=None,
                                      pos=(-0.5, 0, 0))
        self.playerInfo.setBin('gui-popup', 0)

        self.bonusText = OnscreenText(parent=self.playerInfo,
                                      text='2X Cog Office Bonus!',
                                      font=CIGlobals.getToonFont(),
                                      pos=(0, 0.15, 0),
                                      scale=(0.055, 0.055, 0.055),
                                      align=TextNode.ACenter)
        self.bonusText.hide()

        ##################################################################################
        # GUI Elements relating to the Favorite Gag/Gag Popup Used for showing Gag Unlock#
        ##################################################################################
        self.favoriteGagText = OnscreenText(parent=self.playerInfo,
                                            text=FavoriteGag,
                                            font=CIGlobals.getMickeyFont(),
                                            pos=FavoriteGagTitlePos,
                                            fg=(1, 0.2, 0.2, 1),
                                            sort=0)

        glow = loader.loadModel('phase_4/models/minigames/particleGlow.bam')
        self.favoriteGagGlow = OnscreenImage(parent=self.playerInfo,
                                             image=glow,
                                             pos=FavoriteGagPos,
                                             color=GagGlowColor,
                                             scale=(0.8, 0.8, 0.8))
        self.favoriteGagGlow.setBin('gui-popup', 10)
        # particleGlow.bam uses a material since it's normally part of render, not render2d.
        # Since render2d is still fixed-function, we have to explicitly enable shader generation
        # to correctly display the glow in render2d.
        self.favoriteGagGlow.setShaderAuto()

        invIcons = loader.loadModel('phase_3.5/models/gui/inventory_icons.bam')
        gag = invIcons.find(
            GagGlobals.InventoryIconByName.get(GagGlobals.Foghorn))
        self.favoriteGag = OnscreenImage(parent=self.playerInfo,
                                         image=gag,
                                         pos=FavoriteGagPos,
                                         scale=(1.65, 1.65, 1.65))
        self.favoriteGag.setBin('gui-popup', 20)

        self.favoriteGagName = OnscreenText(parent=self.playerInfo,
                                            text=GagGlobals.Foghorn,
                                            font=CIGlobals.getToonFont(),
                                            pos=FavoriteGagNamePos,
                                            mayChange=1)

        ################################################################################
        # GUI elements showing gag experience on the right-side of the gag exp panel   #
        ################################################################################

        self.gagExpFrame = DirectFrame(parent=self,
                                       relief=None,
                                       pos=(0.085, 0, 0.15))
        self.trackLabels = []
        self.trackIncLabels = []
        self.trackBars = []
        self.trackBarsOffset = 0

        for i in range(len(GagGlobals.TrackNameById.values())):
            track = GagGlobals.TrackNameById.values()[i]
            color = GagGlobals.TrackColorByName.get(track)
            label = DirectLabel(parent=self.gagExpFrame,
                                relief=None,
                                text=track.upper(),
                                text_scale=0.05,
                                text_align=TextNode.ARight,
                                pos=(0.13, 0, -0.09 * i),
                                text_pos=(0, -0.02))
            incrementLabel = DirectLabel(parent=self.gagExpFrame,
                                         relief=None,
                                         text='',
                                         text_scale=0.05,
                                         text_align=TextNode.ALeft,
                                         pos=(0.65, 0, -0.09 * i),
                                         text_pos=(0, -0.02))
            progressBar = DirectWaitBar(
                parent=self.gagExpFrame,
                relief=DGG.SUNKEN,
                frameSize=(-1, 1, -0.15, 0.15),
                borderWidth=(0.02, 0.02),
                scale=0.25,
                frameColor=(color[0] * 0.7, color[1] * 0.7, color[2] * 0.7, 1),
                barColor=(color[0], color[1], color[2], 1),
                text='0/0',
                text_scale=0.18,
                text_fg=(0, 0, 0, 1),
                text_align=TextNode.ACenter,
                text_pos=(0, -0.05),
                pos=(0.4, 0, -0.09 * i))
            self.trackLabels.append(label)
            self.trackIncLabels.append(incrementLabel)
            self.trackBars.append(progressBar)

        ################################################################################
        # GUI elements showing progress updates on quests                              #
        ################################################################################

        self.questFrame = DirectFrame(parent=self, relief=None)
        self.questPosters = []

        self.congratsLeft = OnscreenText(parent=self.playerInfo,
                                         pos=(-0.1, 0.125, -0.1),
                                         text='',
                                         scale=0.06,
                                         align=TextNode.ARight)
        self.congratsLeft.setR(-30)
        self.congratsRight = OnscreenText(parent=self.playerInfo,
                                          pos=(0.1, 0.125, 0.1),
                                          text='',
                                          scale=0.06,
                                          align=TextNode.ALeft)
        self.congratsRight.setR(30)

        glow.removeNode()
        invIcons.removeNode()
        gagShopNodes.removeNode()
        dialogBox.removeNode()

    def __getAvatarTextScale(self):
        totalWidth = self.avatarText.node().getWidth()
        panelWidth = 9.2
        defaultTextScale = 1.0

        scale = min(defaultTextScale,
                    defaultTextScale / (totalWidth / panelWidth))
        return (scale, scale, scale)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def setPanelData(self, panelData):
        self.panelData = panelData
        self.avatarText['text'] = self.panelData.avatarName
        self.avatarNamePanel.setScale(self.__getAvatarTextScale())

        # Let's set the data for our gag experience here.
        for i in range(len(self.trackLabels)):
            track = self.panelData.getTrackByName(
                GagGlobals.TrackNameById.values()[i])
            bar = self.trackBars[i]
            bar['text'] = '%d/%d' % (track.exp, track.maxExp)

            # When the maximum experience of a track isn't 0, we know it isn't unlocked.
            if track.maxExp == -1:
                bar.hide()

            self.trackIncLabels[i]['text'] = ''
            self.trackIncLabels[i].show()

    def __chooseRewardShot(self, av):
        shotChoices = [(0, 8, av.getHeight() * 0.66, 179, 15, 0),
                       (5.2, 5.45, av.getHeight() * 0.66, 131.5, 3.6, 0)]
        shot = random.choice(shotChoices)
        return shot

    def getQuestsProgressInterval(self):
        avatar = self.panelData.avatar
        intervals = []

        def toggleFavoriteGagItems(visible):
            for item in [
                    self.favoriteGag, self.favoriteGagGlow,
                    self.favoriteGagText, self.favoriteGagName
            ]:
                if not visible:
                    item.hide()
                else:
                    item.show()

        def setupQuestPosters():
            questManager = avatar.questManager
            numQuests = len(questManager.quests.values())

            yPos = 0.47

            displayData = {
                1: [[Point3(0.0, 0.0, yPos)], 0.88],
                2: [[Point3(-0.42, 0.0, yPos),
                     Point3(0.45, 0.0, yPos)], 0.88],
                3: [[
                    Point3(-0.57, 0.0, yPos),
                    Point3(0.0, 0.0, yPos),
                    Point3(0.57, 0.0, yPos)
                ], 0.70],
                4: [[
                    Point3(-0.32, 0.0, 0.62),
                    Point3(-0.32, 0.0, 0.30),
                    Point3(0.32, 0.0, 0.62),
                    Point3(0.32, 0.0, 0.30)
                ], 0.52]
            }

            # A full frame is a frame showing two quests at once.
            howManyFullFrames = math.ceil(numQuests / 2.0)
            howManyRemainderFrames = (numQuests - howManyFullFrames)

            for i, quest in enumerate(questManager.quests.values()):
                poster = QuestGlobals.generatePoster(quest,
                                                     parent=self.questFrame)
                poster.setScale(displayData.get(numQuests)[1])
                poster.setPos(displayData.get(numQuests)[0][i])
                poster.show()
                self.questPosters.append(poster)

        intervals.append(Func(self.gagExpFrame.hide))
        intervals.append(Func(self.playerInfo.show))
        intervals.append(Func(self.panelContentsTitle.setText,
                              QuestsPanelName))
        intervals.append(Func(toggleFavoriteGagItems, False))
        intervals.append(Func(setupQuestPosters))
        #intervals.append(Func(self.playerInfo.initialiseoptions, DirectFrame))

        return intervals

    def getGagExperienceInterval(self):
        avatar = self.panelData.avatar
        intervals = []

        shot = self.__chooseRewardShot(avatar)

        intervals.append(Func(base.camera.reparentTo, avatar))
        intervals.append(Func(base.camera.setPosHpr, *shot))
        intervals.append(Func(self.congratsLeft.hide))
        intervals.append(Func(self.congratsRight.hide))
        intervals.append(Func(self.panelContentsTitle.setText, GagPanelName))
        intervals.append(Func(self.setFavoriteGag, self.panelData.favoriteGag))
        intervals.append(Func(self.gagExpFrame.show))
        intervals.append(Func(self.playerInfo.show))
        intervals.append(Wait(1.0))

        for i in range(len(self.trackLabels)):
            track = self.panelData.getTrackByName(
                GagGlobals.TrackNameById.values()[i])
            intervals.extend(self.getTrackIntervalList(track, i))

        return intervals

    def getNextExpValue(self, newValue, track):
        if newValue < track.maxExp or track.maxExp == 0:
            return track.maxExp
        else:
            levels = GagGlobals.TrackExperienceAmounts[track.name]
            index = levels.index(track.maxExp)

            if index + 1 < len(levels):
                return levels[index + 1]
            return -1

    def incrementExp(self, trackIndex, track, newValue):
        bar = self.trackBars[trackIndex]
        nextExp = GagGlobals.getMaxExperienceValue(newValue, track.name)
        oldValue = bar['value']
        color = GagGlobals.TrackColorByName.get(track.name)

        bar['text'] = '%d/%d' % (newValue, nextExp)
        bar['range'] = nextExp if not nextExp == -1 else newValue
        bar['value'] = newValue
        bar['barColor'] = (color[0], color[1], color[2], 1)

    def resetBarColor(self, trackIndex):
        color = GagGlobals.TrackColorByName.get(
            GagGlobals.TrackNameById.values()[trackIndex])
        self.trackBars[trackIndex]['barColor'] = (color[0] * 0.8,
                                                  color[1] * 0.8,
                                                  color[2] * 0.8, 1)

    def showTrackIncLabel(self, trackIndex, track, increment):
        label = self.trackIncLabels[trackIndex]

        # Only show increments when that track is unlocked.
        if track.exp != -1:
            label['text'] = '+%d' % increment
        label.show()

    def getTrackIntervalList(self, track, trackIndex):
        tickDelay = 1.0 / 60
        intervalList = []

        intervalList.append(
            Func(self.showTrackIncLabel, trackIndex, track, track.increment))

        barTime = 2.0 if track.exp > 0 else 0.25
        numTicks = int(math.ceil(barTime / tickDelay))
        for i in range(numTicks):
            t = (i + 1) / float(numTicks)
            newValue = int(track.exp + t * track.increment + 0.5)
            intervalList.append(
                Func(self.incrementExp, trackIndex, track, newValue))
            intervalList.append(Wait(tickDelay))

        intervalList.append(Func(self.resetBarColor, trackIndex))
        intervalList.append(Wait(0.2))

        if track.maxExp > 0 and (track.maxExp != GagGlobals.MaxedTrackExperiences.get(track.name) \
                    and (track.exp + track.increment) >= track.maxExp):
            gagIndex = GagGlobals.TrackExperienceAmounts.get(track.name).index(
                track.maxExp) + 1
            newGag = GagGlobals.TrackGagNamesByTrackName.get(
                track.name)[gagIndex]
            intervalList.append(
                self.getShowGagUnlockedInterval(track.name, newGag))

        return intervalList

    def getShowGagUnlockedInterval(self, track, gagName):
        seq = Sequence(
            Func(self.gagExpFrame.hide),
            Func(self.panelContentsTitle.setText, 'Gag Unlocked!'),
            Func(self.playerInfo.show), Func(self.setFavoriteGag, gagName),
            Func(self.favoriteGagName.setY, -0.35),
            Func(self.favoriteGagText.setY, 0.105),
            Func(self.favoriteGagText.setText, 'New %s Gag' % track),
            Func(self.bonusText.hide), Func(self.playerInfo.setPos, 0, 0, 0),
            Func(self.playerInfo.initialiseoptions, DirectFrame))
        seq.append(self.getCongratsInterval())
        seq.append(Wait(1.0))
        seq.append(self.getHideGagUnlockedInterval())
        seq.append(Func(self.gagExpFrame.show))
        seq.append(Wait(0.5))
        return seq

    def getHideGagUnlockedInterval(self):
        def correctPositioning(guiElement, pos):
            guiElement['pos'] = pos

        seq = Sequence(
            Func(self.panelContentsTitle.setText, GagPanelName),
            Func(self.setFavoriteGag, self.panelData.favoriteGag),
            Func(self.playerInfo.setX, -0.5),
            Func(correctPositioning, self.favoriteGagName, FavoriteGagNamePos),
            Func(self.favoriteGagText.setText, FavoriteGag),
            Func(correctPositioning, self.favoriteGagText,
                 FavoriteGagTitlePos), Func(self.congratsLeft.hide),
            Func(self.congratsRight.hide))

        return seq

    def __getRandomCongratsPair(self):
        msgs = list(NewGagCongratsMessages)

        msg = msgs[random.randint(0, len(msgs) - 1)]
        msgs.remove(msg)

        return (msg, msgs[random.randint(0, len(msgs) - 1)])

    def getCongratsInterval(self):
        msgs = self.__getRandomCongratsPair()
        self.congratsLeft['text'] = msgs[0]
        self.congratsRight['text'] = msgs[1]

        sfx = loader.loadSfx('phase_3/audio/sfx/GUI_balloon_popup.ogg')
        sfx.setLoop(False)
        sfx.setVolume(1.0)

        def makeSequence(text):
            seq = Sequence(Wait(1.0), Func(text.show))
            seq.append(Func(sfx.play))
            seq.append(
                CIGlobals.makePulseEffectInterval(text, 1.0, 0.01, 1.05, 0.5,
                                                  0.25))
            seq.append(Func(sfx.stop))
            return seq

        return Sequence(makeSequence(self.congratsLeft),
                        makeSequence(self.congratsRight))

    def setFavoriteGag(self, gagName):
        invIcons = loader.loadModel('phase_3.5/models/gui/inventory_icons.bam')
        gag = invIcons.find(GagGlobals.InventoryIconByName.get(gagName))
        self.favoriteGagName.setText(gagName)
        self.favoriteGag['image'] = gag
        invIcons.removeNode()

    def destroy(self):
        if self.titlePanel:
            self.titlePanel.destroy()
        if self.avatarText:
            self.avatarText.destroy()
        if self.avatarNamePanel:
            self.avatarNamePanel.destroy()
        if self.panelContentsTitle:
            self.panelContentsTitle.destroy()
        if self.favoriteGag:
            self.favoriteGag.destroy()
        if self.favoriteGagGlow:
            self.favoriteGagGlow.destroy()
        if self.favoriteGagName:
            self.favoriteGagName.destroy()
        if self.playerInfo:
            self.playerInfo.destroy()
        if self.trackLabels:
            for label in self.trackLabels:
                label.destroy()
        if self.trackIncLabels:
            for label in self.trackIncLabels:
                label.destroy()
        if self.trackBars:
            for bar in self.trackBars:
                bar.destroy()
        if self.congratsLeft:
            self.congratsLeft.destroy()
        if self.congratsRight:
            self.congratsRight.destroy()
        if self.gagExpFrame:
            self.gagExpFrame.destroy()
        if self.panelData:
            self.panelData = None
        del self.titlePanel
        del self.avatarText
        del self.avatarNamePanel
        del self.panelContentsTitle
        del self.favoriteGag
        del self.favoriteGagGlow
        del self.favoriteGagName
        del self.playerInfo
        del self.trackLabels
        del self.trackIncLabels
        del self.trackBars
        del self.gagExpFrame
        del self.congratsLeft
        del self.congratsRight
        del self.panelData
        DirectFrame.destroy(self)
Esempio n. 14
0
class BookPage(StateData):
    def __init__(self, book, title, doneEvent='%s-done', wantHeader=True):
        StateData.__init__(self, doneEvent % title)
        self.notify = directNotify.newCategory(title)
        self.book = book
        self.title = title
        self.icon = None
        self.iconScale = 1
        self.iconColor = (1, 1, 1, 1)
        self.tabButton = None

        # The actual header that displays the title.
        self.header = None
        self.wantHeader = wantHeader

        # The required access level(s) to view this page.
        self.restriction = []

    def load(self):
        StateData.load(self)

    def unload(self):
        StateData.unload(self)
        if self.header:
            self.header.destroy()
            self.header = None
        self.book = None
        self.tabButton = None
        if self.icon:
            self.icon.removeNode()
            self.icon = None
        if hasattr(self, 'notify'):
            del self.notify
            del self.icon
            del self.iconScale
            del self.iconColor
            del self.book
            del self.title
            del self.header
            del self.wantHeader
            del self.restriction

    def enter(self):
        if not self.isEntered:
            if self.wantHeader:
                # Create the header at the top of the page.
                self.header = OnscreenText(text=self.title,
                                           pos=(0, 0.62, 0),
                                           scale=0.12)
        StateData.enter(self)

    def exit(self):
        if self.isEntered:

            if self.header:
                # Hide the header at the top of the page.
                self.header.hide()
        StateData.exit(self)

    # Sets the required access levels to view this page.
    def setRestriction(self, levels):
        self.restriction = levels

    # Returns the required access levels to view this page.
    def getRestriction(self):
        return self.restriction

    def getName(self):
        return self.title

    # Returns the header at the top of the page.
    def getHeader(self):
        return self.header

    def getIcon(self):
        return self.icon

    def getIconScale(self):
        return self.iconScale

    def getIconColor(self):
        return self.iconColor
Esempio n. 15
0
class NamePage(StateData):
    notify = directNotify.newCategory('NamePage')

    def __init__(self, book, parentFSM):
        self.book = book
        self.parentFSM = parentFSM
        StateData.__init__(self, 'namePageDone')
        self.fsm = ClassicFSM('NamePage', [
            State('off', self.enterOff, self.exitOff),
            State('basePage', self.enterBasePage, self.exitBasePage)
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.parentFSM.getStateNamed('namePage').addChild(self.fsm)
        self.nameServ = base.cr.nameServicesManager
        self.baseRequestIndex = 0
        self.requestsPerCluster = 5
        self.requestsContainer = {}
        self.loadingLabel = None
        self.selectedName = None
        self.nameButtons = []
        self.avId2NameData = {}
        geom = CIGlobals.getDefaultBtnGeom()
        self.acceptBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=0.5,
                                      text='Accept',
                                      pos=(0.5, posY, 0),
                                      text_pos=(0, -0.01),
                                      command=self.acceptName)
        self.acceptBtn.hide()
        self.declineBtn = DirectButton(geom=geom,
                                       text_scale=0.04,
                                       relief=None,
                                       scale=0.5,
                                       text='Decline',
                                       pos=(0.75, posY, 0),
                                       text_pos=(0, -0.01),
                                       command=self.declineName)
        self.declineBtn.hide()
        self.avIdLbl = OnscreenText(text='',
                                    scale=0.08,
                                    pos=(0.3, 0, 0.5),
                                    align=TextNode.ACenter)
        self.avIdLbl.hide()
        self.accIdLbl = OnscreenText(text='',
                                     scale=0.08,
                                     pos=(0.3, 0, 0.3),
                                     align=TextNode.ACenter)
        self.accIdLbl.hide()
        return

    def handleRequests(self):
        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self.nameList = DirectScrolledList(
            relief=None,
            pos=(-0.54, 0, 0.08),
            incButton_image=(gui.find('**/FndsLst_ScrollUp'),
                             gui.find('**/FndsLst_ScrollDN'),
                             gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             gui.find('**/FndsLst_ScrollUp')),
            incButton_relief=None,
            incButton_scale=(arrowButtonScale, arrowButtonScale,
                             -arrowButtonScale),
            incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999),
            incButton_image3_color=Vec4(1, 1, 1, 0.2),
            incButton_command=self.__moveItems,
            incButton_extraArgs=[1],
            decButton_image=(gui.find('**/FndsLst_ScrollUp'),
                             gui.find('**/FndsLst_ScrollDN'),
                             gui.find('**/FndsLst_ScrollUp_Rllvr'),
                             gui.find('**/FndsLst_ScrollUp')),
            decButton_relief=None,
            decButton_scale=(arrowButtonScale, arrowButtonScale,
                             arrowButtonScale),
            decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125),
            decButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_command=self.__moveItems,
            decButton_extraArgs=[0],
            itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin),
            itemFrame_scale=1.0,
            itemFrame_relief=DGG.SUNKEN,
            itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX,
                                 listZorigin, listZorigin + listFrameSizeZ),
            itemFrame_frameColor=(0.85, 0.95, 1, 1),
            itemFrame_borderWidth=(0.01, 0.01),
            numItemsVisible=5,
            forceHeight=0.075,
            items=self.nameButtons)
        self.__buildItems()
        return

    def __moveItems(self, direction):
        if direction == 0:
            self.baseRequestIndex += 1
        else:
            if direction == 1:
                self.baseRequestIndex -= 1
        self.clearItems()
        self.__buildItems()

    def clearItems(self):
        for btn in self.nameButtons:
            btn.destroy()

        self.nameButtons = []
        self.nameList.removeAndDestroyAllItems()

    def __buildItems(self):
        for i in xrange(self.requestsPerCluster):
            request = self.nameServ.getNameRequests()[self.baseRequestIndex +
                                                      i]
            date = request['date']
            date = date.replace(' ', '-')
            data = NameData(request['name'], date, request['avId'],
                            request['accId'])
            self.avId2NameData[data.avId] = data
            btn = DirectButton(relief=None,
                               text=data.name,
                               text_scale=0.07,
                               text_align=TextNode.ALeft,
                               text1_bg=textDownColor,
                               text2_bg=textRolloverColor,
                               text3_fg=textDisabledColor,
                               textMayChange=0,
                               command=self.__handleNameButton,
                               extraArgs=[data],
                               text_pos=(0, 0, 0.0))
            data.btn = btn
            self.nameButtons.append(btn)

        self.loadingLabel.hide()
        return

    def __handleNameButton(self, data):
        self.selectedName = data
        data.btn['state'] = DGG.DISABLED
        self.avIdLbl.setText('Avatar ID:\n' + str(data.avId))
        self.avIdLbl.show()
        self.accIdLbl.setText('Account ID:\n' + str(data.accId))
        self.accIdLbl.show()
        self.acceptBtn.show()
        self.declineBtn.show()

    def acceptName(self):
        pass

    def load(self):
        StateData.load(self)
        self.loadingLabel = OnscreenText(text='Loading...',
                                         font=CIGlobals.getToonFont(),
                                         pos=(0, 0.1, 0),
                                         scale=0.08,
                                         parent=aspect2d)

    def unload(self):
        StateData.unload(self)
        self.loadingLabel.destroy()
        self.loadingLabel = None
        for request in self.requestsContainer.values():
            for element in request:
                element.destroy()

        self.requestsContainer = {}
        return

    def enter(self):
        StateData.enter(self)
        self.fsm.request('basePage')
        base.acceptOnce(self.nameServ.getRequestCompleteName(),
                        self.handleRequests)
        self.nameServ.d_requestNameData()

    def exit(self):
        self.fsm.requestFinalState()
        StateData.exit(self)

    def enterBasePage(self):
        self.book.createPageButtons('adminPage', None)
        self.book.setTitle('Name Approval')
        return

    def exitBasePage(self):
        self.book.deletePageButtons(True, False)
        self.book.clearTitle()

    def enterOff(self):
        pass

    def exitOff(self):
        pass
Esempio n. 16
0
class CharSelection(DirectObject):
    notify = directNotify.newCategory('CharSelection')

    NO_TOON = "Empty Slot"
    PLAY = "Play"
    CREATE = "Create"
    TITLE = "Pick  A  Toon  To  Play"

    def __init__(self, avChooser):
        self.avChooser = avChooser
        self.choice = None
        self.charList = None
        self.charNameLabel = None
        self.charButtons = []
        self.playOrCreateButton = None
        self.deleteButton = None
        self.quitButton = None
        self.title = None
        self.stageToon = None
        self.stageToonRoot = None
        self.deleteConf = None
        self.frame = None
        self.stageFSM = ClassicFSM.ClassicFSM('StageFSM', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('loadSZ', self.enterLoadSZ, self.exitLoadSZ),
            State.State('onStage', self.enterOnStage, self.exitOnStage)
        ], 'off', 'off')
        self.stageFSM.enterInitialState()
        self.selectionFSM = ClassicFSM.ClassicFSM('CharSelection', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('character', self.enterCharSelected,
                        self.exitCharSelected),
            State.State('empty', self.enterEmptySelected,
                        self.exitEmptySelected)
        ], 'off', 'off')
        self.selectionFSM.enterInitialState()

        self.szGeom = None
        self.olc = None
        self.asyncSZLoadStatus = False
        self.isNewToon = False
        self.newToonSlot = None
        self.camIval = None
        self.stAnimSeq = None
        self.newToonAnnounceSfx = base.loadSfx(
            "phase_4/audio/sfx/King_Crab.ogg")
        self.newToonDrumrollSfx = base.loadSfx(
            "phase_5/audio/sfx/SZ_MM_drumroll.ogg")
        self.newToonRevealSfx = base.loadSfx(
            "phase_5/audio/sfx/SZ_MM_fanfare.ogg")

        self.dnaStore = DNAStorage()
        loader.loadDNAFile(self.dnaStore,
                           'phase_4/dna/pickatoon/storage_pickatoon.pdna')

    def __setupStageToon(self):
        self.stageToonRoot = render.attachNewNode('stageToonRoot')
        self.stageToon = Toon(base.cr)
        self.stageToon.setPosHpr(0, 0, 0, 0, 0, 0)
        self.stageToon.reparentTo(self.stageToonRoot)

    def cleanupStageToon(self):
        if self.stageToon != None:
            self.stageToon.disable()
            self.stageToon.delete()
            self.stageToon = None
        if self.stageToonRoot != None:
            self.stageToonRoot.removeNode()
            self.stageToonRoot = None

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def __async_loadSZTask(self, task=None):
        dnas = HOOD_ID_2_DNA[self.choice.lastHood]
        for i in xrange(len(dnas)):
            dnaFile = dnas[i]
            if i == len(dnas) - 1:
                node = loader.loadDNAFile(self.dnaStore, dnaFile)
                if node.getNumParents() == 1:
                    self.szGeom = NodePath(node.getParent(0))
                    self.szGeom.reparentTo(render)
                else:
                    self.szGeom = render.attachNewNode(node)

                # The 2D trees should not be flattened, to do that, we're going to traverse
                # the scene graph for all trees, use #wrtReparentTo(render) on them, flatten
                # the scene with #flattenStrong(), and finally #wrtReparentTo(self.szGeom)
                # the trees back to the main scene node so they get cleaned up properly.
                trees = self.szGeom.findAllMatches('**/*tree*')
                #self.szGeom.find("**/shadow").removeNode()

                #from panda3d.core import CullBinAttrib
                #self.szGeom.find("**/shadow_crack").setAttrib(CullBinAttrib.make("foreground", 10), 10)
                #shs = self.szGeom.findAllMatches("**/*shadow*")
                #for sh in shs:
                #    sh.removeNode()

                # self.szGeom.ls()

                for tree in trees:
                    tree.wrtReparentTo(render)

                self.szGeom.flattenStrong()

                for tree in trees:
                    tree.wrtReparentTo(self.szGeom)

            else:
                loader.loadDNAFile(self.dnaStore, dnaFile)

        self.olc = ZoneUtil.getOutdoorLightingConfig(self.choice.lastHood)
        self.olc.setup()
        self.olc.apply()

        CIGlobals.preRenderScene(render)

        self.asyncSZLoadStatus = True

        #base.accept('l', render.ls)

        if task:
            return task.done

    def enterLoadSZ(self):
        self.loadingDlg = Dialog.GlobalDialog("Loading...")
        self.loadingDlg.show()

        base.cr.renderFrame()
        base.cr.renderFrame()

        self.notify.info("Polling for SZ to load")
        self.asyncSZLoadStatus = False
        self.__async_loadSZTask()

        base.doNextFrame(self.stageFSM.request, ['onStage'])

    def exitLoadSZ(self):
        if hasattr(self, 'loadingDlg'):
            self.loadingDlg.cleanup()
            del self.loadingDlg

    def __changeCamFOV(self, val):
        base.camLens.setMinFov(val / (4. / 3.))

    def enterOnStage(self):
        dna = self.choice.dna
        name = self.choice.name
        self.stageToon.setName(name)
        self.stageToon.setDNAStrand(dna)
        self.stageToon.nametag.setNametagColor(
            NametagGlobals.NametagColors[NametagGlobals.CCLocal])
        self.stageToon.nametag.setActive(0)
        self.stageToon.nametag.nametag3d.request('Rollover')
        self.stageToon.nametag.unmanage(base.marginManager)
        self.stageToon.nametag.updateAll()
        self.stageToon.animFSM.request('neutral')
        self.stageToon.setPosHpr(0, 0, 0, 10, 0, 0)
        self.stageToon.show()

        dat = HOOD_STAGE_DATA[self.choice.lastHood]

        self.stageToonRoot.setPos(dat[2])
        self.stageToonRoot.setHpr(dat[3])

        camera.reparentTo(self.stageToonRoot)

        camera.setPos(dat[0])
        camera.lookAt(self.stageToonRoot, 0, 0, 3)
        startHpr = camera.getHpr()
        camera.setPos(dat[1])
        camera.lookAt(self.stageToonRoot, 0, 0, 3)
        endHpr = camera.getHpr()

        self.camIval = Parallel(
            LerpPosInterval(camera,
                            5.0,
                            dat[1] - (1.6, 0, 0),
                            dat[0] - (1.6, 0, 0),
                            blendType='easeInOut'),
            LerpQuatInterval(camera,
                             5.0,
                             hpr=endHpr,
                             startHpr=startHpr,
                             blendType='easeInOut'),
            LerpFunc(self.__changeCamFOV,
                     duration=5.0,
                     fromData=80.0,
                     toData=CIGlobals.DefaultCameraFov,
                     blendType='easeInOut'))
        if self.isNewToon:
            self.camIval.append(
                Sequence(
                    Func(self.stageToon.hide), Func(base.stopMusic),
                    SoundInterval(self.newToonAnnounceSfx,
                                  startTime=1.674,
                                  duration=4.047),
                    SoundInterval(self.newToonDrumrollSfx),
                    Func(self.stageToon.pose, 'tele',
                         self.stageToon.getNumFrames('tele')),
                    Func(self.newToonAppear), Func(self.stageToon.show),
                    SoundInterval(self.newToonRevealSfx),
                    Func(base.cr.playTheme)))
        else:
            self.camIval.append(
                Sequence(Func(self.showActionButtons),
                         Func(self.enableAllCharButtons), Wait(5.0),
                         Func(self.beginRandomAnims)))

        self.camIval.start()

    def hideActionButtons(self):
        self.playOrCreateButton.hide()
        self.deleteButton.hide()

    def showActionButtons(self):
        self.playOrCreateButton.show()
        self.deleteButton.show()

    def newToonAppear(self):
        self.stopSTAnimSeq()

        self.stAnimSeq = Sequence(
            Func(self.stageToon.animFSM.request, 'teleportIn'), Wait(2.0),
            ActorInterval(self.stageToon, 'wave'),
            Func(self.stageToon.loop, 'neutral'), Func(self.beginRandomAnims),
            Func(self.enableAllCharButtons), Func(self.showActionButtons))
        self.stAnimSeq.start()

    def stopSTAnimSeq(self):
        if self.stAnimSeq:
            self.stAnimSeq.finish()
            self.stAnimSeq = None

    def unloadSZGeom(self):
        if self.szGeom:
            self.szGeom.removeNode()
            self.szGeom = None
        if self.olc:
            self.olc.cleanup()
            self.olc = None

    def beginRandomAnims(self):
        self.stageToon.startLookAround()
        taskMgr.doMethodLater(random.uniform(*ST_ANIM_IVAL),
                              self.__doRandomSTAnim, "doRandomSTAnim")

    def __doRandomSTAnim(self, task):
        anim = random.choice(ST_RANDOM_ANIMS)

        self.stopSTAnimSeq()

        self.stageToon.stopLookAround()

        head = self.stageToon.getPart('head')

        if anim == 'read':
            self.stAnimSeq = Sequence(
                Func(self.stageToon.lerpLookAt, head, (0, -15, 0)),
                Func(self.stageToon.animFSM.request, 'openBook'), Wait(0.5),
                Func(self.stageToon.animFSM.request, 'readBook'), Wait(2.0),
                Func(self.stageToon.lerpLookAt, head, (0, 0, 0)),
                Func(self.stageToon.animFSM.request, 'closeBook'), Wait(1.75),
                Func(self.stageToon.loop, 'neutral'),
                Func(self.stageToon.startLookAround))
        else:
            self.stageToon.lerpLookAt(head, (0, 0, 0))
            self.stAnimSeq = Sequence(ActorInterval(self.stageToon, anim),
                                      Func(self.stageToon.loop, 'neutral'),
                                      Func(self.stageToon.startLookAround))

        self.stAnimSeq.start()

        task.delayTime = random.uniform(*ST_ANIM_IVAL)
        return task.again

    def endRandomAnims(self):
        taskMgr.remove("doRandomSTAnim")
        self.stopSTAnimSeq()

    def exitOnStage(self):
        self.isNewToon = False
        if self.camIval:
            self.camIval.finish()
            self.camIval = None
        self.endRandomAnims()
        self.stopSTAnimSeq()
        camera.reparentTo(render)
        camera.setPosHpr(0, 0, 0, 0, 0, 0)
        #base.transitions.fadeScreen(1.0)
        self.unloadSZGeom()
        self.stageToon.hide()

    def enterCharSelected(self):
        self.playOrCreateButton['text'] = self.PLAY
        self.playOrCreateButton['extraArgs'] = ['play']
        #aspect2d.hide()

    def exitCharSelected(self):
        self.playOrCreateButton.hide()
        self.deleteButton.hide()

    def enterEmptySelected(self):
        self.charNameLabel.setText(self.NO_TOON)
        self.playOrCreateButton['text'] = self.CREATE
        self.playOrCreateButton['extraArgs'] = ['create']
        self.playOrCreateButton.show()

    def exitEmptySelected(self):
        self.playOrCreateButton.hide()

    def __action(self, action):
        for btn in self.charButtons:
            if btn['state'] == DGG.DISABLED:
                self.slot = btn.getPythonTag('slot')
                break
        func = None
        arg = None
        doFade = True
        if action == 'delete':
            func = self.deleteToon
            arg = self.choice.avId
            doFade = False
        elif action == 'play':
            func = self.playGame
            arg = self.choice.slot
        elif action == 'create':
            func = self.enterMAT
        elif action == 'quit':
            func = sys.exit
            doFade = False
        if doFade:
            base.transitions.fadeOut(0.3)
            if arg != None:
                Sequence(Wait(0.31), Func(func, arg)).start()
            else:
                Sequence(Wait(0.31), Func(func)).start()
        else:
            if arg != None:
                func(arg)
            else:
                func()

    def playGame(self, slot):
        messenger.send("avChooseDone",
                       [self.avChooser.getAvChoiceBySlot(slot)])

    def enterMAT(self):
        messenger.send("enterMakeAToon", [self.slot])

    def deleteToon(self, avId):
        # Show a confirmation message
        self.deleteConf = Dialog.GlobalDialog(
            message='This will delete {0} forever.\n\nAre you sure?'.format(
                self.avChooser.getNameFromAvId(avId)),
            style=Dialog.YesNo,
            doneEvent='deleteConfResponse',
            extraArgs=[avId])
        self.acceptOnce('deleteConfResponse', self.__handleDeleteConfResponse)
        self.deleteConf.show()

    def __handleDeleteConfResponse(self, avId):
        doneStatus = self.deleteConf.getValue()
        if doneStatus:
            # Alright, they pressed yes. No complaining to us.
            self.avChooser.avChooseFSM.request("waitForToonDelResponse",
                                               [avId])
        else:
            self.deleteConf.cleanup()
            self.deleteConf = None

    def __handleCharButton(self, slot):
        for btn in self.charButtons:
            if btn.getPythonTag('slot') == slot:
                btn['state'] = DGG.DISABLED
            else:
                btn['state'] = DGG.NORMAL
        if self.avChooser.hasToonInSlot(slot):
            self.choice = self.avChooser.getAvChoiceBySlot(slot)
            self.selectionFSM.request('character')
            self.stageFSM.request('loadSZ')
        else:
            self.selectionFSM.request('empty')
            self.stageFSM.request('off')

    def disableAllCharButtons(self):
        for btn in self.charButtons:
            btn['state'] = DGG.DISABLED

    def enableAllCharButtons(self):
        for btn in self.charButtons:
            if not self.choice or btn.getPythonTag('slot') != self.choice.slot:
                btn['state'] = DGG.NORMAL

    def load(self, newToonSlot=None):
        self.isNewToon = newToonSlot is not None
        self.newToonSlot = newToonSlot

        base.transitions.noTransitions()

        base.cr.renderFrame()
        base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4. / 3.))

        self.__setupStageToon()

        self.title = DirectLabel(text=self.TITLE,
                                 text_font=CIGlobals.getMickeyFont(),
                                 text_fg=(1, 0.9, 0.1, 1),
                                 relief=None,
                                 text_scale=0.13,
                                 pos=(0, 0, 0.82))
        self.charNameLabel = OnscreenText(text="",
                                          font=CIGlobals.getMickeyFont(),
                                          pos=(-0.25, 0.5, 0),
                                          fg=(1, 0.9, 0.1, 1.0))
        self.charNameLabel.hide()
        self.frame = DirectFrame()
        self.frame['image'] = DGG.getDefaultDialogGeom()
        self.frame['image_color'] = CIGlobals.DialogColor
        self.frame['image_scale'] = (-0.9, -0.9, 0.8)
        self.frame['image_pos'] = (0.82, 0, -0.125)
        self.playOrCreateButton = DirectButton(
            text="",
            pos=(0.8125, 0, -0.35),
            command=self.__action,
            geom=CIGlobals.getDefaultBtnGeom(),
            text_scale=0.06,
            relief=None,
            text_pos=(0, -0.01))
        self.playOrCreateButton.hide()
        self.deleteButton = DirectButton(text="Delete",
                                         pos=(0.8125, 0, -0.45),
                                         command=self.__action,
                                         extraArgs=['delete'],
                                         geom=CIGlobals.getDefaultBtnGeom(),
                                         text_scale=0.06,
                                         relief=None,
                                         text_pos=(0, -0.01))
        self.deleteButton.hide()
        self.quitButton = DirectButton(text="Quit",
                                       pos=(-1.10, 0, -0.925),
                                       command=self.__action,
                                       extraArgs=['quit'],
                                       text_scale=0.06,
                                       geom=CIGlobals.getDefaultBtnGeom(),
                                       relief=None,
                                       text_pos=(0, -0.01))

        for slot in range(6):
            if self.avChooser.hasToonInSlot(slot):
                choice = self.avChooser.getAvChoiceBySlot(slot)
                text = choice.name
            else:
                text = self.NO_TOON
            btn = CIGlobals.makeDefaultScrolledListBtn(
                text=text,
                text_scale=0.06,
                command=self.__handleCharButton,
                extraArgs=[slot])
            btn.setPythonTag('slot', slot)
            self.charButtons.append(btn)
            btn['state'] = DGG.NORMAL

        self.charList = CIGlobals.makeDefaultScrolledList(
            pos=(0.75, 0, -0.225),
            listZorigin=-0.43,
            listFrameSizeZ=0.51,
            arrowButtonScale=0.0,
            items=self.charButtons,
            parent=self.frame)

        if self.isNewToon:
            self.__handleCharButton(self.newToonSlot)
            self.disableAllCharButtons()

    def unload(self):
        self.selectionFSM.requestFinalState()
        self.stageFSM.requestFinalState()
        self.cleanupStageToon()
        self.choice = None
        if self.frame:
            self.frame.destroy()
            self.frame = None
        if self.charButtons:
            for btn in self.charButtons:
                btn.destroy()
            self.charButtons = None
        if self.deleteConf:
            self.deleteConf.cleanup()
            self.deleteConf = None
        if self.charList:
            self.charList.destroy()
            self.charList = None
        if self.charNameLabel:
            self.charNameLabel.destroy()
            self.charNameLabel = None
        if self.playOrCreateButton:
            self.playOrCreateButton.destroy()
            self.playOrCreateButton = None
        if self.deleteButton:
            self.deleteButton.destroy()
            self.deleteButton = None
        if self.quitButton:
            self.quitButton.destroy()
            self.quitButton = None
        if self.title:
            self.title.destroy()
            self.title = None
        base.camera.setPos(0, 0, 0)
        base.camera.setHpr(0, 0, 0)
        base.transitions.noTransitions()
        del self.selectionFSM
Esempio n. 17
0
class CharSelection:
    notify = directNotify.newCategory('CharSelection')
    STAGE_TOON_POS = (66.4, 74.47, -25)
    STAGE_TOON_HPR = (227.73, 0, 0)
    NO_TOON = 'Empty Slot'
    PLAY = 'Play'
    CREATE = 'Create'
    TITLE = 'Pick  A  Toon  To  Play'

    def __init__(self, avChooser):
        self.avChooser = avChooser
        self.choice = None
        self.charList = None
        self.charNameLabel = None
        self.charButtons = []
        self.playOrCreateButton = None
        self.deleteButton = None
        self.quitButton = None
        self.world = None
        self.sky = None
        self.fog = None
        self.title = None
        self.stageToon = None
        self.selectionFSM = ClassicFSM.ClassicFSM('CharSelection', [State.State('off', self.enterOff, self.exitOff), State.State('character', self.enterCharSelected, self.exitCharSelected), State.State('empty', self.enterEmptySelected, self.exitEmptySelected)], 'off', 'off')
        self.selectionFSM.enterInitialState()
        return

    def __setupStageToon(self):
        self.stageToon = Toon(base.cr)
        self.stageToon.setPos(self.STAGE_TOON_POS)
        self.stageToon.setHpr(self.STAGE_TOON_HPR)

    def cleanupStageToon(self):
        if self.stageToon != None:
            self.stageToon.disable()
            self.stageToon.delete()
            self.stageToon = None
        return

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterCharSelected(self, slot):
        self.choice = self.avChooser.getAvChoiceBySlot(slot)
        dna = self.choice.dna
        name = self.choice.name
        self.stageToon.setName(name)
        self.stageToon.setDNAStrand(dna)
        self.stageToon.nameTag.setColorLocal()
        self.stageToon.animFSM.request('neutral')
        self.stageToon.reparentTo(base.render)
        self.charNameLabel.setText(name)
        self.playOrCreateButton['text'] = self.PLAY
        self.playOrCreateButton['extraArgs'] = ['play']
        self.playOrCreateButton.show()
        self.deleteButton.show()

    def exitCharSelected(self):
        self.stageToon.animFSM.requestFinalState()
        self.stageToon.deleteCurrentToon()
        self.stageToon.reparentTo(base.hidden)
        self.playOrCreateButton.hide()
        self.deleteButton.hide()
        self.choice = None
        return

    def enterEmptySelected(self):
        self.charNameLabel.setText(self.NO_TOON)
        self.playOrCreateButton['text'] = self.CREATE
        self.playOrCreateButton['extraArgs'] = ['create']
        self.playOrCreateButton.show()

    def exitEmptySelected(self):
        self.playOrCreateButton.hide()

    def __action(self, action):
        for btn in self.charButtons:
            if btn['state'] == DGG.DISABLED:
                self.slot = btn.getPythonTag('slot')
                break

        func = None
        arg = None
        if action == 'delete':
            func = self.deleteToon
            arg = self.choice.avId
        elif action == 'play':
            func = self.playGame
            arg = self.choice.slot
        elif action == 'create':
            func = self.enterMAT
        elif action == 'quit':
            func = sys.exit
        base.transitions.fadeOut(0.3)
        if arg != None:
            Sequence(Wait(0.31), Func(func, arg)).start()
        else:
            Sequence(Wait(0.31), Func(func)).start()
        return

    def playGame(self, slot):
        messenger.send('avChooseDone', [self.avChooser.getAvChoiceBySlot(slot)])

    def enterMAT(self):
        messenger.send('enterMakeAToon', [self.slot])

    def deleteToon(self, avId):
        self.avChooser.avChooseFSM.request('waitForToonDelResponse', [avId])

    def __handleCharButton(self, slot):
        for btn in self.charButtons:
            if btn.getPythonTag('slot') == slot:
                btn['state'] = DGG.DISABLED
            else:
                btn['state'] = DGG.NORMAL

        if self.avChooser.hasToonInSlot(slot):
            self.selectionFSM.request('character', [slot])
        else:
            self.selectionFSM.request('empty')

    def load(self):
        base.cr.renderFrame()
        base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4.0 / 3.0))
        self.__setupStageToon()
        self.world = loader.loadModel('phase_9/models/cogHQ/SellbotHQExterior.bam')
        self.world.reparentTo(base.render)
        self.world.setPos(0, 227.09, -25.36)
        self.sky = loader.loadModel('phase_9/models/cogHQ/cog_sky.bam')
        self.sky.setScale(1)
        self.sky.reparentTo(base.render)
        self.sky.find('**/InnerGroup').removeNode()
        self.fog = Fog('charSelectFog')
        self.fog.setColor(0.2, 0.2, 0.2)
        self.fog.setExpDensity(0.003)
        base.render.setFog(self.fog)
        self.title = DirectLabel(text=self.TITLE, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 0.9, 0.1, 1), relief=None, text_scale=0.13, pos=(0, 0, 0.82))
        self.charNameLabel = OnscreenText(text='', font=CIGlobals.getMickeyFont(), pos=(-0.25, 0.5, 0), fg=(1, 0.9, 0.1, 1.0))
        self.charNameLabel.hide()
        self.playOrCreateButton = DirectButton(text='', pos=(0.8125, 0, -0.735), command=self.__action, geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01))
        self.playOrCreateButton.hide()
        self.deleteButton = DirectButton(text='Delete', pos=(0.8125, 0, -0.835), command=self.__action, extraArgs=['delete'], geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01))
        self.deleteButton.hide()
        self.quitButton = DirectButton(text='Quit', pos=(-1.1, 0, -0.925), command=self.__action, extraArgs=['quit'], text_scale=0.06, geom=CIGlobals.getDefaultBtnGeom(), relief=None, text_pos=(0, -0.01))
        textRolloverColor = Vec4(1, 1, 0, 1)
        textDownColor = Vec4(0.5, 0.9, 1, 1)
        textDisabledColor = Vec4(0.4, 0.8, 0.4, 1)
        for slot in range(6):
            if self.avChooser.hasToonInSlot(slot):
                choice = self.avChooser.getAvChoiceBySlot(slot)
                text = choice.name
            else:
                text = self.NO_TOON
            btn = DirectButton(relief=None, text=text, text_scale=0.06, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleCharButton, extraArgs=[slot], text_pos=(0, 0, 0.0))
            btn.setPythonTag('slot', slot)
            self.charButtons.append(btn)
            btn['state'] = DGG.NORMAL

        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        listXorigin = -0.02
        listFrameSizeX = 0.625
        listZorigin = -0.96
        listFrameSizeZ = 1.04
        arrowButtonScale = 1.3
        itemFrameXorigin = -0.237
        itemFrameZorigin = 0.365
        buttonXstart = itemFrameXorigin + 0.293
        self.charList = DirectScrolledList(relief=None, pos=(0.75, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'),
         gui.find('**/FndsLst_ScrollDN'),
         gui.find('**/FndsLst_ScrollUp_Rllvr'),
         gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(gui.find('**/FndsLst_ScrollUp'),
         gui.find('**/FndsLst_ScrollDN'),
         gui.find('**/FndsLst_ScrollUp_Rllvr'),
         gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin,
         listXorigin + listFrameSizeX,
         listZorigin,
         listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.075, items=self.charButtons)
        base.camera.setPos(75.12, 63.22, -23)
        base.camera.setHpr(26.57, 9.62, 0)
        return

    def unload(self):
        self.selectionFSM.requestFinalState()
        self.cleanupStageToon()
        self.choice = None
        if self.charButtons:
            for btn in self.charButtons:
                btn.destroy()

            self.charButtons = None
        if self.charList:
            self.charList.destroy()
            self.charList = None
        if self.charNameLabel:
            self.charNameLabel.destroy()
            self.charNameLabel = None
        if self.playOrCreateButton:
            self.playOrCreateButton.destroy()
            self.playOrCreateButton = None
        if self.deleteButton:
            self.deleteButton.destroy()
            self.deleteButton = None
        if self.quitButton:
            self.quitButton.destroy()
            self.quitButton = None
        if self.sky:
            self.sky.removeNode()
            self.sky = None
        if self.world:
            self.world.removeNode()
            self.world = None
        if self.title:
            self.title.destroy()
            self.title = None
        base.render.clearFog()
        self.fog = None
        base.camera.setPos(0, 0, 0)
        base.camera.setHpr(0, 0, 0)
        base.transitions.noTransitions()
        del self.selectionFSM
        return
Esempio n. 18
0
class CharSelection(DirectObject):
    notify = directNotify.newCategory('CharSelection')

    STAGE_TOON_POS = (66.4, 74.47, -25)
    STAGE_TOON_HPR = (227.73, 0, 0)

    NO_TOON = "Empty Slot"
    PLAY = "Play"
    CREATE = "Create"
    TITLE = "Pick  A  Toon  To  Play"

    def __init__(self, avChooser):
        self.avChooser = avChooser
        self.choice = None
        self.charList = None
        self.charNameLabel = None
        self.charButtons = []
        self.playOrCreateButton = None
        self.deleteButton = None
        self.quitButton = None
        self.world = None
        self.sky = None
        self.fog = None
        self.title = None
        self.stageToon = None
        self.deleteConf = None
        self.frame = None
        self.selectionFSM = ClassicFSM.ClassicFSM(
            'CharSelection',
            [
                State.State('off', self.enterOff, self.exitOff),
                State.State('character', self.enterCharSelected, self.exitCharSelected),
                State.State('empty', self.enterEmptySelected, self.exitEmptySelected)
            ],
            'off', 'off'
        )
        self.selectionFSM.enterInitialState()

    def __setupStageToon(self):
        self.stageToon = Toon(base.cr)
        self.stageToon.setPos(self.STAGE_TOON_POS)
        self.stageToon.setHpr(self.STAGE_TOON_HPR)

    def cleanupStageToon(self):
        if self.stageToon != None:
            self.stageToon.disable()
            self.stageToon.delete()
            self.stageToon = None

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterCharSelected(self, slot):
        self.choice = self.avChooser.getAvChoiceBySlot(slot)
        dna = self.choice.dna
        name = self.choice.name
        self.stageToon.setName(name)
        self.stageToon.setDNAStrand(dna)
        self.stageToon.nametag.setNametagColor(NametagGlobals.NametagColors[NametagGlobals.CCLocal])
        self.stageToon.nametag.setActive(0)
        self.stageToon.nametag.updateAll()
        self.stageToon.nametag.nametag3d.request('Rollover')
        self.stageToon.animFSM.request('neutral')
        self.stageToon.reparentTo(base.render)
        self.charNameLabel.setText(name)
        self.playOrCreateButton['text'] = self.PLAY
        self.playOrCreateButton['extraArgs'] = ['play']
        self.playOrCreateButton.show()
        self.deleteButton.show()

    def exitCharSelected(self):
        self.stageToon.animFSM.requestFinalState()
        self.stageToon.deleteCurrentToon()
        self.stageToon.reparentTo(base.hidden)
        self.playOrCreateButton.hide()
        self.deleteButton.hide()
        self.choice = None

    def enterEmptySelected(self):
        self.charNameLabel.setText(self.NO_TOON)
        self.playOrCreateButton['text'] = self.CREATE
        self.playOrCreateButton['extraArgs'] = ['create']
        self.playOrCreateButton.show()

    def exitEmptySelected(self):
        self.playOrCreateButton.hide()

    def __action(self, action):
        for btn in self.charButtons:
            if btn['state'] == DGG.DISABLED:
                self.slot = btn.getPythonTag('slot')
                break
        func = None
        arg = None
        doFade = True
        if action == 'delete':
            func = self.deleteToon
            arg = self.choice.avId
            doFade = False
        elif action == 'play':
            func = self.playGame
            arg = self.choice.slot
        elif action == 'create':
            func = self.enterMAT
        elif action == 'quit':
            func = sys.exit
        if doFade:
            base.transitions.fadeOut(0.3)
            if arg != None:
                Sequence(Wait(0.31), Func(func, arg)).start()
            else:
                Sequence(Wait(0.31), Func(func)).start()
        else:
            if arg != None:
                func(arg)
            else:
                func()

    def playGame(self, slot):
        messenger.send("avChooseDone", [self.avChooser.getAvChoiceBySlot(slot)])

    def enterMAT(self):
        messenger.send("enterMakeAToon", [self.slot])

    def deleteToon(self, avId):
        # Show a confirmation message
        self.deleteConf = Dialog.GlobalDialog(
            message = 'This will delete {0} forever. Are you sure?'.format(self.avChooser.getNameFromAvId(avId)),
            style = Dialog.YesNo, doneEvent = 'deleteConfResponse', extraArgs = [avId])
        self.acceptOnce('deleteConfResponse', self.__handleDeleteConfResponse)
        self.deleteConf.show()

    def __handleDeleteConfResponse(self, avId):
        doneStatus = self.deleteConf.getValue()
        if doneStatus:
            # Alright, they pressed yes. No complaining to us.
            self.avChooser.avChooseFSM.request("waitForToonDelResponse", [avId])
        else:
            self.deleteConf.cleanup()
            self.deleteConf = None

    def __handleCharButton(self, slot):
        for btn in self.charButtons:
            if btn.getPythonTag('slot') == slot:
                btn['state'] = DGG.DISABLED
            else:
                btn['state'] = DGG.NORMAL
        if self.avChooser.hasToonInSlot(slot):
            self.selectionFSM.request('character', [slot])
        else:
            self.selectionFSM.request('empty')

    def load(self):
        base.cr.renderFrame()
        base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4./3.))

        self.__setupStageToon()
        holidayMgr = base.cr.holidayManager

        self.props = []
        self.world = loader.loadModel('phase_9/models/cogHQ/SellbotHQExterior.bam')
        self.world.reparentTo(base.render)
        self.world.setPos(0, 227.09, -25.36)
        self.sky = loader.loadModel('phase_9/models/cogHQ/cog_sky.bam')
        self.sky.setScale(1)
        self.sky.reparentTo(base.render)
        self.sky.find('**/InnerGroup').removeNode()
        self.fog = Fog('charSelectFog')
        self.fog.setColor(0.2, 0.2, 0.2)
        self.fog.setExpDensity(0.003)
        base.render.setFog(self.fog)
        
        # Let's fix the flickering doors.
        doors = self.world.find('**/doors').getChildren()
        
        for door in doors:
            for frameHole in door.findAllMatches('**/doorFrameHole*'): frameHole.removeNode()

        if holidayMgr.getHoliday() == HolidayType.CHRISTMAS:
            piles = {
                'half' : {'pos' : (57.28, 86.47, -25.00), 'hpr' : (46.79, 0, 0)},
                'full' : {'pos' : (71.23, 85.2, -25.00), 'hpr' : (290.82, 0, 0)},
                'half_2' : {'pos' : (-15, 128.69, -25), 'hpr' : (60.26, 0, 0)}
            }

            for pileType, info in piles.items():
                if '_' in pileType:
                    pileType = pileType[:-2]
                pile = loader.loadModel('phase_8/models/props/snow_pile_%s.bam' % (pileType))
                pile.reparentTo(render)
                pile.setPos(info['pos'])
                pile.setHpr(info['hpr'])
                self.props.append(pile)

            self.world.find('**/TopRocks').removeNode()

            snowTxt = loader.loadTexture('winter/maps/sbhq_snow.png')
            self.world.find('**/Ground').setTexture(snowTxt, 1)

            self.particles = ParticleLoader.loadParticleEffect('phase_8/etc/snowdisk.ptf')
            self.particles.setPos(0, 0, 5)
            self.particlesRender = self.world.attachNewNode('snowRender')
            self.particlesRender.setDepthWrite(0)
            self.particlesRender.setBin('fixed', 1)
            self.particles.start(parent = camera, renderParent = self.particlesRender)
            self.fog.setColor(0.486, 0.784, 1)
            self.fog.setExpDensity(0.006)
            base.render.setFog(self.fog)


        self.title = DirectLabel(text=self.TITLE, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 0.9, 0.1, 1),
                                relief=None, text_scale=0.13, pos=(0, 0, 0.82))
        self.charNameLabel = OnscreenText(text = "", font = CIGlobals.getMickeyFont(),
                                        pos = (-0.25, 0.5, 0), fg = (1, 0.9, 0.1, 1.0))
        self.charNameLabel.hide()
        self.frame = DirectFrame()
        self.frame['image'] = DGG.getDefaultDialogGeom()
        self.frame['image_color'] = CIGlobals.DialogColor
        self.frame['image_scale'] = (-0.9, -0.9, 0.8)
        self.frame['image_pos'] = (0.82, 0, -0.125)
        self.playOrCreateButton = DirectButton(text = "", pos = (0.8125, 0, -0.35), command = self.__action,
                                            geom = CIGlobals.getDefaultBtnGeom(), text_scale = 0.06,
                                            relief = None, text_pos = (0, -0.01))
        self.playOrCreateButton.hide()
        self.deleteButton = DirectButton(text = "Delete", pos = (0.8125, 0, -0.45),
                                        command = self.__action, extraArgs = ['delete'],
                                        geom = CIGlobals.getDefaultBtnGeom(), text_scale = 0.06,
                                        relief = None, text_pos = (0, -0.01))
        self.deleteButton.hide()
        self.quitButton = DirectButton(text = "Quit", pos = (-1.10, 0, -0.925), command = self.__action,
                                    extraArgs = ['quit'], text_scale = 0.06, geom = CIGlobals.getDefaultBtnGeom(),
                                    relief = None, text_pos = (0, -0.01))

        textRolloverColor = Vec4(1, 1, 0, 1)
        textDownColor = Vec4(0.5, 0.9, 1, 1)
        textDisabledColor = Vec4(0.4, 0.8, 0.4, 1)

        for slot in range(6):
            if self.avChooser.hasToonInSlot(slot):
                choice = self.avChooser.getAvChoiceBySlot(slot)
                text = choice.name
            else:
                text = self.NO_TOON
            btn = DirectButton(
                relief=None, text = text, text_scale=0.06,
                text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor,
                text3_fg=textDisabledColor, textMayChange=0, command=self.__handleCharButton,
                extraArgs=[slot], text_pos = (0, 0, 0.0)
            )
            btn.setPythonTag('slot', slot)
            self.charButtons.append(btn)
            btn['state'] = DGG.NORMAL

        gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        listXorigin = -0.02
        listFrameSizeX = 0.625
        listZorigin = -0.43
        listFrameSizeZ = 0.51
        arrowButtonScale = 0.0
        itemFrameXorigin = -0.237
        itemFrameZorigin = 0.365
        buttonXstart = itemFrameXorigin + 0.293

        self.charList = DirectScrolledList(
            relief=None,
            pos=(0.75, 0, -0.225),
            incButton_image=None,
            #incButton_relief=None,
            incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale),
            #incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999),
            #incButton_image3_color=Vec4(1, 1, 1, 0.2),
            decButton_image=None,
            #decButton_relief=None,
            decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale),
            #decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125),
            #decButton_image3_color=Vec4(1, 1, 1, 0.2),
            itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin),
            itemFrame_scale=1.0,
            itemFrame_relief=DGG.SUNKEN,
            itemFrame_frameSize=(listXorigin,
                listXorigin + listFrameSizeX,
                listZorigin,
                listZorigin + listFrameSizeZ),
            itemFrame_frameColor=(0.85, 0.95, 1, 1),
            itemFrame_borderWidth=(0.01, 0.01),
            numItemsVisible=15,
            forceHeight=0.075,
            items=self.charButtons,
            parent = self.frame
        )

        base.camera.setPos(75.12, 63.22, -23)
        base.camera.setHpr(26.57, 9.62, 0)

    def unload(self):
        self.selectionFSM.requestFinalState()
        self.cleanupStageToon()
        self.choice = None
        if self.frame:
            self.frame.destroy()
            self.frame = None
        if self.charButtons:
            for btn in self.charButtons:
                btn.destroy()
            self.charButtons = None
        if self.deleteConf:
            self.deleteConf.cleanup()
            self.deleteConf = None
        if self.charList:
            self.charList.destroy()
            self.charList = None
        if self.charNameLabel:
            self.charNameLabel.destroy()
            self.charNameLabel = None
        if self.playOrCreateButton:
            self.playOrCreateButton.destroy()
            self.playOrCreateButton = None
        if self.deleteButton:
            self.deleteButton.destroy()
            self.deleteButton = None
        if self.quitButton:
            self.quitButton.destroy()
            self.quitButton = None
        if self.sky:
            self.sky.removeNode()
            self.sky = None
        if self.world:
            self.world.removeNode()
            self.world = None
        if self.title:
            self.title.destroy()
            self.title = None
        for prop in self.props:
            if not prop.isEmpty():
                prop.removeNode()
        self.props = None
        if hasattr(self, 'particles'):
            self.particles.cleanup()
            self.particlesRender.removeNode()
            self.particles = None
            del self.particlesRender
        base.render.clearFog()
        self.fog = None
        base.camera.setPos(0, 0, 0)
        base.camera.setHpr(0, 0, 0)
        base.transitions.noTransitions()
        del self.selectionFSM