class PowerBar(NodePath): def __init__(self): NodePath.__init__(self, 'pbar') self.bar = DirectWaitBar(range = 150, frameColor = (1, 1, 1, 1), barColor = (0.286, 0.901, 1, 1), relief = DGG.RAISED, borderWidth = (0.04, 0.04), pos = (0, 0, 0.85), scale = 0.2, hpr = (0, 0, 0), parent = self, frameSize = (-0.85, 0.85, -0.12, 0.12)) self.hide() self.reparentTo(aspect2d) self.speed = 0.2 self.exponent = 0.75 self.startTime = 0.0 self.task = None def __getPower(self, time): elapsed = max(time - self.startTime, 0.0) t = elapsed / self.speed t = math.pow(t, self.exponent) power = int(t * 150) % 300 if power > 150: power = 300 - power return power def getPower(self): return self.bar['value'] def start(self): taskMgr.remove("hideBarTask-" + str(id(self))) self.startTime = globalClock.getFrameTime() self.task = taskMgr.add(self.__powerBarUpdate, "powerBarUpdate-" + str(id(self))) self.show() def __powerBarUpdate(self, task): self.bar['value'] = self.__getPower(globalClock.getFrameTime()) return task.cont def stop(self, hideAfter = -1): if self.task: self.task.remove() self.task = None if hideAfter != -1: taskMgr.doMethodLater(hideAfter, self.__hideBarTask, "hideBarTask-" + str(id(self))) def __hideBarTask(self, task): self.hide() return task.done def destroy(self): taskMgr.remove("hideBarTask-" + str(id(self))) taskMgr.remove("powerBarUpdate-" + str(id(self))) self.stop() self.speed = None self.exponent = None self.startTime = None self.bar.destroy() self.bar = None self.removeNode()
class FloatingBar: def __init__(self, unit): self.unit = unit self.node = unit.base_node.attach_new_node("floating bar node") self.node.set_pos(0, 0, unit.actor.HEIGHT) self.health_bar = DirectWaitBar( value=unit.health, parent=self.node, frameColor=(1, 0, 0, 0.3), barColor=(0, 1, 0, 1), ) self.health_bar.reparent_to(self.node) self.health_bar.set_scale(0.13) self.health_bar.set_compass(core.instance.camera) self.mana_bar = DirectWaitBar(value=unit.mana, pos=(0, 0, -0.03), parent=self.node, frameColor=(0, 0, 0, 0.3), barColor=(0, 0, 1, 1), frameSize=(-1, 1, 0.05, 0.15)) self.mana_bar.reparent_to(self.node) self.mana_bar.set_scale(0.13) self.mana_bar.set_compass(core.instance.camera) font = MainFont() self.name_label = DirectLabel( text=unit.name, pos=(0, 0, 0.03), scale=0.04, parent=self.node, text_bg=(0, 0, 0, 0), text_fg=(1, 1, 1, 1), frameColor=(0, 0, 0, 0), text_font=font, ) self.name_label.set_compass(core.instance.camera) def update_vertical_position(self): self.node.set_pos(0, 0, self.unit.actor.HEIGHT) def destroy(self): self.mana_bar.destroy() self.health_bar.destroy() self.name_label.destroy()
class RemoteDodgeballAvatar(RemoteAvatar): """A wrapper around a remote DistributedToon for use in the Dodgeball minigame (client side)""" notify = directNotify.newCategory("RemoteDodgeballAvatar") def __init__(self, mg, cr, avId): RemoteAvatar.__init__(self, mg, cr, avId) self.health = 100 self.retrieveAvatar() if game.process == 'client': self.healthBar = DirectWaitBar(value=100) self.healthBar.setBillboardAxis() self.healthBar.reparentTo(self.avatar) self.healthBar.setZ(self.avatar.nametag3d.getZ(self.avatar) + 1) print "generated health bar" def setHealth(self, hp): self.avatar.announceHealth(0, self.health - hp) self.health = hp self.healthBar['value'] = hp print self.healthBar['value'] ToontownIntervals.start( ToontownIntervals.getPulseSmallerIval( self.healthBar, self.mg.uniqueName('RemoteDodgeballAvatar-PulseHPBar'))) def setTeam(self, team): print "set team {0}".format(team) RemoteAvatar.setTeam(self, team) self.healthBar['barColor'] = TEAM_COLOR_BY_ID[team] self.teamText.node().setText("") self.teamText.node().setTextColor(TEAM_COLOR_BY_ID[team]) def cleanup(self): self.healthBar.destroy() self.healthbar = None self.health = None RemoteAvatar.cleanup(self)
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 CIProgressScreen: def __init__(self): self.defaultLogoScale = 0.85 self.defaultLogoZ = 0.65 self.bgm = loader.loadModel('phase_3/models/gui/progress-background.bam') self.bgm.find('**/logo').stash() self.bg = self.bgm.find('**/bg') self.logo = loader.loadTexture('phase_3/maps/CogInvasion_Logo.png') self.logoNode = hidden.attachNewNode('logoNode') self.logoNode.setScale(self.defaultLogoScale) self.logoNode.setPos(0, self.defaultLogoZ, 0) self.logoImg = OnscreenImage(image=self.logo, scale=(0.685, 0, 0.3), parent=self.logoNode) self.logoImg.setTransparency(True) self.bg_img = OnscreenImage(image=self.bg, parent=hidden) self.bg_img.setSx(1.35) self.bg_img.hide() self.progress_bar = DirectWaitBar(value=0, pos=(0, 0, -0.85), parent=hidden, text_pos=(0, 0, 0.2)) self.progress_bar.setSx(1.064) self.progress_bar.setSz(0.38) toontipgui = loader.loadModel('phase_3.5/models/gui/stickerbook_gui.bam') poster = toontipgui.find('**/questCard') self.toontipFrame = DirectFrame(image=poster, image_scale=(1.4, 1, 1), parent=hidden, relief=None, pos=(0, 0, -0.1), scale=0.85) self.toontipLbl = OnscreenText(text='', parent=self.toontipFrame, fg=(0.35, 0.35, 0.35, 1), font=CIGlobals.getToonFont(), wordwrap=14.5, pos=(-0.59, 0.25), align=TextNode.ALeft, scale=0.08) self.loading_lbl = DirectLabel(text='', relief=None, scale=0.08, pos=(-1.0725, 0, -0.79), text_align=TextNode.ALeft, sortOrder=100, text_fg=(0.343, 0.343, 0.343, 1.0), text_font=CIGlobals.getMinnieFont(), parent=hidden, text_shadow=(0, 0, 0, 1)) return def begin(self, hood, range, wantGui): render.hide() self.renderFrames() base.setBackgroundColor(0, 0, 0) if hood == 'localAvatarEnterGame': self.loading_lbl['text'] = 'Entering...' else: if hood == 'init': self.loading_lbl['text'] = 'Loading...' else: self.loading_lbl['text'] = 'Heading to %s...' % hood self.progress_bar['barColor'] = (0.343, 0.343, 0.343, 1.0) self.progress_bar['range'] = range self.bgm.reparentTo(aspect2d) self.bg.reparentTo(render2d) self.bg_img.reparentTo(hidden) self.loading_lbl.reparentTo(aspect2d) self.logoNode.reparentTo(aspect2d) self.progress_bar.reparentTo(aspect2d) tip = random.choice(CIGlobals.ToonTips) self.toontipLbl.setText('TOON TIP:\n' + tip) self.toontipFrame.reparentTo(aspect2d) self.__count = 0 self.__expectedCount = range self.progress_bar.update(self.__count) def renderFramesTask(self, task): self.renderFrames() return task.cont def end(self): base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) taskMgr.remove('renderFrames') render.show() self.progress_bar.finish() self.bg_img.reparentTo(hidden) self.logoNode.reparentTo(hidden) self.bg.reparentTo(hidden) self.bgm.reparentTo(hidden) self.loading_lbl.reparentTo(hidden) self.progress_bar.reparentTo(hidden) self.toontipFrame.reparentTo(hidden) self.renderFrames() def destroy(self): self.bg.removeNode() del self.bg self.bgm.removeNode() del self.bgm self.bg_img.destroy() self.loading_lbl.destroy() self.progress_bar.destroy() self.bgm.destroy() del self.bg_img del self.loading_lbl del self.progress_bar del self.bgm def renderFrames(self): base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def tick(self): self.__count += 1 self.progress_bar.update(self.__count)
class BossBattleHealthBar(DirectFrame): def __init__(self, dept, maxHp, **kw): DirectFrame.__init__(self, parent=render2d, relief=None, **kw) self.dept = dept self.filePrefix = ModelDict[dept] self.maxHp = float(maxHp) self.hp = self.maxHp self.head = None self.headActor = None self.animDict = {} self.healthBar = None self.healthCondition = None self.hitInterval = None self.blinkTask = None self.dizzy = False self.helmet = False self.healthColors = Suit.Suit.healthColors def load(self): self.head = loader.loadModel(self.filePrefix + '-head-zero') for anim in AnimList: self.animDict[anim] = '%s-%s-%s' % (GenericModel, 'head', anim) self.headActor = Actor(self.head, self.animDict) self.headActor.hide() self.headActor.setBin("fixed", 40) self.headActor.setDepthTest(True) self.headActor.setDepthWrite(True) self.headActor.reparentTo(self) self.headActor.setHpr(-90, 0, 270) self.headActor.setScale(0.021) self.headActor.setPos(-0.25, 0.0, 0.75) self.headActor.setPlayRate(2.0, 'turn2Fb') self.headActor.loop('Ff_neutral') self.eyes = loader.loadModel('phase_10/models/cogHQ/CashBotBossEyes.bam') self.eyes.setPosHprScale(4.5, 0, -2.5, 90, 90, 0, 0.4, 0.4, 0.4) self.eyes.reparentTo(self.headActor) self.eyes.hide() self.stars = globalPropPool.getProp('stun') self.stars.setPosHprScale(7, 0, 0, 0, 0, -90, 3, 3, 3) self.stars.loop('stun') self.safe = loader.loadModel('phase_10/models/cogHQ/CBSafe.bam') self.safe.reparentTo(self.headActor) self.safe.setPosHpr(-1, 0, 0.2, 0, -90, 90) self.safe.setBin("fixed", 40) self.safe.setDepthTest(True) self.safe.setDepthWrite(True) self.safe.hide() self.headActor.show() self.healthBar = DirectWaitBar(parent=self, pos=(0, 0, 0.85), relief=DGG.SUNKEN, frameSize=(-1.75, 1.75, -0.3, 0.3), borderWidth=(0.02, 0.02), scale=0.1, range=1, sortOrder=50, frameColor=(0.5, 0.5, 0.5, 0.5), barColor=(0.75, 0.75, 1.0, 0.8), text='', text_scale=0.35, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05), text_font=getSuitFont()) self.updateHealthBar(self.maxHp) def getHealthCondition(self, hp): hp /= self.maxHp print hp if hp > 0.95: condition = 0 elif hp > 0.9: condition = 1 elif hp > 0.8: condition = 2 elif hp > 0.7: condition = 3 elif hp > 0.6: condition = 4 elif hp > 0.5: condition = 5 elif hp > 0.3: condition = 6 elif hp > 0.15: condition = 7 elif hp > 0.05: condition = 8 elif hp > 0.0: condition = 9 else: condition = 9 return condition def updateHealthBar(self, hp): self.hp = float(hp) self.healthCondition = self.getHealthCondition(hp) if self.healthCondition == 9 and hp > 0: if self.blinkTask is None: self.startBlinkTask() elif self.blinkTask: self.stopBlinkTask() if self.healthBar: self.healthBar.setProp('text', str(int(hp))) self.healthBar.setProp('barColor', self.healthColors[self.healthCondition]) self.healthBar.setProp('value', hp / self.maxHp) self.doHit() def cleanupHit(self): if self.hitInterval: self.hitInterval.finish() self.hitInterval = None return def doHit(self): self.cleanupHit() if not self.headActor: return self.hitInterval = Sequence( Parallel( Sequence( Func(self.headActor.setColorScale, 1, 1, 1, 1), self.headActor.colorScaleInterval(0.1, colorScale=VBase4(1, 0, 0, 1)), self.headActor.colorScaleInterval(0.3, colorScale=VBase4(1, 1, 1, 1)) ), ActorInterval(self.headActor, 'turn2Fb') ), Func(self.headActor.loop, 'Ff_neutral') ) self.hitInterval.start() def startBlinkTask(self): self.blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75), Task(self.__blinkGray), Task.pause(0.1)) taskMgr.add(self.blinkTask, 'bosshealthbar-blink-task') def __blinkRed(self, task): if not self.healthBar: return self.healthBar.setProp('barColor', self.healthColors[8]) return Task.done def __blinkGray(self, task): if not self.healthBar: return self.healthBar.setProp('barColor', self.healthColors[9]) return Task.done def stopBlinkTask(self): taskMgr.remove('bosshealthbar-blink-task') self.blinkTask = None def setDizzy(self, dizzy): self.dizzy = dizzy if dizzy: self.stars.reparentTo(self.headActor) else: self.stars.detachNode() def setHelmet(self, helmet): self.helmet = helmet if helmet: self.safe.show() self.eyes.show() else: self.safe.hide() self.eyes.hide() def destroy(self): self.cleanupHit() self.stars.cleanup() self.stopBlinkTask() self.healthBar.destroy() self.headActor.delete() self.head.removeNode() self.safe.removeNode() self.eyes.removeNode()
class DistributedMazeGame(DistributedMinigame): notify = directNotify.newCategory('DistributedMazeGame') CAMERA_TASK = 'MazeGameCameraTask' UPDATE_SUITS_TASK = 'MazeGameUpdateSuitsTask' TREASURE_GRAB_EVENT_NAME = 'MazeTreasureGrabbed' def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedMazeGame', [ State.State('off', self.enterOff, self.exitOff, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup', 'showScores']), State.State('showScores', self.enterShowScores, self.exitShowScores, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, []) ], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.usesLookAround = 1 def getTitle(self): return TTLocalizer.MazeGameTitle def getInstructions(self): return TTLocalizer.MazeGameInstructions def getMaxDuration(self): return MazeGameGlobals.GAME_DURATION def __defineConstants(self): self.TOON_SPEED = 8.0 self.TOON_Z = 0 self.MinSuitSpeedRange = [0.8 * self.TOON_SPEED, 0.6 * self.TOON_SPEED] self.MaxSuitSpeedRange = [1.1 * self.TOON_SPEED, 2.0 * self.TOON_SPEED] self.FASTER_SUIT_CURVE = 1 self.SLOWER_SUIT_CURVE = self.getDifficulty() < 0.5 self.slowerSuitPeriods = { 2000: { 4: [128, 76], 8: [128, 99, 81, 68], 12: [128, 108, 93, 82, 74, 67], 16: [128, 112, 101, 91, 83, 76, 71, 66] }, 1000: { 4: [110, 69], 8: [110, 88, 73, 62], 12: [110, 95, 83, 74, 67, 61], 16: [110, 98, 89, 81, 75, 69, 64, 60] }, 5000: { 4: [96, 63], 8: [96, 79, 66, 57], 12: [96, 84, 75, 67, 61, 56], 16: [96, 87, 80, 73, 68, 63, 59, 55] }, 4000: { 4: [86, 58], 8: [86, 71, 61, 53], 12: [86, 76, 68, 62, 56, 52], 16: [86, 78, 72, 67, 62, 58, 54, 51] }, 3000: { 4: [78, 54], 8: [78, 65, 56, 49], 12: [78, 69, 62, 57, 52, 48], 16: [78, 71, 66, 61, 57, 54, 51, 48] }, 9000: { 4: [71, 50], 8: [71, 60, 52, 46], 12: [71, 64, 58, 53, 49, 45], 16: [71, 65, 61, 57, 53, 50, 47, 45] } } self.slowerSuitPeriodsCurve = { 2000: { 4: [128, 65], 8: [128, 78, 66, 64], 12: [128, 88, 73, 67, 64, 64], 16: [128, 94, 79, 71, 67, 65, 64, 64] }, 1000: { 4: [110, 59], 8: [110, 70, 60, 58], 12: [110, 78, 66, 61, 59, 58], 16: [110, 84, 72, 65, 61, 59, 58, 58] }, 5000: { 4: [96, 55], 8: [96, 64, 56, 54], 12: [96, 71, 61, 56, 54, 54], 16: [96, 76, 65, 59, 56, 55, 54, 54] }, 4000: { 4: [86, 51], 8: [86, 59, 52, 50], 12: [86, 65, 56, 52, 50, 50], 16: [86, 69, 60, 55, 52, 51, 50, 50] }, 3000: { 4: [78, 47], 8: [78, 55, 48, 47], 12: [78, 60, 52, 48, 47, 47], 16: [78, 63, 55, 51, 49, 47, 47, 47] }, 9000: { 4: [71, 44], 8: [71, 51, 45, 44], 12: [71, 55, 48, 45, 44, 44], 16: [71, 58, 51, 48, 45, 44, 44, 44] } } self.fasterSuitPeriods = { 2000: { 4: [54, 42], 8: [59, 52, 47, 42], 12: [61, 56, 52, 48, 45, 42], 16: [61, 58, 54, 51, 49, 46, 44, 42] }, 1000: { 4: [50, 40], 8: [55, 48, 44, 40], 12: [56, 52, 48, 45, 42, 40], 16: [56, 53, 50, 48, 45, 43, 41, 40] }, 5000: { 4: [47, 37], 8: [51, 45, 41, 37], 12: [52, 48, 45, 42, 39, 37], 16: [52, 49, 47, 44, 42, 40, 39, 37] }, 4000: { 4: [44, 35], 8: [47, 42, 38, 35], 12: [48, 45, 42, 39, 37, 35], 16: [49, 46, 44, 42, 40, 38, 37, 35] }, 3000: { 4: [41, 33], 8: [44, 40, 36, 33], 12: [45, 42, 39, 37, 35, 33], 16: [45, 43, 41, 39, 38, 36, 35, 33] }, 9000: { 4: [39, 32], 8: [41, 37, 34, 32], 12: [42, 40, 37, 35, 33, 32], 16: [43, 41, 39, 37, 35, 34, 33, 32] } } self.fasterSuitPeriodsCurve = { 2000: { 4: [62, 42], 8: [63, 61, 54, 42], 12: [63, 63, 61, 56, 50, 42], 16: [63, 63, 62, 60, 57, 53, 48, 42] }, 1000: { 4: [57, 40], 8: [58, 56, 50, 40], 12: [58, 58, 56, 52, 46, 40], 16: [58, 58, 57, 56, 53, 49, 45, 40] }, 5000: { 4: [53, 37], 8: [54, 52, 46, 37], 12: [54, 53, 52, 48, 43, 37], 16: [54, 54, 53, 51, 49, 46, 42, 37] }, 4000: { 4: [49, 35], 8: [50, 48, 43, 35], 12: [50, 49, 48, 45, 41, 35], 16: [50, 50, 49, 48, 46, 43, 39, 35] }, 3000: { 4: [46, 33], 8: [47, 45, 41, 33], 12: [47, 46, 45, 42, 38, 33], 16: [47, 46, 46, 45, 43, 40, 37, 33] }, 9000: { 4: [43, 32], 8: [44, 42, 38, 32], 12: [44, 43, 42, 40, 36, 32], 16: [44, 44, 43, 42, 40, 38, 35, 32] } } self.CELL_WIDTH = MazeData.CELL_WIDTH self.MAX_FRAME_MOVE = self.CELL_WIDTH / 2 startOffset = 3 self.startPosHTable = [[Point3(0, startOffset, self.TOON_Z), 0], [Point3(0, -startOffset, self.TOON_Z), 180], [Point3(startOffset, 0, self.TOON_Z), 270], [Point3(-startOffset, 0, self.TOON_Z), 90]] self.camOffset = Vec3(0, -19, 45) def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.__defineConstants() mazeName = MazeGameGlobals.getMazeName(self.doId, self.numPlayers, MazeData.mazeNames) self.maze = Maze.Maze(mazeName) model = loader.loadModel('phase_3.5/models/props/mickeySZ') self.treasureModel = model.find('**/mickeySZ') model.removeNode() self.treasureModel.setScale(1.6) self.treasureModel.setP(-90) self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_toontag.ogg') self.toonHitTracks = {} self.scorePanels = [] def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) del self.toonHitTracks self.maze.destroy() del self.maze self.treasureModel.removeNode() del self.treasureModel del self.music self.removeChildGameFSM(self.gameFSM) del self.gameFSM def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.maze.onstage() self.randomNumGen.shuffle(self.startPosHTable) lt = base.localAvatar lt.reparentTo(render) lt.hideName() self.__placeToon(self.localAvId) lt.setAnimState('Happy', 1.0) lt.setSpeed(0, 0) self.camParent = render.attachNewNode('mazeGameCamParent') self.camParent.reparentTo(base.localAvatar) self.camParent.setPos(0, 0, 0) self.camParent.setHpr(render, 0, 0, 0) camera.reparentTo(self.camParent) camera.setPos(self.camOffset) self.__spawnCameraTask() self.toonRNGs = [] for i in range(self.numPlayers): self.toonRNGs.append(RandomNumGen.RandomNumGen(self.randomNumGen)) self.treasures = [] for i in range(self.maze.numTreasures): self.treasures.append( MazeTreasure.MazeTreasure(self.treasureModel, self.maze.treasurePosList[i], i, self.doId)) self.__loadSuits() for suit in self.suits: suit.onstage() self.sndTable = { 'hitBySuit': [None] * self.numPlayers, 'falling': [None] * self.numPlayers } for i in range(self.numPlayers): self.sndTable['hitBySuit'][i] = base.loader.loadSfx( 'phase_4/audio/sfx/MG_Tag_C.ogg') self.sndTable['falling'][i] = base.loader.loadSfx( 'phase_4/audio/sfx/MG_cannon_whizz.ogg') self.grabSounds = [] for i in range(5): self.grabSounds.append( base.loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')) self.grabSoundIndex = 0 for avId in self.avIdList: self.toonHitTracks[avId] = Wait(0.1) self.scores = [0] * self.numPlayers self.goalBar = DirectWaitBar(parent=render2d, relief=DGG.SUNKEN, frameSize=(-0.35, 0.35, -0.15, 0.15), borderWidth=(0.02, 0.02), scale=0.42, pos=(0.84, 0, 0.5 - 0.28 * self.numPlayers + 0.05), barColor=(0, 0.7, 0, 1)) self.goalBar.setBin('unsorted', 0) self.goalBar.hide() self.introTrack = self.getIntroTrack() self.introTrack.start() return def offstage(self): self.notify.debug('offstage') if self.introTrack.isPlaying(): self.introTrack.finish() del self.introTrack for avId in list(self.toonHitTracks.keys()): track = self.toonHitTracks[avId] if track.isPlaying(): track.finish() self.__killCameraTask() camera.wrtReparentTo(render) self.camParent.removeNode() del self.camParent for panel in self.scorePanels: panel.cleanup() self.scorePanels = [] self.goalBar.destroy() del self.goalBar base.setCellsAvailable(base.rightCells, 1) for suit in self.suits: suit.offstage() self.__unloadSuits() for treasure in self.treasures: treasure.destroy() del self.treasures del self.sndTable del self.grabSounds del self.toonRNGs self.maze.offstage() base.localAvatar.showName() DistributedMinigame.offstage(self) def __placeToon(self, avId): toon = self.getAvatar(avId) if self.numPlayers == 1: toon.setPos(0, 0, self.TOON_Z) toon.setHpr(180, 0, 0) else: posIndex = self.avIdList.index(avId) toon.setPos(self.startPosHTable[posIndex][0]) toon.setHpr(self.startPosHTable[posIndex][1], 0, 0) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.setAnimState('Happy', 1.0) toon.startSmooth() toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) if self.introTrack.isPlaying(): self.introTrack.finish() for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.gameFSM.request('play') def handleDisabledAvatar(self, avId): hitTrack = self.toonHitTracks[avId] if hitTrack.isPlaying(): hitTrack.finish() DistributedMinigame.handleDisabledAvatar(self, avId) def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterPlay(self): self.notify.debug('enterPlay') for i in range(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel( avId, avName) scorePanel.setPos(1.12, 0.0, 0.5 - 0.28 * i) self.scorePanels.append(scorePanel) self.goalBar.show() self.goalBar['value'] = 0.0 base.setCellsAvailable(base.rightCells, 0) self.__spawnUpdateSuitsTask() orthoDrive = OrthoDrive( self.TOON_SPEED, maxFrameMove=self.MAX_FRAME_MOVE, customCollisionCallback=self.__doMazeCollisions, priority=1) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=not self.isSinglePlayer()) self.orthoWalk.start() self.accept(MazeSuit.COLLISION_EVENT_NAME, self.__hitBySuit) self.accept(self.TREASURE_GRAB_EVENT_NAME, self.__treasureGrabbed) self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.setTime(MazeGameGlobals.GAME_DURATION) self.timer.countdown(MazeGameGlobals.GAME_DURATION, self.timerExpired) self.accept('resetClock', self.__resetClock) base.playMusic(self.music, looping=0, volume=0.8) def exitPlay(self): self.notify.debug('exitPlay') self.ignore('resetClock') self.ignore(MazeSuit.COLLISION_EVENT_NAME) self.ignore(self.TREASURE_GRAB_EVENT_NAME) self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk self.__killUpdateSuitsTask() self.timer.stop() self.timer.destroy() del self.timer for avId in self.avIdList: toon = self.getAvatar(avId) if toon: toon.loop('neutral') def __resetClock(self, tOffset): self.notify.debug('resetClock') self.gameStartTime += tOffset self.timer.countdown(self.timer.currentTime + tOffset, self.timerExpired) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.grabSounds[self.grabSoundIndex].play() self.grabSoundIndex = (self.grabSoundIndex + 1) % len(self.grabSounds) self.sendUpdate('claimTreasure', [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) total = 0 for score in self.scores: total += score self.goalBar['value'] = 100.0 * (float(total) / float(self.maze.numTreasures)) def __hitBySuit(self, suitNum): self.notify.debug('hitBySuit') timestamp = globalClockDelta.localToNetworkTime( globalClock.getFrameTime()) self.sendUpdate('hitBySuit', [self.localAvId, timestamp]) self.__showToonHitBySuit(self.localAvId, timestamp) def hitBySuit(self, avId, timestamp): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in [ 'play', 'showScores' ]: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return self.notify.debug('avatar ' + repr(avId) + ' hit by a suit') if avId != self.localAvId: self.__showToonHitBySuit(avId, timestamp) def __showToonHitBySuit(self, avId, timestamp): toon = self.getAvatar(avId) if toon == None: return rng = self.toonRNGs[self.avIdList.index(avId)] curPos = toon.getPos(render) oldTrack = self.toonHitTracks[avId] if oldTrack.isPlaying(): oldTrack.finish() toon.setPos(curPos) toon.setZ(self.TOON_Z) parentNode = render.attachNewNode('mazeFlyToonParent-' + repr(avId)) parentNode.setPos(toon.getPos()) toon.reparentTo(parentNode) toon.setPos(0, 0, 0) startPos = parentNode.getPos() dropShadow = toon.dropShadow.copyTo(parentNode) dropShadow.setScale(toon.dropShadow.getScale(render)) trajectory = Trajectory.Trajectory(0, Point3(0, 0, 0), Point3(0, 0, 50), gravMult=1.0) flyDur = trajectory.calcTimeOfImpactOnPlane(0.0) while 1: endTile = [ rng.randint(2, self.maze.width - 1), rng.randint(2, self.maze.height - 1) ] if self.maze.isWalkable(endTile[0], endTile[1]): break endWorldCoords = self.maze.tile2world(endTile[0], endTile[1]) endPos = Point3(endWorldCoords[0], endWorldCoords[1], startPos[2]) def flyFunc(t, trajectory, startPos=startPos, endPos=endPos, dur=flyDur, moveNode=parentNode, flyNode=toon): u = t / dur moveNode.setX(startPos[0] + u * (endPos[0] - startPos[0])) moveNode.setY(startPos[1] + u * (endPos[1] - startPos[1])) flyNode.setPos(trajectory.getPos(t)) flyTrack = Sequence(LerpFunctionInterval(flyFunc, fromData=0.0, toData=flyDur, duration=flyDur, extraArgs=[trajectory]), name=toon.uniqueName('hitBySuit-fly')) if avId != self.localAvId: cameraTrack = Sequence() else: self.camParent.reparentTo(parentNode) startCamPos = camera.getPos() destCamPos = camera.getPos() zenith = trajectory.getPos(flyDur / 2.0)[2] destCamPos.setZ(zenith * 1.3) destCamPos.setY(destCamPos[1] * 0.3) def camTask(task, zenith=zenith, flyNode=toon, startCamPos=startCamPos, camOffset=destCamPos - startCamPos): u = flyNode.getZ() / zenith camera.setPos(startCamPos + camOffset * u) camera.lookAt(toon) return Task.cont camTaskName = 'mazeToonFlyCam-' + repr(avId) taskMgr.add(camTask, camTaskName, priority=20) def cleanupCamTask(self=self, toon=toon, camTaskName=camTaskName, startCamPos=startCamPos): taskMgr.remove(camTaskName) self.camParent.reparentTo(toon) camera.setPos(startCamPos) camera.lookAt(toon) cameraTrack = Sequence(Wait(flyDur), Func(cleanupCamTask), name='hitBySuit-cameraLerp') geomNode = toon.getGeomNode() startHpr = geomNode.getHpr() destHpr = Point3(startHpr) hRot = rng.randrange(1, 8) if rng.choice([0, 1]): hRot = -hRot destHpr.setX(destHpr[0] + hRot * 360) spinHTrack = Sequence(LerpHprInterval(geomNode, flyDur, destHpr, startHpr=startHpr), Func(geomNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinH')) parent = geomNode.getParent() rotNode = parent.attachNewNode('rotNode') geomNode.reparentTo(rotNode) rotNode.setZ(toon.getHeight() / 2.0) oldGeomNodeZ = geomNode.getZ() geomNode.setZ(-toon.getHeight() / 2.0) startHpr = rotNode.getHpr() destHpr = Point3(startHpr) pRot = rng.randrange(1, 3) if rng.choice([0, 1]): pRot = -pRot destHpr.setY(destHpr[1] + pRot * 360) spinPTrack = Sequence(LerpHprInterval(rotNode, flyDur, destHpr, startHpr=startHpr), Func(rotNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinP')) i = self.avIdList.index(avId) soundTrack = Sequence(Func(base.playSfx, self.sndTable['hitBySuit'][i]), Wait(flyDur * (2.0 / 3.0)), SoundInterval(self.sndTable['falling'][i], duration=flyDur * (1.0 / 3.0)), name=toon.uniqueName('hitBySuit-soundTrack')) def preFunc(self=self, avId=avId, toon=toon, dropShadow=dropShadow): forwardSpeed = toon.forwardSpeed rotateSpeed = toon.rotateSpeed if avId == self.localAvId: self.orthoWalk.stop() else: toon.stopSmooth() if forwardSpeed or rotateSpeed: toon.setSpeed(forwardSpeed, rotateSpeed) toon.dropShadow.hide() def postFunc(self=self, avId=avId, oldGeomNodeZ=oldGeomNodeZ, dropShadow=dropShadow, parentNode=parentNode): if avId == self.localAvId: base.localAvatar.setPos(endPos) if hasattr(self, 'orthoWalk'): if self.gameFSM.getCurrentState().getName() == 'play': self.orthoWalk.start() dropShadow.removeNode() del dropShadow toon.dropShadow.show() geomNode = toon.getGeomNode() rotNode = geomNode.getParent() baseNode = rotNode.getParent() geomNode.reparentTo(baseNode) rotNode.removeNode() del rotNode geomNode.setZ(oldGeomNodeZ) toon.reparentTo(render) toon.setPos(endPos) parentNode.removeNode() del parentNode if avId != self.localAvId: toon.startSmooth() preFunc() hitTrack = Sequence(Parallel(flyTrack, cameraTrack, spinHTrack, spinPTrack, soundTrack), Func(postFunc), name=toon.uniqueName('hitBySuit')) self.toonHitTracks[avId] = hitTrack hitTrack.start(globalClockDelta.localElapsedTime(timestamp)) def allTreasuresTaken(self): if not self.hasLocalToon: return self.notify.debug('all treasures taken') if not MazeGameGlobals.ENDLESS_GAME: self.gameFSM.request('showScores') def timerExpired(self): self.notify.debug('local timer expired') if not MazeGameGlobals.ENDLESS_GAME: self.gameFSM.request('showScores') def __doMazeCollisions(self, oldPos, newPos): offset = newPos - oldPos WALL_OFFSET = 1.0 curX = oldPos[0] curY = oldPos[1] curTX, curTY = self.maze.world2tile(curX, curY) def calcFlushCoord(curTile, newTile, centerTile): EPSILON = 0.01 if newTile > curTile: return (newTile - centerTile) * self.CELL_WIDTH - EPSILON - WALL_OFFSET else: return (curTile - centerTile) * self.CELL_WIDTH + WALL_OFFSET offsetX = offset[0] offsetY = offset[1] WALL_OFFSET_X = WALL_OFFSET if offsetX < 0: WALL_OFFSET_X = -WALL_OFFSET_X WALL_OFFSET_Y = WALL_OFFSET if offsetY < 0: WALL_OFFSET_Y = -WALL_OFFSET_Y newX = curX + offsetX + WALL_OFFSET_X newY = curY newTX, newTY = self.maze.world2tile(newX, newY) if newTX != curTX: if self.maze.collisionTable[newTY][newTX]: offset.setX( calcFlushCoord(curTX, newTX, self.maze.originTX) - curX) newX = curX newY = curY + offsetY + WALL_OFFSET_Y newTX, newTY = self.maze.world2tile(newX, newY) if newTY != curTY: if self.maze.collisionTable[newTY][newTX]: offset.setY( calcFlushCoord(curTY, newTY, self.maze.originTY) - curY) offsetX = offset[0] offsetY = offset[1] newX = curX + offsetX + WALL_OFFSET_X newY = curY + offsetY + WALL_OFFSET_Y newTX, newTY = self.maze.world2tile(newX, newY) if self.maze.collisionTable[newTY][newTX]: cX = calcFlushCoord(curTX, newTX, self.maze.originTX) cY = calcFlushCoord(curTY, newTY, self.maze.originTY) if abs(cX - curX) < abs(cY - curY): offset.setX(cX - curX) else: offset.setY(cY - curY) return oldPos + offset def __spawnCameraTask(self): self.notify.debug('spawnCameraTask') camera.lookAt(base.localAvatar) taskMgr.remove(self.CAMERA_TASK) taskMgr.add(self.__cameraTask, self.CAMERA_TASK, priority=45) def __killCameraTask(self): self.notify.debug('killCameraTask') taskMgr.remove(self.CAMERA_TASK) def __cameraTask(self, task): self.camParent.setHpr(render, 0, 0, 0) return Task.cont def __loadSuits(self): self.notify.debug('loadSuits') self.suits = [] self.numSuits = 4 * self.numPlayers safeZone = self.getSafezoneId() slowerTable = self.slowerSuitPeriods if self.SLOWER_SUIT_CURVE: slowerTable = self.slowerSuitPeriodsCurve slowerPeriods = slowerTable[safeZone][self.numSuits] fasterTable = self.fasterSuitPeriods if self.FASTER_SUIT_CURVE: fasterTable = self.fasterSuitPeriodsCurve fasterPeriods = fasterTable[safeZone][self.numSuits] suitPeriods = slowerPeriods + fasterPeriods self.notify.debug('suit periods: ' + repr(suitPeriods)) self.randomNumGen.shuffle(suitPeriods) for i in range(self.numSuits): self.suits.append( MazeSuit(i, self.maze, self.randomNumGen, suitPeriods[i], self.getDifficulty())) def __unloadSuits(self): self.notify.debug('unloadSuits') for suit in self.suits: suit.destroy() del self.suits def __spawnUpdateSuitsTask(self): self.notify.debug('spawnUpdateSuitsTask') for suit in self.suits: suit.gameStart(self.gameStartTime) taskMgr.remove(self.UPDATE_SUITS_TASK) taskMgr.add(self.__updateSuitsTask, self.UPDATE_SUITS_TASK) def __killUpdateSuitsTask(self): self.notify.debug('killUpdateSuitsTask') taskMgr.remove(self.UPDATE_SUITS_TASK) for suit in self.suits: suit.gameEnd() def __updateSuitsTask(self, task): curT = globalClock.getFrameTime() - self.gameStartTime curTic = int(curT * float(MazeGameGlobals.SUIT_TIC_FREQ)) suitUpdates = [] for i in range(len(self.suits)): updateTics = self.suits[i].getThinkTimestampTics(curTic) suitUpdates.extend(list(zip(updateTics, [i] * len(updateTics)))) suitUpdates.sort(key=functools.cmp_to_key(lambda a, b: a[0] - b[0])) if len(suitUpdates) > 0: curTic = 0 for i in range(len(suitUpdates)): update = suitUpdates[i] tic = update[0] suitIndex = update[1] suit = self.suits[suitIndex] if tic > curTic: curTic = tic j = i + 1 while j < len(suitUpdates): if suitUpdates[j][0] > tic: break self.suits[suitUpdates[j][1]].prepareToThink() j += 1 unwalkables = [] for si in range(suitIndex): unwalkables.extend(self.suits[si].occupiedTiles) for si in range(suitIndex + 1, len(self.suits)): unwalkables.extend(self.suits[si].occupiedTiles) suit.think(curTic, curT, unwalkables) return Task.cont def enterShowScores(self): self.notify.debug('enterShowScores') lerpTrack = Parallel() lerpDur = 0.5 lerpTrack.append( Parallel( LerpPosInterval(self.goalBar, lerpDur, Point3(0, 0, -.6), blendType='easeInOut'), LerpScaleInterval(self.goalBar, lerpDur, Vec3(self.goalBar.getScale()) * 2.0, blendType='easeInOut'))) tY = 0.6 bY = -.05 lX = -.5 cX = 0 rX = 0.5 scorePanelLocs = (((cX, bY), ), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY))) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in range(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] lerpTrack.append( Parallel( LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut'))) self.showScoreTrack = Parallel( lerpTrack, Sequence(Wait(MazeGameGlobals.SHOWSCORES_DURATION), Func(self.gameOver))) self.showScoreTrack.start() def exitShowScores(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass def getIntroTrack(self): self.__cameraTask(None) origCamParent = camera.getParent() origCamPos = camera.getPos() origCamHpr = camera.getHpr() iCamParent = base.localAvatar.attachNewNode('iCamParent') iCamParent.setH(180) camera.reparentTo(iCamParent) toonHeight = base.localAvatar.getHeight() camera.setPos(0, -15, toonHeight * 3) camera.lookAt(0, 0, toonHeight / 2.0) iCamParent.wrtReparentTo(origCamParent) waitDur = 5.0 lerpDur = 4.5 lerpTrack = Parallel() startHpr = iCamParent.getHpr() startHpr.setX(PythonUtil.reduceAngle(startHpr[0])) lerpTrack.append( LerpPosHprInterval(iCamParent, lerpDur, pos=Point3(0, 0, 0), hpr=Point3(0, 0, 0), startHpr=startHpr, name=self.uniqueName('introLerpParent'))) lerpTrack.append( LerpPosHprInterval(camera, lerpDur, pos=origCamPos, hpr=origCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos'))) base.localAvatar.startLookAround() def cleanup(origCamParent=origCamParent, origCamPos=origCamPos, origCamHpr=origCamHpr, iCamParent=iCamParent): camera.reparentTo(origCamParent) camera.setPos(origCamPos) camera.setHpr(origCamHpr) iCamParent.removeNode() del iCamParent base.localAvatar.stopLookAround() return Sequence(Wait(waitDur), lerpTrack, Func(cleanup))
class DistributedCannonDefenseShip(DistributedNPCSimpleShip): __module__ = __name__ specialHitSfx = {} coldShotHitSfx = None sharkChompSfx = {} def __init__(self, cr): DistributedNPCSimpleShip.__init__(self, cr) self.goldStolenlbl = None self.hasGoldlbl = None self.hasBNote = None self.textureCard = None self.goldIcon = None self.flameEffects = [] self.isSinkingWhileOnFire = False self.healthModifier = 0 self.modifierSet = False self.shipStatsSet = False self.shipStatIndex = None self.initHealthBar() self.initIndicatorIcons() self.sinkTimeScale = CannonDefenseGlobals.SHIP_SINK_DURATION_SCALE self.sharkActor = Actor( 'models/char/pir_r_gam_fsh_lgComTshark.bam', {'attack': 'models/char/pir_a_gam_fsh_lgComTshark_attack.bam'}) self.sharkParallel = None self.fader = None if not self.coldShotHitSfx: DistributedCannonDefenseShip.specialHitSfx = { InventoryType.DefenseCannonMineInWater: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_MINE_HIT), InventoryType.DefenseCannonBomb: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_BOMB_HIT), InventoryType.DefenseCannonHotShot: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_HOTSHOT_HIT), InventoryType.DefenseCannonFireStorm: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_FIRESTORM_HIT), InventoryType.DefenseCannonChumShot: loadSfx(SoundGlobals.SFX_MINIGAME_CANNON_SHARK) } DistributedCannonDefenseShip.coldShotHitSfx = loadSfx( SoundGlobals.SFX_MINIGAME_CANNON_ICE_HIT) DistributedCannonDefenseShip.sharkChompSfxs = [ loadSfx(SoundGlobals.SFX_MONSTER_SMASH_01), loadSfx(SoundGlobals.SFX_MONSTER_SMASH_02), loadSfx(SoundGlobals.SFX_MONSTER_SMASH_03) ] return def buildShip(self): DistributedNPCSimpleShip.buildShip(self) self.model.sfxAlternativeStyle = True def setupLocalStats(self): DistributedNPCSimpleShip.setupLocalStats(self) def setShipStatIndex(self, statIndex): self.shipStatsSet = True self.shipStatIndex = statIndex self.maxHp = CannonDefenseGlobals.shipStats[ self.shipStatIndex]['shipHp'] self.maxMastHealth = CannonDefenseGlobals.shipStats[ self.shipStatIndex]['mastHp'] self.healthBar.setPos( 0.0, 0.0, CannonDefenseGlobals.shipStats[self.shipStatIndex] ['healthBarHeight']) if self.modifierSet: self.calcModifiedHealth() def setHealthModifier(self, modifier): self.modifierSet = True self.healthModifier = modifier if self.shipStatsSet: self.calcModifiedHealth() def calcModifiedHealth(self): if self.healthModifier == 0: return self.maxHp += self.healthModifier * ( self.maxHp * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE) mastList = CannonDefenseGlobals.shipStats[self.shipStatIndex]['mastHp'] mastFinalHp = [] for mastHealth in mastList: hp = mastHealth hp += self.healthModifier * ( mastHealth * CannonDefenseGlobals.ENEMY_DIFFICULTY_INCREASE) mastFinalHp.append(hp) self.maxMastHealth = mastFinalHp def setLogo(self, logo): self.logo = logo def setStyle(self, style): self.style = style def announceGenerate(self): DistributedNPCSimpleShip.announceGenerate(self) rad = (self.model.dimensions / 2.0).length() cn = NodePath(CollisionNode('c')) cs = CollisionSphere(0, 0, 0, rad) cn.node().addSolid(cs) cn.reparentTo(self.model.modelCollisions) cn.setTransform(self.model.center.getTransform(self)) cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask) self.model.defendSphere = cn self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE) self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN) self.smoother.setExpectedBroadcastPeriod(0.3) self.smoother.setDelay(2) self.healthBar.reparentTo(self.model.modelRoot) def initHealthBar(self): self.healthBar = DirectWaitBar(frameSize=(-0.35, 0.35, -0.04, 0.04), relief=DGG.FLAT, frameColor=(0.0, 0.0, 0.0, 0.0), borderWidth=(0.0, 0.0), barColor=(0.0, 1.0, 0.0, 1.0), scale=100) self.healthBar.setBillboardPointEye() self.healthBar['value'] = 100 self.healthBar.hide(OTPRender.ReflectionCameraBitmask) self.healthBar.setLightOff() def initIndicatorIcons(self): self.textureCard = loader.loadModel( 'models/textureCards/pir_m_gam_can_ship_icons') if self.textureCard: self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*') self.goldStolenlbl = DirectLabel( parent=self.healthBar, relief=None, pos=(0, 0, 0.2), text_align=TextNode.ACenter, text_scale=0.5, textMayChange=0, text='!', text_fg=PiratesGuiGlobals.TextFG23, text_shadow=PiratesGuiGlobals.TextShadow, text_font=PiratesGlobals.getPirateBoldOutlineFont(), sortOrder=2) self.goldStolenlbl.setTransparency(1) self.goldStolenlbl.hide() self.hasGoldlbl = DirectLabel(parent=self.healthBar, relief=None, pos=(0, 0, 0.35), image=self.goldIcon, image_scale=0.5, image_pos=(0, 0, 0), sortOrder=2) self.hasGoldlbl.setTransparency(1) self.hasGoldlbl.hide() self.hasBNote = self.healthBar.attachNewNode('noteIndicator') self.bnoteBack = loader.loadModel( 'models/textureCards/skillIcons').find( '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote) self.hasBNote.setZ(0.35) self.hasBNote.setScale(0.6) self.hasBNote.hide() return def getHealthBarColor(self, health): return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int( health / 100.0 * (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))] def setHealthState(self, health): DistributedNPCSimpleShip.setHealthState(self, health) self.healthBar['value'] = health self.healthBar['barColor'] = self.getHealthBarColor(health) def setCurrentState(self, state): if state == CannonDefenseGlobals.SHIP_STATE_STEALING: self.goldStolenlbl.show() else: if state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE: self.hasGoldlbl.show() self.goldStolenlbl.hide() else: if state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES: self.hasBNote.show() self.goldStolenlbl.hide() else: self.hasGoldlbl.hide() self.hasBNote.hide() self.goldStolenlbl.hide() rad = (self.model.dimensions / 2.0).length() cn = NodePath(CollisionNode('c')) cs = CollisionSphere(0, 0, 0, rad) cn.node().addSolid(cs) cn.reparentTo(self.model.modelCollisions) cn.setTransform(self.model.center.getTransform(self)) cn.node().setIntoCollideMask(PiratesGlobals.GenericShipBitmask) self.model.defendSphere = cn self.model.modelRoot.setScale(CannonDefenseGlobals.SHIP_SCALE) self.fadeIn(CannonDefenseGlobals.SHIP_FADEIN) self.smoother.setExpectedBroadcastPeriod(0.3) self.smoother.setDelay(2) self.healthBar.reparentTo(self.model.modelRoot) def initHealthBar(self): self.healthBar = DirectWaitBar(frameSize=(-0.35, 0.35, -0.04, 0.04), relief=DGG.FLAT, frameColor=(0.0, 0.0, 0.0, 0.0), borderWidth=(0.0, 0.0), barColor=(0.0, 1.0, 0.0, 1.0), scale=100) self.healthBar.setBillboardPointEye() self.healthBar['value'] = 100 self.healthBar.hide(OTPRender.ReflectionCameraBitmask) self.healthBar.setLightOff() def initIndicatorIcons(self): self.textureCard = loader.loadModel( 'models/textureCards/pir_m_gam_can_ship_icons') if self.textureCard: self.goldIcon = self.textureCard.find('**/pir_t_shp_can_gold*') self.goldStolenlbl = DirectLabel( parent=self.healthBar, relief=None, pos=(0, 0, 0.2), text_align=TextNode.ACenter, text_scale=0.5, textMayChange=0, text='!', text_fg=PiratesGuiGlobals.TextFG23, text_shadow=PiratesGuiGlobals.TextShadow, text_font=PiratesGlobals.getPirateBoldOutlineFont(), sortOrder=2) self.goldStolenlbl.setTransparency(1) self.goldStolenlbl.hide() self.hasGoldlbl = DirectLabel(parent=self.healthBar, relief=None, pos=(0, 0, 0.35), image=self.goldIcon, image_scale=0.5, image_pos=(0, 0, 0), sortOrder=2) self.hasGoldlbl.setTransparency(1) self.hasGoldlbl.hide() self.hasBNote = self.healthBar.attachNewNode('noteIndicator') self.bnoteBack = loader.loadModel( 'models/textureCards/skillIcons').find( '**/pir_t_gui_can_moneyIcon').copyTo(self.hasBNote) self.hasBNote.setZ(0.35) self.hasBNote.setScale(0.6) self.hasBNote.hide() return def getHealthBarColor(self, health): return CannonDefenseGlobals.SHIP_HEALTH_COLORS[int( health / 100.0 * (len(CannonDefenseGlobals.SHIP_HEALTH_COLORS) - 1))] def setHealthState(self, health): DistributedNPCSimpleShip.setHealthState(self, health) self.healthBar['value'] = health self.healthBar['barColor'] = self.getHealthBarColor(health) def setCurrentState(self, state): if state == CannonDefenseGlobals.SHIP_STATE_STEALING: self.goldStolenlbl.show() else: if state == CannonDefenseGlobals.SHIP_STATE_HASTREASURE: self.hasGoldlbl.show() self.goldStolenlbl.hide() else: if state == CannonDefenseGlobals.SHIP_STATE_HASBNOTES: self.hasBNote.show() self.goldStolenlbl.hide() else: self.hasGoldlbl.hide() self.hasBNote.hide() self.goldStolenlbl.hide() def calculateLook(self): pass def playProjectileHitSfx(self, ammoSkillId, hitSail): if ammoSkillId in [ InventoryType.DefenseCannonColdShotInWater, InventoryType.DefenseCannonSmokePowder ]: return if ammoSkillId in self.specialHitSfx: sfx = self.specialHitSfx[ammoSkillId] base.playSfx(sfx, node=self, cutoff=2000) return DistributedNPCSimpleShip.playProjectileHitSfx(self, ammoSkillId, hitSail) def projectileWeaponHit(self, skillId, ammoSkillId, skillResult, targetEffects, pos, normal, codes, attacker, itemEffects=[]): DistributedNPCSimpleShip.projectileWeaponHit(self, skillId, ammoSkillId, skillResult, targetEffects, pos, normal, codes, attacker, itemEffects) def sinkingBegin(self): self.healthBar.reparentTo(hidden) if len(self.flameEffects) > 0: self.isSinkingWhileOnFire = True DistributedNPCSimpleShip.sinkingBegin(self) def sinkingEnd(self): while len(self.flameEffects) > 0: effect = self.flameEffects.pop() effect.stopLoop() DistributedNPCSimpleShip.sinkingEnd(self) def addStatusEffect(self, effectId, attackerId, duration=0, timeLeft=0, timestamp=0, buffData=[0]): if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE: self.addFireEffect(self.getModelRoot().getPos()) if effectId == WeaponGlobals.C_CANNON_DEFENSE_ICE: base.playSfx(self.coldShotHitSfx, node=self, cutoff=2000) DistributedNPCSimpleShip.addStatusEffect(self, effectId, attackerId, duration, timeLeft, timestamp, buffData) def removeStatusEffect(self, effectId, attackerId): DistributedNPCSimpleShip.removeStatusEffect(self, effectId, attackerId) if effectId == WeaponGlobals.C_CANNON_DEFENSE_FIRE: if not self.isSinkingWhileOnFire: while len(self.flameEffects) > 0: effect = self.flameEffects.pop() effect.stopLoop() def addFireEffect(self, pos): fireEffect = ShipFire.getEffect() if fireEffect: fireEffect.reparentTo(self.getModelRoot()) fireEffect.setPos(pos) fireEffect.setHpr(90, -15, 0) fireEffect.startLoop() fireEffect.setEffectScale(20.0) self.flameEffects.append(fireEffect) def playSharkAttack(self, pos): if self.sharkActor.getCurrentAnim() == None: self.sharkActor.wrtReparentTo(self.getModelRoot()) self.sharkActor.setPos(self, pos) self.sharkActor.setScale(20) self.sharkActor.play('attack') sharkAttackEffect = None if base.options.getSpecialEffectsSetting( ) >= base.options.SpecialEffectsLow: effect = CannonSplash.getEffect() if effect: effect.reparentTo(base.effectsRoot) effect.setPos(self, pos) effect.setZ(1) effect.play() sharkAttackEffect = Func(self.playAttackEffect, pos) hprIvalShip = LerpHprInterval(self.getModelRoot(), duration=3, hpr=(0, 0, -180)) s1 = Sequence(Wait(0.75), hprIvalShip, Func(self.getModelRoot().stash)) s2 = Sequence(Wait(0.75), sharkAttackEffect, Wait(0.5), sharkAttackEffect) self.sharkParallel = Parallel(s1, s2) self.sharkParallel.start() taskMgr.doMethodLater(self.sharkActor.getDuration('attack'), self.detachShark, self.uniqueName('playSharkAttack'), extraArgs=[]) return def playAttackEffect(self, pos): effect = BulletEffect.getEffect() if effect: effect.reparentTo(base.effectsRoot) effect.setPos(self, pos) effect.loadObjects(6) effect.play() sfx = random.choice(self.sharkChompSfxs) base.playSfx(sfx, node=self.getModelRoot(), cutoff=2000) def detachShark(self): self.sharkActor.detachNode() def delete(self): if self.fader: self.fader.pause() self.fader = None DistributedNPCSimpleShip.delete(self) return def destroy(self): if self.goldStolenlbl: self.goldStolenlbl.destroy() self.goldStolenlbl = None if self.hasGoldlbl: self.hasGoldlbl.destroy() self.hasGoldlbl = None if self.textureCard: self.textureCard.removeNode() self.textureCard = None self.goldIcon = None if self.healthBar: self.healthBar.destroy() if self.sharkActor: self.sharkActor.cleanUp() self.sharkActor.removeNode() if self.sharkParallel: self.sharkParallel.pause() self.sharkParallel = None DistributedNPCSimpleShip.destroy(self) return def fadeIn(self, length): if self.fader: self.fader.finish() self.fader = None self.setTransparency(1) self.fader = Sequence( self.colorScaleInterval(length, Vec4(1, 1, 1, 1), Vec4(1, 1, 1, 0)), Func(self.clearTransparency)) self.fader.start() return def fadeOut(self, length): if self.fader: self.fader.finish() self.fader = None self.setTransparency(1) self.fader = Sequence( self.colorScaleInterval(length, Vec4(1, 1, 1, 0), Vec4(1, 1, 1, 1)), Func(self.hide), Func(self.clearTransparency)) self.fader.start() return
class DistributedBRPond(DistributedObject): notify = directNotify.newCategory('DistributedBRPond') LowerPowerBarTaskName = 'BRWater-lowerPowerBar' WatchMouseMovementTaskName = 'BRWater-watchMouseMovement' WaterWatchTaskName = 'BRWater-waterWatch' InWaterZ = 0.93 PowerLoss = 1 def __init__(self, cr): DistributedObject.__init__(self, cr) self.freezeUpSfx = base.audio3d.loadSfx( 'phase_8/audio/sfx/freeze_up.ogg') self.freezeUpSfx.setVolume(12) self.frozenSfxArray = [ base.audio3d.loadSfx('phase_8/audio/sfx/frozen_1.ogg'), base.audio3d.loadSfx('phase_8/audio/sfx/frozen_2.ogg'), base.audio3d.loadSfx('phase_8/audio/sfx/frozen_3.ogg') ] self.coolSfxArray = [ base.audio3d.loadSfx('phase_8/audio/sfx/cool_down_1.ogg'), base.audio3d.loadSfx('phase_8/audio/sfx/cool_down_2.ogg') ] # Fancy code that will iterate through both lists and set their volume to 12. for sfx in itertools.chain(self.frozenSfxArray, self.coolSfxArray): sfx.setVolume(12) # A dictionary of avIds that point to a list of useful data. # Example: 0 : [iceCubeNode, interval] self.avId2Data = {} # Variables that store values for local stuff such as the GUI and the lastMouseX. self.frame = None self.powerBar = None self.label = None self.lastMouseX = 0 def attachSoundToAvatar(self, avatar, sound): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ base.audio3d.attachSoundToObject(sound, avatar) base.playSfx(sound, node=avatar) def __resetAvatarIvalAndUnloadIceCube(self, avatar): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly This deletes the ice cube node, pauses the current interval, and deletes the data. """ iceCube, ival = self.__fetchAvatarIntervalAndIceCube(avatar) if iceCube: iceCube.removeNode() iceCube = None if ival: ival.pause() ival = None if avatar.doId in self.avId2Data.keys(): del self.avId2Data[avatar.doId] def __setAvatarIntervalAndIceCube(self, avatar, iceCube, ival, ts): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly NOTE: This starts the interval if one is passed! """ if ival: ival.start(ts) self.avId2Data.update({avatar.doId: [iceCube, ival]}) def __fetchAvatarIntervalAndIceCube(self, avatar): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly This returns the ice cube node and the current interval """ # Let's default both of the data to None. data = [None, None] if avatar.doId in self.avId2Data.keys(): data = self.avId2Data.get(avatar.doId) return data[0], data[1] def processStateRequest(self, avId, stateId, lastStateId, timestamp): """ This is the processing part of the state system that mimics the FSM system """ avatar = base.cr.doId2do.get(avId, None) elapsedTime = globalClockDelta.localElapsedTime(timestamp) if not avatar: self.notify.warning( 'SUSPICIOUS! Attempted to change the state of a non-existent avatar!' ) return # Let's exit out of the previous state. if lastStateId == 0: self.exitFreezeUp(avatar) elif lastStateId == 1: self.exitFrozen(avatar) if stateId == 0: self.enterFreezeUp(avatar, elapsedTime) elif stateId == 1: self.enterFrozen(avatar, elapsedTime) elif stateId == 2: self.enterCooldown(avatar, elapsedTime) elif stateId == 3: self.enterCooldown(avatar, elapsedTime, fromFrozen=1) elif stateId == 4: self.handleCooldownFinish(avatar) elif stateId == 5: # The AI is just clearing the state of the specified avatar. self.__resetAvatarIvalAndUnloadIceCube(avatar) else: self.notify.warning( 'Attempted to set state with unknown state id: {0}.'.format( stateId)) def d_requestState(self, stateId): """ This is the requesting part of the state system that mimics the FSM system """ self.sendUpdate('requestState', [stateId]) def enterFreezeUp(self, avatar, ts): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ def shouldFreeze(): if avatar == base.localAvatar: self.d_requestState(1) length = 1.0 ival = Sequence(Func(self.attachSoundToAvatar, avatar, self.freezeUpSfx), ToonEffects.getToonFreezeInterval(avatar, duration=length), Func(shouldFreeze), name='FreezeUp') if avatar == base.localAvatar: self.__startWaterWatch(0) self.__setAvatarIntervalAndIceCube(avatar, None, ival, ts) def exitFreezeUp(self, avatar): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ self.__resetAvatarIvalAndUnloadIceCube(avatar) if avatar == base.localAvatar: self.__stopWaterWatch() def enterFrozen(self, avatar, ts): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ iceCube = ToonEffects.generateIceCube(avatar) if avatar == base.localAvatar: base.cr.playGame.getPlace().fsm.request('stop', [0]) base.localAvatar.stop() # We need to hide the mouse cursor. props = WindowProperties() props.setCursorHidden(True) base.win.requestProperties(props) # Let's setup our GUI elements. self.frame = DirectFrame(pos=(0.0, 0.0, 0.7)) self.powerBar = DirectWaitBar(frameColor=(1.0, 1.0, 1.0, 1.0), 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.0, 0.0, 1.0), fg=(0.55, 0.7, 1.0, 1.0), pos=(0.0, -0.1, 0.0), parent=self.frame) # Let's add our tasks taskMgr.add(self.__lowerPowerBar, self.LowerPowerBarTaskName) taskMgr.add(self.__watchMouseMovement, self.WatchMouseMovementTaskName) mw = base.mouseWatcherNode if mw.hasMouse(): self.lastMouseX = mw.getMouseX() else: avatar.stop() ival = Sequence( Func(self.attachSoundToAvatar, avatar, choice(self.frozenSfxArray)), ToonEffects.getIceCubeFormInterval(iceCube)) self.__setAvatarIntervalAndIceCube(avatar, iceCube, ival, ts) def exitFrozen(self, avatar): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ self.__resetAvatarIvalAndUnloadIceCube(avatar) if avatar == base.localAvatar: # Let's make our cursor visible again. props = WindowProperties() props.setCursorHidden(False) base.win.requestProperties(props) # Let's remove our tasks taskMgr.remove(self.LowerPowerBarTaskName) taskMgr.remove(self.WatchMouseMovementTaskName) # Let's destroy all of our UI elements. if self.frame: self.label.destroy() self.label = None self.powerBar.destroy() self.powerBar = None self.frame.destroy() self.frame = None self.lastMouseX = 0 base.cr.playGame.getPlace().fsm.request('walk') base.localAvatar.b_setAnimState('neutral') else: avatar.loop('neutral') def enterCooldown(self, avatar, ts, fromFrozen=0): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ ival = Parallel() iceCube = None def handleComplete(): if avatar == base.localAvatar: self.d_requestState(4) if fromFrozen: iceCube = ToonEffects.generateIceCube(avatar) iceCube.setColorScale(ToonEffects.ICE_CUBE_SOLID_COLOR) ival.append(ToonEffects.getIceCubeThawInterval(iceCube)) # Let's do the color scale interval on the avatar. ival.append( Sequence( Func(self.attachSoundToAvatar, avatar, choice(self.coolSfxArray)), ToonEffects.getToonThawInterval(avatar, duration=1.0), Wait(4.0), Func(handleComplete))) self.__setAvatarIntervalAndIceCube(avatar, iceCube, ival, ts) def handleCooldownFinish(self, avatar): """ This is expecting a valid avatar object, either fetched from base.cr.doId2do#get() or passed directly """ self.__resetAvatarIvalAndUnloadIceCube(avatar) if avatar == base.localAvatar: self.__startWaterWatch() def __lowerPowerBar(self, task): if self.powerBar['value'] <= 0: self.powerBar.update(0) self.powerBar.update( int(self.powerBar['value'] - (self.PowerLoss * globalClock.getDt()))) return task.cont def __watchMouseMovement(self, task): if self.powerBar['value'] >= self.powerBar['range']: self.d_requestState(3) return task.done mw = base.mouseWatcherNode if mw.hasMouse(): if not self.lastMouseX or self.lastMouseX != mw.getMouseX(): value = abs(self.lastMouseX - mw.getMouseX()) / 0.001 self.lastMouseX = mw.getMouseX() self.powerBar.update(self.powerBar['value'] + abs(value)) return task.cont def __startWaterWatch(self, enter=1): taskMgr.add(self.__waterWatch, self.WaterWatchTaskName, extraArgs=[enter], appendTask=True) def __stopWaterWatch(self): taskMgr.remove(self.WaterWatchTaskName) def __waterWatch(self, enter, task): """ This task is ran locally to control when to switch to certain states """ z = base.localAvatar.getZ(render) if enter and z <= self.InWaterZ: self.d_requestState(0) return task.done elif not enter and z > self.InWaterZ: _, ival = self.__fetchAvatarIntervalAndIceCube(base.localAvatar) if ival and ival.getName() is 'FreezeUp': self.d_requestState(2) return task.done return task.cont def announceGenerate(self): DistributedObject.announceGenerate(self) self.__startWaterWatch() self.sendUpdate('requestAvatarStates', []) def disable(self): taskMgr.remove(self.LowerPowerBarTaskName) taskMgr.remove(self.WatchMouseMovementTaskName) self.__stopWaterWatch() DistributedObject.disable(self) def delete(self): DistributedObject.delete(self) self.LowerPowerBarTaskName = None self.WatchMouseMovementTaskName = None self.WaterWatchTaskName = None self.InWaterZ = None self.freezeUpSfx = None self.frozenSfxArray = None self.coolSfxArray = None self.avId2Data = None if self.frame: self.label.destroy() self.label = None self.powerBar.destroy() self.powerBar = None self.frame.destroy() self.frame = None del self.LowerPowerBarTaskName del self.WatchMouseMovementTaskName del self.WaterWatchTaskName del self.InWaterZ del self.freezeUpSfx del self.frozenSfxArray del self.coolSfxArray del self.avId2Data del self.label del self.powerBar del self.frame
class DistributedMazeGame(DistributedMinigame): notify = directNotify.newCategory('DistributedMazeGame') CAMERA_TASK = 'MazeGameCameraTask' UPDATE_SUITS_TASK = 'MazeGameUpdateSuitsTask' TREASURE_GRAB_EVENT_NAME = 'MazeTreasureGrabbed' def __init__(self, cr): DistributedMinigame.__init__(self, cr) self.gameFSM = ClassicFSM.ClassicFSM('DistributedMazeGame', [State.State('off', self.enterOff, self.exitOff, ['play']), State.State('play', self.enterPlay, self.exitPlay, ['cleanup', 'showScores']), State.State('showScores', self.enterShowScores, self.exitShowScores, ['cleanup']), State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup') self.addChildGameFSM(self.gameFSM) self.usesLookAround = 1 def getTitle(self): return TTLocalizer.MazeGameTitle def getInstructions(self): return TTLocalizer.MazeGameInstructions def getMaxDuration(self): return MazeGameGlobals.GAME_DURATION def __defineConstants(self): self.TOON_SPEED = 8.0 self.TOON_Z = 0 self.MinSuitSpeedRange = [0.8 * self.TOON_SPEED, 0.6 * self.TOON_SPEED] self.MaxSuitSpeedRange = [1.1 * self.TOON_SPEED, 2.0 * self.TOON_SPEED] self.FASTER_SUIT_CURVE = 1 self.SLOWER_SUIT_CURVE = self.getDifficulty() < 0.5 self.slowerSuitPeriods = {2000: {4: [128, 76], 8: [128, 99, 81, 68], 12: [128, 108, 93, 82, 74, 67], 16: [128, 112, 101, 91, 83, 76, 71, 66]}, 1000: {4: [110, 69], 8: [110, 88, 73, 62], 12: [110, 95, 83, 74, 67, 61], 16: [110, 98, 89, 81, 75, 69, 64, 60]}, 5000: {4: [96, 63], 8: [96, 79, 66, 57], 12: [96, 84, 75, 67, 61, 56], 16: [96, 87, 80, 73, 68, 63, 59, 55]}, 4000: {4: [86, 58], 8: [86, 71, 61, 53], 12: [86, 76, 68, 62, 56, 52], 16: [86, 78, 72, 67, 62, 58, 54, 51]}, 3000: {4: [78, 54], 8: [78, 65, 56, 49], 12: [78, 69, 62, 57, 52, 48], 16: [78, 71, 66, 61, 57, 54, 51, 48]}, 9000: {4: [71, 50], 8: [71, 60, 52, 46], 12: [71, 64, 58, 53, 49, 45], 16: [71, 65, 61, 57, 53, 50, 47, 45]}} self.slowerSuitPeriodsCurve = {2000: {4: [128, 65], 8: [128, 78, 66, 64], 12: [128, 88, 73, 67, 64, 64], 16: [128, 94, 79, 71, 67, 65, 64, 64]}, 1000: {4: [110, 59], 8: [110, 70, 60, 58], 12: [110, 78, 66, 61, 59, 58], 16: [110, 84, 72, 65, 61, 59, 58, 58]}, 5000: {4: [96, 55], 8: [96, 64, 56, 54], 12: [96, 71, 61, 56, 54, 54], 16: [96, 76, 65, 59, 56, 55, 54, 54]}, 4000: {4: [86, 51], 8: [86, 59, 52, 50], 12: [86, 65, 56, 52, 50, 50], 16: [86, 69, 60, 55, 52, 51, 50, 50]}, 3000: {4: [78, 47], 8: [78, 55, 48, 47], 12: [78, 60, 52, 48, 47, 47], 16: [78, 63, 55, 51, 49, 47, 47, 47]}, 9000: {4: [71, 44], 8: [71, 51, 45, 44], 12: [71, 55, 48, 45, 44, 44], 16: [71, 58, 51, 48, 45, 44, 44, 44]}} self.fasterSuitPeriods = {2000: {4: [54, 42], 8: [59, 52, 47, 42], 12: [61, 56, 52, 48, 45, 42], 16: [61, 58, 54, 51, 49, 46, 44, 42]}, 1000: {4: [50, 40], 8: [55, 48, 44, 40], 12: [56, 52, 48, 45, 42, 40], 16: [56, 53, 50, 48, 45, 43, 41, 40]}, 5000: {4: [47, 37], 8: [51, 45, 41, 37], 12: [52, 48, 45, 42, 39, 37], 16: [52, 49, 47, 44, 42, 40, 39, 37]}, 4000: {4: [44, 35], 8: [47, 42, 38, 35], 12: [48, 45, 42, 39, 37, 35], 16: [49, 46, 44, 42, 40, 38, 37, 35]}, 3000: {4: [41, 33], 8: [44, 40, 36, 33], 12: [45, 42, 39, 37, 35, 33], 16: [45, 43, 41, 39, 38, 36, 35, 33]}, 9000: {4: [39, 32], 8: [41, 37, 34, 32], 12: [42, 40, 37, 35, 33, 32], 16: [43, 41, 39, 37, 35, 34, 33, 32]}} self.fasterSuitPeriodsCurve = {2000: {4: [62, 42], 8: [63, 61, 54, 42], 12: [63, 63, 61, 56, 50, 42], 16: [63, 63, 62, 60, 57, 53, 48, 42]}, 1000: {4: [57, 40], 8: [58, 56, 50, 40], 12: [58, 58, 56, 52, 46, 40], 16: [58, 58, 57, 56, 53, 49, 45, 40]}, 5000: {4: [53, 37], 8: [54, 52, 46, 37], 12: [54, 53, 52, 48, 43, 37], 16: [54, 54, 53, 51, 49, 46, 42, 37]}, 4000: {4: [49, 35], 8: [50, 48, 43, 35], 12: [50, 49, 48, 45, 41, 35], 16: [50, 50, 49, 48, 46, 43, 39, 35]}, 3000: {4: [46, 33], 8: [47, 45, 41, 33], 12: [47, 46, 45, 42, 38, 33], 16: [47, 46, 46, 45, 43, 40, 37, 33]}, 9000: {4: [43, 32], 8: [44, 42, 38, 32], 12: [44, 43, 42, 40, 36, 32], 16: [44, 44, 43, 42, 40, 38, 35, 32]}} self.CELL_WIDTH = MazeData.CELL_WIDTH self.MAX_FRAME_MOVE = self.CELL_WIDTH / 2 startOffset = 3 self.startPosHTable = [[Point3(0, startOffset, self.TOON_Z), 0], [Point3(0, -startOffset, self.TOON_Z), 180], [Point3(startOffset, 0, self.TOON_Z), 270], [Point3(-startOffset, 0, self.TOON_Z), 90]] self.camOffset = Vec3(0, -19, 45) def load(self): self.notify.debug('load') DistributedMinigame.load(self) self.__defineConstants() mazeName = MazeGameGlobals.getMazeName(self.doId, self.numPlayers, MazeData.mazeNames) self.maze = Maze.Maze(mazeName) model = loader.loadModel('phase_3.5/models/props/mickeySZ') self.treasureModel = model.find('**/mickeySZ') model.removeNode() self.treasureModel.setScale(1.6) self.treasureModel.setP(-90) self.music = base.loadMusic('phase_4/audio/bgm/MG_toontag.ogg') self.toonHitTracks = {} self.scorePanels = [] def unload(self): self.notify.debug('unload') DistributedMinigame.unload(self) del self.toonHitTracks self.maze.destroy() del self.maze self.treasureModel.removeNode() del self.treasureModel del self.music self.removeChildGameFSM(self.gameFSM) del self.gameFSM def onstage(self): self.notify.debug('onstage') DistributedMinigame.onstage(self) self.maze.onstage() self.randomNumGen.shuffle(self.startPosHTable) lt = base.localAvatar lt.reparentTo(render) lt.hideName() self.__placeToon(self.localAvId) lt.setAnimState('Happy', 1.0) lt.setSpeed(0, 0) self.camParent = render.attachNewNode('mazeGameCamParent') self.camParent.reparentTo(base.localAvatar) self.camParent.setPos(0, 0, 0) self.camParent.setHpr(render, 0, 0, 0) camera.reparentTo(self.camParent) camera.setPos(self.camOffset) self.__spawnCameraTask() self.toonRNGs = [] for i in xrange(self.numPlayers): self.toonRNGs.append(RandomNumGen.RandomNumGen(self.randomNumGen)) self.treasures = [] for i in xrange(self.maze.numTreasures): self.treasures.append(MazeTreasure.MazeTreasure(self.treasureModel, self.maze.treasurePosList[i], i, self.doId)) self.__loadSuits() for suit in self.suits: suit.onstage() self.sndTable = {'hitBySuit': [None] * self.numPlayers, 'falling': [None] * self.numPlayers} for i in xrange(self.numPlayers): self.sndTable['hitBySuit'][i] = base.loadSfx('phase_4/audio/sfx/MG_Tag_C.ogg') self.sndTable['falling'][i] = base.loadSfx('phase_4/audio/sfx/MG_cannon_whizz.ogg') self.grabSounds = [] for i in xrange(5): self.grabSounds.append(base.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')) self.grabSoundIndex = 0 for avId in self.avIdList: self.toonHitTracks[avId] = Wait(0.1) self.scores = [0] * self.numPlayers self.goalBar = DirectWaitBar(parent=render2d, relief=DGG.SUNKEN, frameSize=(-0.35, 0.35, -0.15, 0.15), borderWidth=(0.02, 0.02), scale=0.42, pos=(0.84, 0, 0.5 - 0.28 * self.numPlayers + 0.05), barColor=(0, 0.7, 0, 1)) self.goalBar.setBin('unsorted', 0) self.goalBar.hide() self.introTrack = self.getIntroTrack() self.introTrack.start() return def offstage(self): self.notify.debug('offstage') if self.introTrack.isPlaying(): self.introTrack.finish() del self.introTrack for avId in self.toonHitTracks.keys(): track = self.toonHitTracks[avId] if track.isPlaying(): track.finish() self.__killCameraTask() camera.wrtReparentTo(render) self.camParent.removeNode() del self.camParent for panel in self.scorePanels: panel.cleanup() self.scorePanels = [] self.goalBar.destroy() del self.goalBar base.setCellsAvailable(base.rightCells, 1) for suit in self.suits: suit.offstage() self.__unloadSuits() for treasure in self.treasures: treasure.destroy() del self.treasures del self.sndTable del self.grabSounds del self.toonRNGs self.maze.offstage() base.localAvatar.showName() DistributedMinigame.offstage(self) def __placeToon(self, avId): toon = self.getAvatar(avId) if self.numPlayers == 1: toon.setPos(0, 0, self.TOON_Z) toon.setHpr(180, 0, 0) else: posIndex = self.avIdList.index(avId) toon.setPos(self.startPosHTable[posIndex][0]) toon.setHpr(self.startPosHTable[posIndex][1], 0, 0) def setGameReady(self): if not self.hasLocalToon: return self.notify.debug('setGameReady') if DistributedMinigame.setGameReady(self): return for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.reparentTo(render) self.__placeToon(avId) toon.setAnimState('Happy', 1.0) toon.startSmooth() toon.startLookAround() def setGameStart(self, timestamp): if not self.hasLocalToon: return self.notify.debug('setGameStart') DistributedMinigame.setGameStart(self, timestamp) if self.introTrack.isPlaying(): self.introTrack.finish() for avId in self.remoteAvIdList: toon = self.getAvatar(avId) if toon: toon.stopLookAround() self.gameFSM.request('play') def handleDisabledAvatar(self, avId): hitTrack = self.toonHitTracks[avId] if hitTrack.isPlaying(): hitTrack.finish() DistributedMinigame.handleDisabledAvatar(self, avId) def enterOff(self): self.notify.debug('enterOff') def exitOff(self): pass def enterPlay(self): self.notify.debug('enterPlay') for i in xrange(self.numPlayers): avId = self.avIdList[i] avName = self.getAvatarName(avId) scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName) scorePanel.reparentTo(base.a2dTopRight) scorePanel.setPos(-0.213, 0.0, -0.5 - 0.28 * i) self.scorePanels.append(scorePanel) self.goalBar.show() self.goalBar['value'] = 0.0 base.setCellsAvailable(base.rightCells, 0) self.__spawnUpdateSuitsTask() orthoDrive = OrthoDrive(self.TOON_SPEED, maxFrameMove=self.MAX_FRAME_MOVE, customCollisionCallback=self.__doMazeCollisions, priority=1) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=not self.isSinglePlayer()) self.orthoWalk.start() self.accept(MazeSuit.COLLISION_EVENT_NAME, self.__hitBySuit) self.accept(self.TREASURE_GRAB_EVENT_NAME, self.__treasureGrabbed) self.timer = ToontownTimer.ToontownTimer() self.timer.posInTopRightCorner() self.timer.setTime(MazeGameGlobals.GAME_DURATION) self.timer.countdown(MazeGameGlobals.GAME_DURATION, self.timerExpired) self.accept('resetClock', self.__resetClock) base.playMusic(self.music, looping=0, volume=0.8) def exitPlay(self): self.notify.debug('exitPlay') self.ignore('resetClock') self.ignore(MazeSuit.COLLISION_EVENT_NAME) self.ignore(self.TREASURE_GRAB_EVENT_NAME) self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk self.__killUpdateSuitsTask() self.timer.stop() self.timer.destroy() del self.timer for avId in self.avIdList: toon = self.getAvatar(avId) if toon: toon.loop('neutral') def __resetClock(self, tOffset): self.notify.debug('resetClock') self.gameStartTime += tOffset self.timer.countdown(self.timer.currentTime + tOffset, self.timerExpired) def __treasureGrabbed(self, treasureNum): self.treasures[treasureNum].showGrab() self.grabSounds[self.grabSoundIndex].play() self.grabSoundIndex = (self.grabSoundIndex + 1) % len(self.grabSounds) self.sendUpdate('claimTreasure', [treasureNum]) def setTreasureGrabbed(self, avId, treasureNum): if not self.hasLocalToon: return if avId != self.localAvId: self.treasures[treasureNum].showGrab() i = self.avIdList.index(avId) self.scores[i] += 1 self.scorePanels[i].setScore(self.scores[i]) total = 0 for score in self.scores: total += score self.goalBar['value'] = 100.0 * (float(total) / float(self.maze.numTreasures)) def __hitBySuit(self, suitNum): self.notify.debug('hitBySuit') timestamp = globalClockDelta.localToNetworkTime(globalClock.getFrameTime()) self.sendUpdate('hitBySuit', [self.localAvId, timestamp]) self.__showToonHitBySuit(self.localAvId, timestamp) def hitBySuit(self, avId, timestamp): if not self.hasLocalToon: return if self.gameFSM.getCurrentState().getName() not in ['play', 'showScores']: self.notify.warning('ignoring msg: av %s hit by suit' % avId) return self.notify.debug('avatar ' + `avId` + ' hit by a suit') if avId != self.localAvId: self.__showToonHitBySuit(avId, timestamp) def __showToonHitBySuit(self, avId, timestamp): toon = self.getAvatar(avId) if toon == None: return rng = self.toonRNGs[self.avIdList.index(avId)] curPos = toon.getPos(render) oldTrack = self.toonHitTracks[avId] if oldTrack.isPlaying(): oldTrack.finish() toon.setPos(curPos) toon.setZ(self.TOON_Z) parentNode = render.attachNewNode('mazeFlyToonParent-' + `avId`) parentNode.setPos(toon.getPos()) toon.reparentTo(parentNode) toon.setPos(0,0,0) startPos = parentNode.getPos() dropShadow = toon.dropShadow.copyTo(parentNode) dropShadow.setScale(toon.dropShadow.getScale(render)) trajectory = Trajectory.Trajectory( 0, Point3(0,0,0), Point3(0,0,50), gravMult=1.0) flyDur = trajectory.calcTimeOfImpactOnPlane(0.0) while 1: endTile = [rng.randint(2, self.maze.width-1), rng.randint(2, self.maze.height-1)] if self.maze.isWalkable(endTile[0], endTile[1]): break endWorldCoords = self.maze.tile2world(endTile[0], endTile[1]) endPos = Point3(endWorldCoords[0], endWorldCoords[1], startPos[2]) def flyFunc(t, trajectory, startPos = startPos, endPos = endPos, dur = flyDur, moveNode = parentNode, flyNode = toon): u = t/dur moveNode.setX(startPos[0] + u * (endPos[0]-startPos[0])) moveNode.setY(startPos[1] + u * (endPos[1]-startPos[1])) flyNode.setPos(trajectory.getPos(t)) flyTrack = Sequence( LerpFunctionInterval(flyFunc, fromData=0.0, toData=flyDur, duration=flyDur, extraArgs=[trajectory]), name=toon.uniqueName('hitBySuit-fly')) if avId != self.localAvId: cameraTrack = Sequence() else: self.camParent.reparentTo(parentNode) startCamPos = camera.getPos() destCamPos = camera.getPos() zenith = trajectory.getPos(flyDur/2.0)[2] destCamPos.setZ(zenith*1.3) destCamPos.setY(destCamPos[1]*0.3) def camTask(task, zenith = zenith, flyNode = toon, startCamPos = startCamPos, camOffset = destCamPos - startCamPos): u = flyNode.getZ()/zenith camera.setPos(startCamPos + camOffset*u) camera.lookAt(toon) return Task.cont camTaskName = 'mazeToonFlyCam-' + `avId` taskMgr.add(camTask, camTaskName, priority=20) def cleanupCamTask(self = self, toon = toon, camTaskName = camTaskName, startCamPos = startCamPos): taskMgr.remove(camTaskName) self.camParent.reparentTo(toon) camera.setPos(startCamPos) camera.lookAt(toon) cameraTrack = Sequence( Wait(flyDur), Func(cleanupCamTask), name='hitBySuit-cameraLerp') geomNode = toon.getGeomNode() startHpr = geomNode.getHpr() destHpr = Point3(startHpr) hRot = rng.randrange(1, 8) if rng.choice([0, 1]): hRot = -hRot destHpr.setX(destHpr[0] + hRot*360) spinHTrack = Sequence( LerpHprInterval(geomNode, flyDur, destHpr, startHpr=startHpr), Func(geomNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinH')) parent = geomNode.getParent() rotNode = parent.attachNewNode('rotNode') geomNode.reparentTo(rotNode) rotNode.setZ(toon.getHeight()/2.0) oldGeomNodeZ = geomNode.getZ() geomNode.setZ(-toon.getHeight()/2.0) startHpr = rotNode.getHpr() destHpr = Point3(startHpr) pRot = rng.randrange(1,3) if rng.choice([0, 1]): pRot = -pRot destHpr.setY(destHpr[1] + pRot*360) spinPTrack = Sequence( LerpHprInterval(rotNode, flyDur, destHpr, startHpr=startHpr), Func(rotNode.setHpr, startHpr), name=toon.uniqueName('hitBySuit-spinP')) i = self.avIdList.index(avId) soundTrack = Sequence( Func(base.playSfx, self.sndTable['hitBySuit'][i]), Wait(flyDur * (2.0/3.0)), SoundInterval(self.sndTable['falling'][i], duration=flyDur * (1.0/3.0)), name=toon.uniqueName('hitBySuit-soundTrack')) def preFunc(self = self, avId = avId, toon = toon, dropShadow = dropShadow): forwardSpeed = toon.forwardSpeed rotateSpeed = toon.rotateSpeed if avId == self.localAvId: self.orthoWalk.stop() else: toon.stopSmooth() if forwardSpeed or rotateSpeed: toon.setSpeed(forwardSpeed, rotateSpeed) toon.dropShadow.hide() def postFunc(self = self, avId = avId, oldGeomNodeZ = oldGeomNodeZ, dropShadow = dropShadow, parentNode = parentNode): if avId == self.localAvId: base.localAvatar.setPos(endPos) if hasattr(self, 'orthoWalk'): if self.gameFSM.getCurrentState().getName() == 'play': self.orthoWalk.start() dropShadow.removeNode() del dropShadow toon.dropShadow.show() geomNode = toon.getGeomNode() rotNode = geomNode.getParent() baseNode = rotNode.getParent() geomNode.reparentTo(baseNode) rotNode.removeNode() del rotNode geomNode.setZ(oldGeomNodeZ) toon.reparentTo(render) toon.setPos(endPos) parentNode.removeNode() del parentNode if avId != self.localAvId: toon.startSmooth() preFunc() hitTrack = Sequence(Parallel(flyTrack, cameraTrack, spinHTrack, spinPTrack, soundTrack), Func(postFunc), name=toon.uniqueName('hitBySuit')) self.toonHitTracks[avId] = hitTrack hitTrack.start(globalClockDelta.localElapsedTime(timestamp)) def allTreasuresTaken(self): if not self.hasLocalToon: return self.notify.debug('all treasures taken') if not MazeGameGlobals.ENDLESS_GAME: self.gameFSM.request('showScores') def timerExpired(self): self.notify.debug('local timer expired') if not MazeGameGlobals.ENDLESS_GAME: self.gameFSM.request('showScores') def __doMazeCollisions(self, oldPos, newPos): offset = newPos - oldPos WALL_OFFSET = 1.0 curX = oldPos[0] curY = oldPos[1] curTX, curTY = self.maze.world2tile(curX, curY) def calcFlushCoord(curTile, newTile, centerTile): EPSILON = 0.01 if newTile > curTile: return (newTile - centerTile) * self.CELL_WIDTH - EPSILON - WALL_OFFSET else: return (curTile - centerTile) * self.CELL_WIDTH + WALL_OFFSET offsetX = offset[0] offsetY = offset[1] WALL_OFFSET_X = WALL_OFFSET if offsetX < 0: WALL_OFFSET_X = -WALL_OFFSET_X WALL_OFFSET_Y = WALL_OFFSET if offsetY < 0: WALL_OFFSET_Y = -WALL_OFFSET_Y newX = curX + offsetX + WALL_OFFSET_X newY = curY newTX, newTY = self.maze.world2tile(newX, newY) if newTX != curTX: if self.maze.collisionTable[newTY][newTX]: offset.setX(calcFlushCoord(curTX, newTX, self.maze.originTX) - curX) newX = curX newY = curY + offsetY + WALL_OFFSET_Y newTX, newTY = self.maze.world2tile(newX, newY) if newTY != curTY: if self.maze.collisionTable[newTY][newTX]: offset.setY(calcFlushCoord(curTY, newTY, self.maze.originTY) - curY) offsetX = offset[0] offsetY = offset[1] newX = curX + offsetX + WALL_OFFSET_X newY = curY + offsetY + WALL_OFFSET_Y newTX, newTY = self.maze.world2tile(newX, newY) if self.maze.collisionTable[newTY][newTX]: cX = calcFlushCoord(curTX, newTX, self.maze.originTX) cY = calcFlushCoord(curTY, newTY, self.maze.originTY) if abs(cX - curX) < abs(cY - curY): offset.setX(cX - curX) else: offset.setY(cY - curY) return oldPos + offset def __spawnCameraTask(self): self.notify.debug('spawnCameraTask') camera.lookAt(base.localAvatar) taskMgr.remove(self.CAMERA_TASK) taskMgr.add(self.__cameraTask, self.CAMERA_TASK, priority=45) def __killCameraTask(self): self.notify.debug('killCameraTask') taskMgr.remove(self.CAMERA_TASK) def __cameraTask(self, task): self.camParent.setHpr(render, 0, 0, 0) return Task.cont def __loadSuits(self): self.notify.debug('loadSuits') self.suits = [] self.numSuits = 4 * self.numPlayers safeZone = self.getSafezoneId() slowerTable = self.slowerSuitPeriods if self.SLOWER_SUIT_CURVE: slowerTable = self.slowerSuitPeriodsCurve slowerPeriods = slowerTable[safeZone][self.numSuits] fasterTable = self.fasterSuitPeriods if self.FASTER_SUIT_CURVE: fasterTable = self.fasterSuitPeriodsCurve fasterPeriods = fasterTable[safeZone][self.numSuits] suitPeriods = slowerPeriods + fasterPeriods self.notify.debug('suit periods: ' + `suitPeriods`) self.randomNumGen.shuffle(suitPeriods) for i in xrange(self.numSuits): self.suits.append(MazeSuit(i, self.maze, self.randomNumGen, suitPeriods[i], self.getDifficulty())) def __unloadSuits(self): self.notify.debug('unloadSuits') for suit in self.suits: suit.destroy() self.suits = [] def __spawnUpdateSuitsTask(self): self.notify.debug('spawnUpdateSuitsTask') for suit in self.suits: suit.gameStart(self.gameStartTime) taskMgr.remove(self.UPDATE_SUITS_TASK) taskMgr.add(self.__updateSuitsTask, self.UPDATE_SUITS_TASK) def __killUpdateSuitsTask(self): self.notify.debug('killUpdateSuitsTask') taskMgr.remove(self.UPDATE_SUITS_TASK) for suit in self.suits: suit.gameEnd() def __updateSuitsTask(self, task): curT = globalClock.getFrameTime() - self.gameStartTime curTic = int(curT * float(MazeGameGlobals.SUIT_TIC_FREQ)) suitUpdates = [] for i in xrange(len(self.suits)): updateTics = self.suits[i].getThinkTimestampTics(curTic) suitUpdates.extend(zip(updateTics, [i] * len(updateTics))) suitUpdates.sort(lambda a, b: a[0] - b[0]) if len(suitUpdates) > 0: curTic = 0 for i in xrange(len(suitUpdates)): update = suitUpdates[i] tic = update[0] suitIndex = update[1] suit = self.suits[suitIndex] if tic > curTic: curTic = tic j = i + 1 while j < len(suitUpdates): if suitUpdates[j][0] > tic: break self.suits[suitUpdates[j][1]].prepareToThink() j += 1 unwalkables = [] for si in xrange(suitIndex): unwalkables.extend(self.suits[si].occupiedTiles) for si in xrange(suitIndex + 1, len(self.suits)): unwalkables.extend(self.suits[si].occupiedTiles) suit.think(curTic, curT, unwalkables) return Task.cont def enterShowScores(self): self.notify.debug('enterShowScores') lerpTrack = Parallel() lerpDur = 0.5 lerpTrack.append(Parallel(LerpPosInterval(self.goalBar, lerpDur, Point3(0, 0, -.6), blendType='easeInOut'), LerpScaleInterval(self.goalBar, lerpDur, Vec3(self.goalBar.getScale()) * 2.0, blendType='easeInOut'))) tY = 0.6 bY = -.05 lX = -.5 cX = 0 rX = 0.5 scorePanelLocs = (((cX, bY),), ((lX, bY), (rX, bY)), ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY), (lX, bY), (rX, bY))) scorePanelLocs = scorePanelLocs[self.numPlayers - 1] for i in xrange(self.numPlayers): panel = self.scorePanels[i] pos = scorePanelLocs[i] panel.wrtReparentTo(aspect2d) lerpTrack.append(Parallel(LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut'))) self.showScoreTrack = Parallel(lerpTrack, Sequence(Wait(MazeGameGlobals.SHOWSCORES_DURATION), Func(self.gameOver))) self.showScoreTrack.start() #For the Alpha Blueprint ARG if config.GetBool('want-blueprint4-ARG', False): MinigameGlobals.generateDebugARGPhrase() def exitShowScores(self): self.showScoreTrack.pause() del self.showScoreTrack def enterCleanup(self): self.notify.debug('enterCleanup') def exitCleanup(self): pass def getIntroTrack(self): self.__cameraTask(None) origCamParent = camera.getParent() origCamPos = camera.getPos() origCamHpr = camera.getHpr() iCamParent = base.localAvatar.attachNewNode('iCamParent') iCamParent.setH(180) camera.reparentTo(iCamParent) toonHeight = base.localAvatar.getHeight() camera.setPos(0, -15, toonHeight * 3) camera.lookAt(0, 0, toonHeight / 2.0) iCamParent.wrtReparentTo(origCamParent) waitDur = 5.0 lerpDur = 4.5 lerpTrack = Parallel() startHpr = iCamParent.getHpr() startHpr.setX(PythonUtil.reduceAngle(startHpr[0])) lerpTrack.append(LerpPosHprInterval(iCamParent, lerpDur, pos=Point3(0, 0, 0), hpr=Point3(0, 0, 0), startHpr=startHpr, name=self.uniqueName('introLerpParent'))) lerpTrack.append(LerpPosHprInterval(camera, lerpDur, pos=origCamPos, hpr=origCamHpr, blendType='easeInOut', name=self.uniqueName('introLerpCameraPos'))) base.localAvatar.startLookAround() def cleanup(origCamParent = origCamParent, origCamPos = origCamPos, origCamHpr = origCamHpr, iCamParent = iCamParent): camera.reparentTo(origCamParent) camera.setPos(origCamPos) camera.setHpr(origCamHpr) iCamParent.removeNode() del iCamParent base.localAvatar.stopLookAround() return Sequence(Wait(waitDur), lerpTrack, Func(cleanup))
class ValueBar(rootsim.RootSim): """Display Value in a loading bar fashion""" def __init__(self, path, scale=0.5, extraText='', decimal=0, showOverValues=1): rootsim.RootSim.__init__(self, path, scale=scale) self.extraText = extraText self.currentValue = 0.0 self.maxValue = 0.0 self.barValue = 0.0 self.scale = scale self.decimal = decimal self.showOverValues = showOverValues self.myText = '' self.textOverValue = None self.myBar = DirectWaitBar(text = '0 / 0', scale = scale, frameColor = globals.colors['guiblue2'], borderWidth = (0.01, 0.01)) self.barColor = globals.colors['guiblue1'] def setMyPosition(self, x, y, z): self.x = x self.y = y self.z = z self.myBar.setPos(x, y, z) if self.textOverValue != None: barWidth = self.myBar.getWidth()*self.scale/2.0 barHeight = self.myBar.getHeight()*self.scale/3.0 self.textOverValue.setMyPosition(x+barWidth, y, z-barHeight) def updateMyBar(self): """Update the bar on the screen""" self.myBar['text'] = self.myText self.myBar['value'] = self.barValue self.myBar['barColor'] = self.barColor def setMyValues(self, currentValue, maxValue): self.currentValue = float(currentValue) self.maxValue = float(maxValue) self.setMyText() self.setBarValue() self.updateMyBar() self.writeOverValue() def setMyText(self): if self.currentValue == self.maxValue: if self.decimal == 1: self.myText = '%s' % self.currentValue else: self.myText = '%d' % self.currentValue else: if self.decimal == 1: self.myText = '%s / %s' % (self.currentValue, self.maxValue) else: self.myText = '%d / %d' % (self.currentValue, self.maxValue) self.myText = self.myText + ' %s' % self.extraText def setBarValue(self): """Bar Value can only be from 0 to 100""" if self.currentValue > self.maxValue: self.barValue = 100 elif self.maxValue == 0: self.barValue = 0 else: self.barValue = (self.currentValue / self.maxValue) * 100.0 def setColor(self, color): """set the text color = Vec4(red, green, blue, alpha)""" self.barColor = color self.updateMyBar() def writeOverValue(self): """Set the textOverValue text if currentValue > maxValue""" if self.showOverValues == 1: value = self.currentValue - self.maxValue self.clearText(self.textOverValue) if int(value) > 0: self.textOverValue = textonscreen.TextOnScreen(self.path, '+ %d' % value, self.scale/8.0, parent=aspect2d) self.textOverValue.writeTextToScreen(self.x, self.y, self.z) self.textOverValue.setColor(globals.colors['guiyellow']) def clearText(self, textSim): """If sim exists remove from panda""" if textSim != None: textSim.destroy() textSim = None def destroy(self): """remove Bar, text""" self.myBar.destroy() self.clearText(self.textOverValue)
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 DistributedPieTurretManager(DistributedObject): notify = directNotify.newCategory("DistributedPieTurretManager") def __init__(self, cr): DistributedObject.__init__(self, cr) self.myTurret = None self.guiFrame = None self.guiLabel = None self.guiBar = None self.guiBg = None self.turretGag = None return def announceGenerate(self): DistributedObject.announceGenerate(self) base.taskMgr.add(self.__pollMyBattle, "__pollMyBattle") def disable(self): base.taskMgr.remove("DPTM.pollTurret") base.taskMgr.remove("__pollMyBattle") if hasattr(self, "makeTurretBtn"): self.makeTurretBtn.destroy() del self.makeTurretBtn self.destroyGui() self.myTurret = None if base.localAvatar.getMyBattle(): base.localAvatar.getMyBattle().setTurretManager(None) DistributedObject.disable(self) return def __pollTurret(self, turretId, task): turret = self.cr.doId2do.get(turretId) if turret != None: self.myTurret = turret self.turretGag = None self.makeGui() return Task.done else: return Task.cont def setGag(self, upgradeId): self.turretGag = upgradeId def d_requestPlace(self, posHpr): self.sendUpdate("requestPlace", [posHpr]) def turretPlaced(self, turretId): turret = self.cr.doId2do.get(turretId) turret.b_setGag(self.turretGag) self.turretGag = None base.taskMgr.add(self.__pollTurret, "DPTM.pollTurret", extraArgs=[turretId], appendTask=True) return def yourTurretIsDead(self): base.taskMgr.remove("DPTM.pollTurret") self.destroyGui() self.myTurret = None if base.localAvatar.getPUInventory()[0] > 0: self.createTurretButton() return def makeGui(self): self.destroyGui() self.guiFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.55, 0, 0.15)) self.guiBg = OnscreenImage(image="phase_4/maps/turret_gui_bg.png", scale=(0.15, 0, 0.075), parent=self.guiFrame) self.guiBg.setTransparency(True) self.guiLabel = DirectLabel( text="Turret", text_fg=(1, 0, 0, 1), relief=None, text_scale=0.05, text_font=loader.loadFont("phase_3/models/fonts/ImpressBT.ttf"), pos=(0, 0, 0.025), parent=self.guiFrame, ) self.guiBar = DirectWaitBar( range=self.myTurret.getMaxHealth(), value=self.myTurret.getHealth(), scale=0.125, parent=self.guiFrame, pos=(0, 0, -0.01), ) return def createTurretButton(self): self.makeTurretBtn = DirectButton( relief=None, geom=CIGlobals.getDefaultBtnGeom(), text="Turret", text_scale=0.055, command=self.handleMakeTurretBtn, pos=(-0.47, 0, 0.1), geom_scale=(0.5, 1.0, 1.0), text_pos=(0, -0.01), parent=base.a2dBottomRight, ) return def handleMakeTurretBtn(self): self.makeTurretBtn.destroy() del self.makeTurretBtn x, y, z = base.localAvatar.getPos() h, p, r = base.localAvatar.getHpr() self.d_requestPlace([x, y, z, h, p, r]) base.localAvatar.sendUpdate("usedPU", [0]) def __pollMyBattle(self, task): if base.localAvatar.getMyBattle(): base.localAvatar.getMyBattle().setTurretManager(self) if base.localAvatar.getPUInventory()[0] > 0: self.createTurretButton() return Task.done return Task.cont def destroyGui(self): if self.guiBar: self.guiBar.destroy() self.guiBar = None if self.guiLabel: self.guiLabel.destroy() self.guiLabel = None if self.guiBg: self.guiBg.destroy() self.guiBg = None if self.guiFrame: self.guiFrame.destroy() self.guiFrame = None return def updateTurretGui(self): if self.guiBar: self.guiBar.update(self.myTurret.getHealth())
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 CIProgressScreen: def __init__(self): self.bgm = loader.loadModel('phase_3/models/gui/progress-background.bam') self.bgm.find('**/logo').stash() self.bg = self.bgm.find('**/bg') self.logo = loader.loadTexture('phase_3/maps/CogInvasion_Logo.png') self.logoImg = OnscreenImage(image=self.logo, scale=(0.5, 0, 0.3), pos=(0, 0, 0), parent=hidden) self.logoImg.setTransparency(True) self.bg_img = OnscreenImage(image=self.bg, parent=hidden) self.bg_img.setSx(1.35) self.bg_img.hide() self.progress_bar = DirectWaitBar(value=0, pos=(0, 0, -0.85), parent=hidden, text_pos=(0, 0, 0.2)) self.progress_bar.setSx(1.064) self.progress_bar.setSz(0.38) self.loading_lbl = DirectLabel(text='', relief=None, scale=0.08, pos=(-1.0725, 0, -0.79), text_align=TextNode.ALeft, sortOrder=100, text_fg=(0.343, 0.343, 0.343, 1.0), text_font=CIGlobals.getMinnieFont(), parent=hidden, text_shadow=(0, 0, 0, 1)) return def begin(self, hood, range, wantGui): render.hide() self.renderFrames() base.setBackgroundColor(0, 0, 0) if hood == 'localAvatarEnterGame': self.loading_lbl['text'] = 'Entering...' elif hood == 'init': self.loading_lbl['text'] = 'Loading...' else: self.loading_lbl['text'] = 'Heading to %s...' % hood self.progress_bar['barColor'] = (0.343, 0.343, 0.343, 1.0) self.progress_bar['range'] = range self.bgm.reparentTo(aspect2d) self.bg.reparentTo(render2d) self.bg_img.reparentTo(hidden) self.loading_lbl.reparentTo(aspect2d) self.logoImg.reparentTo(aspect2d) self.progress_bar.reparentTo(aspect2d) self.__count = 0 self.__expectedCount = range self.progress_bar.update(self.__count) def renderFramesTask(self, task): self.renderFrames() return task.cont def end(self): base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) taskMgr.remove('renderFrames') render.show() self.progress_bar.finish() self.bg_img.reparentTo(hidden) self.logoImg.reparentTo(hidden) self.bg.reparentTo(hidden) self.bgm.reparentTo(hidden) self.loading_lbl.reparentTo(hidden) self.progress_bar.reparentTo(hidden) self.renderFrames() def destroy(self): self.bg.removeNode() del self.bg self.bgm.removeNode() del self.bgm self.bg_img.destroy() self.loading_lbl.destroy() self.progress_bar.destroy() self.bgm.destroy() del self.bg_img del self.loading_lbl del self.progress_bar del self.bgm def renderFrames(self): base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def tick(self): self.__count += 1 self.progress_bar.update(self.__count)
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 DistributedCogBattle(DistributedObject): notify = directNotify.newCategory("DistributedCogBattle") DNCData = { 0: [[(-50, 98.73, 0.40), (351.31, 0.00, 0.00), 1.25], [(-41.07, 97.20, 0.40), (350.34, 0.00, 0.00), 1.25], [(-152.73, -0.58, 0.40), (90.00, 0, 0), 1.25], [(-152.73, 8.81, 0.40), (85.30, 0, 0), 1.25], [(34.34, -157.19, 2.95), (150.75, 0, 0), 1.25], [(26.21, -152.66, 2.95), (147.09, 0, 0), 1.25]], 1: [], 2: [], 5: [] } def __init__(self, cr): try: self.DistributedCogBattle_initialized return except: self.DistributedCogBattle_initialized = 1 DistributedObject.__init__(self, cr) self.hoodIndex = None self.totalCogs = None self.cogsRemaining = None self.cogProgressBar = None self.DNCSigns = [] self.introMessageSeq = None self.victorySeq = None self.turretManager = None self.isGettingBeans = False self.getBeansLabel = OnscreenText( text="Hurry and pick up all of the jellybeans!", fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(0, 0.7), font=CIGlobals.getMinnieFont()) self.getBeansLabel.hide() self.timer = Timer() self.timer.setZeroCommand(self.getBeansTimeUp) # Give toons 30 seconds to get the beans at the end. self.timer.setInitialTime(60) self.endMusic = base.loadMusic( 'phase_7/audio/bgm/encntr_toon_winning_indoor.mid') self.balloonSound = base.loadSfx( 'phase_3/audio/sfx/GUI_balloon_popup.ogg') def d_left(self): self.sendUpdate('iLeft') def monitorHP(self, task): if base.localAvatar.getHealth() < 1: taskMgr.doMethodLater(7.0, self.diedTask, self.uniqueName('diedTask')) return task.done return task.cont def diedTask(self, task): self.d_left() return task.done def setTurretManager(self, tmgr): self.turretManager = tmgr def getTurretManager(self): return self.turretManager def getTurretCount(self): avatars = self.cr.doFindAll('DistributedToon') turrets = 0 if self.turretManager: if self.turretManager.getTurret(): turrets += 1 if base.localAvatar.getPUInventory()[0] > 0: turrets += 1 for avatar in avatars: if avatar.zoneId == base.localAvatar.zoneId: battle = avatar.getMyBattle() if avatar.getPUInventory()[0] > 0: turrets += 1 if battle: if battle.getTurretManager(): if battle.getTurretManager().getTurret(): turrets += 1 return turrets def victory(self): self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('win') self.victorySeq = Sequence(Wait(5.0), Func(self.finishVictory)) self.victorySeq.start() def finishVictory(self): # Give the players some time to pick up jellybeans before they leave. self.cr.playGame.getPlace().fsm.request('walk') self.cr.playGame.hood.loader.music.stop() base.playMusic(self.endMusic, volume=0.8, looping=1) self.timer.load() self.timer.startTiming() self.getBeansLabel.show() base.playSfx(self.balloonSound) def getBeansTimeUp(self): self.timer.unload() self.getBeansLabel.hide() hoodId = self.cr.playGame.hood.hoodId zoneId = CogBattleGlobals.HoodIndex2HoodId[self.getHoodIndex()] requestStatus = { 'zoneId': zoneId, 'hoodId': hoodId, 'where': 'playground', 'avId': base.localAvatar.doId, 'loader': 'safeZoneLoader', 'shardId': None, 'how': 'teleportIn' } self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) def setTotalCogs(self, num): self.totalCogs = num def getTotalCogs(self): return self.totalCogs def setCogsRemaining(self, num): self.cogsRemaining = num if self.cogProgressBar: self.__updateProgressBar() def getCogsRemaining(self): return self.cogsRemaining def setHoodIndex(self, index): self.hoodIndex = index def getHoodIndex(self): return self.hoodIndex def startPlacePoll(self): taskMgr.add(self.__placePoll, "DistributedCogBattle-placePoll") def __placePoll(self, task): # Wait for the place to come out of None if self.cr.playGame.getPlace() != None: self.sendUpdate("arrived", []) self.constructArea() self.createInterface() self.__doIntroMessages() return task.done else: return task.cont def stopPlacePoll(self): taskMgr.remove("DistributedCogBattle-placePoll") def createInterface(self): self.cogProgressBar = DirectWaitBar(pos=(0, 0, -0.9), relief=DGG.RAISED, scale=0.6, frameColor=(1, 0.5, 0.3, 0.75), barColor=(1, 0.25, 0.25, 0.5), value=0, range=self.getTotalCogs(), text="", text_scale=0.08) self.__updateProgressBar() def __updateProgressBar(self): self.cogProgressBar.update(self.getCogsRemaining()) self.cogProgressBar['text'] = "{0}/{1} {2} Remaining".format( self.getCogsRemaining(), self.getTotalCogs(), CIGlobals.Suits) def destroyInterface(self): if self.cogProgressBar: self.cogProgressBar.destroy() self.cogProgressBar = None def createBossGui(self): self.destroyInterface() backgroundGui = loader.loadModel( 'phase_5/models/cogdominium/tt_m_gui_csa_flyThru.bam') backgroundGui.find('**/chatBubble').removeNode() bg = backgroundGui.find('**/background') bg.setScale(5.2) bg.setPos(0.14, 0, -0.6667) bg.reparentTo(aspect2d) self.frame = DirectFrame(geom=bg, relief=None, pos=(0.2, 0, -0.6667)) def constructArea(self): for data in self.DNCData[self.hoodIndex]: dnc = loader.loadModel("phase_3.5/models/props/do_not_cross.egg") dnc.setPos(*data[0]) dnc.setHpr(*data[1]) dnc.setScale(data[2]) dnc.reparentTo(render) self.DNCSigns.append(dnc) def deconstructArea(self): for dnc in self.DNCSigns: dnc.removeNode() def createWhisper(self, msg): whisper = WhisperPopup('Toon HQ: ' + msg, CIGlobals.getToonFont(), ChatGlobals.WTSystem) whisper.manage(base.marginManager) def __doIntroMessages(self): self.introMessageSeq = Sequence( name="DistributedCogBattle-introMessageSeq") self.introMessageSeq.append( Func( self.createWhisper, "Welcome, Toons! The Cogs will be here soon, so get prepared!") ) self.introMessageSeq.append(Wait(7.5)) self.introMessageSeq.append( Func( self.createWhisper, "The pink bar at the bottom of the screen shows the amount of Cogs remaining to defeat." )) self.introMessageSeq.append(Wait(8.5)) self.introMessageSeq.append( Func( self.createWhisper, "Purchase gags from Goofy at the Gag Shop to restock your used gags." )) self.introMessageSeq.append(Wait(7.5)) self.introMessageSeq.append( Func( self.createWhisper, "Purchase battle tools from Coach at Coach's Battle Shop in between invasions." )) self.introMessageSeq.setDoneEvent(self.introMessageSeq.getName()) self.acceptOnce(self.introMessageSeq.getDoneEvent(), self.__introMessagesDone) self.introMessageSeq.start() def __introMessagesDone(self): if self.introMessageSeq: self.introMessageSeq.finish() self.introMessageSeq = None def announceGenerate(self): DistributedObject.announceGenerate(self) base.localAvatar.setMyBattle(self) self.startPlacePoll() taskMgr.add(self.monitorHP, "DCB.monitorHP") def disable(self): taskMgr.remove("DCB.monitorHP") taskMgr.remove(self.uniqueName('diedTask')) self.endMusic.stop() self.endMusic = None self.getBeansLabel.destroy() self.getBeansLabel = None self.timer.unload() self.timer.cleanup() self.timer = None self.balloonSound = None self.turretManager = None base.localAvatar.setMyBattle(None) self.stopPlacePoll() self.deconstructArea() self.destroyInterface() if self.victorySeq: self.victorySeq.pause() self.victorySeq = None self.hoodIndex = None self.DNCSigns = None self.totalCogs = None self.cogsRemaining = None if self.introMessageSeq: self.introMessageSeq.pause() self.introMessageSeq = None DistributedObject.disable(self)
class CIProgressScreen: Color = (118 / 255.0, 121 / 255.0, 127 / 255.0, 1.0) BarColor = (152 / 255.0, 129 / 255.0, 64 / 255.0, 1.0) def __init__(self): self.defaultLogoScale = 1 self.defaultLogoZ = 0.65 self.bgm = loader.loadModel( "phase_3/models/gui/progress-background.bam") self.bgm.find('**/logo').stash() self.barShadow = OnscreenImage(image=self.bgm.find("**/bar_shadow"), parent=hidden) self.bgm.find("**/bar_shadow").removeNode() self.bg = self.bgm.find('**/bg') self.defaultBgTexture = self.bg.findTexture('*') self.logoNode, self.logoImg = CIGlobals.getLogoImage( hidden, self.defaultLogoScale, (0, 0, self.defaultLogoZ)) self.bg_img = OnscreenImage(image=self.bg, parent=hidden) self.bg_img.setSx(1.35) self.bg_img.hide() self.progress_bar = DirectWaitBar(value=0, pos=(0, 0, -0.85), parent=hidden, text_pos=(0, 0, 0.2)) self.progress_bar.setSx(1.064) self.progress_bar.setSz(0.38) toontipgui = loader.loadModel( 'phase_3.5/models/gui/stickerbook_gui.bam') poster = toontipgui.find('**/questCard') self.toontipFrame = DirectFrame(image=poster, image_scale=(1.4, 1, 1), parent=hidden, relief=None, pos=(0, 0, -0.1), scale=0.85) self.toontipLbl = OnscreenText(text="", parent=self.toontipFrame, fg=(89.0 / 255, 95.0 / 255, 98.0 / 255, 1), font=CIGlobals.getToonFont(), wordwrap=13, pos=(-0.59, 0.25), align=TextNode.ALeft, scale=0.08) self.loading_lbl = DirectLabel(text="", relief=None, scale=0.08, pos=(-1.0725, 0, -0.79), text_align=TextNode.ALeft, sortOrder=100, text_fg=(1, 1, 1, 1), text_font=CIGlobals.getMinnieLogoFont(), parent=hidden, text_shadow=(0, 0, 0, 0)) # This is useful when the user has chosen to hide aspect2d before the loading screen. # However, we want to show the loading screen all the time, so we need to restore the # previous state after the loading screen ends. self.mustRestoreHiddenAspect2d = False def begin(self, hood, range, wantGui): render.hide() NametagGlobals.setWant2dNametags(False) if base.aspect2d.isHidden(): base.aspect2d.show() self.mustRestoreHiddenAspect2d = True self.renderFrames() base.setBackgroundColor(0, 0, 0) if hood == "localAvatarEnterGame": self.loading_lbl['text'] = "Entering..." elif hood == "init": self.loading_lbl['text'] = "Loading..." else: self.loading_lbl['text'] = "Heading to %s..." % hood self.progress_bar['barColor'] = self.BarColor self.progress_bar['range'] = range self.bgm.reparentTo(aspect2d) ZoneUtil.Hood2ZoneId.keys() # We only want to show special loading screens for actual in-game locations. if hood in ZoneUtil.Hood2ZoneId.keys(): abbr = ZoneUtil.ZoneId2HoodAbbr.get( ZoneUtil.Hood2ZoneId.get(hood)).lower() bgTexture = loader.loadTexture( 'phase_14/maps/{0}_loading.png'.format(abbr), okMissing=True) if bgTexture: self.bg.setTexture(bgTexture, 1) self.barShadow.reparentTo(aspect2d) self.bg.reparentTo(render2d) self.bg_img.reparentTo(hidden) self.loading_lbl.reparentTo(aspect2d) self.logoNode.reparentTo(aspect2d) self.progress_bar.reparentTo(aspect2d) tip = random.choice(CIGlobals.ToonTips) self.toontipLbl.setText("TOON TIP:\n" + tip) self.toontipFrame.reparentTo(aspect2d) self.__count = 0 self.__expectedCount = range self.progress_bar.update(self.__count) def renderFramesTask(self, task): self.renderFrames() return task.cont def end(self): base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) taskMgr.remove("renderFrames") render.show() if self.mustRestoreHiddenAspect2d: base.aspect2d.hide() self.mustRestoreHiddenAspect2d = False self.progress_bar.finish() self.bg_img.reparentTo(hidden) self.logoNode.reparentTo(hidden) self.barShadow.reparentTo(hidden) self.bg.reparentTo(hidden) # Let's get rid of the extra texture stage. self.bg.setTexture(self.defaultBgTexture, 1) self.bgm.reparentTo(hidden) self.loading_lbl.reparentTo(hidden) self.progress_bar.reparentTo(hidden) self.toontipFrame.reparentTo(hidden) base.transitions.fadeScreen(1.0) NametagGlobals.setWant2dNametags(True) self.renderFrames() def destroy(self): self.bg.removeNode() del self.bg self.bgm.removeNode() del self.bgm self.bg_img.destroy() self.barShadow.destroy() del self.barShadow self.loading_lbl.destroy() self.progress_bar.destroy() self.bgm.destroy() self.mustRestoreHiddenAspect2d = False del self.bg_img del self.loading_lbl del self.progress_bar del self.bgm del self.defaultBgTexture del self.mustRestoreHiddenAspect2d def renderFrames(self): base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def tick(self): self.__count += 1 self.progress_bar.update(self.__count)
class ExperienceBar(DirectFrame): def __init__(self, exp, level, avdna): DirectFrame.__init__(self, relief=None, sortOrder=50) self.av = None self.style = avdna if self.style.type == 't': self.isToon = 1 else: self.isToon = 0 self.exp = exp self.level = level self.maxExp = ToonExperience.ToonExperience().getLevelMaxExp( self.level) self.expBar = None self.__obscured = 0 self.bgBar = None self.levelLabel = None self.visToggle = None self.levelUpSfx = loader.loadSfx('phase_3.5/audio/sfx/AV_levelup.ogg') self.load() def load(self): if self.isToon: self.barGeom = loader.loadModel('phase_3.5/models/gui/exp_bar') self.color = self.style.getHeadColor() self.bgBar = DirectFrame(parent=base.a2dBottomLeft, relief=None, geom=self.barGeom, pos=(.6, 0, .3), geom_scale=(0.3, 0.25, 0.1), geom_color=self.color) self.expBar = DirectWaitBar(parent=self.bgBar, guiId='expBar', pos=(0.0, 0, 0), relief=DGG.SUNKEN, frameSize=(-2.0, 2.0, -0.1, 0.1), borderWidth=(0.01, 0.01), scale=0.25, range=self.maxExp, sortOrder=50, frameColor=(0.5, 0.5, 0.5, 0.5), barColor=(0.0, 1.0, 0.0, 0.5), text=str(self.exp) + '/' + str(self.maxExp), text_scale=0.2, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05)) self.expBar['value'] = self.exp if self.level == ToontownGlobals.MaxToonLevel: self.expBar['range'] = 1 self.expBar['value'] = 1 self.expBar['text'] = 'MAX' self.levelLabel = OnscreenText( parent=self.bgBar, text=TTLocalizer.ExpBarLevel + str(self.level + 1), pos=(0.0, 0.05), scale=0.05, font=ToontownGlobals.getBuildingNametagFont(), fg=(1, 1, 1, 1)) self.levelLabel.hide() gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui') arrowImage = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'), gui.find('**/tt_t_gui_mat_shuffleArrowDown'), gui.find('**/tt_t_gui_mat_shuffleArrowUp'), gui.find('**/tt_t_gui_mat_shuffleArrowDisabled')) self.visToggle = DirectButton(parent=self.bgBar, relief=None, geom=arrowImage, hpr=(0, 0, 0), pos=(.53, 0, 0), scale=(0.4, 0.4, 0.4), command=self.toggleVis) if not settings.get('experienceBarMode'): self.hide() def destroy(self): if self.av: self.ignore(self.av.uniqueName('toonExpChange')) del self.av del self.exp del self.maxExp if self.visToggle: self.visToggle.destroy() del self.visToggle if self.bgBar: self.bgBar.destroy() del self.bgBar if self.expBar: self.expBar.destroy() if self.levelLabel: self.levelLabel.destroy() DirectFrame.destroy(self) def updateBar(self, exp, level): if level >= ToontownGlobals.MaxToonLevel: self.hide() return if self.__obscured: Sequence(Func(self.show), Wait(3), Func(self.hide)).start() currExp = self.exp self.exp = exp currMax = self.maxExp currLevel = self.level self.level = level self.maxExp = ToonExperience.ToonExperience().getLevelMaxExp( self.level) name = self.av.uniqueName('laffMeterBoing') + '-' + str(self.this) if currLevel != self.level: self.levelLabel['text'] = TTLocalizer.ExpBarLevel + str( self.level + 1) if currMax != self.maxExp: self.expBar['range'] = self.maxExp base.playSfx(self.levelUpSfx) self.expBar['range'] = self.maxExp self.expBar['value'] = exp self.expBar['text'] = str(exp) + '/' + str(self.maxExp) ToontownIntervals.start( ToontownIntervals.getPulseLargerIval(self.bgBar, name)) def start(self): if self.isToon: if self.bgBar: self.bgBar.show() if self.levelLabel: self.levelLabel.show() if self.visToggle: self.visToggle.show() if self.av: self.accept(self.av.uniqueName('toonExpChange'), self.updateBar) def stop(self): if self.isToon: if self.bgBar: self.bgBar.hide() if self.levelLabel: self.levelLabel.hide() if self.visToggle: self.visToggle.hide() if self.av: self.ignore(self.av.uniqueName('toonExpChange')) def setAvatar(self, av): if self.av: self.ignore(self.av.uniqueName('toonExpChange')) self.av = av def toggleVis(self): if self.__obscured: self.show() else: self.hide() def hide(self): if self.bgBar: self.bgBar.posInterval(0.2, Point3(-.5, 0, .3), blendType='easeInOut').start() if self.levelLabel: self.levelLabel.hide() self.visToggle.setHpr(0, 0, 180) self.__obscured = 1 settings['experienceBarMode'] = False def show(self): if self.bgBar: self.bgBar.posInterval(0.2, Point3(.6, 0, .3), blendType='easeInOut').start() if self.levelLabel: self.levelLabel.show() self.visToggle.setHpr(0, 0, 0) self.__obscured = 0 settings['experienceBarMode'] = True
class DistributedCogBattle(DistributedObject): notify = directNotify.newCategory('DistributedCogBattle') DNCData = {0: [[(-50, 98.73, 0.4), (351.31, 0.0, 0.0), 1.25], [(-41.07, 97.2, 0.4), (350.34, 0.0, 0.0), 1.25], [(-152.73, -0.58, 0.4), (90.0, 0, 0), 1.25], [(-152.73, 8.81, 0.4), (85.3, 0, 0), 1.25], [(34.34, -157.19, 2.95), (150.75, 0, 0), 1.25], [(26.21, -152.66, 2.95), (147.09, 0, 0), 1.25]], 1: [], 2: [], 5: []} def __init__(self, cr): try: self.DistributedCogBattle_initialized return except: self.DistributedCogBattle_initialized = 1 DistributedObject.__init__(self, cr) self.hoodIndex = None self.totalCogs = None self.cogsRemaining = None self.cogProgressBar = None self.DNCSigns = [] self.introMessageSeq = None self.victorySeq = None self.turretManager = None return def setTurretManager(self, tmgr): self.turretManager = tmgr def getTurretManager(self): return self.turretManager def victory(self): self.cr.playGame.getPlace().fsm.request('stop') base.localAvatar.b_setAnimState('win') self.victorySeq = Sequence(Wait(7.0), Func(self.finishVictory)) self.victorySeq.start() def finishVictory(self): hoodId = self.cr.playGame.hood.hoodId if hoodId == CIGlobals.BattleTTC: hoodId = CIGlobals.ToontownCentral zoneId = CIGlobals.ToontownCentralId else: zoneId = CogBattleGlobals.HoodIndex2HoodId[self.getHoodIndex()] requestStatus = {'zoneId': zoneId, 'hoodId': hoodId, 'where': 'playground', 'avId': base.localAvatar.doId, 'loader': 'safeZoneLoader', 'shardId': None, 'how': 'teleportIn'} self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) return def setTotalCogs(self, num): self.totalCogs = num def getTotalCogs(self): return self.totalCogs def setCogsRemaining(self, num): self.cogsRemaining = num if self.cogProgressBar: self.__updateProgressBar() def getCogsRemaining(self): return self.cogsRemaining def setHoodIndex(self, index): self.hoodIndex = index def getHoodIndex(self): return self.hoodIndex def startPlacePoll(self): taskMgr.add(self.__placePoll, 'DistributedCogBattle-placePoll') def __placePoll(self, task): if self.cr.playGame.getPlace() != None: self.sendUpdate('arrived', []) self.constructArea() self.createInterface() self.__doIntroMessages() return task.done else: return task.cont return def stopPlacePoll(self): taskMgr.remove('DistributedCogBattle-placePoll') def createInterface(self): self.cogProgressBar = DirectWaitBar(pos=(0, 0, -0.9), relief=DGG.RAISED, scale=0.6, frameColor=(1, 0.5, 0.3, 0.75), barColor=(1, 0.25, 0.25, 0.5), value=0, range=self.getTotalCogs(), text='', text_scale=0.08) self.__updateProgressBar() def __updateProgressBar(self): self.cogProgressBar.update(self.getCogsRemaining()) self.cogProgressBar['text'] = '{0}/{1} {2} Remaining'.format(self.getCogsRemaining(), self.getTotalCogs(), CIGlobals.Suits) def destroyInterface(self): if self.cogProgressBar: self.cogProgressBar.destroy() self.cogProgressBar = None return def createBossGui(self): self.destroyInterface() backgroundGui = loader.loadModel('phase_5/models/cogdominium/tt_m_gui_csa_flyThru.bam') backgroundGui.find('**/chatBubble').removeNode() bg = backgroundGui.find('**/background') bg.setScale(5.2) bg.setPos(0.14, 0, -0.6667) bg.reparentTo(aspect2d) self.frame = DirectFrame(geom=bg, relief=None, pos=(0.2, 0, -0.6667)) return def constructArea(self): for data in self.DNCData[self.hoodIndex]: dnc = loader.loadModel('phase_3.5/models/props/do_not_cross.egg') dnc.setPos(*data[0]) dnc.setHpr(*data[1]) dnc.setScale(data[2]) dnc.reparentTo(render) self.DNCSigns.append(dnc) def deconstructArea(self): for dnc in self.DNCSigns: dnc.removeNode() def createWhisper(self, msg): whisper = Whisper() whisper.createSystemMessage(msg) def __doIntroMessages(self): self.introMessageSeq = Sequence(name='DistributedCogBattle-introMessageSeq') self.introMessageSeq.append(Func(self.createWhisper, 'Welcome, Toons! The Cogs will be here soon, so get prepared!')) self.introMessageSeq.append(Wait(7.5)) self.introMessageSeq.append(Func(self.createWhisper, 'The pink bar at the bottom of the screen shows the amount of Cogs remaining to defeat.')) self.introMessageSeq.append(Wait(8.5)) self.introMessageSeq.append(Func(self.createWhisper, 'Purchase gags from Goofy at the Gag Shop to restock your used gags.')) self.introMessageSeq.append(Wait(7.5)) self.introMessageSeq.append(Func(self.createWhisper, "Purchase battle tools from Coach at Coach's Battle Shop in between invasions.")) self.introMessageSeq.setDoneEvent(self.introMessageSeq.getName()) self.acceptOnce(self.introMessageSeq.getDoneEvent(), self.__introMessagesDone) self.introMessageSeq.start() def __introMessagesDone(self): if self.introMessageSeq: self.introMessageSeq.finish() self.introMessageSeq = None return def announceGenerate(self): DistributedObject.announceGenerate(self) base.localAvatar.setMyBattle(self) self.startPlacePoll() def disable(self): self.turretManager = None base.localAvatar.setMyBattle(None) self.stopPlacePoll() self.deconstructArea() self.destroyInterface() if self.victorySeq: self.victorySeq.pause() self.victorySeq = None self.hoodIndex = None self.DNCSigns = None self.totalCogs = None self.cogsRemaining = None if self.introMessageSeq: self.introMessageSeq.pause() self.introMessageSeq = None DistributedObject.disable(self) return
class DistributedPieTurretManager(DistributedObject): notify = directNotify.newCategory('DistributedPieTurretManager') def __init__(self, cr): DistributedObject.__init__(self, cr) self.myTurret = None self.guiFrame = None self.guiLabel = None self.guiBar = None self.guiBg = None self.turretGag = None def announceGenerate(self): DistributedObject.announceGenerate(self) base.taskMgr.add(self.__pollMyBattle, '__pollMyBattle') def disable(self): base.taskMgr.remove("DPTM.pollTurret") base.taskMgr.remove("__pollMyBattle") if hasattr(self, 'makeTurretBtn'): self.makeTurretBtn.destroy() del self.makeTurretBtn self.destroyGui() self.myTurret = None if base.localAvatar.getMyBattle(): base.localAvatar.getMyBattle().setTurretManager(None) DistributedObject.disable(self) def clearTurret(self): self.turret = None def __pollTurret(self, turretId, task): turret = self.cr.doId2do.get(turretId) if turret != None: self.myTurret = turret self.myTurret.b_setGag(self.turretGag) self.turretGag = None self.acceptOnce(turret.getDeathEvent(), self.clearTurret) self.makeGui() return Task.done return Task.cont def setGag(self, upgradeId): self.turretGag = upgradeId def d_requestPlace(self, posHpr): self.sendUpdate('requestPlace', [posHpr]) def turretPlaced(self, turretId): base.taskMgr.add(self.__pollTurret, 'DPTM.pollTurret', extraArgs=[turretId], appendTask=True) def yourTurretIsDead(self): base.taskMgr.remove('DPTM.pollTurret') self.destroyGui() self.myTurret = None if base.localAvatar.getPUInventory()[0] > 0: self.createTurretButton() def makeGui(self): self.destroyGui() self.guiFrame = DirectFrame(parent=base.a2dBottomRight, pos=(-0.55, 0, 0.15)) self.guiBg = OnscreenImage(image="phase_4/maps/turret_gui_bg.png", scale=(0.15, 0, 0.075), parent=self.guiFrame) self.guiBg.setTransparency(True) self.guiLabel = DirectLabel( text="Turret", text_fg=(1, 0, 0, 1), relief=None, text_scale=0.05, text_font=loader.loadFont("phase_3/models/fonts/ImpressBT.ttf"), pos=(0, 0, 0.025), parent=self.guiFrame) self.guiBar = DirectWaitBar(range=self.myTurret.getMaxHealth(), value=self.myTurret.getHealth(), scale=0.125, parent=self.guiFrame, pos=(0, 0, -0.01)) def createTurretButton(self): self.makeTurretBtn = DirectButton(relief=None, geom=CIGlobals.getDefaultBtnGeom(), text='Turret', text_scale=0.055, command=self.handleMakeTurretBtn, pos=(-0.47, 0, 0.1), geom_scale=(0.5, 1.0, 1.0), text_pos=(0, -0.01), parent=base.a2dBottomRight) if base.localAvatar.getPUInventory()[0]: self.setGag(base.localAvatar.getPUInventory()[1]) def handleMakeTurretBtn(self): self.makeTurretBtn.destroy() del self.makeTurretBtn x, y, z = base.localAvatar.getPos() h, p, r = base.localAvatar.getHpr() self.d_requestPlace([x, y, z, h, p, r]) base.localAvatar.sendUpdate('usedPU', [0]) def __pollMyBattle(self, task): if base.localAvatar.getMyBattle(): base.localAvatar.getMyBattle().setTurretManager(self) if base.localAvatar.getPUInventory()[0] > 0: self.createTurretButton() return Task.done return Task.cont def destroyGui(self): if self.guiBar: self.guiBar.destroy() self.guiBar = None if self.guiLabel: self.guiLabel.destroy() self.guiLabel = None if self.guiBg: self.guiBg.destroy() self.guiBg = None if self.guiFrame: self.guiFrame.destroy() self.guiFrame = None def updateTurretGui(self): if self.guiBar: self.guiBar.update(self.myTurret.getHealth()) def getTurret(self): return self.myTurret
class Fighter(DirectObject): def __init__(self): base.disableMouse() # Carga el fondo del juego self.bg = loader.loadModel("models/plane") self.bg.reparentTo(camera) self.bg.setPos(0, 200, 0) self.bg.setScale(300, 0, 146) self.bg.setTexture(loader.loadTexture("models/Backgrounds/farback.png"), 1) # Inicializa el gestor de teclado y los objetos del juego self.inputManager = InputManager() # Inicializa el menu del juego self.inicializarMenu() self.marcador = None self.barraEnergia = None self.marcadorFinalNP = None self.entrada = None self.rankingNP = None self.mostrarMenuJuego() self.accept("m", self.cambiarMenuJuego) self.accept("q", self.salir) # Inicializa el menu def inicializarMenu(self): self.menuGraphics = loader.loadModel("models/MenuGraphics") self.fonts = {"silver" : loader.loadFont("fonts/LuconSilver"), "blue" : loader.loadFont("fonts/LuconBlue"), "orange" : loader.loadFont("fonts/LuconOrange")} self.menu = Menu(self.menuGraphics, self.fonts, self.inputManager) self.menu.initMenu([0, None, ["Nueva Partida", "Salir"], [[self.nuevaPartida], [self.salir]], [[None], [None]]]) # Comienza una partida def nuevaPartida(self): if (not self.marcadorFinalNP is None): self.marcadorFinalNP.detachNode() self.marcadorFinalNP.remove() if (not self.rankingNP is None): self.rankingNP.detachNode() self.rankingNP.remove() self.ship = Ship(self.inputManager) self.mostrarInfo() taskMgr.add(self.actualizarInfo, "Actualizar Puntuacion") # Inicializa y muestra el marcador del jugador def mostrarInfo(self): self.marcador = TextNode("Marcador") self.marcador.setText("Puntos: " + str(self.ship.puntos)) self.marcador.setCardColor(0, 0, 0, 1) self.marcador.setCardDecal(True) self.marcador.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.marcadorNP = aspect2d.attachNewNode(self.marcador) self.marcadorNP.reparentTo(base.a2dTopLeft) self.marcadorNP.setPos(0.02, 0, -0.05) self.marcadorNP.setScale(0.07) self.barraEnergia = DirectWaitBar(text = "Energia", value = 5, range = 5, scale = 0.3, pos = (0, 0, 0.95)) # Actualiza la puntuacion del jugador en pantalla def actualizarInfo(self, tarea): self.marcador.setText("Puntos: " + str(self.ship.puntos)) self.barraEnergia["value"] = self.ship.vida self.barraEnergia.setValue() # Termina la partida if (self.ship.terminarPartida): self.terminarPartida() return tarea.done return tarea.cont # Termina partida liberando recursos para poder empezar una nueva # sin reiniciar el juego def terminarPartida(self): # Solicita al usuario un nombre para la tabla de puntuaciones self.entrada = DirectEntry(width = 15, numLines = 1, scale = 0.07, cursorKeys = 1, frameSize = (0, 15, 0, 1), command = self.almacenarPuntuacion, pos = (-0.3, 0, 0.1), focus = True, text_pos = (0.2, 0.2)) self.puntos = self.ship.puntos self.ship.ship.detachNode() self.ship.ship.remove() taskMgr.remove("Mover Nave") taskMgr.remove("Generar Enemigos") taskMgr.remove("Comprobar Impactos") taskMgr.remove("Actualizar Puntuacion") taskMgr.remove("Explosionar*") self.mostrarFinPartida() # Libera los recursos de la partida que ha terminado self.ship.eliminarObjetos() del self.ship del self.menuGraphics del self.menu self.marcadorNP.detachNode() self.marcadorNP.remove() self.barraEnergia.destroy() del self.marcador del self.barraEnergia #self.inicializarMenu() # Almacena la puntuacion del jugador def almacenarPuntuacion(self, valor): self.crearBDD() db = sqlite3.connect("datos.db") cursor = db.cursor() parametros = (valor, self.puntos) cursor.execute("insert into puntuaciones values (?, ?)", parametros) db.commit() cursor.close() self.entrada.destroy() self.mostrarTopPuntuacion() self.inicializarMenu() # Crea la Base de Datos si no existe ya def crearBDD(self): db = sqlite3.connect("datos.db") cursor = db.cursor() args = ("puntuaciones",) cursor.execute("select name from sqlite_master where name = ?", args) if len(cursor.fetchall()) == 0: cursor.execute("create table puntuaciones (nombre text, puntuacion numeric)") db.commit() cursor.close() # Muestra las 10 mejores puntuaciones def mostrarTopPuntuacion(self): # Extrae las 10 mejores puntuaciones de la base de datos db = sqlite3.connect("datos.db") cursor = db.cursor() cursor.execute("select nombre, puntuacion from puntuaciones order by puntuacion desc limit 10") puntuaciones = cursor.fetchall() cursor.close() resultado = "-- MEJORES PUNTUACIONES --\n-Jugador- -Puntuacion-\n\n" for nombre, puntuacion in puntuaciones: resultado += nombre + " " + str(puntuacion) + "\n" # Muestra las 10 mejores puntuaciones self.ranking = TextNode("Ranking") self.ranking.setText(resultado) self.ranking.setCardColor(0, 0, 0, 1) self.ranking.setCardDecal(True) self.ranking.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.rankingNP = aspect2d.attachNewNode(self.ranking) self.rankingNP.reparentTo(base.a2dTopLeft) self.rankingNP.setPos(1, 0, -1) self.rankingNP.setScale(0.07) # Muestra el mensaje de fin de partida def mostrarFinPartida(self): self.marcadorFinal = TextNode("Marcador Final") self.marcadorFinal.setText("Game Over!\nPuntuacion: " + str(self.ship.puntos) +"\n\n" + "Escribe tu nombre:") self.marcadorFinal.setCardColor(0, 0, 0, 1) self.marcadorFinal.setCardDecal(True) self.marcadorFinal.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.marcadorFinalNP = aspect2d.attachNewNode(self.marcadorFinal) self.marcadorFinalNP.setPos(-0.3, 0, 0.5) self.marcadorFinalNP.setScale(0.07) # Muestra un menu con las opciones durante el juego def mostrarMenuJuego(self): self.textoMenu = {} self.textoMenu["titulo"] = OnscreenText(text = "", pos = (0, 0.92), scale = 0.08, fg = (1, 1, 1, 1), bg = (0, 0, 1, 0.7)) self.textoMenu["descripcion"] = OnscreenText(text = "", pos = (0, 0.84), scale = 0.05, fg = (1, 1, 0, 1), bg = (0, 0, 0, 0.5)) self.textoMenu["opciones"] = OnscreenText(text = "", pos = (-1.3, 0), scale = 0.05, fg = (1, 1, 1, 1), bg = (1, 0.3, 0, 0.6), align=TextNode.ALeft, wordwrap = 15) self.textoMenu["opciones"].setText("** OPCIONES **\n" + "m = ocultar menu\n" + "q = salir") # Inicialmente el menu se deja oculto for linea in self.textoMenu.values(): linea.hide() # Muestra / Oculta el menu de juego def cambiarMenuJuego(self): for linea in self.textoMenu.values(): if linea.isHidden(): linea.show() else: linea.hide() # Sale del juego def salir(self): print("Saliendo . . .") sys.exit()
class ThrowGag(Gag): def __init__(self, name, model, damage, hitSfx, splatColor, anim=None, scale=1): Gag.__init__(self, name, model, damage, GagType.THROW, hitSfx, anim=anim, scale=scale) self.splatScale = GagGlobals.splatSizes[self.name] self.splatColor = splatColor self.entities = [] self.timeout = 1.0 self.power = 50 self.powerBar = None self.tossPieStart = 0 self.pieSpeed = 0.2 self.pieExponent = 0.75 def setAvatar(self, avatar): Gag.setAvatar(self, avatar) if self.isLocal(): self.powerBar = DirectWaitBar(range=150, frameColor=(1, 1, 1, 1), barColor=(0.286, 0.901, 1, 1), relief=DGG.RAISED, borderWidth=(0.04, 0.04), pos=(0, 0, 0.85), scale=0.2, hpr=(0, 0, 0), parent=aspect2d, frameSize=(-0.85, 0.85, -0.12, 0.12)) self.powerBar.hide() def __getPiePower(self, time): elapsed = max(time - self.tossPieStart, 0.0) t = elapsed / self.pieSpeed t = math.pow(t, self.pieExponent) power = int(t * 150) % 300 if power > 150: power = 300 - power return power def build(self): if not self.gag: Gag.build(self) self.equip() if self.anim and self.gag: self.gag.loop('chan') return self.gag def start(self): super(ThrowGag, self).start() self.build() self.avatar.setPlayRate(self.playRate, 'pie') self.avatar.play('pie', fromFrame=0, toFrame=45) if self.isLocal(): taskMgr.remove("hidePowerBarTask" + str(hash(self))) self.powerBar.show() self.startPowerBar() def startPowerBar(self): self.tossPieStart = globalClock.getFrameTime() taskMgr.add(self.__powerBarUpdate, "powerBarUpdate" + str(hash(self))) def __powerBarUpdate(self, task): if self.powerBar is None: return task.done self.powerBar['value'] = self.__getPiePower(globalClock.getFrameTime()) return task.cont def stopPowerBar(self): taskMgr.remove("powerBarUpdate" + str(hash(self))) self.power = self.powerBar['value'] def __hidePowerBarTask(self, task): self.powerBar.hide() def throw(self): if self.isLocal(): self.stopPowerBar() self.power += 50 self.power = 250 - self.power print self.power # Make other toons set the throw power on my gag. base.localAvatar.sendUpdate('setThrowPower', [self.id, self.power]) self.startTimeout() taskMgr.doMethodLater(1.5, self.__hidePowerBarTask, "hidePowerBarTask" + str(hash(self))) self.avatar.play('pie', fromFrame=45, toFrame=90) if not self.gag: self.build() def setPower(self, power): self.power = power def release(self): Gag.release(self) base.audio3d.attachSoundToObject(self.woosh, self.gag) base.playSfx(self.woosh, node=self.gag) throwPath = NodePath('ThrowPath') throwPath.reparentTo(self.avatar) throwPath.setScale(render, 1) throwPath.setPos(0, self.power, -90) throwPath.setHpr(90, -90, 90) entity = self.gag if not entity: entity = self.build() entity.wrtReparentTo(render) entity.setHpr(throwPath.getHpr(render)) self.gag = None if not self.handJoint: self.handJoint = self.avatar.find('**/def_joint_right_hold') track = ProjectileInterval(entity, startPos=self.handJoint.getPos(render), endPos=throwPath.getPos(render), gravityMult=0.9, duration=3) event = self.avatar.uniqueName('throwIvalDone') + '-' + str( hash(entity)) track.setDoneEvent(event) base.acceptOnce(event, self.__handlePieIvalDone, [entity]) track.start() self.entities.append([entity, track]) if self.isLocal(): self.buildCollisions(entity) base.localAvatar.sendUpdate('usedGag', [self.id]) self.reset() def __handlePieIvalDone(self, pie): if not pie.isEmpty(): pie.removeNode() def handleSplat(self): base.audio3d.detachSound(self.woosh) if self.woosh: self.woosh.stop() self.buildSplat(self.splatScale, self.splatColor) base.audio3d.attachSoundToObject(self.hitSfx, self.splat) self.splat.reparentTo(render) self.splat.setPos(self.splatPos) base.playSfx(self.hitSfx, node=self.splat) self.cleanupEntity(self.splatPos) self.splatPos = None taskMgr.doMethodLater(0.5, self.delSplat, 'Delete Splat') return def cleanupEntity(self, pos): closestPie = None trackOfClosestPie = None pieHash2range = {} for entity, track in self.entities: if not entity.isEmpty(): pieHash2range[hash(entity)] = (entity.getPos(render) - pos).length() ranges = [] for distance in pieHash2range.values(): ranges.append(distance) ranges.sort() for pieHash in pieHash2range.keys(): distance = pieHash2range[pieHash] if not distance is None and distance == ranges[0]: for entity, track in self.entities: if hash(entity) == pieHash: closestPie = entity trackOfClosestPie = track break break if closestPie != None and trackOfClosestPie != None: if [closestPie, trackOfClosestPie] in self.entities: self.entities.remove([closestPie, trackOfClosestPie]) if not closestPie.isEmpty(): if isinstance(closestPie, Actor): closestPie.cleanup() closestPie.removeNode() def onCollision(self, entry): intoNP = entry.getIntoNodePath() avNP = intoNP.getParent() fromNP = entry.getFromNodePath().getParent() if fromNP.isEmpty(): return for key in base.cr.doId2do.keys(): obj = base.cr.doId2do[key] if obj.__class__.__name__ in CIGlobals.SuitClasses: if obj.getKey() == avNP.getKey(): obj.sendUpdate('hitByGag', [self.getID()]) elif obj.__class__.__name__ == "DistributedToon": if obj.getKey() == avNP.getKey(): if obj.getHealth() < obj.getMaxHealth(): if obj != self.avatar: self.avatar.sendUpdate( 'toonHitByPie', [obj.doId, self.getID()]) else: self.avatar.acceptOnce('gagSensor-into', self.onCollision) return elif obj.__class__.__name__ == "DistributedPieTurret": if obj.getKey() == avNP.getKey(): if obj.getHealth() < obj.getMaxHealth(): self.avatar.sendUpdate( 'toonHitByPie', [obj.doId, self.getID()]) self.splatPos = fromNP.getPos() self.avatar.sendUpdate('setSplatPos', [ self.getID(), self.splatPos.getX(), self.splatPos.getY(), self.splatPos.getZ() ]) self.handleSplat() def buildCollisions(self, entity): pieSphere = CollisionSphere(0, 0, 0, 1) pieSensor = CollisionNode('gagSensor') pieSensor.addSolid(pieSphere) pieNP = entity.attachNewNode(pieSensor) pieNP.setCollideMask(BitMask32(0)) pieNP.node().setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) event = CollisionHandlerEvent() event.set_in_pattern("%fn-into") event.set_out_pattern("%fn-out") base.cTrav.add_collider(pieNP, event) self.avatar.acceptOnce('gagSensor-into', self.onCollision) def unEquip(self): taskMgr.remove("hidePowerBarTask" + str(hash(self))) if self.powerBar: self.powerBar.hide() Gag.unEquip(self) def delete(self): taskMgr.remove("powerBarUpdate" + str(hash(self))) taskMgr.remove("hidePowerBarTask" + str(hash(self))) if self.powerBar: self.powerBar.destroy() self.powerBar = None Gag.delete(self)
class ToonFPSGui: def __init__(self, base): self.base = base self.noAmmoLabel = None self.ammo_gui = None self.hp_meter = None self.crosshair = None self.stats_container = None self.stats_bg = None self.stats_lbl = None self.kills_lbl = None self.deaths_lbl = None self.points_lbl = None return def load(self): self.ammo_gui = loader.loadModel('phase_4/models/minigames/gun_ammo_gui.egg') self.ammo_gui.setScale(0.15) self.ammo_gui.setPos(0.38, 0, 0.1) self.hp_meter = DirectWaitBar(text=str(self.base.hp), text_roll=-90, text_scale=0.2, text_pos=(-0.025, 0), relief=DGG.RAISED, barColor=(1, 0, 0, 1), range=self.base.max_hp, value=self.base.hp, parent=base.a2dBottomRight, scale=0.4, pos=(-0.12, 0, 0.2), frameSize=(-0.4, 0.4, -0.2, 0.2)) self.hp_meter.setR(-90) self.hp_meter.hide() self.crosshair = getCrosshair() font = CIGlobals.getToonFont() box = DGG.getDefaultDialogGeom() if self.base.__class__.__name__ == 'GunGameToonFPS': self.stats_container = DirectFrame(parent=base.a2dTopLeft, pos=(0.3, 0.2, -0.185)) self.stats_bg = OnscreenImage(image=box, color=(1, 1, 0.75, 1), scale=(0.5, 0.3, 0.3), parent=self.stats_container) self.stats_lbl = OnscreenText(font=font, text='Stats', pos=(-0.01, 0.08, 0), parent=self.stats_container) self.kills_lbl = OnscreenText(font=font, text='Kills: ' + str(self.base.kills), pos=(-0.235, 0.025, 0), scale=0.055, parent=self.stats_container, align=TextNode.ALeft) self.deaths_lbl = OnscreenText(font=font, text='Deaths: ' + str(self.base.deaths), pos=(-0.235, -0.04, 0), scale=0.055, parent=self.stats_container, align=TextNode.ALeft) self.points_lbl = OnscreenText(font=font, text='Points: ' + str(self.base.points), pos=(-0.235, -0.105, 0), scale=0.055, parent=self.stats_container, align=TextNode.ALeft) self.stats_container.hide() del font del box def start(self): self.ammo_gui.reparentTo(base.a2dBottomLeft) self.crosshair.show() self.hp_meter.show() if self.base.__class__.__name__ == 'GunGameToonFPS': self.stats_container.show() def end(self): self.ammo_gui.reparentTo(hidden) if self.base.__class__.__name__ == 'GunGameToonFPS': self.stats_container.hide() self.crosshair.hide() self.hp_meter.hide() def cleanup(self): self.ammo_gui.removeNode() self.ammo_gui = None self.hp_meter.destroy() self.hp_meter = None self.crosshair.destroy() self.crosshair = None self.deleteNoAmmoLabel() self.deleteStatsGui() return def deleteStatsGui(self): if self.stats_container: self.stats_container.destroy() self.stats_container = None if self.stats_bg: self.stats_bg.destroy() self.stats_bg = None if self.stats_lbl: self.stats_lbl.destroy() self.stats_lbl = None if self.kills_lbl: self.kills_lbl.destroy() self.kills_lbl = None if self.deaths_lbl: self.deaths_lbl.destroy() self.deaths_lbl = None if self.points_lbl: self.points_lbl.destroy() self.points_lbl = None return def updateStats(self): self.kills_lbl['text'] = 'Kills: ' + str(self.base.kills) self.deaths_lbl['text'] = 'Deaths: ' + str(self.base.deaths) self.points_lbl['text'] = 'Points: ' + str(self.base.points) def deleteNoAmmoLabel(self): if self.noAmmoLabel: self.noAmmoLabel.destroy() self.noAmmoLabel = None return def adjustAmmoGui(self): self.ammo_gui.find('**/bar_' + str(self.base.ammo + 1)).hide() def adjustHpMeter(self): self.hp_meter['text'] = str(self.base.hp) self.hp_meter['value'] = self.base.hp if self.base.hp <= 40: self.hp_meter['barColor'] = (1, 0, 0, 1) else: self.hp_meter['barColor'] = (1, 1, 1, 1) def resetAmmo(self): for bar in self.ammo_gui.findAllMatches('**/bar_*'): bar.show() def notifyNoAmmo(self): self.deleteNoAmmoLabel() self.noAmmoLabel = DirectLabel(text='Press R to reload!', relief=None, text_scale=0.1, text_pos=(0, 0.5, 0), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1)) 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 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