class AvChooser(StateData): notify = directNotify.newCategory('AvChooser') def __init__(self, parentFSM): StateData.__init__(self, 'avChooseDone') self.avChooseFSM = ClassicFSM('avChoose', [ State('getToonData', self.enterGetToonData, self.exitGetToonData), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('waitForToonDelResponse', self.enterWaitForToonDelResponse, self.exitWaitForToonDelResponse), State('off', self.enterOff, self.exitOff) ], 'off', 'off') self.avChooseFSM.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('avChoose').addChild(self.avChooseFSM) self.pickAToon = None self.setAvatarsNone() return def enter(self): StateData.enter(self) base.transitions.noTransitions() self.avChooseFSM.request('getToonData') def exit(self): StateData.exit(self) self.setAvatarsNone() self.avChooseFSM.requestFinalState() def setAvatarsNone(self): self.avChoices = [] def enterOff(self): pass def exitOff(self): pass def enterGetToonData(self): self.acceptOnce(base.cr.csm.getSetAvatarsEvent(), self.handleToonData) base.cr.csm.d_requestAvatars() def handleToonData(self, avatarList): for av in avatarList: avId = av[0] dna = av[1] name = av[2] slot = av[3] choice = AvChoice(dna, name, slot, avId) self.avChoices.append(choice) self.avChooseFSM.request('avChoose') def exitGetToonData(self): self.ignore(base.cr.csm.getSetAvatarsEvent()) def enterAvChoose(self): if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: base.cr.music.stop() base.cr.music = base.loadMusic(CIGlobals.getHolidayTheme()) base.cr.music.setLoop(True) base.cr.music.setVolume(0.75) base.cr.music.play() whisper = WhisperPopup(HolidayGlobals.CHRISTMAS_TIME, CIGlobals.getToonFont(), ChatGlobals.WTSystem) whisper.manage(base.marginManager) self.pickAToon = CharSelection(self) self.pickAToon.load() def enterWaitForToonDelResponse(self, avId): self.acceptOnce(base.cr.csm.getToonDeletedEvent(), self.handleDeleteToonResp) base.cr.csm.sendDeleteToon(avId) def exitWaitForToonDelResponse(self): self.ignore(base.cr.csm.getToonDeletedEvent()) def hasToonInSlot(self, slot): if self.getAvChoiceBySlot(slot) != None: return True return False return def getNameInSlot(self, slot): return self.getAvChoiceBySlot(slot).getName() def getNameFromAvId(self, avId): for avChoice in self.avChoices: if avChoice.getAvId() == avId: return avChoice.getName() def getAvChoiceBySlot(self, slot): for avChoice in self.avChoices: if avChoice.getSlot() == slot: return avChoice return def getHeadInfo(self, slot): dna = self.getAvChoiceBySlot(slot).getDNA() self.pickAToon.dna.setDNAStrand(dna) return [ self.pickAToon.dna.getGender(), self.pickAToon.dna.getAnimal(), self.pickAToon.dna.getHead(), self.pickAToon.dna.getHeadColor() ] def handleDeleteToonResp(self): base.cr.loginFSM.request('avChoose') def exitAvChoose(self): self.pickAToon.unload() self.pickAToon = None return
class TownLoader(StateData): notify = directNotify.newCategory('TownLoader') def __init__(self, hood, parentFSMState, doneEvent): self.hood = hood self.parentFSMState = parentFSMState StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('TownLoader', [State('start', self.enterStart, self.exitStart, ['quietZone', 'street']), State('street', self.enterStreet, self.exitStreet, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior']), State('final', self.enterFinal, self.exitFinal, ['start'])], 'start', 'final') self.branchZone = None self.canonicalBranchZone = None self.placeDoneEvent = 'placeDone' self.linkTunnels = [] return def findAndMakeLinkTunnels(self, requestStatus): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr) zone = LinkTunnel.maybeFixZone(zone) tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone) link = tunnelClass(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self, zoneId): StateData.load(self) self.zoneId = zoneId self.branchZone = ZoneUtil.getBranchZone(zoneId) self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId) self.music = base.loadMusic(self.musicFile) self.interiorMusic = base.loadMusic(self.interiorMusicFile) def unload(self): self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm del self.streetClass self.landmarkBlocks.removeNode() del self.landmarkBlocks self.hood.dnaStore.resetSuitPoints() self.hood.dnaStore.resetBattleCells() del self.hood del self.nodeDict del self.zoneDict del self.fadeInDict del self.fadeOutDict del self.nodeList self.geom.removeNode() del self.geom del self.music del self.interiorMusic ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.unload(self) def enter(self, requestStatus): StateData.enter(self) self.findAndMakeLinkTunnels(requestStatus) self.fsm.enterInitialState() self.setState(requestStatus['where'], requestStatus) def exit(self): self.fsm.requestFinalState() self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.exit(self) def setState(self, state, requestStatus): self.fsm.request(state, [requestStatus]) def enterStart(self): pass def exitStart(self): pass def enterStreet(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.streetDone) self.place = self.streetClass(self, self.fsm, self.placeDoneEvent) self.place.load() def exitStreet(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def streetDone(self): self.requestStatus = self.place.doneStatus status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) self.place.enter(requestStatus) def handleToonInteriorDone(self): status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getRequestStatus() self.exitQuietZone() self.enterThePlace(status) def enterFinal(self): pass def exitFinal(self): pass def createHood(self, dnaFile, loadStorage = 1): if loadStorage: loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.dna') loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) self.makeDictionaries(self.hood.dnaStore) self.reparentLandmarkBlockNodes() self.renameFloorPolys(self.nodeList) gsg = base.win.getGsg() if gsg: self.geom.prepareScene(gsg) self.geom.flattenLight() self.geom.setName('town_top_level') def reparentLandmarkBlockNodes(self): bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks') npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) def makeDictionaries(self, dnaStore): self.nodeDict = {} self.zoneDict = {} self.zoneVisDict = {} self.nodeList = [] self.fadeInDict = {} self.fadeOutDict = {} a1 = Vec4(1, 1, 1, 1) a0 = Vec4(1, 1, 1, 0) numVisGroups = dnaStore.getNumDNAVisGroupsAI() for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) visGroup = dnaStore.getDNAVisGroupAI(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) zoneId = int(groupName) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): continue else: if ':' in groupName: groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):]) else: groupName = '%s' % zoneId groupNode.setName(groupName) groupNode.flattenMedium() self.nodeDict[zoneId] = [] self.nodeList.append(groupNode) self.zoneDict[zoneId] = groupNode visibles = [] for i in xrange(visGroup.getNumVisibles()): visibles.append(int(visGroup.visibles[i])) visibles.append(ZoneUtil.getBranchZone(zoneId)) self.zoneVisDict[zoneId] = visibles fadeDuration = 0.5 self.fadeOutDict[groupNode] = Sequence(Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), name='fadeZone-' + str(zoneId), autoPause=1) self.fadeInDict[groupNode] = Sequence(Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1) for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)): visName = dnaStore.getVisibleName(i, j) groupName = base.cr.hoodMgr.extractGroupName(visName) nextZoneId = int(groupName) nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId) visNode = self.zoneDict[nextZoneId] self.nodeDict[zoneId].append(visNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def renameFloorPolys(self, nodeList): for i in nodeList: collNodePaths = i.findAllMatches('**/+CollisionNode') numCollNodePaths = collNodePaths.getNumPaths() visGroupName = i.node().getName() for j in xrange(numCollNodePaths): collNodePath = collNodePaths.getPath(j) bitMask = collNodePath.node().getIntoCollideMask() if bitMask.getBit(1): collNodePath.node().setName(visGroupName)
class DistributedSuit(Suit, DistributedAvatar, DistributedSmoothNode, DelayDeletable): notify = directNotify.newCategory("DistributedSuit") def __init__(self, cr): try: self.DistributedSuit_initialized return except: self.DistributedSuit_initialized = 1 Suit.__init__(self) DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.suitFSM = ClassicFSM('DistributedSuit', [ State('off', self.enterSuitOff, self.exitSuitOff), State('walking', self.enterWalking, self.exitWalking), State('flyingDown', self.enterFlyingDown, self.exitFlyingDown), State('flyingUp', self.enterFlyingUp, self.exitFlyingUp), State('bossFlying', self.enterBossFlying, self.exitBossFlying) ], 'off', 'off' ) self.suitFSM.enterInitialState() self.makeStateDict() self.makeAnimStateDict() # These are just default values, we'll set them later on. self.anim = None self.state = "alive" self.health = None self.type = None self.team = None self.head = None self.skeleton = 0 self.battle = None self.suitState = None self.startPoint = None self.endPoint = None self.moveIval = None self.walkPaused = None self.animIval = None self.level = None return def d_disableMovement(self, wantRay = False): self.sendUpdate('disableMovement', []) self.interruptAttack() if not wantRay: Suit.disableRay(self) def d_enableMovement(self): self.sendUpdate('enableMovement', []) Suit.initializeRay(self, self.avatarType, 2) def startRay(self): Suit.initializeRay(self, self.avatarType, 2) def setLevel(self, level): self.level = level def getLevel(self): return self.level def makeStateDict(self): self.suitState2stateIndex = {} for state in self.suitFSM.getStates(): self.suitState2stateIndex[state.getName()] = self.suitFSM.getStates().index(state) self.stateIndex2suitState = {v: k for k, v in self.suitState2stateIndex.items()} def makeAnimStateDict(self): self.animState2animId = {} for index in range(len(self.animFSM.getStates())): self.animState2animId[self.animFSM.getStates()[index].getName()] = index self.animId2animState = {v: k for k, v in self.animState2animId.items()} def setLatePos(self, x, y): self.setX(x) self.setY(y) def enterAttack(self, attack, target, ts = 0): Suit.enterAttack(self, attack, target, ts) if target: self.headsUp(target) def setSuitState(self, index, startPoint, endPoint, timestamp = None): if timestamp != None: ts = globalClockDelta.localElapsedTime(timestamp) else: ts = 0.0 self.suitState = self.stateIndex2suitState[index] self.startPoint = startPoint self.endPoint = endPoint self.suitFSM.request(self.suitState, [startPoint, endPoint, ts]) def getSuitState(self): return self.suitState def enterWalking(self, startIndex, endIndex, ts = 0.0): durationFactor = 0.2 if startIndex > -1: startPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[self.getHood()][startPoint] else: startPos = self.getPos(render) endPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] if self.moveIval: self.moveIval.pause() self.moveIval = None self.moveIval = NPCWalkInterval(self, endPos, durationFactor, startPos, fluid = 1) self.moveIval.start(ts) self.animFSM.request('walk') def exitWalking(self): if self.moveIval: self.moveIval.pause() self.moveIval = None if not self.isDead(): self.animFSM.request('off') def enterFlyingDown(self, startIndex, endIndex, ts = 0.0): duration = 3 startPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[self.getHood()][startPoint] + (0, 0, 50) endPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] if self.moveIval: self.moveIval.finish() self.moveIval = None self.moveIval = LerpPosInterval(self, duration = duration, pos = endPos, startPos = startPos, fluid = 1) self.moveIval.start(ts) self.animFSM.request('flydown', [ts]) yaw = random.uniform(0.0, 360.0) self.setH(yaw) def exitFlyingDown(self): if self.moveIval: self.moveIval.finish() self.moveIval = None self.animFSM.request('off') def enterFlyingUp(self, startIndex, endIndex, ts = 0.0): duration = 3 startPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[startIndex] endPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[endIndex] startPos = CIGlobals.SuitSpawnPoints[self.getHood()][startPoint] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] + (0, 0, 50) if self.moveIval: self.moveIval.finish() self.moveIval = None self.moveIval = LerpPosInterval(self, duration = duration, pos = endPos, startPos = startPos, fluid = 1) self.moveIval.start(ts) self.animFSM.request('flyaway', [ts]) def exitFlyingUp(self): if self.moveIval: self.moveIval.finish() self.moveIval = None self.animFSM.request('off') def enterBossFlying(self, startIndex, endIndex, ts = 0.0): duration = 3.5 startPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[startIndex] endPoint = CIGlobals.SuitSpawnPoints[self.getHood()].keys()[endIndex] startPos = CIGlobals.SuitSpawnPoints[self.getHood()][startPoint] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] if self.moveIval: self.moveIval.finish() self.moveIval = None self.animIval = Sequence( Func(self.animFSM.request, 'flyaway', [ts]), Wait(1.0), Func(self.animFSM.request, 'flydown', [ts]) ) self.moveIval = Sequence( Wait(0.5), Func(self.headsUp, endPos), ProjectileInterval( self, startPos = startPos, endPos = endPos, gravityMult = 0.25, duration = duration ) ) self.moveIval.start(ts) self.animIval.start(ts) def exitBossFlying(self): if self.animIval: self.animIval.finish() self.animIval = None if self.moveIval: self.moveIval.finish() self.moveIval = None self.animFSM.request('off') def enterSuitOff(self, foo1 = None, foo2 = None, foo3 = None): pass def exitSuitOff(self): pass #def setWalking(self, value, startPos, endPath, timestamp = None): # # # self.value = value # self.startPath = startPath # self.endPath = endPath # # if self.walkIval: # self.walkIval.finish() # self.walkIval = None # # if value: # durationFactor = 0.2 # path = CIGlobals.SuitSpawnPoints.values()[endPath] # self.walkIval = NPCWalkInterval(self, path, startPos = self.getPos(render), name = pathName, durationFactor = durationFactor, fluid = 1) def setBattle(self, battle): self.battle = battle def getBattle(self): return self.battle def printPos(self, task): print self.getPos(render) print self.getHpr(render) return task.cont def announceHealth(self, level, hp): DistributedAvatar.announceHealth(self, level, hp) if level == 1: healthSfx = base.audio3d.loadSfx("phase_3/audio/sfx/health.mp3") base.audio3d.attachSoundToObject(healthSfx, self) SoundInterval(healthSfx).start() del healthSfx def setSuit(self, suitType, head, team, skeleton): for obj in self.cr.doId2do.values(): if obj.zoneId == self.zoneId: if obj.__class__.__name__ == "DistributedCogBattle": # This has to be the Cog Battle we're in because it's in the same zone. self.setBattle(obj) hp = CIGlobals.SuitHealthAmounts[head] Suit.generateSuit(self, suitType, head, team, hp, skeleton) def getSuit(self): return tuple((self.type, self.head, self.team, self.skeleton)) def setName(self, name): Suit.setName(self, name, self.head) def setHealth(self, health): DistributedAvatar.setHealth(self, health) self.updateHealthBar(health) def setAnimState(self, anim, timestamp = None): self.anim = anim if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) if type(anim) == types.IntType: anim = self.animId2animState[anim] if self.animFSM.getStateNamed(anim): self.animFSM.request(anim, [ts]) def doAttack(self, attackId, avId, timestamp = None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) attackName = SuitAttacks.SuitAttackLengths.keys()[attackId] avatar = self.cr.doId2do.get(avId) self.animFSM.request('attack', [attackName, avatar, ts]) def throwObject(self): self.acceptOnce("enter" + self.wsnp.node().getName(), self.__handleWeaponCollision) Suit.throwObject(self) def __handleWeaponCollision(self, entry): self.sendUpdate('toonHitByWeapon', [self.attack, base.localAvatar.doId]) base.localAvatar.handleHitByWeapon(self.attack, self) self.b_handleWeaponTouch() def b_handleWeaponTouch(self): self.sendUpdate('handleWeaponTouch', []) self.handleWeaponTouch() def announceGenerate(self): DistributedAvatar.announceGenerate(self) if self.animFSM.getCurrentState().getName() == 'off': self.setAnimState('neutral') def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) self.startSmooth() def disable(self): if self.suitTrack != None: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.stopSmooth() self.suitFSM.requestFinalState() self.suitFSM = None self.suitState2stateIndex = None self.stateIndex2suitState = None self.anim = None self.state = None self.health = None self.type = None self.team = None self.head = None self.skeleton = None self.battle = None Suit.disable(self) DistributedAvatar.disable(self) def delete(self): Suit.delete(self) DistributedAvatar.delete(self) DistributedSmoothNode.delete(self)
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 CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [ State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge) ], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence( Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __traverse(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont mpos = base.mouseWatcherNode.getMouse() self.focusRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.focusTrav.traverse(render) if self.focusHandler.getNumEntries() > 0: self.focusHandler.sortEntries() firstObj = self.focusHandler.getEntry(0).getIntoNodePath() avId = firstObj.getParent().getPythonTag('player') avatar = self.mg.cr.doId2do.get(avId) toonInFoc = False if avatar: remoteAvatar = self.mg.getRemoteAvatar(avatar.doId) if remoteAvatar: toonInFoc = True self.__handleToonInFocus(avatar) if not toonInFoc: self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return task.cont def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx( 'phase_4/audio/sfx/MG_pairing_match.ogg') self.rechargeSound = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage( image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel( 'phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusTrav = CollisionTraverser('CSFP.focusTrav') ray = CollisionRay() rayNode = CollisionNode('CSFP.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = ray self.focusRayNode = base.camera.attachNewNode(rayNode) self.focusHandler = CollisionHandlerQueue() self.focusTrav.addCollider(self.focusRayNode, self.focusHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): taskMgr.add(self.__traverse, 'CSFP.__traverse') self.camFSM.request('recharge') base.localAvatar.startTrackAnimToSpeed() FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') taskMgr.remove('CSFP.__traverse') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusHandler = None self.focusRay = None self.focusRayNode.removeNode() self.focusRayNode = None self.focusTrav = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return
class Suit(Avatar): notify = directNotify.newCategory('Suit') def __init__(self): Avatar.__init__(self) self.dept = None self.suit = None self.head = None self.headModel = None self.variant = None self.handColor = None self.voice = None self.chat = None self.chatDial = None self.shadow = None self.deathSound = None self.propeller = None self.smallExp = None self.largeExp = None self.explosion = None self.hasSpawned = False self.suitTrack = None self.timestampAnimTrack = None self.propellerSounds = {} self.healthBar = None self.healthBarGlow = None self.condition = 0 self.avatarType = CIGlobals.Suit self.suitPlan = None self.footstepSound = None self.showNametagInMargins = False self.surfaceProp = "metal" self.activities = { ACT_WAKE_ANGRY: WakeAngry(self), ACT_SMALL_FLINCH: Flinch(self), ACT_DIE: Die(self), ACT_VICTORY_DANCE: VictoryDance(self), ACT_COG_FLY_DOWN: FlyDown(self), ACT_SIT: Sit(self), ACT_STUN: Stun(self) } self.standWalkRunReverse = [('neutral', 'walk', 0.0, 5.0, 1.0, 1.0)] self.gruntSound = base.audio3d.loadSfx( "phase_14/audio/sfx/cog_grunt.ogg") base.audio3d.attachSoundToObject(self.gruntSound, self) self.animFSM = ClassicFSM('Suit', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('win', self.enterWin, self.exitWin), State('flail', self.enterFlail, self.exitFlail), State('flyDown', self.enterFlyDown, self.exitFlyDown), State('flyAway', self.enterFlyAway, self.exitFlyAway), State('flyNeutral', self.enterFlyNeutral, self.exitFlyNeutral), State('trayWalk', self.enterTrayWalk, self.exitTrayWalk), State('trayNeutral', self.enterTrayNeutral, self.exitTrayNeutral), State('stunned', self.enterStunned, self.exitStunned), State('pie', self.enterPie, self.exitPie), State('drop', self.enterDrop, self.exitDrop), State('drop-react', self.enterDropReact, self.exitDropReact), State('soak', self.enterSoak, self.exitSoak), State('squirt-small', self.enterSquirtSmall, self.exitSquirtSmall) ], 'off', 'off') self.animFSM.enterInitialState() def getRightHandNode(self): return self.find("**/joint_Rhold") def getLeftHandNode(self): return self.find("**/joint_Lhold") def getHeadNode(self): return self.headModel def getUpperBodySubpart(self): return [None] def getLowerBodySubpart(self): return [None] def getMoveAction(self, forward, rotate, strafe): return 0 def enterPie(self, ts=0): self.play('pie') def exitPie(self): self.stop() def enterDrop(self, ts=0): self.play("drop") def exitDrop(self): self.stop() def enterDropReact(self, ts=0): self.play('drop-react') def exitDropReact(self): self.stop() def enterSoak(self, ts=0): self.play('soak') def exitSoak(self): self.stop() def enterSquirtSmall(self, ts=0): self.play('squirt-small') def exitSquirtSmall(self): self.stop() def enterStunned(self, animB4Stun, ts=0): self.show() if isinstance(animB4Stun, int): animB4Stun = SuitGlobals.getAnimById(animB4Stun).getName() self.stunnedSound = base.loadSfxOnNode( "phase_4/audio/sfx/SZ_TC_bird1.ogg", self) self.stunnedSound.setLoop(True) self.stunnedSound.play() self.stunnedIval = Parallel( Sequence(ActorInterval(self, animB4Stun), Func(self.loop, 'stunned')), SuitGlobals.createStunInterval(self, 0, 100)) self.stunnedIval.start() def clearStunnedIval(self): if hasattr(self, 'stunnedSound'): self.stunnedSound.stop() del self.stunnedSound if hasattr(self, 'stunnedIval'): self.stunnedIval.finish() del self.stunnedIval def exitStunned(self): self.clearStunnedIval() self.stop() def getLeftHand(self): return self.find("**/joint_Lhold") def getRightHand(self): return self.find("**/joint_Rhold") def getNametagJoints(self): return [] # BEGIN STATES def enterOff(self, ts=0): pass def exitOff(self): pass def exitGeneral(self): pass def enterTrayWalk(self, ts=0): self.show() self.loop('tray-walk') def exitTrayWalk(self): self.exitGeneral() def enterTrayNeutral(self, ts=0): self.loop('tray-neutral') def exitTrayNeutral(self): self.stop() def enterNeutral(self, ts=0): self.show() self.loop("neutral") def exitNeutral(self): self.exitTimestampAnimTrack() self.exitGeneral() def enterWalk(self, ts=0): self.show() self.loop("walk") self.enableRay() self.disableShadowRay() self.startFootsteps() def exitWalk(self): self.stopFootsteps() self.exitTimestampAnimTrack() self.exitGeneral() self.enableShadowRay() def enterFlail(self, ts=0): self.pingpong('flail', fromFrame=30, toFrame=35) def exitFlail(self): self.stop() def exitTimestampAnimTrack(self): if self.timestampAnimTrack: self.timestampAnimTrack.pause() self.timestampAnimTrack = None def enterFlyNeutral(self, ts=0): self.disableRay() self.enableShadowRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['neutral'] base.playSfx(sfx, node=self, looping=1) self.propeller.loop('chan', fromFrame=0, toFrame=3) self.setPlayRate(0.8, 'land') self.pingpong('land', fromFrame=0, toFrame=10) def exitFlyNeutral(self): self.cleanupPropeller() def enterFlyDown(self, ts=0): self.disableRay() self.enableShadowRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['in'] base.playSfx(sfx, node=self) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength waitTime = timeTillLanding - animTimeInAir lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyDown') else: name = 'enterFlyDown' animTrack = Sequence(Func(self.pose, 'land', 0), Wait(waitTime), ActorInterval(self, 'land', duration=dur)) propTrack = Parallel( SoundInterval(sfx, duration=waitTime + dur, node=self), Sequence( ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=waitTime + spinTime, startTime=0.0, endTime=spinTime), ActorInterval(self.propeller, 'chan', duration=propDur - openTime, startTime=openTime))) self.suitTrack = Parallel(animTrack, propTrack, name=self.taskName('flyDown')) if not self.hasSpawned: self.show() fadeInTrack = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency)) self.hasSpawned = True self.suitTrack.append(fadeInTrack) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyDown) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) def exitFlyDown(self): self.cleanupPropeller() self.enableRay() if self.suitTrack != None: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() def enterFlyAway(self, ts=0, doFadeOut=0): self.show() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['out'] if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyAway') else: name = 'enterFlyAway' dur = self.getDuration('land') actInt = ActorInterval(self, 'land', loop=0, startTime=dur, endTime=0.0) lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr propTrack = Parallel( SoundInterval(sfx, node=self), Sequence( Func(self.propeller.show), ActorInterval(self.propeller, 'chan', endTime=openTime, startTime=propDur), ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=propDur - openTime, startTime=spinTime, endTime=0.0))) self.suitTrack = Parallel(actInt, propTrack, name=self.taskName('trackName')) if doFadeOut: fadeOut = Sequence( Wait(4.0), Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, hidden)) self.suitTrack.append(fadeOut) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) self.disableRay() self.enableShadowRay() def exitFlyAway(self): self.cleanupPropeller() if self.suitTrack: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() def enterDie(self, ts=0): self.show() self.clearStunnedIval() self.generateCog(isLose=1) self.nametag.clearChatText() self.deleteNameTag() self.deathSound = base.audio3d.loadSfx( "phase_3.5/audio/sfx/Cog_Death_Full.ogg") base.audio3d.attachSoundToObject(self.deathSound, self) trackName = self.uniqueName('enterDie') smallGears = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionSmall.ptf') #smallGears.getParticlesNamed('particles-1').setPoolSize(30) singleGear = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') singleGear.getParticlesNamed('particles-1').setPoolSize(1) smallGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10) bigGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionBig.ptf') bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) gearPoint = self.getPos(render) + (0, 0, self.getHeight() - 0.2) self.smallGears = smallGears self.smallGears.setPos(gearPoint) self.singleGear = singleGear self.singleGear.setPos(gearPoint) self.smallGearExp = smallGearExplosion self.smallGearExp.setPos(gearPoint) self.bigGearExp = bigGearExplosion self.bigGearExp.setPos(gearPoint) gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp)) self.suitTrack = Parallel( Sequence(Wait(0.8), SoundInterval(self.deathSound, duration=4.28)), Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.5), Func(self.suitExplode), Wait(1.0), Func(self.disableBodyCollisions)), gearTrack, Sequence(ActorInterval(self, 'lose', duration=6), Func(self.getGeomNode().hide)), name=trackName) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getName(), self.exitDie) if self.isDistributed(): self.suitTrack.delayDelete = DelayDelete.DelayDelete( self, trackName) self.suitTrack.start(ts) def doSingleGear(self): self.singleGear.start(CIGlobals.getParticleRender()) def doSmallGears(self): self.smallGears.start(CIGlobals.getParticleRender()) def doSmallExp(self): self.smallGearExp.start(CIGlobals.getParticleRender()) def doBigExp(self): self.bigGearExp.start(CIGlobals.getParticleRender()) def suitExplode(self): pos = self.getPart('body').find('**/joint_head').getPos(render) + ( 0, 0, 2) # Force the loser suit to use UnlitGeneric shader, workaround for the has_mat() assertion BSPUtility.applyUnlitOverride(self) CIGlobals.makeExplosion(pos, 0.5, soundVol=0.32, smoke=False) def exitDie(self): if self.suitTrack != None: self.ignore(self.suitTrack.getName()) self.suitTrack.finish() if self.isDistributed(): DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'singleGear'): self.singleGear.softStop() del self.singleGear if hasattr(self, 'smallGears'): self.smallGears.softStop() del self.smallGears if hasattr(self, 'smallGearExp'): self.smallGearExp.softStop() del self.smallGearExp if hasattr(self, 'bigGearExp'): self.bigGearExp.softStop() del self.bigGearExp if self.deathSound: self.deathSound.stop() self.deathSound = None def enterWin(self, ts=0): self.play('win') def exitWin(self): self.exitGeneral() # END STATES def generateSuit(self, suitPlan, variant, voice=None, hideFirst=False): startTime = globalClock.getRealTime() self.suitPlan = suitPlan self.suit = suitPlan.getSuitType() self.head = suitPlan.getHead() self.dept = suitPlan.getDept() self.handColor = suitPlan.getHandColor() self.variant = variant self.setVoice(voice) self.generateCog() mat = CIGlobals.getCharacterMaterial(shininess=50.0, specular=(0.4, 0.4, 0.4, 1)) self.setMaterial(mat) #ts = TextureStage('shiny') #ts.setMode(TextureStage.MAdd) #ts.setRgbScale(2) #tex = loader.loadCubeMap('phase_14/maps/cubemap/defaultcubemap_#.png') #tex = loader.loadTexture('phase_14/maps/envmap001a_cog.png') #self.setTexGen(ts, TexGenAttrib.MEyeSphereMap) #self.setTexture(ts, tex) self.initializeBodyCollisions() if hideFirst: self.hide() else: self.show() endTime = globalClock.getRealTime() print("generateSuit took {0} ms".format((endTime - startTime) * 1000)) def __blinkRed(self, task): self.healthBar.setColor(SuitGlobals.healthColors[3], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(SuitGlobals.healthColors[4], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return task.done def generateHealthBar(self): self.removeHealthBar() button = loader.loadModel('phase_3.5/models/gui/matching_game_gui.bam' ).find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(SuitGlobals.healthColors[0]) chestNull = self.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button #self.healthBarGlow = loader.loadModel('phase_3.5/models/props/glow.bam') #self.healthBarGlow.reparentTo(self.healthBar) #self.healthBarGlow.setScale(0.28) #self.healthBarGlow.setPos(-0.005, 0.01, 0.015) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[0]) button.flattenLight() button.setLightOff() self.condition = 0 if hasattr(self, 'getHealth'): self.updateHealthBar(self.getHealth()) def updateHealthBar(self, hp): if not self.healthBar: return if hp > self.health: self.health = hp health = 0.0 try: health = float(hp) / float(self.maxHealth) except: pass if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: taskMgr.remove(self.taskName('blink-task')) if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(SuitGlobals.healthColors[condition], 1) #self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[condition], 1) self.condition = condition def removeHealthBar(self): if self.healthBar: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def initializeBodyCollisions(self): self.notify.info('Initializing Body Collisions!') self.setupPhysics(2, self.getHeight()) self.enableRay() def hideSuit(self): self.hide() def showSuit(self): self.show() fadeIn = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() def doStunEffect(self): self.clearStunnedIval() self.stunnedIval = SuitGlobals.createStunInterval(self, 0, 2) self.stunnedIval.start() def doGagEffect(self, flags): GagEffects.doGagEffect(self, flags) def generateCog(self, isLose=0, nameTag=True): #startTime = globalClock.getRealTime() generateCollector.start() cleanupCollector.start() self.cleanup() cleanupCollector.stop() if not isLose: if self.suitPlan in SuitBank.suitSetups: setup = SuitBank.suitSetups[self.suitPlan] else: setup = SuitBank.SuitSetup() SuitBank.suitSetups[self.suitPlan] = setup if not self.variant in setup.actor: setupActor = Actor() if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: setupActor.loadModel( 'phase_5/models/char/cog%s_robot-zero.bam' % (str(self.suit)), 'body') else: setupActor.loadModel( 'phase_3.5/models/char/suit%s-mod.bam' % (str(self.suit)), 'body') animations = SuitGlobals.animations anims = {} for anim in animations: if not self.suit in anim.getSuitTypes(): continue path = 'phase_%s/models/char/suit%s-%s.bam' % ( anim.getPhase(), self.suit, anim.getFile()) anims[anim.getName()] = path setupActor.loadAnims(anims, 'body') setup.actor[self.variant] = setupActor actorCollector.start() self.copyActor(setup.actor[self.variant]) actorCollector.stop() healthBarCollector.start() self.generateHealthBar() healthBarCollector.stop() footstepCollector.start() if self.suitPlan.suitType == SuitType.A: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogafssm.ogg") elif self.suitPlan.suitType == SuitType.B: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogbfssm.ogg") elif self.suitPlan.suitType == SuitType.C: self.footstepSound = base.audio3d.loadSfx( "phase_5/audio/sfx/ENC_cogcfssm.ogg") if self.footstepSound: base.audio3d.attachSoundToObject(self.footstepSound, self) self.footstepSound.setVolume(0.0) self.footstepSound.setLoop(True) self.footstepSound.play() footstepCollector.stop() else: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-lose-mod.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_4/models/char/suit%s-lose-mod.bam' % (str(self.suit)), 'body') self.loadAnims( { 'lose': 'phase_4/models/char/suit%s-lose.bam' % (str(self.suit)) }, 'body') genHeadCollector.start() if self.variant != Variant.SKELETON: self.headModel = self.head.generate() self.headModel.reparentTo(self.find("**/joint_head")) if self.suitPlan.getName() == SuitGlobals.VicePresident: self.headModel.setScale(0.35) self.headModel.setHpr(270, 0, 270) self.headModel.setZ(-0.10) self.headModel.loop('neutral') if self.variant == Variant.SKELETON: self.headModel = self.find("**/joint_head") #antenna = loader.loadModel("models/police_antenna.bam") ##antenna.reparentTo(self.find("**/joint_head")) #antenna.setPos(0.5, -0.5, 0) #antenna.setScale(1.25) #antenna.clearModelNodes() #antenna.flattenStrong() genHeadCollector.stop() self.setClothes() classScale = 1.0 #self.suitPlan.getCogClassAttrs().scaleMod self.setAvatarScale( (self.suitPlan.getScale() / SuitGlobals.scaleFactors[self.suit]) * classScale) self.setHeight(self.suitPlan.getHeight()) nametagCollector.start() if nameTag: self.setupNameTag() nametagCollector.stop() Avatar.initShadow(self) if self.variant != Variant.SKELETON: # We've already done all manipulating to the cog, we can just flatten it. self.getPart('body').flattenStrong() self.postFlatten() self.headModel.flattenStrong() if isinstance(self.headModel, Actor): self.headModel.postFlatten() #endTime = globalClock.getRealTime() #print("GenerateCog took {0} seconds".format(endTime - startTime)) generateCollector.stop() def cleanup(self): if self.footstepSound: self.footstepSound.stop() self.footstepSound = None self.cleanupPropeller() self.clearChatbox() if self.shadow: self.deleteShadow() if self.headModel: self.headModel.removeNode() self.headModel = None if self.getPart('body'): self.removePart('body') self.timestampAnimTrack = None def generatePropeller(self): self.cleanupPropeller() self.propeller = Actor( 'phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.propeller.reparentTo(self.find("**/joint_head")) self.propellerSounds['in'] = base.audio3d.loadSfx( SuitGlobals.propellerInSfx) self.propellerSounds['out'] = base.audio3d.loadSfx( SuitGlobals.propellerOutSfx) self.propellerSounds['neutral'] = base.audio3d.loadSfx( SuitGlobals.propellerNeutSfx) for sound in self.propellerSounds.values(): base.audio3d.attachSoundToObject(sound, self.propeller) def cleanupPropeller(self): for sound in self.propellerSounds.values(): base.audio3d.detachSound(sound) sound.stop() self.propellerSounds = {} if self.propeller and not self.propeller.isEmpty(): self.propeller.cleanup() self.propeller = None def setVoice(self, voice): if not voice: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.voice = Voice.SKELETON else: self.voice = Voice.NORMAL else: self.voice = voice if self.variant == Variant.SKELETON: head = self else: head = self.headModel self.addSound("statement", self.voice.getSoundFile('statement'), node=head) self.addSound("grunt", self.voice.getSoundFile('grunt'), node=head) self.addSound("question", self.voice.getSoundFile('question'), node=head) if self.voice == Voice.NORMAL: self.addSound("question2", self.voice.getSoundFile('question_2'), node=head) self.chatSoundTable[CHAT_SHORT] = "statement" self.chatSoundTable[CHAT_MEDIUM] = "statement" self.chatSoundTable[CHAT_LONG] = "statement" self.chatSoundTable[CHAT_EXCLAIM] = "grunt" self.chatSoundTable[CHAT_HOWL] = "statement" if self.voice == Voice.NORMAL: self.chatSoundTable[CHAT_QUESTION] = ["question", "question2"] else: self.chatSoundTable[CHAT_QUESTION] = "question" def setClothes(self): setClothesCollector.start() if self.variant == Variant.SKELETON: parts = self.findAllMatches('**/pPlane*') for partNum in range(0, parts.getNumPaths()): bb = parts.getPath(partNum) bb.setTwoSided(1) tie = 'phase_5/maps/cog_robot_tie_%s.mat' % self.dept.getTie() #tie.setMinfilter(Texture.FTLinearMipmapLinear) #tie.setMagfilter(Texture.FTLinear) self.find('**/tie').setBSPMaterial(tie, 1) else: texture = 'phase_3.5/maps/tt_t_ene_' + self.dept.getName().lower( ) + '.mat' #texture = 'materials/models/suit/tt_t_ene_police.mat' #if self.variant == Variant.WAITER: # prefix = 'phase_3.5/maps/waiter_m_%s.mat' #elif self.variant == Variant.CORRODED: # prefix = 'phase_3.5/maps/' + self.dept.getClothingPrefix() + '_rust_%s.mat' #legTex = prefix % 'leg' #armTex = prefix % 'sleeve' #blazTex = prefix % 'blazer' #texs = [legTex, armTex, blazTex] #for texture in texs: # texture.setMinfilter(Texture.FTLinearMipmapLinear) # texture.setMagfilter(Texture.FTLinear) #self.find('**/legs').setBSPMaterial(legTex, 1) #self.find('**/arms').setBSPMaterial(armTex, 1) #self.find('**/torso').setBSPMaterial(blazTex, 1) #self.find('**/hands').setBSPMaterial("phase_3.5/maps/tt_t_ene_sellbotRental_hand.mat", 1) body = self.getPart('body') for child in body.getChildren(): if isinstance(child.node(), GeomNode): child.setBSPMaterial(texture, 1) if not self.variant == Variant.CORRODED: self.find('**/hands').setColor(self.handColor) else: self.find('**/hands').setColor(Variant.CORRODED_HAND_COLOR) setClothesCollector.stop() def startFootsteps(self): classAttrs = self.suitPlan.getCogClassAttrs() if not self.footstepSound or not classAttrs.footsteps: return self.footstepSound.setPlayRate(classAttrs.walkMod) self.footstepSound.setLoop(True) self.footstepSound.play() def stopFootsteps(self): if not self.footstepSound: return self.footstepSound.stop() def setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed=0.0): Avatar.setSpeed(self, forwardSpeed, rotateSpeed, strafeSpeed) currSpeed = self.currentSpeed if self.doingActivity: currSpeed = 0 if self.footstepSound and self.standWalkRunReverse is not None: action = self.getMoveAction(forwardSpeed, rotateSpeed, strafeSpeed) minSpeed = self.standWalkRunReverse[action][2] maxSpeed = self.standWalkRunReverse[action][3] self.footstepSound.setVolume( CIGlobals.clamp( CIGlobals.remapVal(currSpeed, minSpeed, maxSpeed, 0, 1), 0, 1)) self.footstepSound.setPlayRate(max(1, currSpeed / maxSpeed)) def setName(self, nameString, charName): Avatar.setName(self, nameString, charName=charName, createNow=1) def setupNameTag(self, tempName=None): Avatar.setupNameTag(self, tempName=tempName) if self.nametag: if self.level > 0: self.nametag.setText(self.nametag.getText() + '\n%s\nLevel %s %s' % (self.dept.getName(), self.level, self.suitPlan.getCogClassName())) else: self.nametag.setText(self.nametag.getText() + '\n%s' % (self.dept.getName())) def clearChatbox(self): self.clearChat() self.chat = None if self.chatDial: base.audio3d.detachSound(self.chatDial) self.chatDial.stop() self.chatDial = None def getDept(self): return self.dept def getVariant(self): return self.variant def disable(self): if self.suitTrack: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.animFSM.requestFinalState() self.cleanup() Avatar.disable(self) def delete(self): Avatar.delete(self) self.cleanup()
class BRWater: notify = directNotify.newCategory('BRWater') def __init__(self, playground): self.playground = playground self.fsm = ClassicFSM('BRWater', [State('off', self.enterOff, self.exitOff), State('freezeUp', self.enterFreezeUp, self.exitFreezeUp), State('coolDown', self.enterCoolDown, self.exitCoolDown), State('frozen', self.enterFrozen, self.exitFrozen)], 'off', 'off') self.fsm.enterInitialState() self.freezeUpSfx = base.loadSfx('phase_8/audio/sfx/freeze_up.mp3') self.frozenSfxArray = [base.loadSfx('phase_8/audio/sfx/frozen_1.mp3'), base.loadSfx('phase_8/audio/sfx/frozen_2.mp3'), base.loadSfx('phase_8/audio/sfx/frozen_3.mp3')] self.coolSfxArray = [base.loadSfx('phase_8/audio/sfx/cool_down_1.mp3'), base.loadSfx('phase_8/audio/sfx/cool_down_2.mp3')] self.freezeUpSfx.setVolume(12) for sfx in self.frozenSfxArray: sfx.setVolume(12) for sfx in self.coolSfxArray: sfx.setVolume(12) def attachSound(self, sound): base.localAvatar.audio3d.attachSoundToObject(sound, base.localAvatar) def enterOff(self): self.playground.startWaterWatch() def exitOff(self): self.playground.stopWaterWatch() def loadIceCube(self): self.iceCube = loader.loadModel('phase_8/models/props/icecube.bam') for node in self.iceCube.findAllMatches('**/billboard*'): node.removeNode() for node in self.iceCube.findAllMatches('**/drop_shadow*'): node.removeNode() for node in self.iceCube.findAllMatches('**/prop_mailboxcollisions*'): node.removeNode() self.iceCube.reparentTo(base.localAvatar) self.iceCube.setScale(1.2, 1.0, base.localAvatar.getHeight() / 1.7) self.iceCube.setTransparency(1) self.iceCube.setColorScale(0.76, 0.76, 1.0, 0.0) def unloadIceCube(self): self.iceCube.removeNode() del self.iceCube def enterFreezeUp(self): length = 1.0 base.playSfx(self.freezeUpSfx) self.fucsIval = Sequence(LerpColorScaleInterval(base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(0.5, 0.5, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'frozen')) self.fucsIval.start() self.playground.startWaterWatch(0) def exitFreezeUp(self): self.fucsIval.pause() del self.fucsIval self.playground.stopWaterWatch() def enterFrozen(self): self.loadIceCube() base.cr.playGame.getPlace().fsm.request('stop', [0]) base.localAvatar.stop() base.playSfx(choice(self.frozenSfxArray)) self.iccsIval = LerpColorScaleInterval(self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 1.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccsIval.start() props = WindowProperties() props.setCursorHidden(True) base.win.requestProperties(props) self.frame = DirectFrame(pos=(0, 0, 0.7)) self.powerBar = DirectWaitBar(frameColor=(1, 1, 1, 1), range=100, value=0, scale=(0.4, 0.5, 0.25), parent=self.frame, barColor=(0.55, 0.7, 1.0, 1.0)) self.label = OnscreenText(text='SHAKE MOUSE', shadow=(0, 0, 0, 1), fg=(0.55, 0.7, 1.0, 1.0), pos=(0, -0.1, 0), parent=self.frame) taskMgr.add(self.__watchMouseMovement, 'BRWater-watchMouseMovement') taskMgr.add(self.__lowerPowerBar, 'BRWater-lowerPowerBar') mw = base.mouseWatcherNode if mw.hasMouse(): self.lastMouseX = mw.getMouseX() def __lowerPowerBar(self, task): if self.powerBar['value'] <= 0: self.powerBar.update(0) decrement = 1 self.powerBar.update(self.powerBar['value'] - decrement) task.delayTime = 0.1 return task.again def __watchMouseMovement(self, task): if self.powerBar['value'] >= self.powerBar['range']: self.fsm.request('coolDown', [1]) return task.done mw = base.mouseWatcherNode if mw.hasMouse(): if not self.lastMouseX or self.lastMouseX != mw.getMouseX(): value = 3 * self.lastMouseX - mw.getMouseX() self.lastMouseX = mw.getMouseX() self.powerBar.update(self.powerBar['value'] + abs(value)) return task.cont def exitFrozen(self): props = WindowProperties() props.setCursorHidden(False) base.win.requestProperties(props) self.iccsIval.pause() del self.iccsIval self.unloadIceCube() taskMgr.remove('BRWater-lowerPowerBar') taskMgr.remove('BRWater-watchMouseMovement') self.label.destroy() del self.label self.powerBar.destroy() del self.powerBar self.frame.destroy() del self.frame del self.lastMouseX base.cr.playGame.getPlace().fsm.request('walk') base.localAvatar.b_setAnimState('neutral') def enterCoolDown(self, fromFrozen = 0): if fromFrozen: self.loadIceCube() self.iceCube.setColorScale(0.76, 0.76, 1.0, 1.0) self.iccdIval = LerpColorScaleInterval(self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 0.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccdIval.start() length = 1.0 base.playSfx(choice(self.coolSfxArray)) self.cdcsIval = Sequence(LerpColorScaleInterval(base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(1.0, 1.0, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'off')) self.cdcsIval.start() def exitCoolDown(self): if hasattr(self, 'iccdIval'): self.iccdIval.pause() del self.iccdIval self.unloadIceCube() self.cdcsIval.pause() del self.cdcsIval def cleanup(self): self.fsm.requestFinalState() self.playground.stopWaterWatch() del self.fsm del self.freezeUpSfx del self.frozenSfxArray del self.coolSfxArray del self.playground
class RaceGameMovement(DirectObject): MINIMUM_POWER = 0.3 MINIMUM_KEY_DELAY = 0.015 POWER_FACTOR = 2.5 defaultBoostBarColor = (0.4, 0.4, 0.7, 1.0) fullBoostBarColor = (0.0, 0.0, 0.7, 1.0) def __init__(self, avatar): DirectObject.__init__(self) self.avatar = avatar self.power = self.MINIMUM_POWER self.boost = 0.0 self.fsm = ClassicFSM('RaceGameMovement', [State('off', self.enterOff, self.exitOff, ['run']), State('run', self.enterRun, self.exitRun, ['fall', 'off']), State('fall', self.enterFall, self.exitFall, ['run', 'off']), State('final', self.enterFinal, self.exitFinal)], 'off', 'final') self.fsm.enterInitialState() self.boostFSM = ClassicFSM('Boost', [State('off', self.enterBoostOff, self.exitBoostOff, ['boost']), State('boost', self.enterBoost, self.exitBoost)], 'off', 'off') self.boostFSM.enterInitialState() self.keysPressed = {'arrow_left': 0, 'arrow_right': 0} self.startTime = 0.0 self.endTime = 0.0 self.fallTrack = None self.isStopped = True self.isBoosting = False return def setBoosting(self, value): self.isBoosting = value def getBoosting(self): return self.isBoosting def enterBoostOff(self): self.ignore('control') def exitBoostOff(self): pass def createGui(self): """ Create the GUI that will tell the client how much running power they have. """ self.powerFrame = DirectFrame() self.powerBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(1.02, 0, 0.7), parent=self.powerFrame, color=CIGlobals.DialogColor) self.powerBar = DirectWaitBar(barColor=(0, 0.7, 0, 1), range=20.0, value=0, parent=self.powerFrame, scale=(0.15, 0, 1.1), pos=(1.02, 0, 0.66)) self.powerBar.setR(-90) self.powerTitle = DirectLabel(text='POWER', text_scale=0.08, pos=(1.02, 0, 0.85), relief=None, parent=self.powerFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFrame = DirectFrame() self.boostBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(0.45, 0, 0.7), parent=self.boostFrame, color=CIGlobals.DialogColor) self.boostBar = DirectWaitBar(barColor=self.defaultBoostBarColor, range=10, value=0, parent=self.boostFrame, scale=(0.15, 0, 1.1), pos=(0.45, 0, 0.66)) self.boostBar.setR(-90) self.boostTitle = DirectLabel(text='BOOST', text_scale=0.08, pos=(0.45, 0, 0.85), relief=None, parent=self.boostFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFullLbl = DirectLabel(text='BOOST READY', text_scale=0.065, pos=(0.45, 0, 0.3), relief=None, parent=self.boostFrame, text_fg=self.fullBoostBarColor, text_shadow=(0.4, 0.4, 0.4, 1.0), text_font=CIGlobals.getToonFont()) self.boostFullLbl.hide() return def deleteGui(self): """ Delete the GUI that will tell the client how much running power they have. """ self.powerFrame.destroy() self.powerBg.destroy() self.powerBar.destroy() self.powerTitle.destroy() self.boostFrame.destroy() self.boostBg.destroy() self.boostBar.destroy() self.boostTitle.destroy() self.boostFullLbl.destroy() def enableArrowKeys(self): """ Enable the arrow keys to increase movement power. """ self.accept('arrow_left', self.keyPressed, ['arrow_left']) self.accept('arrow_right', self.keyPressed, ['arrow_right']) def disableArrowKeys(self): """ Disable the arrow keys to increase movement power. """ self.ignore('arrow_left') self.ignore('arrow_right') def boostKeyPressed(self): self.boostFullLbl.hide() self.boostFSM.request('boost') def keyPressed(self, key): """ Figure out which key was pressed and increment the movement power if the values of both keys are 1. Also, make the avatar fall down if the time between key presses is too fast or the avatar pressed the same key more than once.""" self.stopDelayTimer() if self.keysPressed[key] == 1 or self.isTooFast(): self.resetKeys() self.fsm.request('fall') return self.keysPressed[key] = 1 if self.keysPressed['arrow_left'] == 1 and self.keysPressed['arrow_right'] == 1: self.resetKeys() self.changePower() self.restartDelayTimer() def enterBoost(self): self.disableArrowKeys() self.resetKeys() base.localAvatar.b_setAnimState('swim') self.power = 30.0 taskMgr.add(self.boostTask, 'boostTask') self.boostSfx = base.loadSfx('phase_6/audio/sfx/KART_turboLoop.wav') base.playSfx(self.boostSfx, looping=1) def exitBoost(self): self.enableArrowKeys() base.localAvatar.b_setAnimState('run') self.power = 17.0 taskMgr.remove('boostTask') self.boostSfx.stop() del self.boostSfx def boostTask(self, task): if self.boostBar['value'] <= 0.0: self.boostFSM.request('off') self.boostBar['barColor'] = self.defaultBoostBarColor return task.done self.boostBar['value'] -= 0.3 task.delayTime = 0.05 return task.again def enterFall(self): """ The avatar is pressing his arrow keys too fast. Stop running and make the avatar fall down. """ self.avatar.b_setAnimState('fallFWD') self.fallTrack = Sequence(Wait(2.5), Func(self.fsm.request, 'run')) self.fallTrack.start() def exitFall(self): self.fallTrack.pause() self.fallTrack = None return def isTooFast(self): """ Determine if the delay between key presses in seconds is too low. """ return self.getDelayTime() < self.MINIMUM_KEY_DELAY def resetKeys(self): """ Reset the value of the keys. """ for key in self.keysPressed: self.keysPressed[key] = 0 def changePower(self): """ Increase the avatar's movement power. """ self.power = self.POWER_FACTOR / self.getDelayTime() if self.boostBar['barColor'] != self.fullBoostBarColor: if self.power >= self.powerBar['range']: self.boostBar['value'] += 0.8 if self.boostBar['value'] >= self.boostBar['range']: self.boostBar['barColor'] = self.fullBoostBarColor self.boostFullLbl.show() self.acceptOnce('control', self.boostKeyPressed) print self.power self.powerBar.update(self.power) def startDelayTimer(self): self.startTime = globalClock.getFrameTime() def stopDelayTimer(self): self.endTime = globalClock.getFrameTime() def resetDelayTimer(self): self.startTime = 0.0 self.endTime = 0.0 def restartDelayTimer(self): self.stopDelayTimer() self.resetDelayTimer() self.startDelayTimer() def getDelayTime(self): return self.endTime - self.startTime def enterRun(self): """ Start moving the avatar, make the avatar run, and start tracking the delay between key presses. """ taskMgr.add(self.move, 'move') if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.show() self.acceptOnce('control', self.boostKeyPressed) self.startDelayTimer() self.enableArrowKeys() self.avatar.b_setAnimState('run') self.isStopped = False def exitRun(self): """ Stop moving the avatar, make the avatar stand, and stop tracking the delay between key presses. """ taskMgr.remove('move') self.boostFSM.request('off') if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.hide() self.ignore('control') self.stopDelayTimer() self.resetDelayTimer() self.disableArrowKeys() self.avatar.b_setAnimState('neutral') self.isStopped = True self.power = self.MINIMUM_POWER self.powerBar.update(0) def enterOff(self): pass def exitOff(self): pass def enterFinal(self): pass def exitFinal(self): pass def decreasePower(self, task): """ Decrease power so the avatar does not keep the same amount of power while not tapping the arrow keys. """ if self.power > self.MINIMUM_POWER: self.power -= self.POWER_FACTOR / 0.01 if self.power < self.MINIMUM_POWER: self.power = self.MINIMUM_POWER task.delayTime = 0.5 return Task.again def move(self, task): """ Move the avatar forward on the Y axis with the current amount of power. """ dt = globalClock.getDt() self.avatar.setY(self.avatar.getY() + self.power * dt) return Task.cont def cleanup(self): self.fsm.requestFinalState()
class CameraShyFirstPerson(FirstPerson): notify = directNotify.newCategory("CameraShyFirstPerson") defaultColor = VBase4(1.0, 1.0, 1.0, 1.0) toonInFocusColor = VBase4(0.0, 0.7, 0.0, 1.0) toonOutOfFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) redColor = VBase4(0.8, 0.0, 0.0, 1.0) batteryLevelTwoColor = VBase4(0.9, 0.36, 0.0, 1.0) batteryLevelThreeColor = VBase4(0.9, 0.9, 0.0, 1.0) batteryLevelFourColor = VBase4(1.0, 1.0, 0.0, 1.0) batteryLevelFiveColor = VBase4(0.0, 1.0, 0.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.viewfinder = None self.camFSM = ClassicFSM('CameraFSM', [ State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge) ], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce("mouse1", self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None def __mouse1Pressed(self): self.cameraFlashSeq = Sequence( Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() self.viewfinder['image'].setColorScale(self.defaultColor) picData = self.viewfinder.takePictureRaw() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore("mouse1") def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, "rechargeCamera") def __rechargeNextState(self, task): if self.cameraRechargeState is None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) if self.cameraRechargeState <= 1: self.batteryBar.setColorScale(self.redColor) elif self.cameraRechargeState == 2: self.batteryBar.setColorScale(self.batteryLevelTwoColor) elif self.cameraRechargeState == 3: self.batteryBar.setColorScale(self.batteryLevelThreeColor) elif self.cameraRechargeState == 4: self.batteryBar.setColorScale(self.batteryLevelFourColor) else: self.batteryBar.setColorScale(self.batteryLevelFiveColor) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove("rechargeCamera") self.cameraRechargeState = None def __traverse(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont toonInFoc = False avatar = None for av in self.mg.remoteAvatars: if av.avId != base.localAvatar.doId: if self.viewfinder.isInView(av): self.notify.info("{0} is in our view finder".format( av.avId)) avatar = self.mg.cr.doId2do.get(av.avId) break if avatar: remoteAvatar = self.mg.getRemoteAvatar(avatar.doId) if remoteAvatar: toonInFoc = True self.notify.info("We've got an avatar in focus ({0})".format( avatar.doId)) self.__handleToonInFocus(avatar) if not toonInFoc: self.toonToTakePicOf = None self.hasToonInFocus = False self.notify.info("No avatar in focus") if self.viewfinder['image'].getColorScale( ) == self.toonInFocusColor: self.viewfinder['image'].setColorScale( self.toonOutOfFocusColor) return task.cont def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.viewfinder['image'].setColorScale(self.toonInFocusColor) def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/ring_get.ogg') self.rechargeSound = base.loadSfx( 'phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.ogg') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage( image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBg.setColorScale(0, 0, 0, 1) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.viewfinder = Viewfinder(1.0) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) def reallyStart(self): taskMgr.add(self.__traverse, "CSFP.__traverse") self.camFSM.request('recharge') #taskMgr.add(self.movementTask, "movementTask") base.localAvatar.startTrackAnimToSpeed() FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove("movementTask") taskMgr.remove("CSFP.__traverse") FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.viewfinder.cleanup() self.viewfinder = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self)
class RaceGameMovement(DirectObject): MINIMUM_POWER = 0.3 MINIMUM_KEY_DELAY = 0.015 POWER_FACTOR = 2.5 defaultBoostBarColor = (0.4, 0.4, 0.7, 1.0) fullBoostBarColor = (0.0, 0.0, 0.7, 1.0) RUN_FACTOR = 20.0 RUN_MAX = 1.0 RUN_PR_FACTOR = 1.2 def __init__(self, avatar): DirectObject.__init__(self) self.avatar = avatar self.power = self.MINIMUM_POWER self.boost = 0.0 self.fsm = ClassicFSM('RaceGameMovement', [ State('off', self.enterOff, self.exitOff, ['run']), State('run', self.enterRun, self.exitRun, ['fall', 'off']), State('fall', self.enterFall, self.exitFall, ['run', 'off']), State('final', self.enterFinal, self.exitFinal) ], 'off', 'final') self.fsm.enterInitialState() self.boostFSM = ClassicFSM('Boost', [ State('off', self.enterBoostOff, self.exitBoostOff, ['boost']), State('boost', self.enterBoost, self.exitBoost) ], 'off', 'off') self.boostFSM.enterInitialState() self.keysPressed = {"arrow_left": 0, "arrow_right": 0} self.startTime = 0.0 self.endTime = 0.0 self.fallTrack = None self.isStopped = True self.isBoosting = False return def setBoosting(self, value): self.isBoosting = value def getBoosting(self): return self.isBoosting def enterBoostOff(self): self.ignore("control") def exitBoostOff(self): pass def createGui(self): """ Create the GUI that will tell the client how much running power they have. """ self.powerFrame = DirectFrame() self.powerBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(1.02, 0, 0.7), parent=self.powerFrame, color=CIGlobals.DialogColor) self.powerBar = DirectWaitBar(barColor=(0, 0.7, 0, 1), range=20.0, value=0, parent=self.powerFrame, scale=(0.15, 0, 1.1), pos=(1.02, 0, 0.66)) self.powerBar.setR(-90) self.powerTitle = DirectLabel(text="POWER", text_scale=0.08, pos=(1.02, 0, 0.85), relief=None, parent=self.powerFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFrame = DirectFrame() self.boostBg = OnscreenImage(image=DGG.getDefaultDialogGeom(), scale=(0.5, 1.0, 0.5), pos=(0.45, 0, 0.7), parent=self.boostFrame, color=CIGlobals.DialogColor) self.boostBar = DirectWaitBar(barColor=self.defaultBoostBarColor, range=10, value=0, parent=self.boostFrame, scale=(0.15, 0, 1.1), pos=(0.45, 0, 0.66)) self.boostBar.setR(-90) self.boostTitle = DirectLabel(text="BOOST", text_scale=0.08, pos=(0.45, 0, 0.85), relief=None, parent=self.boostFrame, text_fg=(1, 1, 0, 1), text_font=CIGlobals.getMickeyFont()) self.boostFullLbl = DirectLabel(text="BOOST READY", text_scale=0.065, pos=(0.45, 0, 0.3), relief=None, parent=self.boostFrame, text_fg=self.fullBoostBarColor, text_shadow=(0.4, 0.4, 0.4, 1.0), text_font=CIGlobals.getToonFont()) self.boostFullLbl.hide() def deleteGui(self): """ Delete the GUI that will tell the client how much running power they have. """ self.powerFrame.destroy() self.powerBg.destroy() self.powerBar.destroy() self.powerTitle.destroy() self.boostFrame.destroy() self.boostBg.destroy() self.boostBar.destroy() self.boostTitle.destroy() self.boostFullLbl.destroy() def enableArrowKeys(self): """ Enable the arrow keys to increase movement power. """ self.accept("arrow_left", self.keyPressed, ["arrow_left"]) self.accept("arrow_right", self.keyPressed, ["arrow_right"]) def disableArrowKeys(self): """ Disable the arrow keys to increase movement power. """ self.ignore("arrow_left") self.ignore("arrow_right") def boostKeyPressed(self): self.boostFullLbl.hide() self.boostFSM.request('boost') def keyPressed(self, key): """ Figure out which key was pressed and increment the movement power if the values of both keys are 1. Also, make the avatar fall down if the time between key presses is too fast or the avatar pressed the same key more than once.""" self.stopDelayTimer() if self.keysPressed[key] == 1 or self.isTooFast(): self.resetKeys() self.fsm.request('fall') return self.keysPressed[key] = 1 if self.keysPressed["arrow_left"] == 1 and self.keysPressed[ "arrow_right"] == 1: self.resetKeys() self.changePower() self.restartDelayTimer() def enterBoost(self): self.disableArrowKeys() self.resetKeys() base.localAvatar.b_setAnimState("swim") self.power = 30.0 taskMgr.add(self.boostTask, 'boostTask') self.boostSfx = base.loadSfx("phase_6/audio/sfx/KART_turboLoop.ogg") base.playSfx(self.boostSfx, looping=1) def exitBoost(self): self.enableArrowKeys() base.localAvatar.b_setAnimState("run") self.power = 17.0 taskMgr.remove('boostTask') self.boostSfx.stop() del self.boostSfx def boostTask(self, task): if self.boostBar['value'] <= 0.0: self.boostFSM.request('off') self.boostBar['barColor'] = self.defaultBoostBarColor return task.done self.boostBar['value'] -= 0.3 task.delayTime = 0.05 return task.again def enterFall(self): """ The avatar is pressing his arrow keys too fast. Stop running and make the avatar fall down. """ self.avatar.b_setAnimState("fallFWD") self.fallTrack = Sequence(Wait(2.5), Func(self.fsm.request, "run")) self.fallTrack.start() def exitFall(self): self.fallTrack.pause() self.fallTrack = None def isTooFast(self): """ Determine if the delay between key presses in seconds is too low. """ return (self.getDelayTime() < self.MINIMUM_KEY_DELAY) def resetKeys(self): """ Reset the value of the keys. """ for key in self.keysPressed: self.keysPressed[key] = 0 def changePower(self): """ Increase the avatar's movement power. """ self.power = self.POWER_FACTOR / self.getDelayTime() if self.boostBar['barColor'] != self.fullBoostBarColor: if self.power >= self.powerBar['range']: self.boostBar['value'] += 0.8 if self.boostBar['value'] >= self.boostBar['range']: self.boostBar['barColor'] = self.fullBoostBarColor self.boostFullLbl.show() self.acceptOnce("control", self.boostKeyPressed) self.powerBar.update(self.power) def startDelayTimer(self): self.startTime = globalClock.getFrameTime() def stopDelayTimer(self): self.endTime = globalClock.getFrameTime() def resetDelayTimer(self): self.startTime = 0.0 self.endTime = 0.0 def restartDelayTimer(self): self.stopDelayTimer() self.resetDelayTimer() self.startDelayTimer() def getDelayTime(self): return self.endTime - self.startTime def enterRun(self): """ Start moving the avatar, make the avatar run, and start tracking the delay between key presses. """ self.avatar.enableBlend() self.avatar.setControlEffect('neutral', self.RUN_MAX) self.avatar.setControlEffect('run', 0.0) self.avatar.loop('run') self.avatar.loop('neutral') taskMgr.add(self.move, "move") if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.show() self.acceptOnce("control", self.boostKeyPressed) self.startDelayTimer() self.enableArrowKeys() self.isStopped = False def exitRun(self): """ Stop moving the avatar, make the avatar stand, and stop tracking the delay between key presses. """ taskMgr.remove("move") self.boostFSM.request('off') if self.boostBar['barColor'] == self.fullBoostBarColor: self.boostFullLbl.hide() self.ignore("control") self.stopDelayTimer() self.resetDelayTimer() self.disableArrowKeys() self.avatar.disableBlend() self.isStopped = True self.avatar.setPlayRate(1.0, 'run') self.power = self.MINIMUM_POWER self.powerBar.update(0) def enterOff(self): pass def exitOff(self): pass def enterFinal(self): pass def exitFinal(self): pass def decreasePower(self, task): """ Decrease power so the avatar does not keep the same amount of power while not tapping the arrow keys. """ if self.power > self.MINIMUM_POWER: self.power -= self.POWER_FACTOR / 0.01 if self.power < self.MINIMUM_POWER: self.power = self.MINIMUM_POWER task.delayTime = 0.5 return Task.again def move(self, task): """ Move the avatar forward on the Y axis with the current amount of power. """ dt = globalClock.getDt() runEffectRaw = self.power / self.RUN_FACTOR runEffect = min(self.RUN_MAX, runEffectRaw) neutralEffect = self.RUN_MAX - runEffect self.avatar.setControlEffect('run', runEffect) self.avatar.setControlEffect('neutral', neutralEffect) if runEffectRaw > self.RUN_MAX: print runEffectRaw self.avatar.setPlayRate(runEffectRaw * self.RUN_PR_FACTOR, 'run') else: self.avatar.setPlayRate(1.0, 'run') self.avatar.setY(self.avatar.getY() + self.power * dt) return Task.cont def cleanup(self): self.fsm.requestFinalState()
class DistributedRaceGame(DistributedMinigame.DistributedMinigame): def __init__(self, cr): try: self.DistributedRaceGame_initialized return except: self.DistributedRaceGame_initialized = 1 DistributedMinigame.DistributedMinigame.__init__(self, cr) self.movement = RaceGameMovement.RaceGameMovement(base.localAvatar) self.skyUtil = SkyUtil() self.raceFSM = ClassicFSM('DistributedRaceGame', [State('race', self.enterRace, self.exitRace), State('raceTransition', self.enterRaceTransition, self.exitRaceTransition), State('off', self.enterRaceOff, self.exitRaceOff)], 'off', 'off') self.raceFSM.enterInitialState() self.cr = cr self.track = None self.sky = None self.countSfx = base.loadSfx('phase_5/audio/sfx/firehydrant_popup.mp3') self.goSfx = base.loadSfx('phase_4/audio/sfx/AA_sound_whistle.mp3') self.game = CIGlobals.RaceGame self.trackPath = 'phase_4/models/minigames/sprint_track.egg' self.skyPath = 'phase_3.5/models/props/TT_sky.bam' self.lanePos = [(-22.0, -205.0, 0.0), (-11.66, -205.0, 0.0), (0.0, -205.0, 0.0), (-33.66, -205.0, 0.0)] self.initialCamPos = {'pos': (41.1, -145.0, 25.88), 'hpr': (135.0, 345.96, 0.0)} self.raceCamPos = (-24.52, -37.22, 25.0) self.lane = 0 return def load(self): self.deleteWorld() self.track = loader.loadModel(self.trackPath) self.track.reparentTo(render) self.sky = loader.loadModel(self.skyPath) self.sky.reparentTo(self.track) self.skyUtil.startSky(self.sky) self.setMinigameMusic('phase_4/audio/bgm/MG_toontag.mid') self.setDescription('Tap the left and right arrow keys repeatedly, in turns, as fast as ' + 'you can to win the race! Every time your power bar hits the top, the boost bar starts' + ' to fill. When the boost bar is full, press CTRL to boost for a few seconds.') self.setWinnerPrize(20) self.setLoserPrize(5) self.d_requestToonLane() camera.reparentTo(render) camera.setPos(self.initialCamPos['pos']) camera.setHpr(self.initialCamPos['hpr']) DistributedMinigame.DistributedMinigame.load(self) def enterPlay(self): DistributedMinigame.DistributedMinigame.enterPlay(self) self.raceFSM.request('raceTransition') def exitPlay(self): DistributedMinigame.DistributedMinigame.exitPlay(self) self.raceFSM.request('off') def enterRace(self): self.startMovement() def exitRace(self): self.stopMovement() def enterRaceOff(self): pass def exitRaceOff(self): pass def enterRaceTransition(self): self.raceTrans = Sequence(Wait(0.5), Func(self.moveCameraToToon), Wait(4.5), Func(self.moveCameraToTop), Wait(4.5), Func(self.startCountdown)) self.raceTrans.start() def exitRaceTransition(self): self.raceTrans.pause() del self.raceTrans def startMovement(self): self.movement.createGui() self.movement.fsm.request('run') def enterGameOver(self, winner = 0, winnerDoId = 0, allPrize = 0): self.raceFSM.request('off') DistributedMinigame.DistributedMinigame.enterGameOver(self, winner, winnerDoId, allPrize) def stopMovement(self): self.movement.cleanup() self.movement.deleteGui() def startCountdown(self): """ Start the countdown to the start of the race. """ self.countdownLbl = DirectLabel(text='', text_scale=0.3, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 1, 0, 1), pos=(0, 0, 0.5)) Sequence(Func(self.setCountdownText, '3'), Wait(1.0), Func(self.setCountdownText, '2'), Wait(1.0), Func(self.setCountdownText, '1'), Wait(1.0), Func(self.setCountdownText, 'GO!'), Wait(1.5), Func(self.deleteCountdownLabel)).start() def setCountdownText(self, number): self.countdownLbl['text'] = number if number == 'GO!': self.countdownLbl['text_fg'] = (0, 1, 0, 1) self.goSfx.play() self.raceFSM.request('race') else: self.countSfx.play() def deleteCountdownLabel(self): self.countdownLbl.destroy() del self.countdownLbl def moveCameraToToon(self): camPInt = LerpPosInterval(camera, duration=3.0, pos=self.localAv.getPos(render) + (0, 15, 3), startPos=camera.getPos(render), blendType='easeInOut') camQInt = camera.quatInterval(3.0, hpr=Vec3(180, 0, 0), blendType='easeInOut') camPInt.start() camQInt.start() def moveCameraToTop(self): camera.setPos(camera.getPos(self.localAv)) camera.reparentTo(self.localAv) oldPos = camera.getPos() camera.setPos(self.raceCamPos) oldHpr = camera.getHpr() camera.lookAt(self.localAv.getPart('head')) newHpr = camera.getHpr() camera.setHpr(oldHpr) camera.setPos(oldPos) camPInt = LerpPosInterval(camera, duration=3.0, pos=self.raceCamPos, startPos=oldPos, blendType='easeInOut') camQInt = camera.quatInterval(3.0, hpr=newHpr, blendType='easeInOut') camPInt.start() camQInt.start() def deleteWorld(self): if self.track: self.track.removeNode() self.track = None if self.sky: self.skyUtil.stopSky() self.sky.removeNode() self.sky = None return def setToonLane(self, lane): self.lane = lane base.localAvatar.setPos(self.lanePos[lane]) base.localAvatar.setHpr(0, 0, 0) def getToonLane(self): return self.lane def d_requestToonLane(self): self.sendUpdate('requestToonLane', []) def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) self.load() def disable(self): DistributedMinigame.DistributedMinigame.disable(self) self.deleteWorld() self.raceFSM.requestFinalState() del self.raceFSM self.countSfx = None self.goSfx = None return
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.mp3') self.loseSfx = base.loadSfx('phase_4/audio/sfx/MG_lose.mp3') self.prizeHigh = base.loadSfx('phase_6/audio/sfx/KART_Applause_1.mp3') self.prizeLow = base.loadSfx('phase_6/audio/sfx/KART_Applause_4.mp3') self.music = None self.description = '' self.descDialog = None self.winnerPrize = 0 self.loserPrize = 0 self.winnerMsg = 'Winner!\nYou have earned: %s' self.loserMsg = 'Loser!\nYou have earned: %s' 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 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() elif scenario == 'loser': msg = self.loserMsg % self.loserPrize self.prizeLow.play() elif 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): self.fsm.request('start') base.transitions.irisIn() def d_leaving(self): """ Tell the AI that we are leaving. """ 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.7) 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) def disable(self): DistributedObject.DistributedObject.disable(self) 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 return
class AdminPage(BookPage): def __init__(self, book): BookPage.__init__(self, book, 'Admin Panel') self.fsm = ClassicFSM( 'AdminPage', [ State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('kickSection', self.enterKickSection, self.exitKickSection), #State('clickOnToon', self.enterClickOnToon, self.exitClickOnToon), State('sysMsgSection', self.enterSysMsgSection, self.exitSysMsgSection) ], 'off', 'off') self.fsm.enterInitialState() def load(self): BookPage.load(self) icons = loader.loadModel('phase_4/models/gui/tfa_images.bam') self.icon = icons.find('**/hq-dialog-image') icons.detachNode() def enterOff(self): pass def exitOff(self): pass def enter(self): BookPage.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.requestFinalState() BookPage.exit(self) def unload(self): del self.book del self.fsm BookPage.unload(self) def enterSysMsgSection(self): geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText( text="Inform all online players about something.", pos=(0, 0.45)) self.msgEntry = DirectEntry( initialText="System Message...", scale=0.055, width=15, numLines=4, command=self.sendSystemMessageCommand, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts, pos=(-0.4, 0, 0)) self.sendBtn = DirectButton( geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Send", pos=(0, 0, -0.35), text_pos=(0, -0.01), command=self.sendSystemMessageCommand, ) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Cancel", pos=(-0.45, 0.15, -0.55), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) # Occasionally, extra arguments are sent and this extra variable must be here to capture them. def sendSystemMessageCommand(self, _=None): msg = self.msgEntry.get() DISTRICT_WIDE_MSG(msg) self.fsm.request('basePage') def exitSysMsgSection(self): self.infoLbl.destroy() del self.infoLbl self.msgEntry.destroy() del self.msgEntry self.sendBtn.destroy() del self.sendBtn self.cancelBtn.destroy() del self.cancelBtn def enterKickSection(self): geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText(text="Kick or Ban?", pos=(0, 0.45)) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Kick", pos=(0, 0, 0.1), text_pos=(0, -0.01), command=self.book.finishedResume, extraArgs=[KickBanDialog, [0]]) self.banBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Ban", pos=(0, 0, 0.0), text_pos=(0, -0.01), command=self.book.finishedResume, extraArgs=[KickBanDialog, [1]]) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Cancel", pos=(-0.45, 0.15, -0.45), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) def exitKickSection(self): self.banBtn.destroy() del self.banBtn self.infoLbl.destroy() del self.infoLbl self.cancelBtn.destroy() del self.cancelBtn self.kickBtn.destroy() del self.kickBtn def enterBasePage(self): geom = CIGlobals.getDefaultBtnGeom() self.ghostBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle Ghost", pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01), command=TOGGLE_GHOST) self.bgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle Background", pos=(-0.45, 0.15, 0.40), text_pos=(0, -0.01), command=self.toggleBackground) self.idBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle Player Ids", pos=(-0.45, 0.15, 0.3), text_pos=(0, -0.01), command=TOGGLE_PLAYER_IDS) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Kick/Ban Player", pos=(0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.openKickPage) self.systemMsgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="System Message", pos=(-0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.openSysMsgPage) self.oobeBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle OOBE", pos=(-0.45, 0.15, 0.2), text_pos=(0, -0.01), command=base.oobe) self.directBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Start DIRECT", pos=(-0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.doStartDirect) self.pstatsBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle PStats", pos=(-0.45, 0.15, 0.0), text_pos=(0, -0.01), command=self.togglePStats) self.pingBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle Ping", pos=(-0.45, 0.15, -0.1), text_pos=(0, -0.01), command=base.cr.togglePing) self.tokenBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Modify Access Level", pos=(0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.book.finishedResume, extraArgs=[AdminTokenDialog, []]) self.worldBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Give World Access", pos=(0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.book.finishedResume, extraArgs=[WorldAccessDialog, []]) self.allGagsBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Restock All Gags", pos=(0.45, 0.15, 0.2), text_pos=(0, -0.01), command=SEND_REQ_UNLOCK_GAGS) self.allLaffBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Refill Laff", pos=(0.45, 0.15, 0.1), text_pos=(0, -0.01), command=SEND_REQ_REFILL_LAFF) self.physDbgBtn = DirectButton(geom=geom, text_scale=0.039, relief=None, scale=1.0, text="Toggle Physics Debug", pos=(0.45, 0.15, 0.0), text_pos=(0, -0.01), command=self.togglePhysDbg) self.analyzeBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Analyze Scene", pos=(0.45, 0.15, -0.1), text_pos=(0, -0.01), command=self.doAnalyzeScene) self.listBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="List Scene", pos=(0.45, 0.15, -0.2), text_pos=(0, -0.01), command=render.ls) self.noClipBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text="Toggle No Clip", pos=(0.45, 0.15, -0.3), text_pos=(0, -0.01), command=self.toggleNoClip) base.cr.playGame.getPlace().maybeUpdateAdminPage() del geom def doStartDirect(self): base.startTk() base.startDirect() def doAnalyzeScene(self): render.analyze() ls = LineStream() sga = SceneGraphAnalyzer() sga.addNode(render.node()) sga.write(ls) text = "" while ls.isTextAvailable(): text += ls.getLine() + "\n" self.acceptOnce('analyzedone', self.__handleAnalyzeDone) self.analyzeDlg = GlobalDialog(message=text, style=Ok, doneEvent='analyzedone', text_scale=0.05) self.analyzeDlg.show() def __handleAnalyzeDone(self): self.analyzeDlg.cleanup() del self.analyzeDlg def toggleNoClip(self): ncl = not base.localAvatar.walkControls.controller.noClip base.localAvatar.walkControls.controller.noClip = ncl if ncl: base.cr.myDistrict.systemMessage("No Clip Enabled") else: base.cr.myDistrict.systemMessage("No Clip Disabled") def togglePhysDbg(self): base.setPhysicsDebug(not base.physicsDbgFlag) def togglePStats(self): if PStatClient.isConnected(): PStatClient.disconnect() else: # in production, show stats viewer on the server if base.config.GetBool("pstats-view-on-server", False): PStatClient.connect("127.0.0.1" if not metadata.IS_PRODUCTION else "gameserver.coginvasion.online") else: PStatClient.connect("127.0.0.1") def toggleBackground(self): if render.isHidden(): render.show() else: render.hide() if self.book.isBackgroundHidden(): self.book.show() self.book.setBackgroundHidden(False) else: self.book.hide() self.book.setBackgroundHidden(True) def openKickPage(self): self.fsm.request('kickSection') def openSysMsgPage(self): self.fsm.request('sysMsgSection') def exitBasePage(self): self.noClipBtn.destroy() del self.noClipBtn self.systemMsgBtn.destroy() del self.systemMsgBtn self.idBtn.destroy() del self.idBtn self.kickBtn.destroy() del self.kickBtn self.bgBtn.destroy() del self.bgBtn self.ghostBtn.destroy() del self.ghostBtn self.oobeBtn.destroy() del self.oobeBtn self.tokenBtn.destroy() del self.tokenBtn self.worldBtn.destroy() del self.worldBtn self.allGagsBtn.destroy() del self.allGagsBtn self.allLaffBtn.destroy() del self.allLaffBtn self.physDbgBtn.destroy() del self.physDbgBtn self.analyzeBtn.destroy() del self.analyzeBtn if hasattr(self, 'analyzeDlg'): self.ignore('analyzedone') self.analyzeDlg.cleanup() del self.analyzeDlg self.directBtn.destroy() del self.directBtn self.listBtn.destroy() del self.listBtn self.pstatsBtn.destroy() del self.pstatsBtn self.pingBtn.destroy() del self.pingBtn
class DistributedBoat(DistributedObject): notify = directNotify.newCategory("DistributedBoat") def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [ State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast) ], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.ogg' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.ogg' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.ogg' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.ogg' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.boatPath = '*donalds_boat*' self.track = None self.state = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) base.playSfx(self.soundWaterLap, looping=1) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) self.soundWaterLap.stop() def __pollBoat(self, task): try: self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) except: return task.cont self.generated() return task.done def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.loadSfx(self.fogHorn) self.soundShipBell = base.loadSfx(self.shipBell) self.soundWaterLap = base.loadSfx(self.waterLap) self.soundDockCreak = base.loadSfx(self.dockCreak) #try: # self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) #except: # base.taskMgr.add(self.__pollBoat, self.uniqueName('__pollBoat')) # return self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boat) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() del self.fsm del self.soundFogHorn del self.soundShipBell del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp=None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None def enterWestToEast(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat) self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0)), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0)), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass
class AvChooser(StateData): notify = directNotify.newCategory('AvChooser') def __init__(self, parentFSM): StateData.__init__(self, 'avChooseDone') self.avChooseFSM = ClassicFSM('avChoose', [State('getToonData', self.enterGetToonData, self.exitGetToonData), State('avChoose', self.enterAvChoose, self.exitAvChoose), State('waitForToonDelResponse', self.enterWaitForToonDelResponse, self.exitWaitForToonDelResponse), State('off', self.enterOff, self.exitOff)], 'off', 'off') self.avChooseFSM.enterInitialState() self.parentFSM = parentFSM self.parentFSM.getStateNamed('avChoose').addChild(self.avChooseFSM) self.pickAToon = None self.setAvatarsNone() return def enter(self): StateData.enter(self) base.transitions.noTransitions() self.avChooseFSM.request('getToonData') def exit(self): StateData.exit(self) self.setAvatarsNone() self.avChooseFSM.requestFinalState() def setAvatarsNone(self): self.avChoices = [] def enterOff(self): pass def exitOff(self): pass def enterGetToonData(self): self.acceptOnce(base.cr.csm.getSetAvatarsEvent(), self.handleToonData) base.cr.csm.d_requestAvatars() def handleToonData(self, avatarList): for av in avatarList: avId = av[0] dna = av[1] name = av[2] slot = av[3] choice = AvChoice(dna, name, slot, avId) self.avChoices.append(choice) self.avChooseFSM.request('avChoose') def exitGetToonData(self): self.ignore(base.cr.csm.getSetAvatarsEvent()) def enterAvChoose(self): self.pickAToon = CharSelection(self) self.pickAToon.load() def enterWaitForToonDelResponse(self, avId): self.acceptOnce(base.cr.csm.getToonDeletedEvent(), self.handleDeleteToonResp) base.cr.csm.sendDeleteToon(avId) def exitWaitForToonDelResponse(self): self.ignore(base.cr.csm.getToonDeletedEvent()) def hasToonInSlot(self, slot): if self.getAvChoiceBySlot(slot) != None: return True else: return False return def getNameInSlot(self, slot): return self.getAvChoiceBySlot(slot).getName() def getAvChoiceBySlot(self, slot): for avChoice in self.avChoices: if avChoice.getSlot() == slot: return avChoice return None def getHeadInfo(self, slot): dna = self.getAvChoiceBySlot(slot).getDNA() self.pickAToon.dna.setDNAStrand(dna) return [self.pickAToon.dna.getGender(), self.pickAToon.dna.getAnimal(), self.pickAToon.dna.getHead(), self.pickAToon.dna.getHeadColor()] def handleDeleteToonResp(self): base.cr.loginFSM.request('avChoose') def exitAvChoose(self): self.pickAToon.unload() self.pickAToon = None return
class DistributedDisneyChar(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory('DistributedDisneyChar') def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM('DDisneyChar', [ State('off', self.enterOff, self.exitOff), State('walking', self.enterWalking, self.exitWalking), State('neutral', self.enterNeutral, self.exitNeutral) ], 'off', 'off') self.fsm.enterInitialState() self.neutralFSM = ClassicFSM('DDisneyChar-neutral', [ State('off', self.enterOff, self.exitOff), State('turn2target', self.enterTurn2Target, self.exitTurn2Target), State('talk2target', self.enterTalk2Target, self.exitTalk2Target) ], 'off', 'off') self.neutralFSM.enterInitialState() self.charId = 0 self.geoEyes = 0 self.avatarType = CIGlobals.CChar self.isInRange = False self.currentPointLetter = "a" self.walkIval = None self.currentChat = "" self.talkEnabled = True self.speechSound = None self.chatsSinceLastNoise = 0 self.chatsWithoutNoise = 5 self.eyes = None self.lpupil = None self.rpupil = None self.eyesOpen = None self.eyesClosed = None def setCharId(self, charId): self.charId = charId def enterOff(self): pass def exitOff(self): pass def doNeutral(self, pointLetter): self.fsm.request('neutral', [pointLetter]) def doWalking(self, pointLetter, startPointLetter, timestamp): ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('walking', [pointLetter, startPointLetter, ts]) def enterWalking(self, pointLetter, startPointLetter, ts): if self.walkIval: self.walkIval.finish() self.walkIval = None self.nametag.clearChatText() self.loop('walk') point = WALK_POINTS[self.charId][pointLetter][0] lastPoint = WALK_POINTS[self.charId][startPointLetter][0] seq = Sequence(name=self.uniqueName('DCharWalkIval')) if self.charId == PLUTO: seq.append(ActorInterval(self, 'stand')) elif self.charId == SLEEP_DONALD: seq.append(ActorInterval(self, 'neutral2walk')) seq.append(Func(self.loop, 'walk')) ival = NPCWalkInterval(self, point, startPos=lastPoint, fluid=1) seq.append(ival) seq.append(Func(self.loop, 'neutral')) seq.start(ts) self.currentPointLetter = pointLetter self.walkIval = ival def exitWalking(self): if self.walkIval: self.walkIval.finish() self.walkIval = None def enterNeutral(self, pointLetter): point = WALK_POINTS[self.charId][pointLetter][0] self.setPos(point) if self.charId == PLUTO: seq = Sequence(ActorInterval(self, 'sit'), Func(self.loop, 'neutral')) seq.start() elif self.charId == SLEEP_DONALD: seq = Sequence(ActorInterval(self, 'walk2neutral'), Func(self.loop, 'neutral')) seq.start() else: self.loop('neutral') def talk2Toon(self, chatType, chatIndex, avId): toon = self.cr.doId2do.get(avId) if not toon: return if chatType in [SHARED_GREETINGS, SHARED_COMMENTS, SHARED_GOODBYES]: self.currentChat = CHATTER[chatType][chatIndex] elif chatType in [CHAR_GREETINGS, CHAR_COMMENTS, CHAR_GOODBYES]: self.currentChat = CHATTER[chatType][self.charId][chatIndex] if '%s' in self.currentChat: self.currentChat = self.currentChat % toon.getName() self.neutralFSM.request('turn2target', [toon]) def enterTurn2Target(self, toon): self.turnIval = NPCLookInterval(self, toon, fluid=1, name=self.uniqueName('turnIval')) if self.turnIval.distance > 30: self.loop('walk') elif self.turnIval.distance < 10.0: self.headsUp(toon) self.neutralFSM.request('talk2target') return self.turnIval.setDoneEvent(self.turnIval.getName()) self.acceptOnce(self.turnIval.getDoneEvent(), self.__handleTurningDone) self.turnIval.start() def __handleTurningDone(self): self.neutralFSM.request('talk2target') def exitTurn2Target(self): self.ignore(self.turnIval.getDoneEvent()) self.turnIval.finish() del self.turnIval def enterTalk2Target(self): self.setChat(self.currentChat) if self.getCurrentAnim() != 'neutral': if self.charId == SLEEP_DONALD: seq = Sequence(ActorInterval(self, 'walk2neutral'), Func(self.loop, 'neutral')) seq.start() else: self.loop('neutral') def exitTalk2Target(self): pass def exitNeutral(self): self.neutralFSM.request('off') self.stop() def setChat(self, chat): if self.charId == SLEEP_DONALD: chat = "." + chat DistributedAvatar.setChat(self, chat) if self.chatsSinceLastNoise >= self.chatsWithoutNoise or self.chatsSinceLastNoise == 0: base.playSfx(self.speechSound, node=self) self.chatsSinceLastNoise = 0 self.chatsWithoutNoise = random.randint(1, 5) self.chatsSinceLastNoise += 1 def loadChar(self): data = CHAR_DATA[self.charId] self.loadModel(data[0], 'modelRoot') self.loadAnims(data[1], 'modelRoot') if self.charId == SLEEP_DONALD: self.setPlayRate(0.5, 'neutral') self.setHeight(data[2]) self.setName(data[3]) self.talkEnabled = data[4] if self.talkEnabled: self.speechSound = data[5] if self.speechSound is not None: base.audio3d.attachSoundToObject(self.speechSound, self) self.setupNameTag() self.ears = [] if self.charId in [MINNIE, MICKEY]: for bundle in self.getPartBundleDict().values(): bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') earNull.clearNetTransforms() for bundle in self.getPartBundleDict().values(): charNodepath = bundle['modelRoot'].partBundleNP bundle = bundle['modelRoot'].getBundle() earNull = bundle.findChild('sphere3') if not earNull: earNull = bundle.findChild('*sphere3') ears = charNodepath.find('**/sphere3') if ears.isEmpty(): ears = charNodepath.find('**/*sphere3') ears.clearEffect(CharacterJointEffect.getClassType()) earRoot = charNodepath.attachNewNode('earRoot') earPitch = earRoot.attachNewNode('earPitch') earPitch.setP(40.0) ears.reparentTo(earPitch) earNull.addNetTransform(earRoot.node()) ears.clearMat() ears.node().setPreserveTransform(ModelNode.PTNone) ears.setP(-40.0) ears.flattenMedium() self.ears.append(ears) ears.setBillboardAxis() self.eyesOpen = loader.loadTexture('phase_3/maps/eyes1.jpg', 'phase_3/maps/eyes1_a.rgb') self.eyesClosed = loader.loadTexture( 'phase_3/maps/mickey_eyes_closed.jpg', 'phase_3/maps/mickey_eyes_closed_a.rgb') self.eyes = self.find('**/eyes') self.eyes.setBin('transparent', 0) self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) elif self.charId == PLUTO: self.eyesOpen = loader.loadTexture( 'phase_6/maps/plutoEyesOpen.jpg', 'phase_6/maps/plutoEyesOpen_a.rgb') self.eyesClosed = loader.loadTexture( 'phase_6/maps/plutoEyesClosed.jpg', 'phase_6/maps/plutoEyesClosed_a.rgb') self.eyes = self.find('**/eyes') self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) elif self.charId == DAISY: self.geoEyes = 1 self.eyeOpenList = [] self.eyeCloseList = [] self.eyeCloseList.append(self.find('**/eyesclose')) self.eyeOpenList.append(self.find('**/eyesclose')) self.eyeOpenList.append(self.find('**/eyespupil')) self.eyeOpenList.append(self.find('**/eyesopen')) for part in self.eyeOpenList: part.show() for part in self.eyeCloseList: part.hide() elif self.charId == SAILOR_DONALD: self.eyes = self.find('**/eyes') self.lpupil = self.find('**/joint_pupilL') self.rpupil = self.find('**/joint_pupilR') self.drawInFront('joint_pupil?', 'eyes*', -3) if self.lpupil is not None: self.lpupil.adjustAllPriorities(1) self.rpupil.adjustAllPriorities(1) if self.eyesOpen: self.eyesOpen.setMinfilter(Texture.FTLinear) self.eyesOpen.setMagfilter(Texture.FTLinear) if self.eyesClosed: self.eyesClosed.setMinfilter(Texture.FTLinear) self.eyesClosed.setMagfilter(Texture.FTLinear) if self.charId == MICKEY: pupilParent = self.rpupil.getParent() pupilOffsetNode = pupilParent.attachNewNode('pupilOffsetNode') pupilOffsetNode.setPos(0, 0.025, 0) self.rpupil.reparentTo(pupilOffsetNode) self.initShadow() self.shadow.setScale(0.6) self.initializeBodyCollisions(self.avatarType, self.getHeight(), 1.0) self.initializeRay(self.avatarType, 1) self.disableShadowRay() self.__blinkName = 'blink-' + data[3] def setupNameTag(self): DistributedAvatar.setupNameTag(self) self.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCNPC]) self.nametag.setActive(0) self.nametag.updateAll() def __monitorRange(self, task): if base.localAvatar.getDistance(self) <= MAX_RANGE: if self.isInRange is False: self.sendUpdate('avatarEnter') self.isInRange = True else: if self.isInRange is True: self.sendUpdate('avatarExit') self.isInRange = False return task.cont def __blinkOpenEyes(self, task): self.openEyes() r = random.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return task.done def __blinkCloseEyes(self, task): self.closeEyes() taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return task.done def openEyes(self): if self.geoEyes: for part in self.eyeOpenList: part.show() for part in self.eyeCloseList: part.hide() else: if self.eyes: self.eyes.setTexture(self.eyesOpen, 1) self.lpupil.show() self.rpupil.show() def closeEyes(self): if self.geoEyes: for part in self.eyeOpenList: part.hide() for part in self.eyeCloseList: part.show() else: if self.eyes: self.eyes.setTexture(self.eyesClosed, 1) self.lpupil.hide() self.rpupil.hide() def startBlink(self): if self.eyesOpen or self.geoEyes: taskMgr.remove(self.__blinkName) taskMgr.doMethodLater(random.random() * 4 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): if self.eyesOpen or self.geoEyes: taskMgr.remove(self.__blinkName) self.openEyes() def getNametagJoints(self): return [] def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.loadChar() self.startBlink() base.taskMgr.add(self.__monitorRange, self.uniqueName('monitorRange')) self.sendUpdate('requestStateData') if self.charId == SAILOR_DONALD: self.disableRay() self.stashBodyCollisions() boat = self.cr.playGame.hood.loader.geom.find('**/*donalds_boat*') boat.find('**/wheel').hide() self.setPos(0, -1, 3.95) self.reparentTo(boat) self.loop('wheel') else: self.reparentTo(render) def disable(self): base.taskMgr.remove(self.uniqueName('monitorRange')) self.stopBlink() self.fsm.requestFinalState() self.fsm = None self.neutralFSM.requestFinalState() self.neutralFSM = None self.charId = None self.geoEyes = None self.avatarType = None self.isInRange = None self.currentPointLetter = None self.walkIval = None self.currentChat = None self.talkEnabled = None self.speechSound = None self.chatsSinceLastNoise = None self.eyes = None self.lpupil = None self.rpupil = None self.eyesOpen = None self.eyesClosed = None DistributedAvatar.disable(self) Avatar.disable(self) DistributedSmoothNode.disable(self)
class ToonFPS(DirectObject): notify = directNotify.newCategory("ToonFPS") WeaponName2DamageData = {"pistol": (30.0, 10.0, 150.0, 0.3), "shotgun": (40.0, 15.0, 155.0, 0.5), "sniper": (40.0, 15.0, 155.0, 0.5)} def __init__(self, mg, weaponName = "pistol"): self.mg = mg self.weaponName = weaponName self.v_model_root = None self.v_model = None self.weapon = None self.track = None self.draw = None self.shoot = None self.reload = None self.empty = None self.cockBack = None self.cockFwd = None self.player_node = None # blach (02Aug15) # Drastically improved the accuracy of bullets... DRASTICALLY self.shooterTrav = None self.shooterRay = None self.shooterRayNode = None self.shooterHandler = None self.gui = ToonFPSGui(self) self.fsm = ClassicFSM('ToonFPS', [State('off', self.enterOff, self.exitOff), State('alive', self.enterAlive, self.exitAlive), State('dead', self.enterDead, self.exitDead)], 'off', 'off') #self.deadFSM = ClassicFSM('dead', [State('off', self.enterOff, self.exitOff), # State(']) self.aliveFSM = ClassicFSM('alive', [State('off', self.enterOff, self.exitOff), State('draw', self.enterDraw, self.exitDraw, ['idle']), State('idle', self.enterIdle, self.exitIdle, ['shoot', 'reload']), State('shoot', self.enterShoot, self.exitShoot, ['idle']), State('reload', self.enterReload, self.exitReload, ['idle'])], 'off', 'off') self.fsm.getStateNamed('alive').addChild(self.aliveFSM) #self.fsm.getStateNamed('dead').addChild(self.deadFSM) self.fsm.enterInitialState() self.aliveFSM.enterInitialState() if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 self.hp = 125 self.max_hp = 125 self.firstPerson = FirstPerson() def movementTask(self, task): if (inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne): if base.localAvatar.getAnimState() != "jump": base.localAvatar.setAnimState("jump") base.localAvatar.playMovementSfx(None) self.mg.sendUpdate("jumpingAvatar", [base.localAvatar.doId]) return Task.cont def enterAlive(self): if not self.mg.fsm.getCurrentState().getName() in ['gameOver', 'announceGameOver', 'finalScores']: self.start() self.resetHp() self.resetAmmo() if self.mg.fsm.getCurrentState().getName() == "play": self.reallyStart() def exitAlive(self): self.end() self.v_model.reparentTo(hidden) if self.mg.fsm.getCurrentState().getName() != "play": self.reallyEnd() def updatePoints(self): self.points = self.kills - self.deaths def enterDead(self, killer): base.localAvatar.getGeomNode().show() self.gui.end() base.localAvatar.attachCamera() self.freezeCamSfx = base.loadSfx("phase_4/audio/sfx/freeze_cam.ogg") self.freezeCamImage = None self.freezeCamImageFile = None base.camera.setZ(base.camera.getZ() + 2.0) taskMgr.add( self.cameraLookAtKillerTask, "lookAtKiller", extraArgs = [killer], appendTask = True ) taskMgr.doMethodLater( 2.0, self.startZoomOnKiller, "startFreezeCam", extraArgs = [killer], appendTask = True ) def startZoomOnKiller(self, killer, task): taskMgr.add( self.__zoomOnKillerTask, "zoomOnKiller", extraArgs = [killer], appendTask = True ) return task.done def __zoomOnKillerTask(self, killer, task): if base.camera.getDistance(killer) <= 10.0 and self.freezeCamSfx.status() == self.freezeCamSfx.READY: base.playSfx(self.freezeCamSfx) if base.camera.getDistance(killer) < 7.0: self.doFreezeCam() return task.done base.camera.setY(base.camera, 60 * globalClock.getDt()) return task.again def doFreezeCam(self): taskMgr.remove("lookAtKiller") self.frameBuffer = PNMImage() base.win.getScreenshot(self.frameBuffer) self.freezeCamTex = Texture() self.freezeCamTex.load(self.frameBuffer) self.freezeCamImage = OnscreenImage(image = self.freezeCamTex, parent=render2d) def cameraLookAtKillerTask(self, killer, task): try: base.camera.lookAt(killer, 0, 0, 3) except AssertionError: pass return task.cont def exitDead(self): taskMgr.remove("zoomOnKiller") taskMgr.remove("lookAtKiller") taskMgr.remove("startFreezeCam") del self.freezeCamSfx if self.freezeCamImage: self.freezeCamImage.destroy() del self.freezeCamImage self.frameBuffer.clear() self.freezeCamTex.clear() del self.frameBuffer del self.freezeCamTex base.localAvatar.detachCamera() base.localAvatar.getGeomNode().hide() self.gui.start() def load(self): if self.weaponName == "pistol": self.draw = base.loadSfx("phase_4/audio/sfx/draw_secondary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/pistol_shoot.ogg") self.reload = base.loadSfx("phase_4/audio/sfx/pistol_worldreload.ogg") elif self.weaponName == "sniper": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") elif self.weaponName == "shotgun": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") self.empty = base.loadSfx("phase_4/audio/sfx/shotgun_empty.ogg") self.v_model_root = base.camera.attachNewNode('v_model_root') self.v_model = Actor('phase_4/models/minigames/v_dgm.egg', {'pidle': 'phase_4/models/minigames/v_dgm-pistol-idle.egg', 'pshoot': 'phase_4/models/minigames/v_dgm-pistol-shoot.egg', 'preload': 'phase_4/models/minigames/v_dgm-pistol-reload.egg', 'pdraw': 'phase_4/models/minigames/v_dgm-pistol-draw.egg', 'sidle': 'phase_4/models/minigames/v_dgm-shotgun-idle.egg', 'sshoot': 'phase_4/models/minigames/v_dgm-shotgun-shoot.egg'}) if self.weaponName == "pistol": self.weapon = loader.loadModel("phase_4/models/props/water-gun.bam") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.011")) self.weapon.setX(-0.125) self.weapon.setY(0.5) self.weapon.setScale(0.65) elif self.weaponName == "sniper": self.weapon = loader.loadModel("phase_4/models/props/sniper.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) elif self.weaponName == "shotgun": self.weapon = loader.loadModel("phase_4/models/props/shotgun.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) self.gui.load() def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == "pistol": self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == "sniper": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) elif self.weaponName == "shotgun": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw') def reallyStart(self): self.firstPerson.reallyStart() base.localAvatar.startTrackAnimToSpeed() #taskMgr.add(self.movementTask, "toonBattleMovement") def end(self): if self.aliveFSM.getCurrentState().getName() != 'off': self.aliveFSM.request('off') if self.firstPerson: self.firstPerson.enableMouse() self.firstPerson.end() taskMgr.remove("toonBattleMovement") if self.mg.fsm.getCurrentState().getName() != "play": self.fsm.request('off') def reallyEnd(self): try: self.ToonFPS_reallyEnded return except: self.ToonFPS_reallyEnded = 1 if self.shooterRayNode: self.shooterRayNode.removeNode() self.shooterRayNode = None self.shooterRay = None self.shooterTrav = None self.shooterHandler = None if self.firstPerson: self.firstPerson.reallyEnd() if self.v_model_root: self.v_model_root.reparentTo(hidden) if self.v_model: self.v_model.reparentTo(hidden) self.v_model.setPosHpr(0, 0, 0, 0, 0, 0) if self.gui: self.gui.end() base.camLens.setNear(1.0) def cleanup(self): try: self.ToonFPS_cleanedUp return except: self.ToonFPS_cleanedUp = 1 taskMgr.remove("lookAtKiller") taskMgr.remove("toonBattleMovement") if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None self.draw = None self.shoot = None self.reload = None self.empty = None self.ammo = None try: self.aliveFSM.requestFinalState() self.fsm.requestFinalState() except: self.notify.warning('Redundant call to enter the final state.') self.fsm = None self.aliveFSM = None self.player_node = None self.min_camerap = None self.max_camerap = None self.hp = None self.max_hp = None if self.v_model: self.v_model.cleanup() self.v_model = None if self.weapon: self.weapon.removeNode() self.weapon = None if self.weapon: self.v_model_root.removeNode() self.v_model_root = None if self.gui: self.gui.cleanup() def damageTaken(self, amount, avId): if self.hp <= 0.0: killer = self.mg.cr.doId2do.get(avId, None) self.fsm.request('dead', [killer]) self.gui.adjustHpMeter() def enterDraw(self): self.draw.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pdraw', playRate = 1.6, name = 'drawTrack') elif self.weaponName == "shotgun": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') elif self.weaponName == "sniper": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitDraw(self): #self.draw.stop() if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterIdle(self): if self.weaponName == "pistol": self.v_model.loop('pidle') elif self.weaponName == "shotgun": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() elif self.weaponName == "sniper": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() self.accept('mouse1', self.requestShoot) if self.ammo <= 0: self.gui.notifyNoAmmo() if self.ammo < 14: self.accept('r', self.aliveFSM.request, ['reload']) def requestShoot(self): if self.mg.fsm.getCurrentState().getName() != "play": return if self.ammo > 0: self.aliveFSM.request('shoot') else: self.empty.play() def exitIdle(self): self.v_model.stop() if self.track: self.track.finish() self.track = None self.ignore('mouse1') self.ignore('r') def enterShoot(self): self.shoot.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pshoot', playRate = 2, name = 'shootTrack') elif self.weaponName == "shotgun": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) elif self.weaponName == "sniper": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) self.track.setDoneEvent('shootTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() self.ammo -= 1 self.gui.adjustAmmoGui() self.mg.makeSmokeEffect(self.weapon.find('**/joint_nozzle').getPos(render)) self.traverse() def traverse(self): mpos = base.mouseWatcherNode.getMouse() self.shooterRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.shooterTrav.traverse(render) def calcDamage(self, avatar): dmgData = self.WeaponName2DamageData[self.weaponName] maxDamage = dmgData[0] minDistance = dmgData[1] maxDistance = dmgData[2] factor = dmgData[3] distance = base.localAvatar.getDistance(avatar) if distance < minDistance: distance = minDistance elif distance > maxDistance: distance = maxDistance damage = maxDamage - ((distance - minDistance) * factor) return damage def exitShoot(self): #self.shoot.stop() self.ignore('shootTrack') if self.track: self.track.finish() self.track = None def enterReload(self): self.gui.deleteNoAmmoLabel() if self.weaponName == "pistol": self.track = Parallel(Sequence(Wait(0.3), Func(self.reload.play), Func(self.resetAmmo)), ActorInterval(self.v_model, 'preload', playRate = 1.5), name = 'reloadTrack') elif self.weaponName == "shotgun": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') elif self.weaponName == "sniper": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') self.track.setDoneEvent('reloadTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitReload(self): #self.reload.stop() self.ignore('reloadTrack') if self.track: self.track.finish() self.track = None def resetAmmo(self): if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 elif self.weaponName == "sniper": self.ammo = 7 self.gui.resetAmmo() def resetHp(self): self.hp = self.max_hp self.gui.adjustHpMeter() def enterOff(self): pass def exitOff(self): pass
class DistributedPieTurret(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory("DistributedPieTurret") def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM( 'DistributedPieTurret', [ State('off', self.enterOff, self.exitOff), State('scan', self.enterScan, self.exitScan), #State('lockOn', self.enterLockOn, self.exitLockOn), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.cannon = None self.track = None self.avatar = None self.readyPie = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.piesInFlight = [] def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.getAvatar() == base.localAvatar.doId: base.localAvatar.getMyBattle().getTurretManager().updateTurretGui() def die(self): self.fsm.requestFinalState() turretPos = self.cannon.getPos(render) self.removeTurret() self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() self.explosion.setPos(turretPos + (0, 0, 1)) sfx = base.localAvatar.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) def showAndMoveHealthLabel(self): self.unstashHpLabel() self.stopMovingHealthLabel() moveTrack = LerpPosInterval(self.healthLabel, duration = 0.5, pos = Point3(0, 0, 5), startPos = Point3(0, 0, 0), blendType = 'easeOut') self.healthLabelTrack = Sequence(moveTrack, Wait(1.0), Func(self.stashHpLabel)) self.healthLabelTrack.start() def enterOff(self): pass def exitOff(self): pass def makeSplat(self, pos): splat = Actor("phase_3.5/models/props/splat-mod.bam", {"chan": "phase_3.5/models/props/splat-chan.bam"}) splat.setScale(0.5) splat.reparentTo(render) splat.setBillboardPointEye() splat.setColor(VBase4(1, 1, 0, 1)) x, y, z = pos splat.setPos(x, y, z) sfx = base.localAvatar.audio3d.loadSfx("phase_4/audio/sfx/AA_wholepie_only.mp3") base.localAvatar.audio3d.attachSoundToObject(sfx, splat) base.playSfx(sfx) track = Sequence( ActorInterval(splat, "chan"), Func(splat.cleanup), Func(splat.removeNode) ) track.start() def d_makeSplat(self, pos): self.sendUpdate("makeSplat", [pos]) def b_makeSplat(self, pos): self.d_makeSplat(pos) self.makeSplat(pos) def shoot(self, suitId): self.fsm.request('shoot', [suitId]) def enterShoot(self, suitId): if self.cannon: smoke = loader.loadModel("phase_4/models/props/test_clouds.bam") smoke.setBillboardPointEye() smoke.reparentTo(self.cannon.find('**/cannon')) smoke.setPos(0, 6, -3) smoke.setScale(0.5) smoke.wrtReparentTo(render) self.suit = self.cr.doId2do.get(suitId) self.cannon.find('**/cannon').lookAt(self.suit.find('**/joint_head')) self.cannon.find('**/square_drop_shadow').headsUp(self.suit.find('**/joint_head')) self.eventId = random.uniform(0, 100000000) track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) track.start() self.createAndShootPie() def loadPieInTurret(self): if self.cannon: if self.readyPie: self.readyPie.removeNode() self.readyPie = None pie = loader.loadModel("phase_3.5/models/props/tart.bam") pie.reparentTo(self.cannon.find('**/cannon')) pie.setY(5.2) pie.setHpr(90, -90, 90) self.readyPie = pie def removePieInTurret(self): if self.readyPie: self.readyPie.removeNode() self.readyPie = None def createAndShootPie(self): if not self.readyPie: self.loadPieInTurret() local = 0 if base.localAvatar.doId == self.getAvatar(): local = 1 proj = ProjectilePie(self.uniqueName('pieTurretCollision') + str(self.eventId), self.cannon.find('**/cannon'), self.readyPie, Point3(0, 200, -90), 0.9, 2.5, local, self) self.readyPie = None self.piesInFlight.append(proj) if local: self.acceptOnce(self.uniqueName('pieTurretCollision') + str(self.eventId), self.handlePieCollision) Sequence(Wait(0.25), Func(self.loadPieInTurret)).start() def handlePieCollision(self, entry, proj): x, y, z = proj.pie.getPos(render) self.b_makeSplat([x, y, z]) proj.cleanup() if base.localAvatar.doId == self.getAvatar(): intoNP = entry.getIntoNodePath() avNP = intoNP.getParent() for key in self.cr.doId2do.keys(): obj = self.cr.doId2do[key] if obj.__class__.__name__ == "DistributedSuit": if obj.getKey() == avNP.getKey(): if obj.getHealth() > 0: base.localAvatar.sendUpdate('suitHitByPie', [obj.doId, GagGlobals.getIDByName(CIGlobals.WholeCreamPie)]) def exitShoot(self): del self.suit del self.eventId def scan(self, timestamp = None, afterShooting = 0): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('scan', [ts, afterShooting]) def enterScan(self, ts = 0, afterShooting = 0): if afterShooting: self.track = Parallel( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/cannon').getHpr(), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/square_drop_shadow').getHpr(), blendType = 'easeInOut'), name = "afterShootTrack" + str(id(self)) ) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self._afterShootTrackDone) self.track.start(ts) else: self.track = Parallel( Sequence( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ), Sequence( LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ) ) self.track.loop(ts) def _afterShootTrackDone(self): self.track = None self.track = Parallel( Sequence( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ), Sequence( LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ) ) self.track.loop() def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def setAvatar(self, avId): self.avatar = avId def getAvatar(self): return self.avatar def makeTurret(self): self.cannon = loader.loadModel("phase_4/models/minigames/toon_cannon.bam") self.cannon.reparentTo(self) self.loadPieInTurret() self.setupWallSphere() if self.getAvatar() == base.localAvatar.doId: self.setupEventSphere() def setupWallSphere(self): sphere = CollisionSphere(0.0, 0.0, 0.0, 3.0) node = CollisionNode('DistributedPieTurret.WallSphere') node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.wallCollNode = self.cannon.attachNewNode(node) self.wallCollNode.setZ(2) self.wallCollNode.setY(1.0) def removeWallSphere(self): if self.wallCollNode: self.wallCollNode.removeNode() self.wallCollNode = None def removeTurret(self): self.removeWallSphere() self.removePieInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm for projs in self.piesInFlight: projs.cleanup() self.piesInFlight = None if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self)
class Suit(Avatar.Avatar): healthColors = (Vec4(0, 1, 0, 1), Vec4(1, 1, 0, 1), Vec4(1, 0.5, 0, 1), Vec4(1, 0, 0, 1), Vec4(0.3, 0.3, 0.3, 1)) healthGlowColors = (Vec4(0.25, 1, 0.25, 0.5), Vec4(1, 1, 0.25, 0.5), Vec4(1, 0.5, 0.25, 0.5), Vec4(1, 0.25, 0.25, 0.5), Vec4(0.3, 0.3, 0.3, 0)) medallionColors = {'c': Vec4(0.863, 0.776, 0.769, 1.0), 's': Vec4(0.843, 0.745, 0.745, 1.0), 'l': Vec4(0.749, 0.776, 0.824, 1.0), 'm': Vec4(0.749, 0.769, 0.749, 1.0)} health2DmgMultiplier = 2.5 def __init__(self): try: self.Suit_initialized return except: self.Suit_initialized = 1 Avatar.Avatar.__init__(self) self.avatarType = CIGlobals.Suit self.name = '' self.chat = '' self.suit = None self.suitHeads = None self.suitHead = None self.loserSuit = None self.healthBarGlow = None self.healthBar = None self.weapon = None self.weapon_sfx = None self.anim = None self.suit_dial = None self.shadow = None self.balloon_sfx = None self.add_sfx = None self.explosion = None self.largeExp = None self.smallExp = None self.death_sfx = None self.attack = None self.wtrajectory = None self.throwObjectId = None self.hasSpawned = False self.suitTrack = None self.headModel = None self.condition = 0 self.type = "" self.head = "" self.team = "" self.isSkele = 0 self.timestampAnimTrack = None self.animFSM = ClassicFSM('Suit', [State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('attack', self.enterAttack, self.exitAttack), State('flydown', self.enterFlyDown, self.exitFlyDown), State('pie', self.enterPie, self.exitPie), State('win', self.enterWin, self.exitWin), State('flyaway', self.enterFlyAway, self.exitFlyAway), State('rollodex', self.enterRollodex, self.exitRollodex), State('flyNeutral', self.enterFlyNeutral, self.exitFlyNeutral), State('flail', self.enterFlail, self.exitFlail), State('drop', self.enterDrop, self.exitDrop), State('drop-react', self.enterDropReact, self.exitDropReact), State('squirt-large', self.enterLSquirt, self.exitLSquirt), State('squirt-small', self.enterSSquirt, self.exitSSquirt), State('soak', self.enterSoak, self.exitSoak)], 'off', 'off') animStateList = self.animFSM.getStates() self.animFSM.enterInitialState() self.initializeBodyCollisions() def delete(self): try: self.Suit_deleted except: self.Suit_deleted = 1 Avatar.Avatar.delete(self) self.weapon = None self.weapon_sfx = None self.suit_dial = None del self.shadowPlacer def disable(self): if self.suitTrack: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.animFSM.requestFinalState() self.cleanupSuit() self.animFSM = None self.avatarType = None self.name = None self.chat = None self.suit = None self.state = None self.weapon_state = None self.suitHeads = None self.suitHead = None self.loserSuit = None self.healthMeterGlow = None self.healthMeter = None self.weapon = None self.weapon_sfx = None self.anim = None self.suit_dial = None self.shadow = None self.balloon_sfx = None self.add_sfx = None self.explosion = None self.largeExp = None self.smallExp = None self.death_sfx = None self.attack = None self.wtrajectory = None self.throwObjectId = None self.hasSpawned = None self.suitTrack = None self.headModel = None self.condition = None self.type = None self.head = None self.team = None self.isSkele = None self.timestampAnimTrack = None Avatar.Avatar.disable(self) def generateSuit(self, suitType, suitHead, suitTeam, suitHealth, skeleton, hideFirst = True): self.type = suitType self.head = suitHead self.isSkele = skeleton self.team = suitTeam self.health = suitHealth self.maxHealth = suitHealth self.cleanupSuit() self.generateBody(suitType, suitTeam, suitHead, skeleton) self.generateHealthMeter() self.generateHead(suitType, suitHead) #self.setupNameTag() self.parentSuitParts() self.rescaleSuit() Avatar.Avatar.initShadow(self) if hideFirst: self.hide() def rescaleSuit(self): self.setAvatarScale(CIGlobals.SuitScales[self.head] / CIGlobals.SuitScaleFactors[self.type]) def parentSuitParts(self): if not self.isSkele: self.headModel.reparentTo(self.find('**/joint_head')) def unparentSuitParts(self): self.getPart('body').reparentTo(self.getGeomNode()) if not self.isSkele: self.headModel.reparentTo(self.getGeomNode()) def generateBody(self, suitType, suitTeam, suitHead, skeleton): self.team = suitTeam self.type = suitType self.head = suitHead self.isSkele = skeleton if suitType == "A": if skeleton: self.loadModel("phase_5/models/char/cogA_robot-zero.bam", "body") else: self.loadModel("phase_3.5/models/char/suitA-mod.bam", "body") self.loadAnims({"neutral": "phase_4/models/char/suitA-neutral.bam", "walk": "phase_4/models/char/suitA-walk.bam", "pie": "phase_4/models/char/suitA-pie-small.bam", "land": "phase_5/models/char/suitA-landing.bam", "throw-object": "phase_5/models/char/suitA-throw-object.bam", "throw-paper": "phase_5/models/char/suitA-throw-paper.bam", "glower": "phase_5/models/char/suitA-glower.bam", "win": "phase_4/models/char/suitA-victory.bam", "rollodex": "phase_5/models/char/suitA-roll-o-dex.bam", "pickpocket": "phase_5/models/char/suitA-pickpocket.bam", "fountainpen": "phase_7/models/char/suitA-fountain-pen.bam", "phone": "phase_5/models/char/suitA-phone.bam", "flail": "phase_4/models/char/suitA-flailing.bam", "drop" : "phase_5/models/char/suitA-drop.bam", "drop-react" : "phase_5/models/char/suitA-anvil-drop.bam", "squirt-large" : "phase_5/models/char/suitA-squirt-large.bam", "squirt-small" : "phase_4/models/char/suitA-squirt-small.bam", "slip-forward" : "phase_4/models/char/suitA-slip-forward.bam", "slip-backward" : "phase_4/models/char/suitA-slip-backward.bam", "sit": "phase_12/models/char/suitA-sit.bam", "speak": "phase_5/models/char/suitA-speak.bam", "fingerwag": "phase_5/models/char/suitA-fingerwag.bam", "soak" : "phase_5/models/char/suitA-soak.bam"}, "body") if suitType == "B": if skeleton: self.loadModel("phase_5/models/char/cogB_robot-zero.bam", "body") else: self.loadModel("phase_3.5/models/char/suitB-mod.bam", "body") self.loadAnims({"neutral": "phase_4/models/char/suitB-neutral.bam", "walk": "phase_4/models/char/suitB-walk.bam", "pie": "phase_4/models/char/suitB-pie-small.bam", "land": "phase_5/models/char/suitB-landing.bam", "throw-object": "phase_5/models/char/suitB-throw-object.bam", "throw-paper": "phase_5/models/char/suitB-throw-paper.bam", "glower": "phase_5/models/char/suitB-magic1.bam", "win": "phase_4/models/char/suitB-victory.bam", "rollodex": "phase_5/models/char/suitB-roll-o-dex.bam", "pickpocket": "phase_5/models/char/suitB-pickpocket.bam", "fountainpen": "phase_5/models/char/suitB-pen-squirt.bam", "phone": "phase_5/models/char/suitB-phone.bam", "flail": "phase_4/models/char/suitB-flailing.bam", "drop" : "phase_5/models/char/suitB-drop.bam", "drop-react" : "phase_5/models/char/suitB-anvil-drop.bam", "squirt-large" : "phase_5/models/char/suitB-squirt-large.bam", "squirt-small" : "phase_4/models/char/suitB-squirt-small.bam", "slip-forward" : "phase_4/models/char/suitB-slip-forward.bam", "slip-backward" : "phase_4/models/char/suitB-slip-backward.bam", "speak": "phase_5/models/char/suitB-speak.bam", "fingerwag": "phase_5/models/char/suitB-finger-wag.bam", "soak" : "phase_5/models/char/suitB-soak.bam"}, "body") if suitType == "C": if skeleton: self.loadModel("phase_5/models/char/cogC_robot-zero.bam", "body") else: self.loadModel("phase_3.5/models/char/suitC-mod.bam", "body") self.loadAnims({"neutral": "phase_3.5/models/char/suitC-neutral.bam", "walk": "phase_3.5/models/char/suitC-walk.bam", "pie": "phase_3.5/models/char/suitC-pie-small.bam", "land": "phase_5/models/char/suitC-landing.bam", "throw-object": "phase_3.5/models/char/suitC-throw-paper.bam", "throw-paper": "phase_3.5/models/char/suitC-throw-paper.bam", "glower": "phase_5/models/char/suitC-glower.bam", "win": "phase_4/models/char/suitC-victory.bam", "pickpocket": "phase_5/models/char/suitC-pickpocket.bam", "fountainpen": "phase_5/models/char/suitC-fountain-pen.bam", "phone": "phase_3.5/models/char/suitC-phone.bam", "flail": "phase_4/models/char/suitC-flailing.bam", "drop" : "phase_5/models/char/suitC-drop.bam", "drop-react" : "phase_5/models/char/suitC-anvil-drop.bam", "squirt-large" : "phase_5/models/char/suitC-squirt-large.bam", "squirt-small" : "phase_3.5/models/char/suitC-squirt-small.bam", "slip-forward" : "phase_4/models/char/suitC-slip-forward.bam", "slip-backward" : "phase_4/models/char/suitC-slip-backward.bam", "sit": "phase_12/models/char/suitC-sit.bam", "speak": "phase_5/models/char/suitC-speak.bam", "fingerwag": "phase_5/models/char/suitC-finger-wag.bam", "soak" : "phase_5/models/char/suitC-soak.bam"}, "body") if skeleton: self.setTwoSided(1) if skeleton: if suitTeam == "s": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_sales.jpg") elif suitTeam == "m": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_money.jpg") elif suitTeam == "l": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_legal.jpg") elif suitTeam == "c": self.suit_tie = loader.loadTexture("phase_5/maps/cog_robot_tie_boss.jpg") self.find('**/tie').setTexture(self.suit_tie, 1) else: if hasattr(self, 'getBattle') and self.getBattle() != None: if self.getBattle().getHoodIndex() == CogBattleGlobals.WaiterHoodIndex: self.suit_blazer = loader.loadTexture("phase_3.5/maps/waiter_m_blazer.jpg") self.suit_leg = loader.loadTexture("phase_3.5/maps/waiter_m_leg.jpg") self.suit_sleeve = loader.loadTexture("phase_3.5/maps/waiter_m_sleeve.jpg") if not hasattr(self, 'getBattle') or self.getBattle() == None or self.getBattle().getHoodIndex() != CogBattleGlobals.WaiterHoodIndex: self.suit_blazer = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_blazer.jpg") self.suit_leg = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_leg.jpg") self.suit_sleeve = loader.loadTexture("phase_3.5/maps/" + suitTeam + "_sleeve.jpg") self.find('**/legs').setTexture(self.suit_leg, 1) self.find('**/arms').setTexture(self.suit_sleeve, 1) self.find('**/torso').setTexture(self.suit_blazer, 1) if suitHead == "coldcaller": self.find('**/hands').setColor(0.55, 0.65, 1.0, 1.0) elif suitHead == "corporateraider": self.find('**/hands').setColor(0.85, 0.55, 0.55, 1.0) elif suitHead == "bigcheese": self.find('**/hands').setColor(0.75, 0.95, 0.75, 1.0) elif suitHead == "bloodsucker": self.find('**/hands').setColor(0.95, 0.95, 1.0, 1.0) elif suitHead == "spindoctor": self.find('**/hands').setColor(0.5, 0.8, 0.75, 1.0) elif suitHead == "legaleagle": self.find('**/hands').setColor(0.25, 0.25, 0.5, 1.0) elif suitHead == "pennypincher": self.find('**/hands').setColor(1.0, 0.5, 0.6, 1.0) elif suitHead == "loanshark": self.find('**/hands').setColor(0.5, 0.85, 0.75, 1.0) else: self.find('**/hands').setColor(CIGlobals.SuitHandColors[suitTeam]) def generateHead(self, suitType, suitHead): self.type = suitType self.head = suitHead if suitHead == "vp": self.headModel = Actor("phase_9/models/char/sellbotBoss-head-zero.bam") self.headModel.loadAnims({"neutral": "phase_9/models/char/bossCog-head-Ff_neutral.bam"}) self.headModel.setTwoSided(True) self.headModel.loop("neutral") self.headModel.setScale(0.35) self.headModel.setHpr(270, 0, 270) self.headModel.setZ(-0.10) else: if suitType == "A" or suitType == "B": heads = loader.loadModel("phase_4/models/char/suit" + suitType + "-heads.bam") else: heads = loader.loadModel("phase_3.5/models/char/suit" + suitType + "-heads.bam") self.headModel = heads.find('**/' + CIGlobals.SuitHeads[suitHead]) if suitHead == "flunky": glasses = heads.find('**/glasses') glasses.reparentTo(self.headModel) glasses.setTwoSided(True) if suitHead in CIGlobals.SuitSharedHeads: if suitHead == "coldcaller": self.headModel.setColor(0.25, 0.35, 1.0, 1.0) else: headTexture = loader.loadTexture("phase_3.5/maps/" + suitHead + ".jpg") self.headModel.setTexture(headTexture, 1) def cleanupSuit(self): self.removeHealthBar() if 'body' in self._Actor__commonBundleHandles: del self._Actor__commonBundleHandles['body'] if self.shadow: self.deleteShadow() if self.headModel: self.headModel.removeNode() self.headModel = None if self.getPart('body'): self.removePart('body') def setName(self, nameString, charName): Avatar.Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName, createNow = 1) def setupNameTag(self): Avatar.Avatar.setupNameTag(self) self.nameTag.setText(self.nameTag.getText() + "\nLevel %d" % self.level) def setChat(self, chatString): self.chat = chatString if self.isSkele: if "?" in chatString: self.suit_dial = base.audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_question.ogg") elif "!" in chatString: self.suit_dial = base.audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_grunt.ogg") else: self.suit_dial = base.audio3d.loadSfx("phase_5/audio/sfx/Skel_COG_VO_statement.ogg") elif self.head in ["vp"]: if "?" in chatString: self.suit_dial = base.audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_question.ogg") elif "!" in chatString: self.suit_dial = base.audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_grunt.ogg") else: self.suit_dial = base.audio3d.loadSfx("phase_9/audio/sfx/Boss_COG_VO_statement.ogg") else: if "?" in chatString: self.suit_dial = base.audio3d.loadSfx( random.choice( [ "phase_3.5/audio/dial/COG_VO_question.ogg", "phase_3.5/audio/dial/COG_VO_question_2.ogg" ] ) ) elif "!" in chatString: self.suit_dial = base.audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_grunt.ogg") else: self.suit_dial = base.audio3d.loadSfx("phase_3.5/audio/dial/COG_VO_statement.ogg") if self.isSkele: base.audio3d.attachSoundToObject(self.suit_dial, self) else: base.audio3d.attachSoundToObject(self.suit_dial, self.headModel) self.suit_dial.play() Avatar.Avatar.setChat(self, chatString) def generateHealthMeter(self): self.removeHealthBar() model = loader.loadModel("phase_3.5/models/gui/matching_game_gui.bam") button = model.find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(self.healthColors[0]) chestNull = self.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button glow = loader.loadModel("phase_3.5/models/props/glow.bam") glow.reparentTo(self.healthBar) glow.setScale(0.28) glow.setPos(-0.005, 0.01, 0.015) glow.setColor(self.healthGlowColors[0]) button.flattenLight() self.healthBarGlow = glow self.condition = 0 if hasattr(self, 'getHealth'): self.updateHealthBar(self.getHealth()) def updateHealthBar(self, hp): if not self.healthBar: return if hp > self.health: self.health = hp #self.health -= hp health = 0.0 try: health = float(hp) / float(self.maxHealth) except: pass if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: if self.condition == 4: taskMgr.remove(self.taskName('blink-task')) blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(self.healthColors[condition], 1) self.healthBarGlow.setColor(self.healthGlowColors[condition], 1) self.condition = condition def __blinkRed(self, task): self.healthBar.setColor(self.healthColors[3], 1) self.healthBarGlow.setColor(self.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return Task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(self.healthColors[4], 1) self.healthBarGlow.setColor(self.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return Task.done def removeHealthBar(self): if self.healthBar: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def enterOff(self, ts = 0): self.anim = None return def exitOff(self): pass def exitGeneral(self): self.stop() def enterFlail(self, ts = 0): self.pingpong("flail", fromFrame = 30, toFrame = 35) def exitFlail(self): self.stop() def enterNeutral(self, ts = 0): self.show() self.timestampAnimTrack = Sequence(Wait(ts), Func(self.loop, "neutral")) self.timestampAnimTrack.start() def exitNeutral(self): self.timestampAnimTrack.pause() self.timestampAnimTrack = None self.exitGeneral() def enterRollodex(self, ts = 0): self.play("rollodex") def exitRollodex(self): self.exitGeneral() def enterWalk(self, ts = 0): self.show() self.timestampAnimTrack = Sequence(Wait(ts), Func(self.loop, "walk")) self.timestampAnimTrack.start() self.disableShadowRay() def exitWalk(self): self.timestampAnimTrack.pause() self.timestampAnimTrack = None self.exitGeneral() self.enableShadowRay() def __moveSuitUpForDropAnim(self): self.getGeomNode().setZ(0.5) def __moveSuitDownToNormal(self): self.getGeomNode().setZ(0) def enterDrop(self, ts = 0): self.suitTrack = Parallel( ActorInterval(self, 'drop')#, #Sequence(Wait(0.1), Func(self.__moveSuitUpForDropAnim), Wait(2.7), Func(self.__moveSuitDownToNormal)) ) self.suitTrack.start() def exitDrop(self): if self.suitTrack: self.suitTrack.finish() self.suitTrack = None def enterDropReact(self, ts = 0): self.play('drop-react') def exitDropReact(self): self.stop() def enterSSquirt(self, ts = 0): self.play('squirt-small') def exitSSquirt(self): self.stop() def enterLSquirt(self, ts = 0): self.play('squirt-large') def exitLSquirt(self): self.stop() def enterSoak(self, ts = 0): self.play('soak') def exitSoak(self): self.stop() def generateLoserSuit(self): if not self.isSkele: handColor = self.find('**/hands').getColor() self.cleanupSuit() if self.type == "A": if self.isSkele: self.loadModel("phase_5/models/char/cogA_robot-lose-mod.bam", 'body') else: self.loadModel("phase_4/models/char/suitA-lose-mod.bam", 'body') self.loadAnims({"lose": "phase_4/models/char/suitA-lose.bam"}, 'body') if self.type == "B": if self.isSkele: self.loadModel("phase_5/models/char/cogB_robot-lose-mod.bam", 'body') else: self.loadModel("phase_4/models/char/suitB-lose-mod.bam", 'body') self.loadAnims({"lose": "phase_4/models/char/suitB-lose.bam"}, 'body') if self.type == "C": if self.isSkele: self.loadModel("phase_5/models/char/cogC_robot-lose-mod.bam", 'body') else: self.loadModel("phase_3.5/models/char/suitC-lose-mod.bam", 'body') self.loadAnims({"lose": "phase_3.5/models/char/suitC-lose.bam"}, 'body') if self.isSkele: self.find('**/tie').setTexture(self.suit_tie, 1) self.setTwoSided(1) else: self.find('**/hands').setColor(handColor) self.find('**/legs').setTexture(self.suit_leg, 1) self.find('**/arms').setTexture(self.suit_sleeve, 1) self.find('**/torso').setTexture(self.suit_blazer, 1) self.generateHead(self.type, self.head) self.rescaleSuit() self.parentSuitParts() self.deleteNameTag() Avatar.Avatar.initShadow(self) def enterDie(self, ts = 0): self.show() self.generateLoserSuit() self.clearChat() self.state = "dead" self.play("lose") deathSound = base.audio3d.loadSfx("phase_3.5/audio/sfx/Cog_Death_Full.ogg") base.audio3d.attachSoundToObject(deathSound, self) trackName = self.uniqueName('enterDie') smallGears = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosionSmall.ptf') smallGears.getParticlesNamed('particles-1').setPoolSize(30) singleGear = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosion.ptf') singleGear.getParticlesNamed('particles-1').setPoolSize(1) smallGearExplosion = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosion.ptf') smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10) bigGearExplosion = ParticleLoader.loadParticleEffect('phase_3.5/etc/gearExplosionBig.ptf') bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) self.smallGears = smallGears self.smallGears.setPos(self.find('**/joint_head').getPos() + (0,0, 2)) self.singleGear = singleGear self.smallGearExp = smallGearExplosion self.bigGearExp = bigGearExplosion gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp)) self.suitTrack = Parallel(Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.3), Func(self.suitExplode), Wait(1.0), Func(self.delSuit)), gearTrack, name = trackName) self.suitTrack.setDoneEvent(self.suitTrack.getName()) Sequence(Wait(0.8), SoundInterval(deathSound)).start() self.acceptOnce(self.suitTrack.getName(), self.exitDie) if "Distributed" in self.__class__.__name__: self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, trackName) self.suitTrack.start(ts) del deathSound def doSingleGear(self): self.singleGear.start(self.getGeomNode()) def doSmallGears(self): self.smallGears.start(self.getGeomNode()) def doSmallExp(self): self.smallGearExp.start(self.getGeomNode()) def doBigExp(self): self.bigGearExp.start(self.getGeomNode()) def suitExplode(self): self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() self.explosion.setDepthWrite(False) if self.isSkele: self.explosion.setPos(self.getPart("body").find('**/joint_head').getPos(render) + (0, 0, 2)) else: self.explosion.setPos(self.headModel.getPos(render) + (0,0,2)) def delSuit(self): self.disableBodyCollisions() def exitDie(self): if self.suitTrack != None: self.ignore(self.suitTrack.getName()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'singleGear'): self.singleGear.cleanup() del self.singleGear if hasattr(self, 'smallGears'): self.smallGears.cleanup() del self.smallGears if hasattr(self, 'smallGearExp'): self.smallGearExp.cleanup() del self.smallGearExp if hasattr(self, 'bigGearExp'): self.bigGearExp.cleanup() del self.bigGearExp if self.explosion: self.explosion.removeNode() self.explosion = None def enterFlyNeutral(self, ts = 0): self.disableRay() self.sfx = base.audio3d.loadSfx("phase_4/audio/sfx/TB_propeller.ogg") self.prop = Actor("phase_4/models/props/propeller-mod.bam", {"chan": "phase_4/models/props/propeller-chan.bam"}) base.audio3d.attachSoundToObject(self.sfx, self.prop) self.prop.reparentTo(self.find('**/joint_head')) self.sfx.setLoop(True) self.sfx.play() self.prop.loop('chan', fromFrame = 0, toFrame = 3) self.setPlayRate(0.8, 'land') self.pingpong('land', fromFrame = 0, toFrame = 10) def exitFlyNeutral(self): self.prop.cleanup() del self.prop base.audio3d.detachSound(self.sfx) del self.sfx self.stop() def enterFlyDown(self, ts = 0): self.disableRay() self.fd_sfx = base.audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_in.ogg") self.prop = Actor("phase_4/models/props/propeller-mod.bam", {"chan": "phase_4/models/props/propeller-chan.bam"}) base.audio3d.attachSoundToObject(self.fd_sfx, self.prop) self.prop.reparentTo(self.find('**/joint_head')) self.fd_sfx.play() dur = self.getDuration('land') if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyDown') else: name = 'enterFlyDown' self.suitTrack = Parallel(Sequence(Func(self.pose, 'land', 0), Func(self.prop.loop, 'chan', fromFrame=0, toFrame=3), Wait(1.75), Func(self.prop.play, 'chan', fromFrame=3), Wait(0.15), ActorInterval(self, 'land', duration=dur)), name = name) if not self.hasSpawned: showSuit = Sequence(Func(self.hideSuit), Wait(0.3), Func(self.showSuit)) self.hasSpawned = True self.suitTrack.append(showSuit) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) def hideSuit(self): self.hide() def showSuit(self): self.show() fadeIn = Sequence(Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1,1,1,1), startColorScale=Vec4(1,1,1,0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() def initializeLocalCollisions(self, name): Avatar.Avatar.initializeLocalCollisions(self, 1, 3, name) def initializeBodyCollisions(self): Avatar.Avatar.initializeBodyCollisions(self, self.avatarType, 6, 2) self.initializeRay(self.avatarType, 2) def exitFlyDown(self): self.initializeRay(self.avatarType, 2) if self.suitTrack != None: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'fd_sfx'): base.audio3d.detachSound(self.fd_sfx) self.exitGeneral() if self.prop: self.prop.cleanup() self.prop = None def enterFlyAway(self, ts = 0): self.show() self.fa_sfx = base.audio3d.loadSfx("phase_5/audio/sfx/ENC_propeller_out.ogg") self.prop = Actor("phase_4/models/props/propeller-mod.bam", {"chan": "phase_4/models/props/propeller-chan.bam"}) base.audio3d.attachSoundToObject(self.fa_sfx, self.prop) self.fa_sfx.play() self.prop.reparentTo(self.find('**/joint_head')) self.prop.setPlayRate(-1.0, "chan") if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyAway') else: name = 'enterFlyAway' self.suitTrack = Sequence(Func(self.prop.play, 'chan', fromFrame=3), Wait(1.75), Func(self.prop.play, 'chan', fromFrame=0, toFrame=3), name = name) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) self.setPlayRate(-1.0, 'land') self.play('land') def exitFlyAway(self): if self.suitTrack: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'fa_sfx'): base.audio3d.detachSound(self.fa_sfx) self.exitGeneral() if self.prop: self.prop.cleanup() self.prop = None def enterAttack(self, attack, target, ts = 0): self.show() if hasattr(self, 'uniqueName'): doneEvent = self.uniqueName('suitAttackDone') else: doneEvent = 'suitAttackDone' self.suitAttackState = SuitAttacks(doneEvent, self, target) self.suitAttackState.load(attack) self.suitAttackState.enter(ts) self.acceptOnce(doneEvent, self.handleSuitAttackDone) def handleSuitAttackDone(self): self.exitAttack() def exitAttack(self): if hasattr(self, 'uniqueName'): self.ignore(self.uniqueName('suitAttackDone')) else: self.ignore('suitAttackDone') if hasattr(self, 'suitAttackState'): self.suitAttackState.exit() if hasattr(self, 'suitAttackState'): self.suitAttackState.unload() if hasattr(self, 'suitAttackState'): del self.suitAttackState def interruptAttack(self): if hasattr(self, 'suitAttackState'): self.suitAttackState.currentAttack.interruptAttack() def handleWeaponTouch(self): if hasattr(self, 'suitAttackState'): self.suitAttackState.currentAttack.handleWeaponTouch() def enterPie(self, ts = 0): self.show() self.play("pie") def exitPie(self): self.exitGeneral() def enterWin(self, ts = 0): self.play("win") def exitWin(self): self.exitGeneral()
class Suit(Avatar): notify = directNotify.newCategory('Suit') audio3d = Audio3DManager(base.sfxManagerList[0], camera) audio3d.setDistanceFactor(25) audio3d.setDropOffFactor(audio3d.getDistanceFactor() / 1000) def __init__(self): Avatar.__init__(self) self.dept = None self.suit = None self.head = None self.headModel = None self.variant = None self.handColor = None self.voice = None self.chat = None self.chatDial = None self.shadow = None self.propeller = None self.smallExp = None self.largeExp = None self.explosion = None self.hasSpawned = False self.suitTrack = None self.timestampAnimTrack = None self.propellerSounds = {} self.healthBar = None self.healthBarGlow = None self.condition = 0 self.avatarType = CIGlobals.Suit self.suitPlan = None self.animFSM = ClassicFSM('Suit', [ State('off', self.enterOff, self.exitOff), State('neutral', self.enterNeutral, self.exitNeutral), State('walk', self.enterWalk, self.exitWalk), State('die', self.enterDie, self.exitDie), State('win', self.enterWin, self.exitWin), State('attack', self.enterAttack, self.exitAttack), State('flail', self.enterFlail, self.exitFlail), State('flyDown', self.enterFlyDown, self.exitFlyDown), State('flyAway', self.enterFlyAway, self.exitFlyAway), State('flyNeutral', self.enterFlyNeutral, self.exitFlyNeutral), State('trayWalk', self.enterTrayWalk, self.exitTrayWalk), State('trayNeutral', self.enterTrayNeutral, self.exitTrayNeutral) ], 'off', 'off') self.animFSM.enterInitialState() self.initializeBodyCollisions() def getNametagJoints(self): return [] # BEGIN STATES def enterOff(self, ts=0): self.anim = None return def exitOff(self): pass def exitGeneral(self): self.stop() def enterTrayWalk(self, ts=0): self.show() self.loop('tray-walk') def exitTrayWalk(self): self.exitGeneral() def enterTrayNeutral(self, ts=0): self.loop('tray-neutral') def exitTrayNeutral(self): self.stop() def enterNeutral(self, ts=0): self.show() self.loop("neutral") def exitNeutral(self): self.exitTimestampAnimTrack() self.exitGeneral() def enterWalk(self, ts=0): self.show() self.loop("walk") self.disableShadowRay() def exitWalk(self): self.exitTimestampAnimTrack() self.exitGeneral() self.enableShadowRay() def enterFlail(self, ts=0): self.pingpong('flail', fromFrame=30, toFrame=35) def exitFlail(self): self.stop() def exitTimestampAnimTrack(self): if self.timestampAnimTrack: self.timestampAnimTrack.pause() self.timestampAnimTrack = None def enterAttack(self, attack, target, ts=0): self.show() if hasattr(self, 'uniqueName'): doneEvent = self.uniqueName('suitAttackDone') else: doneEvent = 'suitAttackDone' self.suitAttackState = SuitAttacks(doneEvent, self, target) self.suitAttackState.load(attack) self.suitAttackState.enter(ts) self.headsUp(target) self.acceptOnce(doneEvent, self.handleSuitAttackDone) def handleSuitAttackDone(self): self.exitAttack() def exitAttack(self): if hasattr(self, 'uniqueName'): self.ignore(self.uniqueName('suitAttackDone')) else: self.ignore('suitAttackDone') if hasattr(self, 'suitAttackState'): self.suitAttackState.exit() if hasattr(self, 'suitAttackState'): self.suitAttackState.unload() if hasattr(self, 'suitAttackState'): del self.suitAttackState def interruptAttack(self): if hasattr(self, 'suitAttackState'): self.suitAttackState.currentAttack.interruptAttack() self.clearChatbox() def handleWeaponTouch(self): if hasattr(self, 'suitAttackState'): currentAttack = self.suitAttackState.currentAttack if hasattr(currentAttack, 'handleWeaponTouch'): currentAttack.handleWeaponTouch() def enterFlyNeutral(self, ts=0): self.disableRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['neutral'] sfx.setLoop(True) base.playSfx(sfx, node=self) self.propeller.loop('chan', fromFrame=0, toFrame=3) self.setPlayRate(0.8, 'land') self.pingpong('land', fromFrame=0, toFrame=10) def exitFlyNeutral(self): self.cleanupPropeller() def enterFlyDown(self, ts=0): self.disableRay() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['in'] base.playSfx(sfx, node=self) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength waitTime = timeTillLanding - animTimeInAir lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyDown') else: name = 'enterFlyDown' animTrack = Sequence(Func(self.pose, 'land', 0), Wait(waitTime), ActorInterval(self, 'land', duration=dur)) propTrack = Parallel( SoundInterval(sfx, duration=waitTime + dur, node=self), Sequence( ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=waitTime + spinTime, startTime=0.0, endTime=spinTime), ActorInterval(self.propeller, 'chan', duration=propDur - openTime, startTime=openTime))) self.suitTrack = Parallel(animTrack, propTrack, name=self.taskName('flyDown')) if not self.hasSpawned: self.show() fadeInTrack = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency)) self.hasSpawned = True self.suitTrack.append(fadeInTrack) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyDown) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) def exitFlyDown(self): self.initializeRay(self.avatarType, 2) if self.suitTrack != None: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.exitGeneral() self.cleanupPropeller() def enterFlyAway(self, ts=0, doFadeOut=0): self.show() if not self.propeller: self.generatePropeller() sfx = self.propellerSounds['out'] if hasattr(self, 'uniqueName'): name = self.uniqueName('enterFlyAway') else: name = 'enterFlyAway' dur = self.getDuration('land') actInt = ActorInterval(self, 'land', loop=0, startTime=dur, endTime=0.0) lastSpinFrame = 8 propDur = self.propeller.getDuration('chan') fr = self.propeller.getFrameRate('chan') spinTime = lastSpinFrame / fr openTime = (lastSpinFrame + 1) / fr propTrack = Parallel( SoundInterval(sfx, node=self), Sequence( Func(self.propeller.show), ActorInterval(self.propeller, 'chan', endTime=openTime, startTime=propDur), ActorInterval(self.propeller, 'chan', constrainedLoop=1, duration=propDur - openTime, startTime=spinTime, endTime=0.0))) self.suitTrack = Parallel(actInt, propTrack, name=self.taskName('trackName')) if doFadeOut: fadeOut = Sequence( Wait(4.0), Func(self.setTransparency, 1), self.colorScaleInterval(1, colorScale=VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, hidden)) self.suitTrack.append(fadeOut) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getDoneEvent(), self.exitFlyAway) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, name) self.suitTrack.start(ts) self.disableRay() def exitFlyAway(self): if self.suitTrack: self.ignore(self.suitTrack.getDoneEvent()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.cleanupPropeller() self.exitGeneral() def enterDie(self, ts=0): self.show() self.generateCog(isLose=1) self.nametag.clearChatText() self.deleteNameTag() deathSound = base.audio3d.loadSfx( "phase_3.5/audio/sfx/Cog_Death_Full.ogg") base.audio3d.attachSoundToObject(deathSound, self) trackName = self.uniqueName('enterDie') smallGears = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionSmall.ptf') smallGears.getParticlesNamed('particles-1').setPoolSize(30) singleGear = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') singleGear.getParticlesNamed('particles-1').setPoolSize(1) smallGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosion.ptf') smallGearExplosion.getParticlesNamed('particles-1').setPoolSize(10) bigGearExplosion = ParticleLoader.loadParticleEffect( 'phase_3.5/etc/gearExplosionBig.ptf') bigGearExplosion.getParticlesNamed('particles-1').setPoolSize(30) smallGears.setDepthWrite(False) singleGear.setDepthWrite(False) smallGearExplosion.setDepthWrite(False) bigGearExplosion.setDepthWrite(False) self.smallGears = smallGears self.smallGears.setPos(self.find('**/joint_head').getPos() + (0, 0, 2)) self.singleGear = singleGear self.smallGearExp = smallGearExplosion self.bigGearExp = bigGearExplosion gearTrack = Sequence(Wait(0.7), Func(self.doSingleGear), Wait(1.5), Func(self.doSmallGears), Wait(3.0), Func(self.doBigExp)) self.suitTrack = Parallel(Sequence( Wait(0.8), SoundInterval(deathSound, node=self, duration=deathSound.length() / 2)), Sequence(Wait(0.7), Func(self.doSingleGear), Wait(4.3), Func(self.suitExplode), Wait(1.0), Func(self.disableBodyCollisions), Func(self.__cleanupExplosion)), gearTrack, Sequence( ActorInterval(self, 'lose', duration=6), Func(self.getGeomNode().hide)), name=trackName) self.suitTrack.setDoneEvent(self.suitTrack.getName()) self.acceptOnce(self.suitTrack.getName(), self.exitDie) self.suitTrack.delayDelete = DelayDelete.DelayDelete(self, trackName) self.suitTrack.start(ts) del deathSound def doSingleGear(self): self.singleGear.start(self.getGeomNode()) def doSmallGears(self): self.smallGears.start(self.getGeomNode()) def doSmallExp(self): self.smallGearExp.start(self.getGeomNode()) def doBigExp(self): self.bigGearExp.start(self.getGeomNode()) def suitExplode(self): self.explosion = loader.loadModel( 'phase_3.5/models/props/explosion.bam') self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() if self.variant == Variant.SKELETON: self.explosion.setPos( self.getPart('body').find('**/joint_head').getPos(render) + (0, 0, 2)) else: self.explosion.setPos(self.headModel.getPos(render) + (0, 0, 2)) def __cleanupExplosion(self): if self.explosion: self.explosion.removeNode() self.explosion = None def exitDie(self): if self.suitTrack != None: self.ignore(self.suitTrack.getName()) self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None if hasattr(self, 'singleGear'): self.singleGear.cleanup() del self.singleGear if hasattr(self, 'smallGears'): self.smallGears.cleanup() del self.smallGears if hasattr(self, 'smallGearExp'): self.smallGearExp.cleanup() del self.smallGearExp if hasattr(self, 'bigGearExp'): self.bigGearExp.cleanup() del self.bigGearExp self.__cleanupExplosion() def enterWin(self, ts=0): self.play('win') def exitWin(self): self.exitGeneral() # END STATES def generate(self, suitPlan, variant, voice=None, hideFirst=True): self.suitPlan = suitPlan self.suit = suitPlan.getSuitType() self.head = suitPlan.getHead() self.dept = suitPlan.getDept() self.handColor = suitPlan.getHandColor() self.variant = variant self.setVoice(voice) self.generateCog() if hideFirst: self.hide() def __blinkRed(self, task): self.healthBar.setColor(SuitGlobals.healthColors[3], 1) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[3], 1) if self.condition == 5: self.healthBar.setScale(1.17) return Task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setColor(SuitGlobals.healthColors[4], 1) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[4], 1) if self.condition == 5: self.healthBar.setScale(1.0) return Task.done def generateHealthBar(self): self.removeHealthBar() button = loader.loadModel('phase_3.5/models/gui/matching_game_gui.bam' ).find('**/minnieCircle') button.setScale(3.0) button.setH(180) button.setColor(SuitGlobals.healthColors[0]) chestNull = self.find('**/def_joint_attachMeter') if chestNull.isEmpty(): chestNull = self.find('**/joint_attachMeter') button.reparentTo(chestNull) self.healthBar = button self.healthBarGlow = loader.loadModel( 'phase_3.5/models/props/glow.bam') self.healthBarGlow.reparentTo(self.healthBar) self.healthBarGlow.setScale(0.28) self.healthBarGlow.setPos(-0.005, 0.01, 0.015) self.healthBarGlow.setColor(SuitGlobals.healthGlowColors[0]) button.flattenLight() self.condition = 0 if hasattr(self, 'getHealth'): self.updateHealthBar(self.getHealth()) def updateHealthBar(self, hp): if not self.healthBar: return if hp > self.health: self.health = hp health = 0.0 try: health = float(hp) / float(self.maxHealth) except: pass if health > 0.95: condition = 0 elif health > 0.7: condition = 1 elif health > 0.3: condition = 2 elif health > 0.05: condition = 3 elif health > 0.0: condition = 4 else: condition = 5 if self.condition != condition: if condition == 4: blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) elif condition == 5: if self.condition == 4: taskMgr.remove(self.taskName('blink-task')) blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.25), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(blinkTask, self.taskName('blink-task')) else: self.healthBar.setColor(SuitGlobals.healthColors[condition], 1) self.healthBarGlow.setColor( SuitGlobals.healthGlowColors[condition], 1) self.condition = condition def removeHealthBar(self): if self.healthBar: self.healthBar.removeNode() self.healthBar = None if self.condition == 4 or self.condition == 5: taskMgr.remove(self.taskName('blink-task')) self.healthCondition = 0 return def initializeLocalCollisions(self, name): self.notify.info('Initializing Local Collisions!') Avatar.initializeLocalCollisions(self, 1, 3, name) def initializeBodyCollisions(self): self.notify.info('Initializing Body Collisions!') Avatar.initializeBodyCollisions(self, self.avatarType, 6, 2) self.initializeRay(self.avatarType, 2) def hideSuit(self): self.hide() def showSuit(self): self.show() fadeIn = Sequence( Func(self.setTransparency, 1), self.colorScaleInterval(0.6, colorScale=Vec4(1, 1, 1, 1), startColorScale=Vec4(1, 1, 1, 0)), Func(self.clearColorScale), Func(self.clearTransparency), Func(self.reparentTo, render)) fadeIn.start() def generateCog(self, isLose=0): self.cleanup() if not isLose: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-zero.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_3.5/models/char/suit%s-mod.bam' % (str(self.suit)), 'body') animations = SuitGlobals.animations anims = {} for anim in animations: if not self.suit in anim.getSuitTypes(): continue path = 'phase_%s/models/char/suit%s-%s.bam' % ( anim.getPhase(), self.suit, anim.getFile()) anims[anim.getName()] = path self.loadAnims(anims, 'body') self.generateHealthBar() self.generatePropeller() else: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.loadModel( 'phase_5/models/char/cog%s_robot-lose-mod.bam' % (str(self.suit)), 'body') else: self.loadModel( 'phase_4/models/char/suit%s-lose-mod.bam' % (str(self.suit)), 'body') self.loadAnims( { 'lose': 'phase_4/models/char/suit%s-lose.bam' % (str(self.suit)) }, 'body') if self.variant != Variant.SKELETON: self.headModel = self.head.generate() self.headModel.reparentTo(self.find('**/joint_head')) if self.suitPlan.getName() == SuitGlobals.VicePresident: self.headModel.setScale(0.35) self.headModel.setHpr(270, 0, 270) self.headModel.setZ(-0.10) self.headModel.loop('neutral') self.setClothes() self.setAvatarScale(self.suitPlan.getScale() / SuitGlobals.scaleFactors[self.suit]) self.setHeight(self.suitPlan.getHeight()) self.setupNameTag() Avatar.initShadow(self) def cleanup(self): self.cleanupPropeller() self.clearChatbox() if self.shadow: self.deleteShadow() if self.getPart('body'): self.removePart('body') if self.headModel: self.headModel.removeNode() self.headModel = None self.timestampAnimTrack = None def generatePropeller(self): self.cleanupPropeller() self.propeller = Actor( 'phase_4/models/props/propeller-mod.bam', {'chan': 'phase_4/models/props/propeller-chan.bam'}) self.propeller.reparentTo(self.find('**/joint_head')) self.propellerSounds['in'] = self.audio3d.loadSfx( SuitGlobals.propellerInSfx) self.propellerSounds['out'] = self.audio3d.loadSfx( SuitGlobals.propellerOutSfx) self.propellerSounds['neutral'] = self.audio3d.loadSfx( SuitGlobals.propellerNeutSfx) for sound in self.propellerSounds.values(): self.audio3d.attachSoundToObject(sound, self.propeller) def cleanupPropeller(self): for sound in self.propellerSounds.values(): self.audio3d.detachSound(sound) sound.stop() self.propellerSounds = {} if self.propeller: self.propeller.cleanup() self.propeller = None def setVoice(self, voice): if not voice: if self.variant == Variant.SKELETON or self.variant == Variant.ZOMBIE: self.voice = Voice.SKELETON else: self.voice = Voice.NORMAL else: self.voice = voice def setClothes(self): if self.variant == Variant.SKELETON: parts = self.findAllMatches('**/pPlane*') for partNum in range(0, parts.getNumPaths()): bb = parts.getPath(partNum) bb.setTwoSided(1) tie = loader.loadTexture('phase_5/maps/cog_robot_tie_%s.jpg' % self.dept.getTie()) tie.setMinfilter(Texture.FTLinearMipmapLinear) tie.setMagfilter(Texture.FTLinear) self.find('**/tie').setTexture(tie, 1) else: prefix = 'phase_3.5/maps/' + self.dept.getClothingPrefix( ) + '_%s.jpg' if self.variant == Variant.WAITER: prefix = 'phase_3.5/maps/waiter_m_%s.jpg' self.find('**/legs').setTexture(loader.loadTexture(prefix % 'leg'), 1) self.find('**/arms').setTexture( loader.loadTexture(prefix % 'sleeve'), 1) self.find('**/torso').setTexture( loader.loadTexture(prefix % 'blazer'), 1) self.find('**/hands').setColor(self.handColor) def setName(self, nameString, charName): Avatar.setName(self, nameString, avatarType=self.avatarType, charName=charName, createNow=1) def setupNameTag(self, tempName=None): Avatar.setupNameTag(self, tempName=tempName) if self.nametag: if self.level > 0: self.nametag.setText(self.nametag.getText() + '\n%s\nLevel %s' % (self.dept.getName(), self.level)) else: self.nametag.setText(self.nametag.getText() + '\n%s' % (self.dept.getName())) def setChat(self, chat): self.clearChatbox() Avatar.setChat(self, chat) self.chat = chat chatDial = None questionDial = self.voice.getSoundFile('question') question02Dial = None gruntDial = self.voice.getSoundFile('grunt') statementDial = self.voice.getSoundFile('statement') if self.voice == Voice.NORMAL: question02Dial = self.voice.getSoundFile('question_2') if '!' in self.chat: chatDial = self.audio3d.loadSfx(gruntDial) elif '?' in self.chat: questionDials = [questionDial] if self.voice == Voice.NORMAL: questionDials.append(question02Dial) chatDial = self.audio3d.loadSfx(random.choice(questionDials)) else: chatDial = self.audio3d.loadSfx(statementDial) self.chatDial = chatDial if self.variant == Variant.SKELETON: self.audio3d.attachSoundToObject(self.chatDial, self) else: self.audio3d.attachSoundToObject(self.chatDial, self.headModel) base.playSfx(self.chatDial, node=self) def clearChatbox(self): self.clearChat() self.chat = None if self.chatDial: self.chatDial.stop() self.chatDial = None def getDept(self): return self.dept def getVariant(self): return self.variant def disable(self): if self.suitTrack: self.suitTrack.finish() DelayDelete.cleanupDelayDeletes(self.suitTrack) self.suitTrack = None self.animFSM.requestFinalState() self.cleanup() Avatar.disable(self) def delete(self): Avatar.delete(self) self.cleanup()
class DistributedCityCart(DistributedNode): notify = directNotify.newCategory('DistributedCityCart') def __init__(self, cr): DistributedNode.__init__(self, cr) self.fsm = ClassicFSM('DistributedCityCart', [State('off', self.enterOff, self.exitOff), State('pathFollow', self.enterPathFollow, self.exitPathFollow), State('collision', self.enterCollision, self.exitCollision)], 'off', 'off') self.fsm.enterInitialState() self.suitInCar = None self.cart = None self.honkSfxPath = 'phase_14/audio/sfx/cogtropolis_citycar_driveby_horn.ogg' self.cartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam' self.moPaths = ['phase_14/models/paths/ct-citycar-drivepath-1.egg', 'phase_14/models/paths/ct-citycar-drivepath-2.egg', 'phase_14/models/paths/ct-citycar-drivepath-3.egg', 'phase_14/models/paths/ct-citycar-drivepath-4.egg', 'phase_14/models/paths/ct-citycar-drivepath-5.egg', 'phase_14/models/paths/ct-citycar-drivepath-6.egg'] self.moPath = None self.soundEngineLoop = None self.soundDriveByHorn = None self.ivalTDisplace = None self.pathIndex = None self.wheelSpinTrack = None self.collNodePath = None self.soundDriveBy = None def setIvalTDisplace(self, displace): self.ivalTDisplace = displace def setPathIndex(self, index): self.pathIndex = index def setState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def enterOff(self): pass def exitOff(self): pass def enterPathFollow(self, ts): duration = CityCartGlobals.index2Duration[self.pathIndex] self.moPath = NURBSMopath.NURBSMopath(self.moPaths[self.pathIndex], name = self.uniqueName('DCityCart_moPath')) startT = 0.0 if ts > 0.0: startT = (ts % duration) * (1.0 / duration) self.moPath.play(self, loop = True, duration = duration, startT = startT) base.taskMgr.add(self.__drive, self.uniqueName('DCityCart.drive')) self.wheelSpinTrack = Parallel() for name in ['leftFrontWheel', 'rightBackWheel', 'rightFrontWheel', 'leftBackWheel']: wheel = self.find('**/' + name) self.wheelSpinTrack.append(LerpHprInterval(wheel, duration = 0.1, hpr = (0, 360, 0), startHpr = (0, 0, 0))) self.wheelSpinTrack.loop() self.accept('enter' + self.collNodePath.node().getName(), self.__handleRanOver) def __handleRanOver(self, entry): self.suitInCar.setChat(CityCartGlobals.SuitRanOverTaunt) self.sendUpdate('hitByCar') self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('squish', callback = self.cr.playGame.getPlace().fsm.request, extraArgs = ['walk']) def __drive(self, task): if base.localAvatar.getDistance(self) < 10.0: if self.soundDriveByHorn.status() == self.soundDriveByHorn.READY: wantsToHonk = random.randint(0, 3) if wantsToHonk == 3: base.playSfx(self.soundDriveByHorn) return task.cont elif base.localAvatar.getDistance(self) < 20.0: if self.soundDriveBy.status() == self.soundDriveBy.READY: base.playSfx(self.soundDriveBy) return task.cont return task.cont def exitPathFollow(self): self.ignore('enter' + self.collNodePath.node().getName()) base.taskMgr.remove(self.uniqueName('DCityCart.drive')) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None def enterCollision(self, ts): pass def exitCollision(self): pass def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) plans = [] for plan in SuitBank.getSuits(): if plan.getSuitType() != SuitType.B: plans.append(plan) plan = random.choice(plans) self.suitInCar = Suit() self.suitInCar.level = 0 self.suitInCar.generate(plan, Variant.NORMAL) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.suitInCar.show() self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.ogg') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping = 1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.ogg') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75) def disable(self): self.fsm.requestFinalState() if self.moPath: self.moPath.stop() self.moPath = None self.moPaths = None self.honkSfxPath = None self.cartModelPath = None self.soundEngineLoop = None self.soundDriveBy = None if self.suitInCar: self.suitInCar.disable() self.suitInCar.delete() self.suitInCar = None if self.cart: self.cart.removeNode() self.cart = None del self.fsm DistributedNode.disable(self)
class AdminPage(StateData): notify = directNotify.newCategory('AdminPage') def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'adminPageDone') self.fsm = ClassicFSM('AdminPage', [ State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('kickSection', self.enterKickSection, self.exitKickSection), State('sysMsgSection', self.enterSysMsgSection, self.exitSysMsgSection) ], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('adminPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.requestFinalState() StateData.exit(self) def unload(self): del self.book del self.parentFSM del self.fsm StateData.unload(self) def enterSysMsgSection(self): self.book.createPageButtons(None, None) self.book.setTitle('System Message') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText( text='Inform all online players about something.', pos=(0, 0.45)) self.msgEntry = DirectEntry( initialText='System Message...', scale=0.055, width=15, numLines=4, command=self.sendSystemMessageCommand, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts, pos=(-0.4, 0, 0)) self.sendBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Send', pos=(0, 0, -0.35), text_pos=(0, -0.01), command=self.sendSystemMessageCommand) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.55), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendSystemMessageCommand(self, foo=None): msg = self.msgEntry.get() base.cr.myDistrict.sendUpdate('systemMessageCommand', [base.localAvatar.getAdminToken(), msg]) self.fsm.request('basePage') def exitSysMsgSection(self): self.infoLbl.destroy() del self.infoLbl self.msgEntry.destroy() del self.msgEntry self.sendBtn.destroy() del self.sendBtn self.cancelBtn.destroy() del self.cancelBtn self.book.clearTitle() self.book.deletePageButtons(False, False) def enterKickSection(self): self.book.createPageButtons(None, None) self.book.setTitle('Kick Player') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText( text='Type the ID of the player you want to boot out.', pos=(0, 0.45)) self.idEntry = DirectEntry( width=10, scale=0.12, pos=(-0.59, 0, 0.15), command=self.sendKickMessage, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick', pos=(0, 0, -0.15), text_pos=(0, -0.01), command=self.sendKickMessage) self.banBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Ban', pos=(0, 0, -0.25), text_pos=(0, -0.01), command=self.sendKickMessage, extraArgs=[None, 1]) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.45), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendKickMessage(self, foo=None, andBan=0): if self.idEntry.get().isspace() or len(self.idEntry.get()) == 0: return print 'Sending out kick request for avatar id: ' + str( self.idEntry.get()) base.localAvatar.sendUpdate('requestEject', [int(self.idEntry.get()), andBan]) self.fsm.request('basePage') def exitKickSection(self): self.banBtn.destroy() del self.banBtn self.infoLbl.destroy() del self.infoLbl self.cancelBtn.destroy() del self.cancelBtn self.idEntry.destroy() del self.idEntry self.kickBtn.destroy() del self.kickBtn self.book.deletePageButtons(False, False) self.book.clearTitle() def enterBasePage(self): self.book.createPageButtons('mapPage', None) self.book.setTitle('Admin Stuff') geom = CIGlobals.getDefaultBtnGeom() self.suitSpawnerBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suitSpawner']) self.killCogsBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kill All Cogs', pos=(-0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['killCogs']) self.makeTournamentBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Tournament', pos=(-0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['tournament']) self.makeInvasionBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Invasion', pos=(-0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['invasion']) self.makeCogBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog', pos=(-0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suit']) self.ghostBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.changeGhost) self.bgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Background', pos=(0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.toggleBackground) self.idBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Player Ids', pos=(0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.togglePlayerIds) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick Player', pos=(0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.openKickPage) self.systemMsgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='System Message', pos=(0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.openSysMsgPage) if base.localAvatar.getGhost(): self.ghostBtn['text'] = 'Turn Ghost Off' else: self.ghostBtn['text'] = 'Turn Ghost On' base.cr.playGame.getPlace().maybeUpdateAdminPage() del geom return def togglePlayerIds(self): if base.cr.isShowingPlayerIds: base.cr.hidePlayerIds() else: base.cr.showPlayerIds() def toggleBackground(self): if render.isHidden(): render.show() else: render.hide() if self.book.book_img.isHidden(): self.book.book_img.show() else: self.book.book_img.hide() def changeGhost(self): if base.localAvatar.getGhost(): base.localAvatar.b_setGhost(0) self.ghostBtn['text'] = 'Turn Ghost On' else: base.localAvatar.b_setGhost(1) self.ghostBtn['text'] = 'Turn Ghost Off' def sendSuitCommand(self, commandName): if base.cr.playGame.suitManager: base.cr.playGame.suitManager.sendUpdate( 'suitAdminCommand', [base.localAvatar.getAdminToken(), commandName]) def openKickPage(self): self.fsm.request('kickSection') def openSysMsgPage(self): self.fsm.request('sysMsgSection') def exitBasePage(self): self.systemMsgBtn.destroy() del self.systemMsgBtn self.idBtn.destroy() del self.idBtn self.kickBtn.destroy() del self.kickBtn self.bgBtn.destroy() del self.bgBtn self.ghostBtn.destroy() del self.ghostBtn self.suitSpawnerBtn.destroy() del self.suitSpawnerBtn self.killCogsBtn.destroy() del self.killCogsBtn self.makeTournamentBtn.destroy() del self.makeTournamentBtn self.makeInvasionBtn.destroy() del self.makeInvasionBtn self.makeCogBtn.destroy() del self.makeCogBtn self.book.clearTitle() self.book.deletePageButtons(True, False)
class DistributedCityCart(DistributedNode): notify = directNotify.newCategory('DistributedCityCart') def __init__(self, cr): DistributedNode.__init__(self, cr) self.fsm = ClassicFSM('DistributedCityCart', [State('off', self.enterOff, self.exitOff), State('pathFollow', self.enterPathFollow, self.exitPathFollow), State('collision', self.enterCollision, self.exitCollision)], 'off', 'off') self.fsm.enterInitialState() self.suitInCar = None self.cart = None self.honkSfxPath = 'phase_14/audio/sfx/cogtropolis_citycar_driveby_horn.mp3' self.cartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam' self.moPaths = ['phase_14/models/paths/ct-citycar-drivepath-1.egg', 'phase_14/models/paths/ct-citycar-drivepath-2.egg', 'phase_14/models/paths/ct-citycar-drivepath-3.egg', 'phase_14/models/paths/ct-citycar-drivepath-4.egg', 'phase_14/models/paths/ct-citycar-drivepath-5.egg', 'phase_14/models/paths/ct-citycar-drivepath-6.egg'] self.moPath = None self.soundEngineLoop = None self.soundDriveByHorn = None self.ivalTDisplace = None self.pathIndex = None self.wheelSpinTrack = None self.collNodePath = None self.soundDriveBy = None return def setIvalTDisplace(self, displace): self.ivalTDisplace = displace def setPathIndex(self, index): self.pathIndex = index def setState(self, state, timestamp): ts = ClockDelta.globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def enterOff(self): pass def exitOff(self): pass def enterPathFollow(self, ts): duration = CityCartGlobals.index2Duration[self.pathIndex] self.moPath = NURBSMopath.NURBSMopath(self.moPaths[self.pathIndex], name=self.uniqueName('DCityCart_moPath')) startT = 0.0 if ts > 0.0: startT = ts % duration * (1.0 / duration) self.moPath.play(self, loop=True, duration=duration, startT=startT) base.taskMgr.add(self.__drive, self.uniqueName('DCityCart.drive')) self.wheelSpinTrack = Parallel() for name in ['leftFrontWheel', 'rightBackWheel', 'rightFrontWheel', 'leftBackWheel']: wheel = self.find('**/' + name) self.wheelSpinTrack.append(LerpHprInterval(wheel, duration=0.1, hpr=(0, 360, 0), startHpr=(0, 0, 0))) self.wheelSpinTrack.loop() self.accept('enter' + self.collNodePath.node().getName(), self.__handleRanOver) def __handleRanOver(self, entry): self.suitInCar.setChat(CityCartGlobals.SuitRanOverTaunt) self.sendUpdate('hitByCar') self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('squish', callback=self.cr.playGame.getPlace().fsm.request, extraArgs=['walk']) def __drive(self, task): if base.localAvatar.getDistance(self) < 10.0: if self.soundDriveByHorn.status() == self.soundDriveByHorn.READY: wantsToHonk = random.randint(0, 3) if wantsToHonk == 3: base.playSfx(self.soundDriveByHorn) return task.cont elif base.localAvatar.getDistance(self) < 20.0: if self.soundDriveBy.status() == self.soundDriveBy.READY: base.playSfx(self.soundDriveBy) return task.cont return task.cont def exitPathFollow(self): self.ignore('enter' + self.collNodePath.node().getName()) if self.wheelSpinTrack: self.wheelSpinTrack.finish() self.wheelSpinTrack = None if self.moPath: self.moPath.stop() self.moPath = None return def enterCollision(self, ts): pass def exitCollision(self): pass def generate(self): DistributedNode.generate(self) self.cart = loader.loadModel(self.cartModelPath) self.cart.reparentTo(self) self.cart.setH(180) heads = [] for head in CIGlobals.SuitBodyData.keys(): if CIGlobals.SuitBodyData[head][0] != 'B': heads.append(head) head = random.choice(heads) suitType = CIGlobals.SuitBodyData[head][0] suitDept = CIGlobals.SuitBodyData[head][1] self.suitInCar = Suit() self.suitInCar.generateSuit(suitType, head, suitDept, 137, 0, False) self.suitInCar.loop('sit') self.suitInCar.disableRay() self.suitInCar.setScale(0.7) self.suitInCar.setH(180) self.suitInCar.setPos(0, -1, -1.5) self.suitInCar.reparentTo(self.cart.find('**/seat1')) self.soundEngineLoop = base.audio3d.loadSfx('phase_6/audio/sfx/KART_Engine_loop_0.wav') base.audio3d.attachSoundToObject(self.soundEngineLoop, self) base.playSfx(self.soundEngineLoop, looping=1) self.soundDriveByHorn = base.audio3d.loadSfx(self.honkSfxPath) base.audio3d.attachSoundToObject(self.soundDriveByHorn, self) self.soundDriveBy = base.audio3d.loadSfx('phase_14/audio/sfx/cogtropolis_citycar_driveby.mp3') base.audio3d.attachSoundToObject(self.soundDriveBy, self) sphere = CollisionSphere(0, 0, 0, 2.5) sphere.setTangible(0) node = CollisionNode(self.uniqueName('cartSphere')) node.setCollideMask(CIGlobals.WallBitmask) node.addSolid(sphere) self.collNodePath = self.attachNewNode(node) self.collNodePath.setZ(1.5) self.collNodePath.setSy(2.0) self.collNodePath.setSx(1.75) def disable(self): self.fsm.requestFinalState() if self.moPath: self.moPath.stop() self.moPath = None self.moPaths = None self.honkSfxPath = None self.cartModelPath = None self.soundEngineLoop = None self.soundDriveBy = None if self.suitInCar: self.suitInCar.disable() self.suitInCar.delete() self.suitInCar = None if self.cart: self.cart.removeNode() self.cart = None del self.fsm DistributedNode.disable(self) return
class BRWater: notify = directNotify.newCategory("BRWater") def __init__(self, playground): self.playground = playground self.fsm = ClassicFSM('BRWater', [ State('off', self.enterOff, self.exitOff), State('freezeUp', self.enterFreezeUp, self.exitFreezeUp), State('coolDown', self.enterCoolDown, self.exitCoolDown), State('frozen', self.enterFrozen, self.exitFrozen) ], 'off', 'off') self.fsm.enterInitialState() #base.localAvatar.audio3d self.freezeUpSfx = base.loadSfx('phase_8/audio/sfx/freeze_up.ogg') self.frozenSfxArray = [ base.loadSfx('phase_8/audio/sfx/frozen_1.ogg'), base.loadSfx('phase_8/audio/sfx/frozen_2.ogg'), base.loadSfx('phase_8/audio/sfx/frozen_3.ogg') ] self.coolSfxArray = [ base.loadSfx('phase_8/audio/sfx/cool_down_1.ogg'), base.loadSfx('phase_8/audio/sfx/cool_down_2.ogg') ] self.iceFormSfx = base.loadSfx("phase_4/audio/sfx/ice_cube_form.ogg") self.iceBreakSfx = base.loadSfx("phase_4/audio/sfx/ice_cube_break.ogg") self.freezeUpSfx.setVolume(12) for sfx in self.frozenSfxArray: sfx.setVolume(12) for sfx in self.coolSfxArray: sfx.setVolume(12) #for sfx in self.frozenSfxArray: # self.attachSound(sfx) #for sfx in self.coolSfxArray: # self.attachSound(sfx) #self.attachSound(self.freezeUpSfx) def attachSound(self, sound): base.localAvatar.audio3d.attachSoundToObject(sound, base.localAvatar) def enterOff(self): self.playground.startWaterWatch() def exitOff(self): self.playground.stopWaterWatch() def loadIceCube(self): self.iceCube = loader.loadModel('phase_8/models/props/icecube.bam') for node in self.iceCube.findAllMatches('**/billboard*'): node.removeNode() for node in self.iceCube.findAllMatches('**/drop_shadow*'): node.removeNode() for node in self.iceCube.findAllMatches('**/prop_mailboxcollisions*'): node.removeNode() self.iceCube.reparentTo(base.localAvatar) self.iceCube.setScale(1.2, 1.0, base.localAvatar.getHeight() / 1.7) self.iceCube.setTransparency(1) self.iceCube.setColorScale(0.76, 0.76, 1.0, 0.0) def unloadIceCube(self): self.iceCube.removeNode() del self.iceCube def enterFreezeUp(self): length = 1.0 base.playSfx(self.freezeUpSfx) self.fucsIval = Sequence( LerpColorScaleInterval( base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(0.5, 0.5, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'frozen')) self.fucsIval.start() self.playground.startWaterWatch(0) def exitFreezeUp(self): self.fucsIval.pause() del self.fucsIval self.playground.stopWaterWatch() def enterFrozen(self): self.loadIceCube() base.playSfx(self.iceFormSfx) base.cr.playGame.getPlace().fsm.request('stop', [0]) base.localAvatar.stop() base.playSfx(choice(self.frozenSfxArray)) self.iccsIval = LerpColorScaleInterval( self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 1.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccsIval.start() props = WindowProperties() props.setCursorHidden(True) base.win.requestProperties(props) self.frame = DirectFrame(pos=(0, 0, 0.7)) self.powerBar = DirectWaitBar(frameColor=(1, 1, 1, 1), range=100, value=0, scale=(0.4, 0.5, 0.25), parent=self.frame, barColor=(0.55, 0.7, 1.0, 1.0)) self.label = OnscreenText(text="SHAKE MOUSE", shadow=(0, 0, 0, 1), fg=(0.55, 0.7, 1.0, 1.0), pos=(0, -0.1, 0), parent=self.frame) taskMgr.add(self.__watchMouseMovement, 'BRWater-watchMouseMovement') taskMgr.add(self.__lowerPowerBar, 'BRWater-lowerPowerBar') mw = base.mouseWatcherNode if mw.hasMouse(): self.lastMouseX = mw.getMouseX() def __lowerPowerBar(self, task): if self.powerBar['value'] <= 0: self.powerBar.update(0) decrement = 1 self.powerBar.update(self.powerBar['value'] - decrement) task.delayTime = 0.1 return task.again def __watchMouseMovement(self, task): if self.powerBar['value'] >= self.powerBar['range']: self.fsm.request('coolDown', [1]) return task.done mw = base.mouseWatcherNode if mw.hasMouse(): if not self.lastMouseX or self.lastMouseX != mw.getMouseX(): value = (abs(self.lastMouseX - mw.getMouseX()) * globalClock.getDt()) / 0.001 self.lastMouseX = mw.getMouseX() self.powerBar.update(self.powerBar['value'] + abs(value)) return task.cont def exitFrozen(self): props = WindowProperties() props.setCursorHidden(False) base.win.requestProperties(props) self.iccsIval.pause() del self.iccsIval self.unloadIceCube() taskMgr.remove('BRWater-lowerPowerBar') taskMgr.remove('BRWater-watchMouseMovement') self.label.destroy() del self.label self.powerBar.destroy() del self.powerBar self.frame.destroy() del self.frame del self.lastMouseX base.cr.playGame.getPlace().fsm.request('walk') base.localAvatar.b_setAnimState('neutral') def enterCoolDown(self, fromFrozen=0): if fromFrozen: self.loadIceCube() base.playSfx(self.iceBreakSfx) self.iceCube.setColorScale(0.76, 0.76, 1.0, 1.0) self.iccdIval = LerpColorScaleInterval( self.iceCube, duration=0.5, colorScale=VBase4(0.76, 0.76, 1.0, 0.0), startColorScale=self.iceCube.getColorScale(), blendType='easeInOut') self.iccdIval.start() length = 1.0 base.playSfx(choice(self.coolSfxArray)) self.cdcsIval = Sequence( LerpColorScaleInterval( base.localAvatar.getGeomNode(), duration=length, colorScale=VBase4(1.0, 1.0, 1.0, 1.0), startColorScale=base.localAvatar.getGeomNode().getColorScale(), blendType='easeOut'), Func(self.fsm.request, 'off')) self.cdcsIval.start() def exitCoolDown(self): if hasattr(self, 'iccdIval'): self.iccdIval.pause() del self.iccdIval self.unloadIceCube() self.cdcsIval.pause() del self.cdcsIval def cleanup(self): self.fsm.requestFinalState() self.playground.stopWaterWatch() del self.fsm del self.freezeUpSfx del self.frozenSfxArray del self.coolSfxArray del self.playground
class TownLoader(StateData): notify = directNotify.newCategory('TownLoader') def __init__(self, hood, parentFSMState, doneEvent): self.hood = hood self.parentFSMState = parentFSMState StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('TownLoader', [ State('start', self.enterStart, self.exitStart, ['quietZone', 'street']), State('street', self.enterStreet, self.exitStreet, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('suitInterior', self.enterSuitInterior, self.exitSuitInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior', 'suitInterior']), State('final', self.enterFinal, self.exitFinal, ['start']) ], 'start', 'final') self.branchZone = None self.canonicalBranchZone = None self.placeDoneEvent = 'placeDone' self.linkTunnels = [] self.place = None return def findAndMakeLinkTunnels(self, requestStatus): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr) zone = LinkTunnel.maybeFixZone(zone) tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone) link = tunnelClass(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self, zoneId): StateData.load(self) self.zoneId = zoneId self.branchZone = ZoneUtil.getBranchZone(zoneId) self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId) self.music = base.loadMusic(self.musicFile) self.interiorMusic = base.loadMusic(self.interiorMusicFile) def unload(self): self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm del self.streetClass self.landmarkBlocks.removeNode() del self.landmarkBlocks self.hood.dnaStore.resetSuitPoints() self.hood.dnaStore.resetBattleCells() del self.hood del self.nodeDict del self.zoneDict del self.fadeInDict del self.fadeOutDict del self.nodeList self.geom.removeNode() del self.geom del self.music del self.interiorMusic ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.unload(self) def enter(self, requestStatus): StateData.enter(self) self.findAndMakeLinkTunnels(requestStatus) self.fsm.enterInitialState() self.setState(requestStatus['where'], requestStatus) def exit(self): self.fsm.requestFinalState() self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.exit(self) def setState(self, state, requestStatus): self.fsm.request(state, [requestStatus]) def enterStart(self): pass def exitStart(self): pass def enterStreet(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.streetDone) self.place = self.streetClass(self, self.fsm, self.placeDoneEvent) self.place.load() def exitStreet(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def streetDone(self): self.requestStatus = self.place.doneStatus status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone( status['zoneId'] ) == self.branchZone and status['shardId'] == None or status[ 'how'] == 'doorOut' or status['where'] == 'suitInterior': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterSuitInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleSuitInteriorDone) self.place = CogOfficeInterior.CogOfficeInterior( self, self.fsm, self.placeDoneEvent) self.place.load() def exitSuitInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) if self.place is not None: self.place.enter(requestStatus) return def handleToonInteriorDone(self): status = self.place.doneStatus if status['loader'] == 'townLoader' and ZoneUtil.getBranchZone( status['zoneId']) == self.branchZone and status[ 'shardId'] == None or status['how'] == 'doorOut': self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def handleSuitInteriorDone(self): self.handleToonInteriorDone() def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getRequestStatus() self.exitQuietZone() self.enterThePlace(status) def enterFinal(self): pass def exitFinal(self): pass def createHood(self, dnaFile, loadStorage=1): if loadStorage: loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.pdna') loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) self.makeDictionaries(self.hood.dnaStore) self.reparentLandmarkBlockNodes() self.renameFloorPolys(self.nodeList) gsg = base.win.getGsg() if gsg: self.geom.prepareScene(gsg) self.geom.flattenLight() self.geom.setName('town_top_level') def reparentLandmarkBlockNodes(self): bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks') npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) def makeDictionaries(self, dnaStore): self.nodeDict = {} self.zoneDict = {} self.zoneVisDict = {} self.nodeList = [] self.fadeInDict = {} self.fadeOutDict = {} a1 = Vec4(1, 1, 1, 1) a0 = Vec4(1, 1, 1, 0) numVisGroups = dnaStore.getNumDNAVisGroupsAI() for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) visGroup = dnaStore.getDNAVisGroupAI(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) zoneId = int(groupName) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): continue else: if ':' in groupName: groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):]) else: groupName = '%s' % zoneId groupNode.setName(groupName) groupNode.flattenMedium() self.nodeDict[zoneId] = [] self.nodeList.append(groupNode) self.zoneDict[zoneId] = groupNode visibles = [] for i in xrange(visGroup.getNumVisibles()): visibles.append(int(visGroup.get_visible(i))) visibles.append(ZoneUtil.getBranchZone(zoneId)) self.zoneVisDict[zoneId] = visibles fadeDuration = 0.5 self.fadeOutDict[groupNode] = Sequence( Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), name='fadeZone-' + str(zoneId), autoPause=1) self.fadeInDict[groupNode] = Sequence( Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1) for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)): visName = dnaStore.getVisibleName(i, j) groupName = base.cr.hoodMgr.extractGroupName(visName) nextZoneId = int(groupName) nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId) visNode = self.zoneDict[nextZoneId] self.nodeDict[zoneId].append(visNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def renameFloorPolys(self, nodeList): for i in nodeList: collNodePaths = i.findAllMatches('**/+CollisionNode') numCollNodePaths = collNodePaths.getNumPaths() visGroupName = i.node().getName() for j in xrange(numCollNodePaths): collNodePath = collNodePaths.getPath(j) bitMask = collNodePath.node().getIntoCollideMask() if bitMask.getBit(1): collNodePath.node().setName(visGroupName)
class DistributedBoat(DistributedObject): notify = directNotify.newCategory("DistributedBoat") def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [ State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast) ], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.ogg' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.ogg' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.ogg' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.ogg' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.track = None self.state = None self.animBoat1Track = None self.animBoatTrack = None # Variables that handle the winter collision node. self.crashColl = None self.crashCollNP = None def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) base.localAvatar.setR(0) base.localAvatar.setP(0) def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.audio3d.loadSfx(self.fogHorn) self.soundShipBell = base.audio3d.loadSfx(self.shipBell) self.soundWaterLap = base.audio3d.loadSfx(self.waterLap) self.soundDockCreak = base.audio3d.loadSfx(self.dockCreak) geom = self.cr.playGame.hood.loader.geom self.boatMdl = geom.find('**/*donalds_boat*') self.boat = geom.find("**/ddBoatRoot") self.boatMdl1 = geom.find("**/ddBoatMdl1") base.audio3d.attachSoundToObject(self.soundFogHorn, self.boat) base.audio3d.attachSoundToObject(self.soundShipBell, self.boat) base.audio3d.attachSoundToObject(self.soundWaterLap, self.boat) base.audio3d.attachSoundToObject(self.soundDockCreak, self.boat) self.soundWaterLap.setLoop(True) self.soundWaterLap.play() self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find( '**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boatMdl) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() speedFactor = 2 self.animBoatTrack = Sequence( LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, -1), startHpr=(0, 0, 1), blendType='easeInOut'), LerpHprInterval(self.boatMdl, duration=1 * speedFactor, hpr=(0, 0, 1), startHpr=(0, 0, -1), blendType='easeInOut')) import math self.animBoat1Track = Sequence( LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, 1, 0), startHpr=(0, -1, 0), blendType='easeInOut'), LerpHprInterval(self.boatMdl1, duration=math.pi * speedFactor, hpr=(0, -1, 0), startHpr=(0, 1, 0), blendType='easeInOut')) self.animBoat1Track.loop() self.animBoatTrack.loop() if base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS: self.boat.setPosHpr(12.73, -1.6, -4.7, 341.57, 350.0, 26.5) self.fsm.request('off') self.crashColl = CollisionSphere(0, 0, 0, 15) self.crashCollNP = self.boat.attachNewNode( CollisionNode('crashed_boat_collision')) self.crashCollNP.node().addSolid(self.crashColl) self.crashCollNP.node().setCollideMask(CIGlobals.WallBitmask) self.crashCollNP.setSz(2) self.crashCollNP.setSx(0.75) self.crashCollNP.setSy(1.25) self.crashCollNP.setPosHpr(2.05, 3.21, 1.66, 8.44, 6.93, 332.61) def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() if self.animBoat1Track: self.animBoat1Track.finish() self.animBoat1Track = None if self.animBoatTrack: self.animBoatTrack.finish() self.animBoatTrack = None if self.crashCollNP: self.crashCollNP.removeNode() del self.crashCollNP del self.crashColl del self.fsm del self.soundFogHorn del self.soundShipBell self.soundWaterLap.stop() del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.boatMdl = None self.boatMdl1 = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp=None): if timestamp is None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat and base.cr.holidayManager.getHoliday( ) != HolidayType.CHRISTMAS: self.fsm.request(state, [ts]) def enterEastToWest(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat, blendType='easeInOut') self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0), blendType='easeInOut'), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None def enterWestToEast(self, ts=0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat, blendType='easeInOut') self.track = Parallel( SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0), blendType='easeInOut'), Sequence( Wait(15.0), Parallel( LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0), blendType='easeInOut'), Sequence( Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass
class AdminPage(StateData): notify = directNotify.newCategory('AdminPage') def __init__(self, book, parentFSM): self.book = book self.parentFSM = parentFSM StateData.__init__(self, 'adminPageDone') self.fsm = ClassicFSM('AdminPage', [State('off', self.enterOff, self.exitOff), State('basePage', self.enterBasePage, self.exitBasePage), State('kickSection', self.enterKickSection, self.exitKickSection), State('sysMsgSection', self.enterSysMsgSection, self.exitSysMsgSection)], 'off', 'off') self.fsm.enterInitialState() self.parentFSM.getStateNamed('adminPage').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def enter(self): StateData.enter(self) self.fsm.request('basePage') def exit(self): self.fsm.requestFinalState() StateData.exit(self) def unload(self): del self.book del self.parentFSM del self.fsm StateData.unload(self) def enterSysMsgSection(self): self.book.createPageButtons(None, None) self.book.setTitle('System Message') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText(text='Inform all online players about something.', pos=(0, 0.45)) self.msgEntry = DirectEntry(initialText='System Message...', scale=0.055, width=15, numLines=4, command=self.sendSystemMessageCommand, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts, pos=(-0.4, 0, 0)) self.sendBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Send', pos=(0, 0, -0.35), text_pos=(0, -0.01), command=self.sendSystemMessageCommand) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.55), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendSystemMessageCommand(self, foo = None): msg = self.msgEntry.get() base.cr.myDistrict.sendUpdate('systemMessageCommand', [base.localAvatar.getAdminToken(), msg]) self.fsm.request('basePage') def exitSysMsgSection(self): self.infoLbl.destroy() del self.infoLbl self.msgEntry.destroy() del self.msgEntry self.sendBtn.destroy() del self.sendBtn self.cancelBtn.destroy() del self.cancelBtn self.book.clearTitle() self.book.deletePageButtons(False, False) def enterKickSection(self): self.book.createPageButtons(None, None) self.book.setTitle('Kick Player') geom = CIGlobals.getDefaultBtnGeom() self.infoLbl = OnscreenText(text='Type the ID of the player you want to boot out.', pos=(0, 0.45)) self.idEntry = DirectEntry(width=10, scale=0.12, pos=(-0.59, 0, 0.15), command=self.sendKickMessage, focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts, focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick', pos=(0, 0, -0.15), text_pos=(0, -0.01), command=self.sendKickMessage) self.banBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Ban', pos=(0, 0, -0.25), text_pos=(0, -0.01), command=self.sendKickMessage, extraArgs=[None, 1]) self.cancelBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Cancel', pos=(-0.45, 0.15, -0.45), text_pos=(0, -0.01), command=self.fsm.request, extraArgs=['basePage']) return def sendKickMessage(self, foo = None, andBan = 0): if self.idEntry.get().isspace() or len(self.idEntry.get()) == 0: return print 'Sending out kick request for avatar id: ' + str(self.idEntry.get()) base.localAvatar.sendUpdate('requestEject', [int(self.idEntry.get()), andBan]) self.fsm.request('basePage') def exitKickSection(self): self.banBtn.destroy() del self.banBtn self.infoLbl.destroy() del self.infoLbl self.cancelBtn.destroy() del self.cancelBtn self.idEntry.destroy() del self.idEntry self.kickBtn.destroy() del self.kickBtn self.book.deletePageButtons(False, False) self.book.clearTitle() def enterBasePage(self): self.book.createPageButtons('releaseNotesPage', None) self.book.setTitle('Admin Stuff') geom = CIGlobals.getDefaultBtnGeom() self.suitSpawnerBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suitSpawner']) self.killCogsBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kill All Cogs', pos=(-0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['killCogs']) self.makeTournamentBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Tournament', pos=(-0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['tournament']) self.makeInvasionBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog Invasion', pos=(-0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['invasion']) self.makeCogBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Make Cog', pos=(-0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.sendSuitCommand, extraArgs=['suit']) self.ghostBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='', pos=(0.45, 0.15, 0.5), text_pos=(0, -0.01), command=self.changeGhost) self.bgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Background', pos=(0.45, 0.15, 0.4), text_pos=(0, -0.01), command=self.toggleBackground) self.idBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Toggle Player Ids', pos=(0.45, 0.15, 0.3), text_pos=(0, -0.01), command=self.togglePlayerIds) self.kickBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='Kick Player', pos=(0.45, 0.15, 0.2), text_pos=(0, -0.01), command=self.openKickPage) self.systemMsgBtn = DirectButton(geom=geom, text_scale=0.04, relief=None, scale=1.0, text='System Message', pos=(0.45, 0.15, 0.1), text_pos=(0, -0.01), command=self.openSysMsgPage) if base.localAvatar.getGhost(): self.ghostBtn['text'] = 'Turn Ghost Off' else: self.ghostBtn['text'] = 'Turn Ghost On' base.cr.playGame.getPlace().maybeUpdateAdminPage() del geom return def togglePlayerIds(self): if base.cr.isShowingPlayerIds: base.cr.hidePlayerIds() else: base.cr.showPlayerIds() def toggleBackground(self): if render.isHidden(): render.show() else: render.hide() if self.book.book_img.isHidden(): self.book.book_img.show() else: self.book.book_img.hide() def changeGhost(self): if base.localAvatar.getGhost(): base.localAvatar.b_setGhost(0) self.ghostBtn['text'] = 'Turn Ghost On' else: base.localAvatar.b_setGhost(1) self.ghostBtn['text'] = 'Turn Ghost Off' def sendSuitCommand(self, commandName): if base.cr.playGame.suitManager: base.cr.playGame.suitManager.sendUpdate('suitAdminCommand', [base.localAvatar.getAdminToken(), commandName]) def openKickPage(self): self.fsm.request('kickSection') def openSysMsgPage(self): self.fsm.request('sysMsgSection') def exitBasePage(self): self.systemMsgBtn.destroy() del self.systemMsgBtn self.idBtn.destroy() del self.idBtn self.kickBtn.destroy() del self.kickBtn self.bgBtn.destroy() del self.bgBtn self.ghostBtn.destroy() del self.ghostBtn self.suitSpawnerBtn.destroy() del self.suitSpawnerBtn self.killCogsBtn.destroy() del self.killCogsBtn self.makeTournamentBtn.destroy() del self.makeTournamentBtn self.makeInvasionBtn.destroy() del self.makeInvasionBtn self.makeCogBtn.destroy() del self.makeCogBtn self.book.clearTitle() self.book.deletePageButtons(True, False)
class DistributedButterflyAI(DistributedNodeAI): notify = directNotify.newCategory('DistributedButterflyAI') def __init__(self, air, hood, wingType): DistributedNodeAI.__init__(self, air) self.hood = hood self.wingType = wingType self.state = 0 self.stateChangeTimestamp = 0.0 self.fromLoc = 0 self.toLoc = 0 self.fsm = ClassicFSM('DBFAI', [State('off', self.enterOff, self.exitOff), State('sit', self.enterSit, self.exitSit), State('fly', self.enterFly, self.exitFly)], 'off', 'off') self.fsm.enterInitialState() def enterOff(self): pass def exitOff(self): pass def enterSit(self, fromLoc, toLoc): taskMgr.doMethodLater(random.uniform(*ButterflyGlobals.SitTime), self.__flySomewhere, self.uniqueName('stopSittingTask')) def __flySomewhere(self, task): toLoc = ButterflyGlobals.Spots[self.hood].index(random.choice(ButterflyGlobals.Spots[self.hood])) fromLoc = self.toLoc self.b_setState(2, fromLoc, toLoc) return task.done def exitSit(self): taskMgr.remove(self.uniqueName('stopSittingTask')) def enterFly(self, fromLoc, toLoc): distance = (ButterflyGlobals.Spots[self.hood][toLoc] - ButterflyGlobals.Spots[self.hood][fromLoc]).length() time = distance / ButterflyGlobals.Speed taskMgr.doMethodLater(time, self.__land, self.uniqueName('landTask')) def __land(self, task): self.b_setState(1, self.toLoc, self.toLoc) return task.done def exitFly(self): taskMgr.remove(self.uniqueName('landTask')) def setState(self, state, fromLoc, toLoc): self.state = state self.fromLoc = fromLoc self.toLoc = toLoc self.fsm.request(ButterflyGlobals.StateIdx2State[state], [fromLoc, toLoc]) def b_setState(self, state, fromLoc, toLoc): self.setState(state, fromLoc, toLoc) self.d_setState(state, fromLoc, toLoc) def d_setState(self, state, fromLoc, toLoc): self.stateChangeTimestamp = globalClockDelta.getRealNetworkTime() self.sendUpdate('setState', [state, fromLoc, toLoc, self.stateChangeTimestamp]) def getState(self): return [self.state, self.fromLoc, self.toLoc, self.stateChangeTimestamp] def getWingType(self): return self.wingType def getHood(self): return self.hood def announceGenerate(self): DistributedNodeAI.announceGenerate(self) loc = ButterflyGlobals.Spots[self.hood].index(random.choice(ButterflyGlobals.Spots[self.hood])) self.b_setState(1, loc, loc) def delete(self): self.fsm.requestFinalState() self.hood = None self.state = None self.toLoc = None self.fromLoc = None self.stateChangeTimestamp = None self.wingType = None DistributedNodeAI.delete(self)
class DistributedBoat(DistributedObject): notify = directNotify.newCategory('DistributedBoat') def __init__(self, cr): DistributedObject.__init__(self, cr) self.fsm = ClassicFSM('DistributedBoat', [State('off', self.enterOff, self.exitOff), State('eastToWest', self.enterEastToWest, self.exitEastToWest), State('westToEast', self.enterWestToEast, self.exitWestToEast)], 'off', 'off') self.boat = None self.eastPier = None self.eastPierPath = 'east_pier' self.westPier = None self.westPierPath = 'west_pier' self.pierUpP = 0.0 self.pierDownP = -45.0 self.fogHorn = 'phase_5/audio/sfx/SZ_DD_foghorn.mp3' self.shipBell = 'phase_6/audio/sfx/SZ_DD_shipbell.mp3' self.waterLap = 'phase_6/audio/sfx/SZ_DD_waterlap.mp3' self.dockCreak = 'phase_6/audio/sfx/SZ_DD_dockcreak.mp3' self.eastWest = 'phase_6/paths/dd-e-w.bam' self.westEast = 'phase_6/paths/dd-w-e.bam' self.boatPath = '*donalds_boat*' self.track = None self.state = None return def __handleOnBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPDonaldsBoat) base.playSfx(self.soundWaterLap, looping=1) def __handleOffBoat(self, entry): base.localAvatar.b_setParent(CIGlobals.SPRender) self.soundWaterLap.stop() def __pollBoat(self, task): try: self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) except: return task.cont self.generated() return task.done def generate(self): DistributedObject.generate(self) self.soundFogHorn = base.loadSfx(self.fogHorn) self.soundShipBell = base.loadSfx(self.shipBell) self.soundWaterLap = base.loadSfx(self.waterLap) self.soundDockCreak = base.loadSfx(self.dockCreak) self.boat = self.cr.playGame.hood.loader.geom.find('**/' + self.boatPath) self.generated() def generated(self): self.eastPier = self.cr.playGame.hood.loader.geom.find('**/' + self.eastPierPath) self.westPier = self.cr.playGame.hood.loader.geom.find('**/' + self.westPierPath) base.cr.parentMgr.registerParent(CIGlobals.SPDonaldsBoat, self.boat) self.accept('enterdonalds_boat_floor', self.__handleOnBoat) self.accept('exitdonalds_boat_floor', self.__handleOffBoat) self.d_requestCurrentStateAndTimestamp() self.fsm.enterInitialState() def disable(self): base.taskMgr.remove(self.uniqueName('__pollBoat')) base.cr.parentMgr.unregisterParent(CIGlobals.SPDonaldsBoat) self.ignore('enterdonalds_boat_floor') self.ignore('exitdonalds_boat_floor') self.fsm.requestFinalState() del self.fsm del self.soundFogHorn del self.soundShipBell del self.soundWaterLap del self.soundDockCreak self.fogHorn = None self.shipBell = None self.waterLap = None self.dockCreak = None self.boat = None self.track = None self.pierDownP = None self.pierUpP = None self.eastPier = None self.eastPierPath = None self.westPier = None self.westPierPath = None self.boatPath = None self.westEast = None self.eastWest = None DistributedObject.disable(self) return def currentStateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def d_requestCurrentStateAndTimestamp(self): self.sendUpdate('requestCurrentStateAndTimestamp', []) def setState(self, state, timestamp = None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.state = state if self.boat: self.fsm.request(state, [ts]) return def enterEastToWest(self, ts = 0): moPath = Mopath.Mopath() moPath.loadFile(self.eastWest) moIval = MopathInterval(moPath, self.boat) self.track = Parallel(SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.eastPier), moIval, LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierDownP, 0), startHpr=(90, self.pierUpP, 0)), Sequence(Wait(15.0), Parallel(LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierUpP, 0), startHpr=(-90, self.pierDownP, 0)), Sequence(Wait(2.0), SoundInterval(self.soundDockCreak, node=self.westPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitEastToWest(self): if self.track: self.track.finish() self.track = None return def enterWestToEast(self, ts = 0): moPath = Mopath.Mopath() moPath.loadFile(self.westEast) moIval = MopathInterval(moPath, self.boat) self.track = Parallel(SoundInterval(self.soundShipBell, node=self.boat), SoundInterval(self.soundDockCreak, node=self.westPier), moIval, LerpQuatInterval(self.westPier, duration=5.0, quat=(-90, self.pierDownP, 0), startHpr=(-90, self.pierUpP, 0)), Sequence(Wait(15.0), Parallel(LerpQuatInterval(self.eastPier, duration=5.0, quat=(90, self.pierUpP, 0), startHpr=(90, self.pierDownP, 0)), Sequence(Wait(2.0), SoundInterval(self.soundDockCreak, node=self.eastPier))), SoundInterval(self.soundFogHorn, node=self.boat))) self.track.start(ts) def exitWestToEast(self): if self.track: self.track.finish() self.track = None return def enterOff(self): pass def exitOff(self): pass
class DistributedPieTurret(DistributedAvatar, DistributedSmoothNode): notify = directNotify.newCategory('DistributedPieTurret') def __init__(self, cr): DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.fsm = ClassicFSM( 'DistributedPieTurret', [ State('off', self.enterOff, self.exitOff), State('scan', self.enterScan, self.exitScan), State('shoot', self.enterShoot, self.exitShoot) ], 'off', 'off' ) self.fsm.enterInitialState() self.reloadTime = 0.25 self.cannon = None self.track = None self.owner = None self.gag = None self.readyGag = None self.hitGag = None self.explosion = None self.wallCollNode = None self.eventCollNode = None self.event = None self.suit = None self.eventId = None self.entities = [] self.upgradeID = None self.deathEvent = None def setOwner(self, avatar): self.owner = avatar def getOwner(self): return self.owner def setGag(self, upgradeId): gags = {0 : CIGlobals.WholeCreamPie, 1 : CIGlobals.WholeFruitPie, 2 : CIGlobals.BirthdayCake, 3 : CIGlobals.WeddingCake} self.gag = gags.get(upgradeId) if not self.readyGag: self.loadGagInTurret() def b_setGag(self, upgradeId): self.sendUpdate('setGag', [upgradeId]) self.setGag(upgradeId) self.upgradeID = upgradeId def getGag(self): return self.gag def getGagID(self): return self.upgradeID def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def announceGenerate(self): DistributedAvatar.announceGenerate(self) DistributedSmoothNode.announceGenerate(self) self.healthLabel.setScale(1.1) self.deathEvent = self.uniqueName('DistributedPieTurret-death') self.makeTurret() def disable(self): self.fsm.requestFinalState() del self.fsm # This should fix crashes related to Sequences. if self.track: self.track.pause() self.track = None # Cleanup entities. for ent in self.entities: ent.cleanup() self.entities = None # Get rid of explosions. if self.explosion: self.explosion.removeNode() self.explosion = None self.removeTurret() DistributedSmoothNode.disable(self) DistributedAvatar.disable(self) def showAndMoveHealthLabel(self): self.unstashHpLabel() self.stopMovingHealthLabel() moveTrack = LerpPosInterval(self.healthLabel, duration = 0.5, pos = Point3(0, 0, 5), startPos = Point3(0, 0, 0), blendType = 'easeOut') self.healthLabelTrack = Sequence(moveTrack, Wait(1.0), Func(self.stashHpLabel)) self.healthLabelTrack.start() # BEGIN STATES def enterShoot(self, suitId): if self.cannon: smoke = loader.loadModel("phase_4/models/props/test_clouds.bam") smoke.setBillboardPointEye() smoke.reparentTo(self.cannon.find('**/cannon')) smoke.setPos(0, 6, -3) smoke.setScale(0.5) smoke.wrtReparentTo(render) self.suit = self.cr.doId2do.get(suitId) self.cannon.find('**/cannon').lookAt(self.suit.find('**/joint_head')) self.cannon.find('**/square_drop_shadow').headsUp(self.suit.find('**/joint_head')) self.track = Sequence(Parallel(LerpScaleInterval(smoke, 0.5, 3), LerpColorScaleInterval(smoke, 0.5, Vec4(2, 2, 2, 0))), Func(smoke.removeNode)) self.track.start() self.createAndShootGag() def exitShoot(self): if hasattr(self, 'suit'): del self.suit def shoot(self, suitId): self.fsm.request('shoot', [suitId]) def scan(self, timestamp = None, afterShooting = 0): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request('scan', [ts, afterShooting]) def buildScanTrack(self, ts = None): if self.track: self.track.pause() self.track = None self.track = Parallel( Sequence( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ), Sequence( LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (60, 0, 0), startHpr = Vec3(-60, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = Vec3(60, 0, 0), blendType = 'easeInOut'), ) ) if ts: self.track.loop(ts) else: self.track.loop() def enterScan(self, ts = 0, afterShooting = 0): if afterShooting: self.track = Parallel( LerpQuatInterval(self.cannon.find('**/cannon'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/cannon').getHpr(), blendType = 'easeInOut'), LerpQuatInterval(self.cannon.find('**/square_drop_shadow'), duration = 3, quat = (-60, 0, 0), startHpr = self.cannon.find('**/square_drop_shadow').getHpr(), blendType = 'easeInOut'), name = "afterShootTrack" + str(id(self)) ) self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self._afterShootTrackDone) self.track.start(ts) else: self.buildScanTrack(ts) def exitScan(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterOff(self): pass def exitOff(self): pass # END STATES def _afterShootTrackDone(self): self.buildScanTrack() def makeTurret(self): self.cannon = loader.loadModel('phase_4/models/minigames/toon_cannon.bam') self.cannon.reparentTo(self) self.loadGagInTurret() self.setupWallSphere() if self.isLocal(): self.setupEventSphere() def removeTurret(self): self.removeWallSphere() self.removeGagInTurret() if self.cannon: self.cannon.removeNode() self.cannon = None def getCannon(self): return self.cannon.find('**/cannon') def setupWallSphere(self): sphere = CollisionSphere(0.0, 0.0, 0.0, 3.0) node = CollisionNode('DistributedPieTurret.WallSphere') node.addSolid(sphere) node.setCollideMask(CIGlobals.WallBitmask) self.wallCollNode = self.cannon.attachNewNode(node) self.wallCollNode.setZ(2) self.wallCollNode.setY(1.0) def removeWallSphere(self): if self.wallCollNode: self.wallCollNode.removeNode() self.wallCollNode = None def createAndShootGag(self): if not self.readyGag: self.loadGagInTurret() if self.readyGag: self.readyGag.shoot(Point3(0, 200, -90)) self.entities.append(self.readyGag) collideEventName = self.readyGag.getCollideEventName() self.readyGag = None if self.isLocal(): self.acceptOnce(collideEventName, self.handleGagCollision) Sequence(Wait(self.reloadTime), Func(self.loadGagInTurret)).start() def loadGagInTurret(self): if self.cannon and self.gag: self.removeGagInTurret() self.eventId = random.uniform(0, 100000000) self.readyGag = TurretGag(self, self.uniqueName('pieTurretCollision') + str(self.eventId), self.gag) self.readyGag.build() def removeGagInTurret(self): if self.readyGag: self.readyGag.cleanup() self.readyGag = None def makeSplat(self, index, pos): if index >= len(self.entities): return ent = self.entities[index] gagClass = ent.gagClass splat = gagClass.buildSplat(gagClass.splatScale, gagClass.splatColor) base.audio3d.attachSoundToObject(gagClass.hitSfx, splat) splat.reparentTo(render) splat.setPos(pos[0], pos[1], pos[2]) gagClass.hitSfx.play() Sequence(Wait(0.5), Func(splat.cleanup)).start() self.hitGag = None def d_makeSplat(self, index, pos): self.sendUpdate('makeSplat', [index, pos]) def b_makeSplat(self, index, pos): self.d_makeSplat(index, pos) self.makeSplat(index, pos) def handleGagCollision(self, entry, ent): x, y, z = ent.getGag().getPos(render) self.b_makeSplat(self.entities.index(ent), [x, y, z]) if self.isLocal(): intoNP = entry.getIntoNodePath() avNP = intoNP.getParent() for key in self.cr.doId2do.keys(): obj = self.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedSuit': if obj.getKey() == avNP.getKey(): if obj.getHealth() > 0: obj.sendUpdate('hitByGag', [ent.getID()]) ent.cleanup() def setHealth(self, hp): DistributedAvatar.setHealth(self, hp) if self.isLocal(): base.localAvatar.getMyBattle().getTurretManager().updateTurretGui() def die(self): self.fsm.requestFinalState() turretPos = self.cannon.getPos(render) self.removeTurret() self.explosion = loader.loadModel("phase_3.5/models/props/explosion.bam") self.explosion.setScale(0.5) self.explosion.reparentTo(render) self.explosion.setBillboardPointEye() self.explosion.setPos(turretPos + (0, 0, 5)) sfx = base.audio3d.loadSfx("phase_3.5/audio/sfx/ENC_cogfall_apart.ogg") base.audio3d.attachSoundToObject(sfx, self) base.playSfx(sfx) messenger.send(self.deathEvent) def isLocal(self): return self.getOwner() == base.localAvatar.doId def getDeathEvent(self): return self.deathEvent
class TownLoader(StateData): notify = directNotify.newCategory("TownLoader") def __init__(self, hood, parentFSMState, doneEvent): self.hood = hood self.parentFSMState = parentFSMState StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('TownLoader', [ State('start', self.enterStart, self.exitStart, ['quietZone', 'street', 'toonInterior']), State('street', self.enterStreet, self.exitStreet, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('suitInterior', self.enterSuitInterior, self.exitSuitInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior', 'suitInterior']), State('final', self.enterFinal, self.exitFinal, ['start']) ], 'start', 'final') self.branchZone = None self.canonicalBranchZone = None self.placeDoneEvent = 'placeDone' self.streetSong = '' self.interiorSong = '' self.linkTunnels = [] self.place = None return def findAndMakeLinkTunnels(self, requestStatus): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr) zone = LinkTunnel.maybeFixZone(zone) tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone) link = tunnelClass(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self, zoneId): StateData.load(self) self.zoneId = zoneId self.branchZone = ZoneUtil.getBranchZone(zoneId) self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId) def unload(self): self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm del self.streetClass base.disablePhysicsNodes(self.landmarkBlocks) self.landmarkBlocks.removeNode() del self.landmarkBlocks self.hood.dnaStore.resetSuitPoints() self.hood.dnaStore.resetBattleCells() del self.hood del self.nodeDict del self.zoneDict del self.fadeInDict del self.fadeOutDict del self.nodeList del self.zoneVisDict base.disablePhysicsNodes(self.geom) self.geom.removeNode() del self.geom del self.streetSong del self.interiorSong #CIGlobals.doSceneCleanup() StateData.unload(self) def enter(self, requestStatus): StateData.enter(self) self.findAndMakeLinkTunnels(requestStatus) self.fsm.enterInitialState() self.setState(requestStatus['where'], requestStatus) def exit(self): self.fsm.requestFinalState() self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.exit(self) def setState(self, state, requestStatus): self.fsm.request(state, [requestStatus]) def enterStart(self): pass def exitStart(self): pass def enterStreet(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.streetDone) self.place = self.streetClass(self, self.fsm, self.placeDoneEvent) self.place.load() def exitStreet(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def streetDone(self): self.requestStatus = self.place.doneStatus status = self.place.doneStatus if (status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] is None or status['how'] == 'doorOut' or status['where'] == 'suitInterior'): self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterSuitInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleSuitInteriorDone) self.place = CogOfficeInterior.CogOfficeInterior( self, self.fsm, self.placeDoneEvent) self.place.load() def exitSuitInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) if self.place is not None: self.place.enter(requestStatus) def handleToonInteriorDone(self): status = self.place.doneStatus if (status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] is None or status['how'] == 'doorOut'): self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def handleSuitInteriorDone(self): self.handleToonInteriorDone() def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getRequestStatus() self.exitQuietZone() self.enterThePlace(status) def enterFinal(self): pass def exitFinal(self): pass def createHood(self, dnaFile, loadStorage=1, flattenNow=True): if loadStorage: loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.pdna') loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) if flattenNow: self.doFlatten() self.geom.setName('town_top_level') def doFlatten(self): self.makeDictionaries(self.hood.dnaStore) self.reparentLandmarkBlockNodes() base.createPhysicsNodes(self.geom) self.renameFloorPolys(self.nodeList) self.geom.flattenLight() CIGlobals.preRenderScene(self.geom) def reparentLandmarkBlockNodes(self): bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks') npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) def makeDictionaries(self, dnaStore): self.nodeDict = {} self.zoneDict = {} self.zoneVisDict = {} self.nodeList = [] self.fadeInDict = {} self.fadeOutDict = {} a1 = Vec4(1, 1, 1, 1) a0 = Vec4(1, 1, 1, 0) numVisGroups = dnaStore.getNumDNAVisGroupsAI() for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) visGroup = dnaStore.getDNAVisGroupAI(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) zoneId = int(groupName) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): continue else: if ':' in groupName: groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):]) else: groupName = '%s' % zoneId groupNode.setName(groupName) CIGlobals.replaceDecalEffectsWithDepthOffsetAttrib(groupNode) #group all the flat walls block2flatwall = {} flatwalls = groupNode.findAllMatches("**/tb*:*_DNARoot;+s") for flatwall in flatwalls: if "toon_landmark" in flatwall.getName(): print "Skipping", flatwall.getName() continue if flatwall.hasTag("DNACode") and flatwall.hasMat(): continue block = int(flatwall.getName().split(":")[0][2:]) if not block2flatwall.has_key(block): block2flatwall[block] = groupNode.attachNewNode( ModelNode('toonBuildingsBlock' + str(block))) flatwall.wrtReparentTo(block2flatwall[block]) for node in block2flatwall.values(): for child in node.findAllMatches("**"): child.clearEffect(DecalEffect.getClassType()) child.clearTag("DNACode") child.clearTag("cam") CIGlobals.clearModelNodesBelow(node) node.flattenStrong() flattenGroup = groupNode.attachNewNode('optim') flattens = ['street*_DNARoot'] removes = ['interactive_prop*_DNARoot'] for remove in removes: for np in groupNode.findAllMatches("**/" + remove): np.removeNode() for flatten in flattens: for np in groupNode.findAllMatches("**/" + flatten): if np.hasTag("DNACode") and np.hasMat(): continue for child in np.findAllMatches("**"): child.clearEffect(DecalEffect.getClassType()) child.clearTag("DNACode") child.clearTag("cam") np.wrtReparentTo(flattenGroup) flattenGroup.clearModelNodes() flattenGroup.flattenStrong() CIGlobals.flattenModelNodes(groupNode) groupNode.flattenStrong() #groupNode.ls() self.nodeDict[zoneId] = [] self.nodeList.append(groupNode) self.zoneDict[zoneId] = groupNode visibles = [] for i in xrange(visGroup.getNumVisibles()): visibles.append(int(visGroup.get_visible(i))) visibles.append(ZoneUtil.getBranchZone(zoneId)) self.zoneVisDict[zoneId] = visibles fadeDuration = 0.5 self.fadeOutDict[groupNode] = Sequence( Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), Func(base.disablePhysicsNodes, groupNode), name='fadeZone-' + str(zoneId), autoPause=1) self.fadeInDict[groupNode] = Sequence( Func(base.enablePhysicsNodes, groupNode), Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1) for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)): visName = dnaStore.getVisibleName(i, j) groupName = base.cr.hoodMgr.extractGroupName(visName) nextZoneId = int(groupName) nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId) visNode = self.zoneDict[nextZoneId] self.nodeDict[zoneId].append(visNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def renameFloorPolys(self, nodeList): for i in nodeList: collNodePaths = i.findAllMatches('**/+BulletRigidBodyNode') numCollNodePaths = collNodePaths.getNumPaths() visGroupName = i.node().getName() for j in xrange(numCollNodePaths): collNodePath = collNodePaths.getPath(j) bitMask = collNodePath.node().getIntoCollideMask() if bitMask == CIGlobals.FloorGroup: collNodePath.node().setName(visGroupName) collNodePath.setCollideMask(CIGlobals.StreetVisGroup)
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 DistributedTakeOverSuit(DistributedSuit): notify = directNotify.newCategory("DistributedTakeOverSuit") StartPosFromDoor = Point3(1.6, -10, -0.5) AtDoorPos = Point3(1.6, -1, 0) def __init__(self, cr): DistributedSuit.__init__(self, cr) self.showNametagInMargins = True self.doorDoId = None self.door = None self.takeOverTrack = None self.fsm = ClassicFSM('DTOS-fsm', [ State('off', self.enterOff, self.exitOff), State('takeOver', self.enterTakeOver, self.exitTakeOver) ], 'off', 'off') self.fsm.enterInitialState() def interruptTakeOver(self): if self.takeOverTrack: self.takeOverTrack.pause() self.takeOverTrack = None def setState(self, state, timestamp): ts = globalClockDelta.localElapsedTime(timestamp) self.fsm.request(state, [ts]) def disable(self): taskMgr.remove('posTask') self.fsm.requestFinalState() self.fsm = None self.doorDoId = None self.door = None if self.takeOverTrack: self.takeOverTrack.finish() self.takeOverTrack = None DistributedSuit.disable(self) def setDoorDoId(self, doId): self.doorDoId = doId self.door = self.cr.doId2do.get(doId) if self.door is None: taskMgr.add(self.__pollDoor, self.uniqueName('pollDoor')) def stateAndTimestamp(self, state, timestamp): self.setState(state, timestamp) def __pollDoor(self, task): self.door = self.cr.doId2do.get(self.doorDoId) if self.door: self.sendUpdate('requestStateAndTimestamp') return task.done return task.cont def getDoorDoId(self): return self.doorDoId def enterOff(self, ts=0): pass def exitOff(self): pass def enterTakeOver(self, ts=0): if not self.door: return self.stopSmooth() self.hasSpawned = False self.doingActivity = True self.reparentTo(self.door.doorNode) self.setHpr(0, 0, 0) self.takeOverTrack = Parallel( Sequence( Func(self.animFSM.request, 'flyDown', [ts]), Wait(6.834), Func(self.loop, 'neutral'), Wait(0.5), Func(self.loop, 'walk'), LerpPosInterval( self, duration=2.0, pos=render.getRelativePoint(self.door.doorNode, self.AtDoorPos), startPos=render.getRelativePoint(self.door.doorNode, self.StartPosFromDoor)), Func(self.loop, 'neutral'), Wait(0.3), Func(self.loop, 'walk'), LerpPosInterval(self, duration=0.5, pos=self.door.enterWalkBackPos, startPos=self.AtDoorPos), Func(self.loop, 'neutral'), Wait(1.0), Func(self.loop, 'walk'), LerpPosInterval(self, duration=1.0, pos=self.door.enterWalkInPos, startPos=self.door.enterWalkBackPos)), LerpPosInterval(self, duration=4.375, pos=render.getRelativePoint( self.door.doorNode, self.StartPosFromDoor), startPos=render.getRelativePoint( self.door.doorNode, self.StartPosFromDoor) + (0, 0, 6.5 * 4.8))) self.takeOverTrack.start(ts) def exitTakeOver(self): self.doingActivity = False if self.takeOverTrack: self.takeOverTrack.pause() self.takeOverTrack = None
class DistributedRaceGame(DistributedMinigame.DistributedMinigame): def __init__(self, cr): try: self.DistributedRaceGame_initialized return except: self.DistributedRaceGame_initialized = 1 DistributedMinigame.DistributedMinigame.__init__(self, cr) self.movement = RaceGameMovement.RaceGameMovement(base.localAvatar) self.skyUtil = SkyUtil() self.raceFSM = ClassicFSM('DistributedRaceGame', [ State('race', self.enterRace, self.exitRace), State('raceTransition', self.enterRaceTransition, self.exitRaceTransition), State('off', self.enterRaceOff, self.exitRaceOff) ], 'off', 'off') self.raceFSM.enterInitialState() self.cr = cr self.track = None self.sky = None self.countSfx = base.loadSfx("phase_5/audio/sfx/firehydrant_popup.ogg") self.goSfx = base.loadSfx("phase_4/audio/sfx/AA_sound_whistle.ogg") self.game = CIGlobals.RaceGame self.trackPath = "phase_4/models/minigames/sprint_track.egg" self.skyPath = "phase_3.5/models/props/TT_sky.bam" self.lanePos = [(-22.00, -205.00, 0.00), (-11.66, -205.00, 0.00), (0.00, -205.00, 0.00), (-33.66, -205.00, 0.00)] self.initialCamPos = { "pos": (41.10, -145.00, 25.88), "hpr": (135.00, 345.96, 0.0) } self.raceCamPos = (-24.52, -37.22, 25.00) self.lane = 0 return def load(self): self.deleteWorld() self.track = loader.loadModel(self.trackPath) self.track.reparentTo(render) self.sky = loader.loadModel(self.skyPath) self.sky.reparentTo(self.track) self.skyUtil.startSky(self.sky) self.setMinigameMusic("phase_4/audio/bgm/MG_toontag.ogg") self.setDescription("Tap the left and right arrow keys repeatedly, in turns, as fast as " + \ "you can to win the race! Every time your power bar hits the top, the boost bar starts" + \ " to fill. When the boost bar is full, press CTRL to boost for a few seconds.") self.setWinnerPrize(100) self.setLoserPrize(5) self.d_requestToonLane() camera.reparentTo(render) camera.setPos(self.initialCamPos["pos"]) camera.setHpr(self.initialCamPos["hpr"]) DistributedMinigame.DistributedMinigame.load(self) def enterPlay(self): DistributedMinigame.DistributedMinigame.enterPlay(self) self.raceFSM.request('raceTransition') def exitPlay(self): DistributedMinigame.DistributedMinigame.exitPlay(self) self.raceFSM.request('off') def enterRace(self): self.startMovement() def exitRace(self): self.stopMovement() def enterRaceOff(self): pass def exitRaceOff(self): pass def enterRaceTransition(self): self.raceTrans = Sequence(Wait(0.5), Func(self.moveCameraToToon), Wait(4.5), Func(self.moveCameraToTop), Wait(4.5), Func(self.startCountdown)) self.raceTrans.start() def exitRaceTransition(self): self.raceTrans.pause() del self.raceTrans def startMovement(self): self.movement.createGui() self.movement.fsm.request('run') def enterGameOver(self, winner=0, winnerDoId=0, allPrize=0): self.raceFSM.request('off') DistributedMinigame.DistributedMinigame.enterGameOver( self, winner, winnerDoId, allPrize) def stopMovement(self): self.movement.cleanup() self.movement.deleteGui() def startCountdown(self): """ Start the countdown to the start of the race. """ self.countdownLbl = DirectLabel(text="", text_scale=0.3, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 1, 0, 1), pos=(0, 0, 0.5)) Sequence(Func(self.setCountdownText, "3"), Wait(1.0), Func(self.setCountdownText, "2"), Wait(1.0), Func(self.setCountdownText, "1"), Wait(1.0), Func(self.setCountdownText, "GO!"), Wait(1.5), Func(self.deleteCountdownLabel)).start() def setCountdownText(self, number): self.countdownLbl['text'] = number if number == "GO!": self.countdownLbl['text_fg'] = (0, 1, 0, 1) self.goSfx.play() self.raceFSM.request('race') else: self.countSfx.play() def deleteCountdownLabel(self): self.countdownLbl.destroy() del self.countdownLbl def moveCameraToToon(self): camPInt = LerpPosInterval(camera, duration=3.0, pos=self.localAv.getPos(render) + (0, 15, 3), startPos=(camera.getPos(render)), blendType="easeInOut") camQInt = camera.quatInterval(3.0, hpr=Vec3(180, 0, 0), blendType="easeInOut") camPInt.start() camQInt.start() def moveCameraToTop(self): camera.setPos(camera.getPos(self.localAv)) camera.reparentTo(self.localAv) oldPos = camera.getPos() camera.setPos(self.raceCamPos) oldHpr = camera.getHpr() camera.lookAt(self.localAv.getPart('head')) newHpr = camera.getHpr() camera.setHpr(oldHpr) camera.setPos(oldPos) camPInt = LerpPosInterval(camera, duration=3.0, pos=self.raceCamPos, startPos=oldPos, blendType="easeInOut") camQInt = camera.quatInterval(3.0, hpr=newHpr, blendType="easeInOut") camPInt.start() camQInt.start() def deleteWorld(self): if self.track: self.track.removeNode() self.track = None if self.sky: self.skyUtil.stopSky() self.sky.removeNode() self.sky = None def setToonLane(self, lane): self.lane = lane base.localAvatar.setPos(self.lanePos[lane]) base.localAvatar.setHpr(0, 0, 0) def getToonLane(self): return self.lane def d_requestToonLane(self): self.sendUpdate('requestToonLane', []) def announceGenerate(self): DistributedMinigame.DistributedMinigame.announceGenerate(self) self.load() def disable(self): DistributedMinigame.DistributedMinigame.disable(self) self.deleteWorld() self.raceFSM.requestFinalState() del self.raceFSM self.countSfx = None self.goSfx = None
class CameraShyFirstPerson(FirstPerson): toonInFocusColor = VBase4(0.25, 1.0, 0.25, 1.0) toonOutOfFocusColor = VBase4(1.0, 1.0, 1.0, 1.0) fullyChargedState = 5 def __init__(self, mg): self.mg = mg self.cameraFocus = None self.batteryFrame = None self.batteryBg = None self.batteryBar = None self.rechargeSound = None self.fullyChargedSound = None self.hasToonInFocus = False self.toonToTakePicOf = None self.cameraRechargeState = None self.cameraRechargingLabel = None self.cameraFlashSeq = None self.camFSM = ClassicFSM('CameraFSM', [State('off', self.enterOff, self.exitOff), State('ready', self.enterCameraReady, self.exitCameraReady), State('recharge', self.enterCameraRecharge, self.exitCameraRecharge)], 'off', 'off') self.camFSM.enterInitialState() FirstPerson.__init__(self) return def movementTask(self, task): if not inputState.isSet('jump') and not base.localAvatar.walkControls.isAirborne and inputState.isSet('forward') or inputState.isSet('reverse') or inputState.isSet('slideLeft') or inputState.isSet('slideRight'): if base.localAvatar.getAnimState() != 'run': base.localAvatar.setAnimState('run') base.localAvatar.playMovementSfx('run') self.mg.sendUpdate('runningAvatar', [base.localAvatar.doId]) elif inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne: if base.localAvatar.getAnimState() != 'jump': base.localAvatar.setAnimState('jump') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('jumpingAvatar', [base.localAvatar.doId]) elif base.localAvatar.getAnimState() != 'neutral': base.localAvatar.setAnimState('neutral') base.localAvatar.playMovementSfx(None) self.mg.sendUpdate('standingAvatar', [base.localAvatar.doId]) return task.cont def enterOff(self): pass def exitOff(self): pass def enterCameraReady(self): self.acceptOnce('mouse1', self.__mouse1Pressed) def stopCameraFlash(self): if self.cameraFlashSeq: self.cameraFlashSeq.finish() self.cameraFlashSeq = None return def __mouse1Pressed(self): self.cameraFlashSeq = Sequence(Func(base.transitions.setFadeColor, 1, 1, 1), Func(base.transitions.fadeOut, 0.1), Wait(0.1), Func(base.transitions.fadeIn, 0.1), Wait(0.1), Func(base.transitions.setFadeColor, 0, 0, 0)) self.cameraFlashSeq.start() self.mg.sendUpdate('remoteAvatarTakePicture', [base.localAvatar.doId]) self.mg.myRemoteAvatar.takePicture() if self.hasToonInFocus and self.toonToTakePicOf: self.mg.sendUpdate('tookPictureOfToon', [self.toonToTakePicOf.doId]) self.camFSM.request('recharge') def exitCameraReady(self): self.ignore('mouse1') def enterCameraRecharge(self): self.batteryBar.update(0) taskMgr.add(self.__rechargeNextState, 'rechargeCamera') def __rechargeNextState(self, task): if self.cameraRechargeState == None: self.cameraRechargeState = -1 self.cameraRechargeState += 1 if self.cameraRechargeState > 0: base.playSfx(self.rechargeSound) self.batteryBar.update(self.cameraRechargeState) if self.cameraRechargeState == self.fullyChargedState: base.playSfx(self.fullyChargedSound) self.camFSM.request('ready') return task.done else: task.delayTime = 1.0 return task.again def exitCameraRecharge(self): taskMgr.remove('rechargeCamera') self.cameraRechargeState = None return def __handleRayInto(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.__handleToonInFocus(obj) def __handleRayOut(self, entry): intoNP = entry.getIntoNodePath() toonNP = intoNP.getParent() for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ == 'DistributedToon': if obj.getKey() == toonNP.getKey(): self.toonToTakePicOf = None self.hasToonInFocus = False if self.cameraFocus.getColorScale() == self.toonInFocusColor: self.cameraFocus.setColorScale(self.toonOutOfFocusColor) return def __handleToonInFocus(self, toon): if not self.hasToonInFocus or self.toonToTakePicOf is not None or self.toonToTakePicOf.doId != toon.doId: self.toonToTakePicOf = toon self.hasToonInFocus = True self.cameraFocus.setColorScale(self.toonInFocusColor) return def start(self): self.fullyChargedSound = base.loadSfx('phase_4/audio/sfx/MG_pairing_match.mp3') self.rechargeSound = base.loadSfx('phase_4/audio/sfx/MG_sfx_travel_game_blue_arrow.mp3') self.batteryFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.2, 0, 0.1), scale=(0.8, 0, 1)) self.batteryBg = OnscreenImage(image='phase_4/maps/battery_charge_frame.png', parent=self.batteryFrame) self.batteryBg.setTransparency(1) self.batteryBg.setX(0.03) self.batteryBg.setScale(0.17, 0, 0.05) self.batteryBar = DirectWaitBar(value=0, range=5, barColor=(1, 1, 1, 1), relief=None, scale=(0.12, 0.0, 0.3), parent=self.batteryFrame) self.cameraFocus = loader.loadModel('phase_4/models/minigames/photo_game_viewfinder.bam') self.cameraFocus.reparentTo(base.aspect2d) self.focusCollHandler = CollisionHandlerEvent() self.focusCollHandler.setInPattern('%fn-into') self.focusCollHandler.setOutPattern('%fn-out') self.focusCollNode = CollisionNode('mouseRay') self.focusCollNP = base.camera.attachNewNode(self.focusCollNode) self.focusCollNode.setCollideMask(BitMask32(0)) self.focusCollNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = CollisionRay() self.focusRay.setFromLens(base.camNode, 0.0, 0.0) self.focusCollNode.addSolid(self.focusRay) base.cTrav.addCollider(self.focusCollNP, self.focusCollHandler) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, 0.0, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) FirstPerson.start(self) return def reallyStart(self): self.accept('mouseRay-into', self.__handleRayInto) self.accept('mouseRay-out', self.__handleRayOut) self.camFSM.request('recharge') taskMgr.add(self.movementTask, 'movementTask') FirstPerson.reallyStart(self) def end(self): self.camFSM.request('off') taskMgr.remove('movementTask') self.ignore('mouseRay-into') self.ignore('mouseRay-out') FirstPerson.end(self) def reallyEnd(self): self.batteryBar.destroy() self.batteryBar = None self.batteryBg.destroy() self.batteryBg = None self.batteryFrame.destroy() self.batteryFrame = None self.cameraFocus.removeNode() self.cameraFocus = None self.focusCollHandler = None self.focusCollNode = None self.focusCollNP.removeNode() self.focusCollNP = None self.focusRay = None self.hasToonInFocus = None self.toonToTakePicOf = None self.fullyChargedSound = None self.rechargeSound = None self.stopCameraFlash() FirstPerson.reallyEnd(self) base.localAvatar.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) return def cleanup(self): self.camFSM.requestFinalState() self.camFSM = None FirstPerson.cleanup(self) return