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)
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
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)
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()
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
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)
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
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
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
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
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