class ToonHood(Hood.Hood): def __init__(self, parentFSM, doneEvent, dnaStore, hoodId): Hood.Hood.__init__(self, parentFSM, doneEvent, dnaStore, hoodId) self.safeZoneLoader = None self.townLoader = None self.fsm = ClassicFSM('Hood', [ State('off', self.enterOff, self.exitOff), State('safeZoneLoader', self.enterSafeZoneLoader, self.exitSafeZoneLoader, ['quietZone', 'townLoader']), State('townLoader', self.enterTownLoader, self.exitTownLoader, ['quietZone', 'safeZoneLoader']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['safeZoneLoader', 'townLoader']) ], 'off', 'off') self.fsm.enterInitialState() return def loadLoader(self, requestStatus): loader = requestStatus['loader'] if loader == 'safeZoneLoader': if self.safeZoneLoader: self.loader = self.safeZoneLoader( self, self.fsm.getStateNamed('safeZoneLoader'), self.loaderDoneEvent) self.loader.load() else: self.notify.error( 'ToonHood.ToonHood.safeZoneLoader cannot be None!' % loader) else: if loader == 'townLoader': if self.townLoader: self.loader = self.townLoader( self, self.fsm.getStateNamed('townLoader'), self.loaderDoneEvent) self.loader.load(requestStatus['zoneId']) else: self.notify.error('Unknown loader %s!' % loader) def enterTownLoader(self, requestStatus): self.acceptOnce(self.loaderDoneEvent, self.handleTownLoaderDone) self.loader.enter(requestStatus) self.spawnTitleText(requestStatus['zoneId']) def exitTownLoader(self): taskMgr.remove('titleText') self.hideTitleText() self.ignore(self.loaderDoneEvent) self.loader.exit() self.loader.unload() del self.loader def handleTownLoaderDone(self): doneStatus = self.loader.getDoneStatus() if self.isSameHood(doneStatus): self.fsm.request('quietZone', [doneStatus]) else: self.doneStatus = doneStatus messenger.send(self.doneEvent) def load(self): Hood.Hood.load(self) self.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1) self.underwaterFogColor = Vec4(0.0, 0.0, 0.6, 1.0) def unload(self): del self.safeZoneLoader Hood.Hood.unload(self) def enter(self, requestStatus): self.loadLoader(requestStatus) Hood.Hood.enter(self, requestStatus) def exit(self): Hood.Hood.exit(self) def setUnderwaterFog(self): if base.wantFog: self.fog.setColor(self.underwaterColor) self.fog.setLinearRange(0.1, 100.0) render.setFog(self.fog) self.sky.setFog(self.fog) def setWhiteFog(self): if base.wantFog: self.fog.setColor(self.whiteFogColor) self.fog.setLinearRange(0.0, 400.0) render.clearFog() render.setFog(self.fog) self.sky.clearFog() self.sky.setFog(self.fog) def setNoFog(self): if base.wantFog: render.clearFog() self.sky.clearFog()
class ToonFPS(DirectObject): notify = directNotify.newCategory('ToonFPS') WeaponName2DamageData = {'pistol': (36.0, 10.0, 150.0, 0.25), 'shotgun': (40.0, 15.0, 155.0, 0.5)} def __init__(self, mg, weaponName = 'pistol'): self.mg = mg self.weaponName = weaponName self.v_model_root = None self.v_model = None self.weapon = None self.track = None self.draw = None self.shoot = None self.reload = None self.empty = None self.cockBack = None self.cockFwd = None self.player_node = None self.shooterTrav = None self.shooterRay = None self.shooterRayNode = None self.shooterHandler = None self.gui = ToonFPSGui(self) self.fsm = ClassicFSM('ToonFPS', [State('off', self.enterOff, self.exitOff), State('alive', self.enterAlive, self.exitAlive), State('dead', self.enterDead, self.exitDead)], 'off', 'off') self.aliveFSM = ClassicFSM('alive', [State('off', self.enterOff, self.exitOff), State('draw', self.enterDraw, self.exitDraw, ['idle']), State('idle', self.enterIdle, self.exitIdle, ['shoot', 'reload']), State('shoot', self.enterShoot, self.exitShoot, ['idle']), State('reload', self.enterReload, self.exitReload, ['idle'])], 'off', 'off') self.fsm.getStateNamed('alive').addChild(self.aliveFSM) self.fsm.enterInitialState() self.aliveFSM.enterInitialState() if self.weaponName == 'pistol': self.ammo = 14 elif self.weaponName == 'shotgun': self.ammo = 7 self.hp = 125 self.max_hp = 125 self.firstPerson = FirstPerson() 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 enterAlive(self): if self.mg.fsm.getCurrentState().getName() not in ('gameOver', 'announceGameOver', 'finalScores'): base.localAvatar.disableChatInput() self.start() self.resetHp() self.resetAmmo() if self.mg.fsm.getCurrentState().getName() == 'play': self.reallyStart() def exitAlive(self): self.end() self.v_model.reparentTo(hidden) if self.mg.fsm.getCurrentState().getName() != 'play': self.reallyEnd() base.localAvatar.createChatInput() def updatePoints(self): self.points = self.kills - self.deaths def enterDead(self, killer): base.localAvatar.getGeomNode().show() self.gui.end() base.localAvatar.attachCamera() self.freezeCamSfx = base.loadSfx('phase_4/audio/sfx/freeze_cam.wav') self.freezeCamImage = None self.freezeCamImageFile = None base.camera.setZ(base.camera.getZ() + 2.0) taskMgr.add(self.cameraLookAtKillerTask, 'lookAtKiller', extraArgs=[killer], appendTask=True) taskMgr.doMethodLater(2.0, self.startZoomOnKiller, 'startFreezeCam', extraArgs=[killer], appendTask=True) return def startZoomOnKiller(self, killer, task): taskMgr.add(self.__zoomOnKillerTask, 'zoomOnKiller', extraArgs=[killer], appendTask=True) return task.done def __zoomOnKillerTask(self, killer, task): if base.camera.getDistance(killer) <= 10.0 and self.freezeCamSfx.status() == self.freezeCamSfx.READY: base.playSfx(self.freezeCamSfx) if base.camera.getDistance(killer) < 7.0: self.doFreezeCam() return task.done base.camera.setY(base.camera, 60 * globalClock.getDt()) return task.again def doFreezeCam(self): taskMgr.remove('lookAtKiller') self.frameBuffer = PNMImage() base.win.getScreenshot(self.frameBuffer) self.freezeCamTex = Texture() self.freezeCamTex.load(self.frameBuffer) self.freezeCamImage = OnscreenImage(image=self.freezeCamTex, parent=render2d) def cameraLookAtKillerTask(self, killer, task): base.camera.lookAt(killer, 0, 0, 3) return task.cont def exitDead(self): taskMgr.remove('zoomOnKiller') taskMgr.remove('lookAtKiller') taskMgr.remove('startFreezeCam') del self.freezeCamSfx if self.freezeCamImage: self.freezeCamImage.destroy() del self.freezeCamImage self.frameBuffer.clear() self.freezeCamTex.clear() del self.frameBuffer del self.freezeCamTex base.localAvatar.detachCamera() base.localAvatar.getGeomNode().hide() self.gui.start() def load(self): if self.weaponName == 'pistol': self.draw = base.loadSfx('phase_4/audio/sfx/draw_secondary.wav') self.shoot = base.loadSfx('phase_4/audio/sfx/pistol_shoot.wav') self.reload = base.loadSfx('phase_4/audio/sfx/pistol_worldreload.wav') elif self.weaponName == 'shotgun': self.draw = base.loadSfx('phase_4/audio/sfx/draw_primary.wav') self.shoot = base.loadSfx('phase_4/audio/sfx/shotgun_shoot.wav') self.cockBack = base.loadSfx('phase_4/audio/sfx/shotgun_cock_back.wav') self.cockFwd = base.loadSfx('phase_4/audio/sfx/shotgun_cock_forward.wav') self.empty = base.loadSfx('phase_4/audio/sfx/shotgun_empty.wav') self.v_model_root = base.camera.attachNewNode('v_model_root') self.v_model = Actor('phase_4/models/minigames/v_dgm.egg', {'pidle': 'phase_4/models/minigames/v_dgm-pistol-idle.egg', 'pshoot': 'phase_4/models/minigames/v_dgm-pistol-shoot.egg', 'preload': 'phase_4/models/minigames/v_dgm-pistol-reload.egg', 'pdraw': 'phase_4/models/minigames/v_dgm-pistol-draw.egg', 'sidle': 'phase_4/models/minigames/v_dgm-shotgun-idle.egg', 'sshoot': 'phase_4/models/minigames/v_dgm-shotgun-shoot.egg'}) if self.weaponName == 'pistol': self.weapon = loader.loadModel('phase_4/models/props/water-gun.bam') self.weapon.reparentTo(self.v_model.exposeJoint(None, 'modelRoot', 'Bone.011')) self.weapon.setX(-0.125) self.weapon.setY(0.5) self.weapon.setScale(0.65) elif self.weaponName == 'shotgun': self.weapon = loader.loadModel('phase_4/models/props/shotgun.egg') self.weapon.reparentTo(self.v_model.exposeJoint(None, 'modelRoot', 'Bone.029')) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) color = random.choice([VBase4(1, 0.25, 0.25, 1), VBase4(0.25, 1, 0.25, 1), VBase4(0.25, 0.25, 1, 1)]) self.weapon.setColorScale(color) self.gui.load() return def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == 'pistol': self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == 'shotgun': self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.0) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw') def reallyStart(self): self.firstPerson.reallyStart() taskMgr.add(self.movementTask, 'toonBattleMovement') def end(self): self.aliveFSM.request('off') if self.firstPerson: self.firstPerson.enableMouse() self.firstPerson.end() taskMgr.remove('toonBattleMovement') if self.mg.fsm.getCurrentState().getName() != 'play': self.fsm.request('off') def reallyEnd(self): if self.shooterRayNode: self.shooterRayNode.removeNode() self.shooterRayNode = None self.shooterRay = None self.shooterTrav = None self.shooterHandler = None if self.firstPerson: self.firstPerson.reallyEnd() if self.v_model_root: self.v_model_root.reparentTo(hidden) if self.v_model: self.v_model.reparentTo(hidden) self.v_model.setPosHpr(0, 0, 0, 0, 0, 0) if self.gui: self.gui.end() base.camLens.setNear(1.0) return def cleanup(self): taskMgr.remove('lookAtKiller') taskMgr.remove('toonBattleMovement') if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None self.draw = None self.shoot = None self.reload = None self.empty = None self.ammo = None self.fsm = None self.aliveFSM = None self.player_node = None self.min_camerap = None self.max_camerap = None self.hp = None self.max_hp = None if self.v_model: self.v_model.cleanup() self.v_model = None if self.weapon: self.weapon.removeNode() self.weapon = None if self.weapon: self.v_model_root.removeNode() self.v_model_root = None if self.gui: self.gui.cleanup() return def damageTaken(self, amount, avId): if self.hp <= 0.0: killer = self.mg.cr.doId2do.get(avId, None) self.fsm.request('dead', [killer]) self.gui.adjustHpMeter() return def enterDraw(self): self.draw.play() if self.weaponName == 'pistol': self.track = ActorInterval(self.v_model, 'pdraw', playRate=1.6, name='drawTrack') elif self.weaponName == 'shotgun': self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration=0.5, quat=(0, 0, 0), startHpr=(70, -50, 0), blendType='easeOut', name='drawTrack') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitDraw(self): if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None return def enterIdle(self): if self.weaponName == 'pistol': self.v_model.loop('pidle') elif self.weaponName == 'shotgun': self.track = Sequence(LerpQuatInterval(self.v_model, duration=2.0, quat=(0, 1, 0), startHpr=(0, 0, 0), blendType='easeInOut'), LerpQuatInterval(self.v_model, duration=2.0, quat=(0, 0, 0), startHpr=(0, 1, 0), blendType='easeInOut')) self.track.loop() self.accept('mouse1', self.requestShoot) if self.ammo <= 0: self.gui.notifyNoAmmo() if self.ammo < 14: self.accept('r', self.aliveFSM.request, ['reload']) def requestShoot(self): if self.mg.fsm.getCurrentState().getName() != 'play': return if self.ammo > 0: self.aliveFSM.request('shoot') else: self.empty.play() def exitIdle(self): self.v_model.stop() if self.track: self.track.finish() self.track = None self.ignore('mouse1') self.ignore('r') return def enterShoot(self): self.shoot.play() if self.weaponName == 'pistol': self.track = ActorInterval(self.v_model, 'pshoot', playRate=2, name='shootTrack') elif self.weaponName == 'shotgun': self.track = Parallel(Sequence(LerpQuatInterval(self.v_model, duration=0.05, quat=(0, 3, 0), startHpr=(0, 0, 0)), LerpQuatInterval(self.v_model, duration=0.1, quat=(0, 0, 0), startHpr=(0, 3, 0))), Sequence(LerpPosInterval(self.v_model, duration=0.05, pos=(0, -0.3, 0), startPos=(0, 0, 0)), LerpPosInterval(self.v_model, duration=0.1, pos=(0, 0, 0), startPos=(0, -0.3, 0)), Wait(0.1))) self.track.setDoneEvent('shootTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() self.ammo -= 1 self.gui.adjustAmmoGui() self.mg.makeSmokeEffect(self.weapon.find('**/joint_nozzle').getPos(render)) self.traverse() def traverse(self): mpos = base.mouseWatcherNode.getMouse() self.shooterRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.shooterTrav.traverse(render) def calcDamage(self, avatar): dmgData = self.WeaponName2DamageData[self.weaponName] maxDamage = dmgData[0] minDistance = dmgData[1] maxDistance = dmgData[2] factor = dmgData[3] distance = base.localAvatar.getDistance(avatar) if distance < minDistance: distance = minDistance elif distance > maxDistance: distance = maxDistance damage = maxDamage - (distance - minDistance) * factor return damage def exitShoot(self): self.ignore('shootTrack') if self.track: self.track.finish() self.track = None return def enterReload(self): self.gui.deleteNoAmmoLabel() if self.weaponName == 'pistol': self.track = Parallel(Sequence(Wait(0.3), Func(self.reload.play), Func(self.resetAmmo)), ActorInterval(self.v_model, 'preload', playRate=1.5), name='reloadTrack') elif self.weaponName == 'shotgun': self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration=0.5, quat=(70, -50, 0), startHpr=(0, 0, 0), blendType='easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration=0.5, quat=(0, 0, 0), startHpr=(70, -50, 0), blendType='easeOut'), name='reloadTrack') self.track.setDoneEvent('reloadTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitReload(self): self.ignore('reloadTrack') if self.track: self.track.finish() self.track = None return def resetAmmo(self): if self.weaponName == 'pistol': self.ammo = 14 elif self.weaponName == 'shotgun': self.ammo = 7 self.gui.resetAmmo() def resetHp(self): self.hp = self.max_hp self.gui.adjustHpMeter() def enterOff(self): pass def exitOff(self): pass
class ShtickerBook(StateData): def __init__(self, parentFSM, doneEvent): self.parentFSM = parentFSM StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('ShtickerBook', [ State('off', self.enterOff, self.exitOff), State('optionPage', self.enterOptionPage, self.exitOptionPage, ['districtPage', 'off']), State('districtPage', self.enterDistrictPage, self.exitDistrictPage, ['optionPage', 'questPage', 'off']), State('questPage', self.enterQuestPage, self.exitQuestPage, ['inventoryPage', 'districtPage', 'off']), State('inventoryPage', self.enterInventoryPage, self.exitInventoryPage, ['mapPage', 'questPage', 'off']), State('mapPage', self.enterMapPage, self.exitMapPage, ['inventoryPage', 'off']), State('releaseNotesPage', self.enterReleaseNotesPage, self.exitReleaseNotesPage, ['mapPage', 'off']), State('adminPage', self.enterAdminPage, self.exitAdminPage, ['mapPage', 'namePage', 'off']), State('namePage', self.enterNamePage, self.exitNamePage, ['adminPage', 'off']) ], 'off', 'off') if base.localAvatar.getAdminToken() > -1: self.fsm.getStateNamed('mapPage').addTransition('adminPage') self.fsm.enterInitialState() self.entered = 0 self.parentFSM.getStateNamed('shtickerBook').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) self.book_contents = loader.loadModel( "phase_3.5/models/gui/stickerbook_gui.bam") self.book_texture = self.book_contents.find('**/big_book') self.book_open = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_open.ogg") self.book_close = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_delete.ogg") self.book_turn = loader.loadSfx( "phase_3.5/audio/sfx/GUI_stickerbook_turn.ogg") def unload(self): self.book_texture.removeNode() del self.book_texture self.book_contents.removeNode() del self.book_contents loader.unloadSfx(self.book_open) del self.book_open loader.unloadSfx(self.book_close) del self.book_close loader.unloadSfx(self.book_turn) del self.book_turn del self.fsm del self.parentFSM del self.entered StateData.unload(self) def enter(self, page): if self.entered: return self.entered = 1 StateData.enter(self) render.hide() base.setBackgroundColor(0.05, 0.15, 0.4) self.book_img = OnscreenImage(image=self.book_texture, scale=(2, 1, 1.5)) self.book_open.play() if base.localAvatar.getAdminToken() > -1: self.fsm.request('adminPage') else: self.fsm.request(page) def exit(self): if not self.entered: return self.entered = 0 base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) render.show() self.book_img.destroy() del self.book_img self.book_close.play() self.fsm.request('off') StateData.exit(self) def enterDistrictPage(self): self.createPageButtons('optionPage', 'questPage') self.setTitle("Districts") currDistrictName = base.cr.myDistrict.getDistrictName() if not currDistrictName.isalpha(): currDistrictName = currDistrictName[:-1] self.infoLbl = OnscreenText( text='Each District is a copy of the Cog Invasion world.\n' '\n\nYou are currently in the "%s" District' % currDistrictName, pos=(0.05, 0.3), align=TextNode.ALeft, wordwrap=12) self.populationLbl = OnscreenText(text="Population: %d" % base.cr.myDistrict.getPopulation(), pos=(0.44, -0.3), align=TextNode.ACenter) textRolloverColor = Vec4(1, 1, 0, 1) textDownColor = Vec4(0.5, 0.9, 1, 1) textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) self.shardButtons = [] for shard in base.cr.activeDistricts.values(): shardName = shard.getDistrictName() shardId = shard.doId btn = DirectButton(relief=None, text=shardName, text_scale=0.07, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleShardButton, extraArgs=[shardId], text_pos=(0, 0, 0.0)) if shardId == base.localAvatar.parentId: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL self.shardButtons.append(btn) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') listXorigin = -0.02 listFrameSizeX = 0.625 listZorigin = -0.96 listFrameSizeZ = 1.04 arrowButtonScale = 1.3 itemFrameXorigin = -0.237 itemFrameZorigin = 0.365 buttonXstart = itemFrameXorigin + 0.293 self.districtList = DirectScrolledList( relief=None, pos=(-0.54, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX, listZorigin, listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.075, items=self.shardButtons) base.taskMgr.add(self.__updateDistrictPopTask, "SB.updateDistrictPopTask") def __handleShardButton(self, shardId): self.finished("switchShard", shardId) def __updateDistrictPopTask(self, task): population = base.cr.myDistrict.getPopulation() self.populationLbl.setText('Population: %d' % population) task.delayTime = 5.0 return task.again def exitDistrictPage(self): base.taskMgr.remove('SB.updateDistrictPopTask') for btn in self.shardButtons: btn.destroy() del self.shardButtons self.districtList.destroy() del self.districtList self.infoLbl.destroy() del self.infoLbl self.populationLbl.destroy() del self.populationLbl self.deletePageButtons(True, True) self.clearTitle() def enterNamePage(self): self.namePageStateData = NamePage(self, self.fsm) self.namePageStateData.load() self.namePageStateData.enter() def exitNamePage(self): self.namePageStateData.exit() self.namePageStateData.unload() del self.namePageStateData def enterQuestPage(self): self.createPageButtons('districtPage', 'inventoryPage') self.setTitle("Quests") """ self.notes = base.localAvatar.questManager.makeQuestNotes() for note in self.notes: note.show() """ self.posters = [] for quest in base.localAvatar.questManager.getQuests(): poster = QuestPoster(quest) poster.update() self.posters.append(poster) self.infoText = OnscreenText( text= "Return completed Quests to an HQ Officer at any Toon HQ building.", pos=(0, -0.6), scale=0.045) def exitQuestPage(self): self.infoText.destroy() del self.infoText for poster in self.posters: poster.destroy() """ for note in self.notes: note.destroy() """ self.deletePageButtons(True, True) self.clearTitle() def enterInventoryPage(self): self.createPageButtons('questPage', 'mapPage') self.setTitle('Gags') self.gui = BackpackGUI() self.gui.createGUI() def exitInventoryPage(self): self.gui.deleteGUI() del self.gui self.deletePageButtons(True, True) self.clearTitle() def enterMapPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('inventoryPage', 'adminPage') else: self.createPageButtons('inventoryPage', None) self.setTitle("") themap = loader.loadModel('phase_3.5/models/gui/toontown_map.bam') self.frame = DirectFrame(parent=aspect2d, relief=None, image=themap, image_scale=(1.8, 1, 1.35), scale=0.97, pos=(0, 0, 0.0775)) cloudpos = [[(-0.61, 0, 0.18), (0.55, 0.25, 0.37), (180, 0, 0)], [(-0.54, 0, 0.34), (0.76, 0.4, 0.55), (180, 0, 0)], [(-0.55, 0, -0.09), (0.72, 0.4, 0.55), (0, 0, 0)], [(-0.67, 0, -0.51), (0.5, 0.29, 0.38), (180, 0, 0)], [(-0.67, 0, 0.51), (0.50, 0.29, 0.38), (0, 0, 0)], [(0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.35, 0, -0.46), (0.63, 0.35, 0.45), (0, 0, 0)], [(0.18, 0, -0.45), (0.52, 0.27, 0.32), (0, 0, 0)], [(0.67, 0, -0.44), (0.63, 0.35, 0.48), (180, 0, 0)]] hoodclouds = [ #[(0.02, 0, -0.17), (0.63, 0.35, 0.48), (180, 0, 0), CIGlobals.ToontownCentral], [(0.63, 0, -0.13), (0.63, 0.35, 0.40), (0, 0, 0), CIGlobals.DonaldsDock], [(0.51, 0, 0.25), (0.57, 0.35, 0.40), (0, 0, 0), CIGlobals.TheBrrrgh], [(0.03, 0, 0.19), (0.63, 0.35, 0.40), (180, 0, 0), CIGlobals.MinniesMelodyland], [(-0.08, 0, 0.46), (0.54, 0.35, 0.40), (0, 0, 0), CIGlobals.DonaldsDreamland], [(-0.28, 0, -0.49), (0.60, 0.35, 0.45), (0, 0, 0), CIGlobals.DaisyGardens] ] self.clouds = [] self.labels = [] for pos, scale, hpr in cloudpos: cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) for pos, scale, hpr, hood in hoodclouds: if not base.localAvatar.hasDiscoveredHood( ZoneUtil.getZoneId(hood)): cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) labeldata = [[(0, 0, -0.2), CIGlobals.ToontownCentral], [(0.65, 0, -0.125), CIGlobals.DonaldsDock], [(0.07, 0, 0.18), CIGlobals.MinniesMelodyland], [(-0.1, 0, 0.45), CIGlobals.DonaldsDreamland], [(0.5, 0, 0.25), CIGlobals.TheBrrrgh], [(-0.37, 0, -0.525), CIGlobals.DaisyGardens]] for pos, name in labeldata: if base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(name)): text = name if base.localAvatar.hasTeleportAccess( ZoneUtil.getZoneId(name)): text = 'Go To\n' + text label = DirectButton(parent=self.frame, relief=None, pos=pos, pad=(0.2, 0.16), text=('', text, text, ''), text_bg=Vec4(1, 1, 1, 0.4), text_scale=0.055, text_wordwrap=8, rolloverSound=None, clickSound=None, pressEffect=0, sortOrder=1, text_font=CIGlobals.getToonFont()) if base.localAvatar.hasTeleportAccess( ZoneUtil.getZoneId(name)): label['command'] = self.finished label['extraArgs'] = [ZoneUtil.getZoneId(name)] label.resetFrameSize() self.labels.append(label) currHoodName = base.cr.playGame.hood.id currLocation = '' if base.localAvatar.zoneId == CIGlobals.MinigameAreaId or base.localAvatar.getMyBattle( ) is not None: currLocation = '' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) == 'playground': currLocation = 'Playground' elif ZoneUtil.getWhereName( base.localAvatar.zoneId) in ['street', 'interior']: currLocation = CIGlobals.BranchZone2StreetName[ ZoneUtil.getBranchZone(base.localAvatar.zoneId)] self.infoLabel = DirectLabel(relief=None, text='You are in: {0}\n{1}'.format( currHoodName, currLocation), scale=0.06, pos=(-0.4, 0, -0.74), parent=self.frame, text_align=TextNode.ACenter) if currHoodName in [CIGlobals.MinigameArea, CIGlobals.BattleTTC]: currHoodName = base.cr.playGame.lastHood btpText = "Back to Playground" btpEA = [ZoneUtil.getZoneId(currHoodName)] self.BTPButton = DirectButton(relief=None, text=btpText, geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1.3, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.25, 0, -0.75), command=self.finished, extraArgs=btpEA, scale=0.7) if base.localAvatar.zoneId != CIGlobals.MinigameAreaId: self.MGAButton = DirectButton(relief=None, text="Minigame Area", geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.625, 0, -0.75), command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], scale=0.7) def exitMapPage(self): for label in self.labels: label.destroy() del self.labels for cloud in self.clouds: cloud.removeNode() del self.clouds self.frame.destroy() del self.frame self.infoLabel.destroy() del self.infoLabel self.BTPButton.destroy() del self.BTPButton if hasattr(self, 'MGAButton'): self.MGAButton.destroy() del self.MGAButton if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) self.clearTitle() def enterZonePage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle("Places") #self.home_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), # qt_btn.find('**/QuitBtn_DN'), # qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.Estate, command=self.setHood, extraArgs=[10], pos=(-0.45, 0.55, 0.55)) self.ttc_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.ToontownCentral, command=self.finished, extraArgs=[CIGlobals.ToontownCentralId], pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01)) self.tbr_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.TheBrrrgh, command=self.finished, extraArgs=[CIGlobals.TheBrrrghId], pos=(-0.45, 0.15, 0.38), text_pos=(0, -0.01)) self.ddl_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.044, text=CIGlobals.DonaldsDreamland, command=self.finished, extraArgs=[CIGlobals.DonaldsDreamlandId], pos=(-0.45, 0.15, 0.26), text_pos=(0, -0.01)) self.mml_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.0425, text=CIGlobals.MinniesMelodyland, command=self.finished, extraArgs=[CIGlobals.MinniesMelodylandId], pos=(-0.45, 0.35, 0.14), text_pos=(0, -0.01)) self.dg_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DaisyGardens, command=self.finished, extraArgs=[CIGlobals.DaisyGardensId], pos=(-0.45, 0.35, 0.02), text_pos=(0, -0.01)) self.dd_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DonaldsDock, command=self.finished, extraArgs=[CIGlobals.DonaldsDockId], pos=(-0.45, 0.35, -0.1), text_pos=(0, -0.01)) self.minigame_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.MinigameArea, command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], pos=(-0.45, 0.35, -0.34), text_pos=(0, -0.01)) #self.populationLbl = OnscreenText(text = "", pos = (0.45, 0.1), align = TextNode.ACenter) #self.popRecordLbl = OnscreenText(text = "", pos = (0.45, -0.1), align = TextNode.ACenter, scale = 0.05) #taskMgr.add(self.__updateGamePopulation, "ShtickerBook-updateGamePopulation") def __updateGamePopulation(self, task): population = 0 for district in base.cr.activeDistricts.values(): population += district.getPopulation() self.populationLbl.setText("Game Population:\n" + str(population)) recordPopulation = base.cr.myDistrict.getPopRecord() self.popRecordLbl.setText("Record Population:\n" + str(recordPopulation)) task.delayTime = 5.0 return task.again def exitZonePage(self): #taskMgr.remove("ShtickerBook-updateGamePopulation") #self.popRecordLbl.destroy() #del self.popRecordLbl #self.populationLbl.destroy() #del self.populationLbl self.dd_btn.destroy() del self.dd_btn self.ddl_btn.destroy() del self.ddl_btn self.ttc_btn.destroy() del self.ttc_btn self.tbr_btn.destroy() del self.tbr_btn self.minigame_btn.destroy() del self.minigame_btn self.mml_btn.destroy() del self.mml_btn self.dg_btn.destroy() del self.dg_btn self.deletePageButtons(True, True) self.clearTitle() def createPageButtons(self, back, fwd): if back: self.btn_prev = DirectButton( geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(-0.838, 0, -0.661), scale=(-0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[back]) self.acceptOnce('arrow_left-up', self.pageDone, [back]) if fwd: self.btn_next = DirectButton( geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(0.838, 0, -0.661), scale=(0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[fwd]) self.acceptOnce('arrow_right-up', self.pageDone, [fwd]) def deletePageButtons(self, back, fwd): if back: self.ignore('arrow_left-up') self.btn_prev.destroy() del self.btn_prev if fwd: self.ignore('arrow_right-up') self.btn_next.destroy() del self.btn_next def setTitle(self, title): self.page_title = OnscreenText(text=title, pos=(0, 0.62, 0), scale=0.12) def clearTitle(self): self.page_title.destroy() del self.page_title def enterReleaseNotesPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('mapPage', 'adminPage') else: self.createPageButtons('mapPage', None) self.setTitle("Release Notes") self.frame = DirectScrolledFrame(canvasSize=(-1, 1, -3.5, 1), frameSize=(-1, 1, -0.6, 0.6)) self.frame.setPos(0, 0, 0) self.frame.setScale(0.8) self.release_notes = DirectLabel(text=open("release_notes.txt", "r").read(), text_align=TextNode.ALeft, pos=(-0.955, 0, 0.93), relief=None, text_fg=(0, 0, 0, 1), text_wordwrap=37.0, text_scale=0.05, parent=self.frame.getCanvas()) def exitReleaseNotesPage(self): self.frame.destroy() del self.frame self.release_notes.destroy() del self.release_notes self.clearTitle() if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) def enterAdminPage(self): self.adminPageStateData = AdminPage(self, self.fsm) self.adminPageStateData.load() self.adminPageStateData.enter() def exitAdminPage(self): self.adminPageStateData.exit() self.adminPageStateData.unload() del self.adminPageStateData def pageDone(self, nextPage): base.cr.playGame.getPlace().lastBookPage = nextPage if hasattr(self, 'fsm'): self.fsm.request(nextPage) self.book_turn.play() def enterOptionPage(self): self.optionPageStateData = OptionPage(self, self.fsm) #self.acceptOnce(self.optionPageStateData.doneEvent, self.pageDone) self.optionPageStateData.load() self.optionPageStateData.enter() def exitOptionPage(self): #self.ignore(self.optionPageStateData.doneEvent) self.optionPageStateData.exit() self.optionPageStateData.unload() del self.optionPageStateData def prevPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 2: self.optionPage() elif self.currentPage == 3: self.zonePage() elif self.currentPage == 4: self.releaseNotesPage() def nextPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 1: self.zonePage() elif self.currentPage == 2: self.releaseNotesPage() elif self.currentPage == 3: self.adminPage() def clearCurrentPage(self): self.book_turn.play() for m in base.bookpgnode.getChildren(): m.removeNode() def finished(self, zone, shardId=None): if base.localAvatar.getHealth() < 1 and type(zone) == type(1): return doneStatus = {} if zone in [ CIGlobals.ToontownCentralId, CIGlobals.MinigameAreaId, CIGlobals.TheBrrrghId, CIGlobals.DonaldsDreamlandId, CIGlobals.MinniesMelodylandId, CIGlobals.DaisyGardensId, CIGlobals.DonaldsDockId ]: doneStatus["mode"] = 'teleport' doneStatus["zoneId"] = zone doneStatus["hoodId"] = ZoneUtil.getHoodId(zone) doneStatus["where"] = ZoneUtil.getWhereName(zone) doneStatus["how"] = 'teleportIn' doneStatus["avId"] = base.localAvatar.doId doneStatus["shardId"] = None doneStatus["loader"] = ZoneUtil.getLoaderName(zone) else: doneStatus["mode"] = zone if zone == "switchShard": doneStatus["shardId"] = shardId self.doneStatus = doneStatus messenger.send(self.doneEvent) def closeBook(self): self.book_close.play() base.bookpgnode.removeNode() base.booknode.removeNode()
class DistributedSuit(Suit, DistributedAvatar, DistributedSmoothNode, DelayDeletable): notify = directNotify.newCategory('DistributedSuit') def __init__(self, cr): Suit.__init__(self) DistributedAvatar.__init__(self, cr) DistributedSmoothNode.__init__(self, cr) self.anim = None self._state = SuitState.ALIVE self.dept = None self.variant = None self.suitPlan = None self.level = None self.moveIval = None self.hpFlash = None # For PythonCTMusicManager: # Are we in range of the localAvatar? self.isInRange = False self.chaseTarget = 0 self.suitFSM = ClassicFSM('DistributedSuit', [ State('off', self.enterSuitOff, self.exitSuitOff), State('walking', self.enterWalking, self.exitWalking), State('flyingDown', self.enterFlyingDown, self.exitFlyingDown), State('flyingUp', self.enterFlyingUp, self.exitFlyingUp), State('lured', self.enterLured, self.exitLured) ], 'off', 'off') self.stateIndex2suitState = {} self.suitFSM.enterInitialState() self.makeStateDict() def setChaseTarget(self, avId): if avId != base.localAvatar.doId: if self.chaseTarget == base.localAvatar.doId: messenger.send(PCTMM.getCogLostTargetEvent()) else: messenger.send(PCTMM.getCogChasingEvent()) self.chaseTarget = avId def setWalkPath(self, path, timestamp): elapsedT = globalClockDelta.localElapsedTime(timestamp) self.suitFSM.request('walking', [path, elapsedT]) def showAvId(self): self.setDisplayName(self.getName() + "\n" + str(self.doId)) def showName(self): self.setDisplayName(self.getName()) def setDisplayName(self, name): self.setupNameTag(tempName=name) def enterWalking(self, path, elapsedT): # path: A list of point2s. # # We will make a sequence of NPCWalkIntervals for each point2 in the path. self.clearMoveTrack() self.moveIval = getMoveIvalFromPath(self, path, elapsedT, True, 'suitMoveIval') self.moveIval.start(elapsedT) def clearMoveTrack(self): if self.moveIval: self.ignore(self.moveIval.getDoneEvent()) self.moveIval.pause() self.moveIval = None if not self.isDead(): self.animFSM.request('neutral') def exitWalking(self): self.clearMoveTrack() if not self.isDead(): self.animFSM.request('neutral') def enterFlyingDown(self, startIndex, endIndex, ts=0.0): if self.getHood() != '' and startIndex != -1 and endIndex != -1: duration = 3.5 startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] + (0, 0, 6.5 * 4.8) endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] self.stopMoving(finish=1) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength self.moveIval = LerpPosInterval(self, duration=timeTillLanding, pos=endPos, startPos=startPos, fluid=1) self.moveIval.start(ts) self.animFSM.request('flyDown', [ts]) def exitFlyingDown(self): self.stopMoving(finish=1) self.animFSM.request('neutral') def enterFlyingUp(self, startIndex, endIndex, ts=0.0): if self.getHood() != '': duration = 3 if startIndex > -1: startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] else: startPos = self.getPos(render) if endIndex > -1: endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[ self.getHood()][endPoint] + (0, 0, 6.5 * 4.8) else: endPos = self.getPos(render) + (0, 0, 6.5 * 4.8) self.stopMoving(finish=1) groundF = 28 dur = self.getDuration('land') fr = self.getFrameRate('land') if fr: animTimeInAir = groundF / fr else: animTimeInAir = groundF impactLength = dur - animTimeInAir timeTillLanding = 6.5 - impactLength self.moveIval = Sequence( Wait(impactLength), LerpPosInterval(self, duration=timeTillLanding, pos=endPos, startPos=startPos, fluid=1)) self.moveIval.start(ts) self.animFSM.request('flyAway', [ts, 1]) def exitFlyingUp(self): if self.moveIval: self.moveIval.finish() self.moveIval = None self.animFSM.request('neutral') def enterLured(self, _, __, ___): self.loop('lured') def exitLured(self): self.stop() def enterSuitOff(self, foo1=None, foo2=None, foo3=None): pass def exitSuitOff(self): pass def setName(self, name): Suit.setName(self, name, self.suitPlan.getName()) def setLevel(self, level): self.level = level if self.level == 12: self.maxHealth = 200 elif self.level > 0: self.maxHealth = (self.level + 1) * (self.level + 2) else: self.maxHealth = 1 self.health = self.maxHealth self.updateHealthBar(self.health) def getLevel(self): return self.level def startMoveInterval(self, startX, startY, startZ, endX, endY, endZ, duration): self.stopMoving() endPos = Point3(endX, endY, endZ) self.moveIval = NPCWalkInterval(self, endPos, durationFactor=duration, fluid=1) self.moveIval.start() def stopMoveInterval(self, andTurnAround=0): if self.moveIval: self.moveIval.pause() self.moveIval = None if andTurnAround == 1: if self.health > 0: self.animFSM.request('neutral') self.setH(self.getH() - 180) def toggleRay(self, ray=1): if ray: Suit.initializeRay(self, self.avatarType, 2) else: Suit.disableRay(self) def startProjInterval(self, startX, startY, startZ, endX, endY, endZ, duration, gravityMult, ts=0): if isinstance(ts, int) and ts != 0: ts = globalClockDelta.localElapsedTime(ts) self.disableRay() self.stopMoveInterval() startPos = Point3(startX, startY, startZ) endPos = Point3(endX, endY, endZ) oldHpr = self.getHpr(render) self.headsUp(endPos) newHpr = self.getHpr(render) self.setHpr(oldHpr) self.moveIval = Parallel( LerpHprInterval(self, duration=0.5, hpr=newHpr, startHpr=oldHpr, blendType='easeInOut'), Sequence(Func(self.animFSM.request, 'flyAway', [ts]), Wait(3.5), Func(self.animFSM.request, 'flyDown', [1.0])), Sequence( Wait(2.0), Func(self.headsUp, endPos), ProjectileInterval(self, startPos=startPos, endPos=endPos, gravityMult=gravityMult, duration=duration))) self.moveIval.start(ts) def startPosInterval(self, startX, startY, startZ, endX, endY, endZ, duration, blendType, ts=0.0): if ts != 0.0: ts = globalClockDelta.localElapsedTime(ts) self.stopMoveInterval() startPos = Point3(startX, startY, startZ) endPos = Point3(endX, endY, endZ) self.moveIval = LerpPosInterval(self, duration=duration, pos=endPos, startPos=startPos, blendType=blendType) self.moveIval.start(ts) def stopMoving(self, finish=0): if self.moveIval: if finish: self.moveIval.finish() else: self.moveIval.pause() self.moveIval = None def d_disableMovement(self, wantRay=False): self.sendUpdate('disableMovement', []) self.interruptAttack() self.stopMoving() if not wantRay: Suit.disableRay(self) def d_enableMovement(self): self.sendUpdate('enableMovement', []) Suit.initializeRay(self, self.avatarType, 2) def startRay(self): Suit.initializeRay(self, self.avatarType, 2) def setHealth(self, health): if health > self.health: # We got an hp boost. Flash green. flashColor = VBase4(0, 1, 0, 1) elif health < self.health: # We got an hp loss. Flash red. flashColor = VBase4(1, 0, 0, 1) DistributedAvatar.setHealth(self, health) def doBossFlash(): if not self.isEmpty(): LerpColorScaleInterval(self, 0.2, flashColor).start() def clearBossFlash(): if not self.isEmpty(): self.clearColorScale() if self.isDead(): self.setChaseTarget(0) base.taskMgr.remove(self.uniqueName('monitorLocalAvDistance')) if self.isInRange: messenger.send(PCTMM.getCogOutOfRangeEvent()) self.isInRange = False self.interruptAttack() if self.getLevel() > 12: if self.hpFlash: self.hpFlash.finish() self.hpFlash = None self.hpFlash = Sequence(Func(doBossFlash), Wait(0.2), Func(clearBossFlash)) self.hpFlash.start() self.updateHealthBar(health) def announceHealth(self, level, hp): DistributedAvatar.announceHealth(self, level, hp) if level == 1: healthSfx = base.audio3d.loadSfx(SuitGlobals.healedSfx) base.audio3d.attachSoundToObject(healthSfx, self) SoundInterval(healthSfx, node=self).start() del healthSfx # # 'setSuit' sets the suit type and generates it. # 'arg' is an id for a SuitPlan as defined in SuitBank or # an instance of SuitPlan. # 'variant' is an optional argument that sets the variant. # It takes an id for the variant or an instance of Variant. # Default is Variant.NORMAL. def setSuit(self, arg, variant=0): if isinstance(arg, SuitPlan): plan = arg else: plan = SuitBank.getSuitById(arg) voice = Voice.NORMAL if variant: if isinstance(variant, (int, long, float, complex)): variant = Variant.getVariantById(variant) if plan.getForcedVoice(): voice = plan.getForcedVoice() Suit.generate(self, plan, variant, voice=voice) self.suitPlan = plan self.variant = Variant.getVariantById(variant) def getSuit(self): return tuple((self.suitPlan, self.variant)) def spawn(self, startIndex, endIndex, spawnMode=SpawnMode.FLYDOWN): if spawnMode == SpawnMode.FLYDOWN: startPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[startIndex] startPos = CIGlobals.SuitSpawnPoints[ self.getHood()][startPoint] + (0, 0, 50) endPoint = CIGlobals.SuitSpawnPoints[ self.getHood()].keys()[endIndex] endPos = CIGlobals.SuitSpawnPoints[self.getHood()][endPoint] if self.moveIval: self.moveIval.finish() self.moveIval = None self.moveIval = LerpPosInterval(self, duration=3, pos=endPos, startPos=startPos, fluid=1) def makeStateDict(self): self.stateIndex2suitState = { 0: self.suitFSM.getStateNamed('off'), 1: self.suitFSM.getStateNamed('walking'), 2: self.suitFSM.getStateNamed('flyingDown'), 3: self.suitFSM.getStateNamed('flyingUp'), 4: self.suitFSM.getStateNamed('lured') } self.suitState2stateIndex = {} for stateId, state in self.stateIndex2suitState.items(): self.suitState2stateIndex[state.getName()] = stateId def setSuitState(self, index, startPoint, endPoint, timestamp=None): if timestamp != None: ts = globalClockDelta.localElapsedTime(timestamp) else: ts = 0.0 self.suitState = self.stateIndex2suitState[index] self.startPoint = startPoint self.endPoint = endPoint self.suitFSM.request(self.suitState, [startPoint, endPoint, ts]) def getSuitState(self): return self.suitState def setAnimState(self, anim, loop=1, timestamp=None): prevAnim = self.anim self.anim = anim if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) if type(anim) == types.IntType: if anim != 44 and anim != 45: anim = SuitGlobals.getAnimById(anim) animName = anim.getName() elif anim == 44: animName = 'die' elif anim == 45: animName = 'flyNeutral' elif type(anim) == types.StringType: animName = anim if self.animFSM.hasStateNamed(animName): self.animFSM.request(animName, [ts]) else: if loop: self.loop(animName) else: self.play(animName) messenger.send(SuitGlobals.animStateChangeEvent % (self.uniqueName), [anim, prevAnim]) def doAttack(self, attackId, avId, timestamp=None): if timestamp == None: ts = 0.0 else: ts = globalClockDelta.localElapsedTime(timestamp) attackName = SuitAttacks.SuitAttackLengths.keys()[attackId] attackTaunt = CIGlobals.SuitAttackTaunts[attackName][random.randint( 0, len(CIGlobals.SuitAttackTaunts[attackName]) - 1)] avatar = self.cr.doId2do.get(avId) shouldChat = 0 if self.suitPlan in [SuitBank.VicePresident, SuitBank.LucyCrossbill]: shouldChat = random.randint(0, 2) if shouldChat == 0: self.setChat(attackTaunt) self.animFSM.request('attack', [attackName, avatar, 0.0]) def throwObject(self): self.acceptOnce('enter' + self.wsnp.node().getName(), self.__handleWeaponCollision) Suit.throwObject(self) def __handleWeaponCollision(self, entry): self.sendUpdate('toonHitByWeapon', [self.attack, base.localAvatar.doId]) base.localAvatar.handleHitByWeapon(self.attack, self) self.b_handleWeaponTouch() def b_handleWeaponTouch(self): self.sendUpdate('handleWeaponTouch', []) self.handleWeaponTouch() def __monitorLocalAvDistance(self, task): if self.getDistance(base.localAvatar) <= PCTMM.getCogInRangeDistance( ) and not self.isInRange: self.isInRange = True messenger.send(PCTMM.getCogInRangeEvent()) elif self.getDistance(base.localAvatar) > PCTMM.getCogInRangeDistance( ) and self.isInRange: self.isInRange = False messenger.send(PCTMM.getCogOutOfRangeEvent()) return task.cont def announceGenerate(self): DistributedAvatar.announceGenerate(self) self.setAnimState('neutral') base.taskMgr.add(self.__monitorLocalAvDistance, self.uniqueName('monitorLocalAvDistance')) def generate(self): DistributedAvatar.generate(self) DistributedSmoothNode.generate(self) def disable(self): base.taskMgr.remove(self.uniqueName('monitorLocalAvDistance')) self.anim = None self._state = None self.dept = None self.variant = None self.suitPlan = None if self.hpFlash: self.hpFlash.finish() self.hpFlash = None if self.moveIval: self.moveIval.pause() self.moveIval = None Suit.disable(self) DistributedAvatar.disable(self) def delete(self): Suit.delete(self) del self.anim del self._state del self.dept del self.variant del self.suitPlan del self.moveIval DistributedAvatar.delete(self) DistributedSmoothNode.delete(self)
class ToonHood(Hood.Hood): def __init__(self, parentFSM, doneEvent, dnaStore, hoodId): Hood.Hood.__init__(self, parentFSM, doneEvent, dnaStore, hoodId) self.safeZoneLoader = None self.townLoader = None self.fsm = ClassicFSM('Hood', [State('off', self.enterOff, self.exitOff), State('safeZoneLoader', self.enterSafeZoneLoader, self.exitSafeZoneLoader, ['quietZone', 'townLoader']), State('townLoader', self.enterTownLoader, self.exitTownLoader, ['quietZone', 'safeZoneLoader']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['safeZoneLoader', 'townLoader'])], 'off', 'off') self.fsm.enterInitialState() return def loadLoader(self, requestStatus): loader = requestStatus['loader'] if loader == 'safeZoneLoader': if self.safeZoneLoader: self.loader = self.safeZoneLoader(self, self.fsm.getStateNamed('safeZoneLoader'), self.loaderDoneEvent) self.loader.load() else: self.notify.error('ToonHood.ToonHood.safeZoneLoader cannot be None!' % loader) elif loader == 'townLoader': if self.townLoader: self.loader = self.townLoader(self, self.fsm.getStateNamed('townLoader'), self.loaderDoneEvent) self.loader.load(requestStatus['zoneId']) else: self.notify.error('Unknown loader %s!' % loader) def enterTownLoader(self, requestStatus): self.acceptOnce(self.loaderDoneEvent, self.handleTownLoaderDone) self.loader.enter(requestStatus) self.spawnTitleText(requestStatus['zoneId']) def exitTownLoader(self): taskMgr.remove('titleText') self.hideTitleText() self.ignore(self.loaderDoneEvent) self.loader.exit() self.loader.unload() del self.loader def handleTownLoaderDone(self): doneStatus = self.loader.getDoneStatus() if self.isSameHood(doneStatus): self.fsm.request('quietZone', [doneStatus]) else: self.doneStatus = doneStatus messenger.send(self.doneEvent) def load(self): Hood.Hood.load(self) self.whiteFogColor = Vec4(0.8, 0.8, 0.8, 1) self.underwaterFogColor = Vec4(0.0, 0.0, 0.6, 1.0) def unload(self): del self.safeZoneLoader Hood.Hood.unload(self) def enter(self, requestStatus): self.loadLoader(requestStatus) Hood.Hood.enter(self, requestStatus) def exit(self): Hood.Hood.exit(self) def setUnderwaterFog(self): if base.wantFog: self.fog.setColor(self.underwaterColor) self.fog.setLinearRange(0.1, 100.0) render.setFog(self.fog) self.sky.setFog(self.fog) def setWhiteFog(self): if base.wantFog: self.fog.setColor(self.whiteFogColor) self.fog.setLinearRange(0.0, 400.0) render.clearFog() render.setFog(self.fog) self.sky.clearFog() self.sky.setFog(self.fog) def setNoFog(self): if base.wantFog: render.clearFog() self.sky.clearFog()
class ToonFPS(DirectObject): notify = directNotify.newCategory("ToonFPS") WeaponName2DamageData = {"pistol": (30.0, 10.0, 150.0, 0.3), "shotgun": (40.0, 15.0, 155.0, 0.5), "sniper": (40.0, 15.0, 155.0, 0.5)} def __init__(self, mg, weaponName = "pistol"): self.mg = mg self.weaponName = weaponName self.v_model_root = None self.v_model = None self.weapon = None self.track = None self.draw = None self.shoot = None self.reload = None self.empty = None self.cockBack = None self.cockFwd = None self.player_node = None # blach (02Aug15) # Drastically improved the accuracy of bullets... DRASTICALLY self.shooterTrav = None self.shooterRay = None self.shooterRayNode = None self.shooterHandler = None self.gui = ToonFPSGui(self) self.fsm = ClassicFSM('ToonFPS', [State('off', self.enterOff, self.exitOff), State('alive', self.enterAlive, self.exitAlive), State('dead', self.enterDead, self.exitDead)], 'off', 'off') #self.deadFSM = ClassicFSM('dead', [State('off', self.enterOff, self.exitOff), # State(']) self.aliveFSM = ClassicFSM('alive', [State('off', self.enterOff, self.exitOff), State('draw', self.enterDraw, self.exitDraw, ['idle']), State('idle', self.enterIdle, self.exitIdle, ['shoot', 'reload']), State('shoot', self.enterShoot, self.exitShoot, ['idle']), State('reload', self.enterReload, self.exitReload, ['idle'])], 'off', 'off') self.fsm.getStateNamed('alive').addChild(self.aliveFSM) #self.fsm.getStateNamed('dead').addChild(self.deadFSM) self.fsm.enterInitialState() self.aliveFSM.enterInitialState() if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 self.hp = 125 self.max_hp = 125 self.firstPerson = FirstPerson() def movementTask(self, task): if (inputState.isSet('jump') or base.localAvatar.walkControls.isAirborne): if base.localAvatar.getAnimState() != "jump": base.localAvatar.setAnimState("jump") base.localAvatar.playMovementSfx(None) self.mg.sendUpdate("jumpingAvatar", [base.localAvatar.doId]) return Task.cont def enterAlive(self): if not self.mg.fsm.getCurrentState().getName() in ['gameOver', 'announceGameOver', 'finalScores']: self.start() self.resetHp() self.resetAmmo() if self.mg.fsm.getCurrentState().getName() == "play": self.reallyStart() def exitAlive(self): self.end() self.v_model.reparentTo(hidden) if self.mg.fsm.getCurrentState().getName() != "play": self.reallyEnd() def updatePoints(self): self.points = self.kills - self.deaths def enterDead(self, killer): base.localAvatar.getGeomNode().show() self.gui.end() base.localAvatar.attachCamera() self.freezeCamSfx = base.loadSfx("phase_4/audio/sfx/freeze_cam.ogg") self.freezeCamImage = None self.freezeCamImageFile = None base.camera.setZ(base.camera.getZ() + 2.0) taskMgr.add( self.cameraLookAtKillerTask, "lookAtKiller", extraArgs = [killer], appendTask = True ) taskMgr.doMethodLater( 2.0, self.startZoomOnKiller, "startFreezeCam", extraArgs = [killer], appendTask = True ) def startZoomOnKiller(self, killer, task): taskMgr.add( self.__zoomOnKillerTask, "zoomOnKiller", extraArgs = [killer], appendTask = True ) return task.done def __zoomOnKillerTask(self, killer, task): if base.camera.getDistance(killer) <= 10.0 and self.freezeCamSfx.status() == self.freezeCamSfx.READY: base.playSfx(self.freezeCamSfx) if base.camera.getDistance(killer) < 7.0: self.doFreezeCam() return task.done base.camera.setY(base.camera, 60 * globalClock.getDt()) return task.again def doFreezeCam(self): taskMgr.remove("lookAtKiller") self.frameBuffer = PNMImage() base.win.getScreenshot(self.frameBuffer) self.freezeCamTex = Texture() self.freezeCamTex.load(self.frameBuffer) self.freezeCamImage = OnscreenImage(image = self.freezeCamTex, parent=render2d) def cameraLookAtKillerTask(self, killer, task): try: base.camera.lookAt(killer, 0, 0, 3) except AssertionError: pass return task.cont def exitDead(self): taskMgr.remove("zoomOnKiller") taskMgr.remove("lookAtKiller") taskMgr.remove("startFreezeCam") del self.freezeCamSfx if self.freezeCamImage: self.freezeCamImage.destroy() del self.freezeCamImage self.frameBuffer.clear() self.freezeCamTex.clear() del self.frameBuffer del self.freezeCamTex base.localAvatar.detachCamera() base.localAvatar.getGeomNode().hide() self.gui.start() def load(self): if self.weaponName == "pistol": self.draw = base.loadSfx("phase_4/audio/sfx/draw_secondary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/pistol_shoot.ogg") self.reload = base.loadSfx("phase_4/audio/sfx/pistol_worldreload.ogg") elif self.weaponName == "sniper": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") elif self.weaponName == "shotgun": self.draw = base.loadSfx("phase_4/audio/sfx/draw_primary.ogg") self.shoot = base.loadSfx("phase_4/audio/sfx/shotgun_shoot.ogg") self.cockBack = base.loadSfx("phase_4/audio/sfx/shotgun_cock_back.ogg") self.cockFwd = base.loadSfx("phase_4/audio/sfx/shotgun_cock_forward.ogg") self.empty = base.loadSfx("phase_4/audio/sfx/shotgun_empty.ogg") self.v_model_root = base.camera.attachNewNode('v_model_root') self.v_model = Actor('phase_4/models/minigames/v_dgm.egg', {'pidle': 'phase_4/models/minigames/v_dgm-pistol-idle.egg', 'pshoot': 'phase_4/models/minigames/v_dgm-pistol-shoot.egg', 'preload': 'phase_4/models/minigames/v_dgm-pistol-reload.egg', 'pdraw': 'phase_4/models/minigames/v_dgm-pistol-draw.egg', 'sidle': 'phase_4/models/minigames/v_dgm-shotgun-idle.egg', 'sshoot': 'phase_4/models/minigames/v_dgm-shotgun-shoot.egg'}) if self.weaponName == "pistol": self.weapon = loader.loadModel("phase_4/models/props/water-gun.bam") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.011")) self.weapon.setX(-0.125) self.weapon.setY(0.5) self.weapon.setScale(0.65) elif self.weaponName == "sniper": self.weapon = loader.loadModel("phase_4/models/props/sniper.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) elif self.weaponName == "shotgun": self.weapon = loader.loadModel("phase_4/models/props/shotgun.egg") self.weapon.reparentTo(self.v_model.exposeJoint(None, "modelRoot", "Bone.029")) self.weapon.setScale(0.75) self.weapon.setPos(0.45, -1.03, -1.17) self.weapon.setHpr(9.46, 308.19, 75.78) self.gui.load() def start(self): base.camLens.setNear(0.1) self.shooterTrav = CollisionTraverser('ToonFPS.shooterTrav') ray = CollisionRay() rayNode = CollisionNode('ToonFPS.rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask | CIGlobals.FloorBitmask) self.shooterRay = ray self.shooterRayNode = base.camera.attachNewNode(rayNode) self.shooterHandler = CollisionHandlerQueue() self.shooterTrav.addCollider(self.shooterRayNode, self.shooterHandler) self.firstPerson.start() self.v_model_root.reparentTo(base.camera) self.v_model.reparentTo(self.v_model_root) if self.weaponName == "pistol": self.v_model_root.setZ(-1.8) self.v_model_root.setY(0.3) self.v_model_root.setX(-0.1) self.v_model_root.setH(2) elif self.weaponName == "sniper": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) elif self.weaponName == "shotgun": self.v_model_root.setPos(-0.42, -0.81, -1.7) self.v_model_root.setHpr(359, 352.87, 0.00) self.gui.start() self.firstPerson.disableMouse() self.aliveFSM.request('draw') def reallyStart(self): self.firstPerson.reallyStart() base.localAvatar.startTrackAnimToSpeed() #taskMgr.add(self.movementTask, "toonBattleMovement") def end(self): if self.aliveFSM.getCurrentState().getName() != 'off': self.aliveFSM.request('off') if self.firstPerson: self.firstPerson.enableMouse() self.firstPerson.end() taskMgr.remove("toonBattleMovement") if self.mg.fsm.getCurrentState().getName() != "play": self.fsm.request('off') def reallyEnd(self): try: self.ToonFPS_reallyEnded return except: self.ToonFPS_reallyEnded = 1 if self.shooterRayNode: self.shooterRayNode.removeNode() self.shooterRayNode = None self.shooterRay = None self.shooterTrav = None self.shooterHandler = None if self.firstPerson: self.firstPerson.reallyEnd() if self.v_model_root: self.v_model_root.reparentTo(hidden) if self.v_model: self.v_model.reparentTo(hidden) self.v_model.setPosHpr(0, 0, 0, 0, 0, 0) if self.gui: self.gui.end() base.camLens.setNear(1.0) def cleanup(self): try: self.ToonFPS_cleanedUp return except: self.ToonFPS_cleanedUp = 1 taskMgr.remove("lookAtKiller") taskMgr.remove("toonBattleMovement") if self.firstPerson: self.firstPerson.cleanup() self.firstPerson = None self.draw = None self.shoot = None self.reload = None self.empty = None self.ammo = None try: self.aliveFSM.requestFinalState() self.fsm.requestFinalState() except: self.notify.warning('Redundant call to enter the final state.') self.fsm = None self.aliveFSM = None self.player_node = None self.min_camerap = None self.max_camerap = None self.hp = None self.max_hp = None if self.v_model: self.v_model.cleanup() self.v_model = None if self.weapon: self.weapon.removeNode() self.weapon = None if self.weapon: self.v_model_root.removeNode() self.v_model_root = None if self.gui: self.gui.cleanup() def damageTaken(self, amount, avId): if self.hp <= 0.0: killer = self.mg.cr.doId2do.get(avId, None) self.fsm.request('dead', [killer]) self.gui.adjustHpMeter() def enterDraw(self): self.draw.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pdraw', playRate = 1.6, name = 'drawTrack') elif self.weaponName == "shotgun": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') elif self.weaponName == "sniper": self.v_model.pose('sidle', 15) self.track = LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut', name = 'drawTrack') self.track.setDoneEvent(self.track.getName()) self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitDraw(self): #self.draw.stop() if self.track: self.ignore(self.track.getDoneEvent()) self.track.finish() self.track = None def enterIdle(self): if self.weaponName == "pistol": self.v_model.loop('pidle') elif self.weaponName == "shotgun": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() elif self.weaponName == "sniper": self.track = Sequence(LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 1, 0), startHpr = (0, 0, 0), blendType = 'easeInOut'), LerpQuatInterval(self.v_model, duration = 2.0, quat = (0, 0, 0), startHpr = (0, 1, 0), blendType = 'easeInOut')) self.track.loop() self.accept('mouse1', self.requestShoot) if self.ammo <= 0: self.gui.notifyNoAmmo() if self.ammo < 14: self.accept('r', self.aliveFSM.request, ['reload']) def requestShoot(self): if self.mg.fsm.getCurrentState().getName() != "play": return if self.ammo > 0: self.aliveFSM.request('shoot') else: self.empty.play() def exitIdle(self): self.v_model.stop() if self.track: self.track.finish() self.track = None self.ignore('mouse1') self.ignore('r') def enterShoot(self): self.shoot.play() if self.weaponName == "pistol": self.track = ActorInterval(self.v_model, 'pshoot', playRate = 2, name = 'shootTrack') elif self.weaponName == "shotgun": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) elif self.weaponName == "sniper": self.track = Parallel( Sequence( LerpQuatInterval(self.v_model, duration = 0.05, quat = (0, 3, 0), startHpr = (0, 0, 0)), LerpQuatInterval(self.v_model, duration = 0.1, quat = (0, 0, 0), startHpr = (0, 3, 0)) ), Sequence( LerpPosInterval(self.v_model, duration = 0.05, pos = (0, -0.3, 0), startPos = (0, 0, 0)), LerpPosInterval(self.v_model, duration = 0.1, pos = (0, 0, 0), startPos = (0, -0.3, 0)), Wait(0.1) ), ) self.track.setDoneEvent('shootTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() self.ammo -= 1 self.gui.adjustAmmoGui() self.mg.makeSmokeEffect(self.weapon.find('**/joint_nozzle').getPos(render)) self.traverse() def traverse(self): mpos = base.mouseWatcherNode.getMouse() self.shooterRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.shooterTrav.traverse(render) def calcDamage(self, avatar): dmgData = self.WeaponName2DamageData[self.weaponName] maxDamage = dmgData[0] minDistance = dmgData[1] maxDistance = dmgData[2] factor = dmgData[3] distance = base.localAvatar.getDistance(avatar) if distance < minDistance: distance = minDistance elif distance > maxDistance: distance = maxDistance damage = maxDamage - ((distance - minDistance) * factor) return damage def exitShoot(self): #self.shoot.stop() self.ignore('shootTrack') if self.track: self.track.finish() self.track = None def enterReload(self): self.gui.deleteNoAmmoLabel() if self.weaponName == "pistol": self.track = Parallel(Sequence(Wait(0.3), Func(self.reload.play), Func(self.resetAmmo)), ActorInterval(self.v_model, 'preload', playRate = 1.5), name = 'reloadTrack') elif self.weaponName == "shotgun": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') elif self.weaponName == "sniper": self.track = Sequence(Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (70, -50, 0), startHpr = (0, 0, 0), blendType = 'easeIn'), SoundInterval(self.cockBack), SoundInterval(self.cockFwd), Func(self.resetAmmo), Func(self.draw.play), LerpQuatInterval(self.v_model, duration = 0.5, quat = (0, 0, 0), startHpr = (70, -50, 0), blendType = 'easeOut'), name = 'reloadTrack') self.track.setDoneEvent('reloadTrack') self.acceptOnce(self.track.getDoneEvent(), self.aliveFSM.request, ['idle']) self.track.start() def exitReload(self): #self.reload.stop() self.ignore('reloadTrack') if self.track: self.track.finish() self.track = None def resetAmmo(self): if self.weaponName == "pistol": self.ammo = 14 elif self.weaponName == "shotgun": self.ammo = 7 elif self.weaponName == "sniper": self.ammo = 7 self.gui.resetAmmo() def resetHp(self): self.hp = self.max_hp self.gui.adjustHpMeter() def enterOff(self): pass def exitOff(self): pass
class ShtickerBook(StateData): def __init__(self, parentFSM, doneEvent): self.parentFSM = parentFSM StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('ShtickerBook', [State('off', self.enterOff, self.exitOff), State('optionPage', self.enterOptionPage, self.exitOptionPage, ['districtPage', 'off']), State('districtPage', self.enterDistrictPage, self.exitDistrictPage, ['optionPage', 'questPage', 'off']), State('questPage', self.enterQuestPage, self.exitQuestPage, ['inventoryPage', 'districtPage', 'off']), State('inventoryPage', self.enterInventoryPage, self.exitInventoryPage, ['mapPage', 'questPage', 'off']), State('mapPage', self.enterMapPage, self.exitMapPage, ['releaseNotesPage', 'inventoryPage', 'off']), State('releaseNotesPage', self.enterReleaseNotesPage, self.exitReleaseNotesPage, ['mapPage', 'off']), State('adminPage', self.enterAdminPage, self.exitAdminPage, ['releaseNotesPage', 'off'])], 'off', 'off') if base.localAvatar.getAdminToken() > -1: self.fsm.getStateNamed('releaseNotesPage').addTransition('adminPage') self.fsm.enterInitialState() self.entered = 0 self.parentFSM.getStateNamed('shtickerBook').addChild(self.fsm) def enterOff(self): pass def exitOff(self): pass def load(self): StateData.load(self) self.book_contents = loader.loadModel('phase_3.5/models/gui/stickerbook_gui.bam') self.book_texture = self.book_contents.find('**/big_book') self.book_open = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_open.mp3') self.book_close = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_delete.mp3') self.book_turn = loader.loadSfx('phase_3.5/audio/sfx/GUI_stickerbook_turn.mp3') def unload(self): self.book_texture.removeNode() del self.book_texture self.book_contents.removeNode() del self.book_contents loader.unloadSfx(self.book_open) del self.book_open loader.unloadSfx(self.book_close) del self.book_close loader.unloadSfx(self.book_turn) del self.book_turn del self.fsm del self.parentFSM del self.entered StateData.unload(self) def enter(self): if self.entered: return self.entered = 1 StateData.enter(self) render.hide() base.setBackgroundColor(0.05, 0.15, 0.4) self.book_img = OnscreenImage(image=self.book_texture, scale=(2, 1, 1.5)) self.book_open.play() if base.localAvatar.getAdminToken() > -1: self.fsm.request('adminPage') else: self.fsm.request('mapPage') def exit(self): if not self.entered: return self.entered = 0 base.setBackgroundColor(CIGlobals.DefaultBackgroundColor) render.show() self.book_img.destroy() del self.book_img self.book_close.play() self.fsm.request('off') StateData.exit(self) def enterDistrictPage(self): self.createPageButtons('optionPage', 'questPage') self.setTitle('Districts') currDistrictName = base.cr.myDistrict.getDistrictName() if not currDistrictName.isalpha(): currDistrictName = currDistrictName[:-1] self.infoLbl = OnscreenText(text='Each District is a copy of the Cog Invasion world.\n\n\nYou are currently in the "%s" District' % currDistrictName, pos=(0.05, 0.3), align=TextNode.ALeft, wordwrap=12) self.populationLbl = OnscreenText(text='Population: %d' % base.cr.myDistrict.getPopulation(), pos=(0.44, -0.3), align=TextNode.ACenter) textRolloverColor = Vec4(1, 1, 0, 1) textDownColor = Vec4(0.5, 0.9, 1, 1) textDisabledColor = Vec4(0.4, 0.8, 0.4, 1) self.shardButtons = [] for shard in base.cr.activeDistricts.values(): shardName = shard.getDistrictName() shardId = shard.doId btn = DirectButton(relief=None, text=shardName, text_scale=0.07, text_align=TextNode.ALeft, text1_bg=textDownColor, text2_bg=textRolloverColor, text3_fg=textDisabledColor, textMayChange=0, command=self.__handleShardButton, extraArgs=[shardId], text_pos=(0, 0, 0.0)) if shardId == base.localAvatar.parentId: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL self.shardButtons.append(btn) gui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') listXorigin = -0.02 listFrameSizeX = 0.625 listZorigin = -0.96 listFrameSizeZ = 1.04 arrowButtonScale = 1.3 itemFrameXorigin = -0.237 itemFrameZorigin = 0.365 buttonXstart = itemFrameXorigin + 0.293 self.districtList = DirectScrolledList(relief=None, pos=(-0.54, 0, 0.08), incButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), incButton_relief=None, incButton_scale=(arrowButtonScale, arrowButtonScale, -arrowButtonScale), incButton_pos=(buttonXstart, 0, itemFrameZorigin - 0.999), incButton_image3_color=Vec4(1, 1, 1, 0.2), decButton_image=(gui.find('**/FndsLst_ScrollUp'), gui.find('**/FndsLst_ScrollDN'), gui.find('**/FndsLst_ScrollUp_Rllvr'), gui.find('**/FndsLst_ScrollUp')), decButton_relief=None, decButton_scale=(arrowButtonScale, arrowButtonScale, arrowButtonScale), decButton_pos=(buttonXstart, 0, itemFrameZorigin + 0.125), decButton_image3_color=Vec4(1, 1, 1, 0.2), itemFrame_pos=(itemFrameXorigin, 0, itemFrameZorigin), itemFrame_scale=1.0, itemFrame_relief=DGG.SUNKEN, itemFrame_frameSize=(listXorigin, listXorigin + listFrameSizeX, listZorigin, listZorigin + listFrameSizeZ), itemFrame_frameColor=(0.85, 0.95, 1, 1), itemFrame_borderWidth=(0.01, 0.01), numItemsVisible=15, forceHeight=0.075, items=self.shardButtons) base.taskMgr.add(self.__updateDistrictPopTask, 'SB.updateDistrictPopTask') return def __handleShardButton(self, shardId): self.finished('switchShard', shardId) def __updateDistrictPopTask(self, task): population = base.cr.myDistrict.getPopulation() self.populationLbl.setText('Population: %d' % population) task.delayTime = 5.0 return task.again def exitDistrictPage(self): base.taskMgr.remove('SB.updateDistrictPopTask') for btn in self.shardButtons: btn.destroy() del self.shardButtons self.districtList.destroy() del self.districtList self.infoLbl.destroy() del self.infoLbl self.populationLbl.destroy() del self.populationLbl self.deletePageButtons(True, True) self.clearTitle() def enterQuestPage(self): self.createPageButtons('districtPage', 'inventoryPage') self.setTitle('Quests') self.notes = base.localAvatar.questManager.makeQuestNotes() for note in self.notes: note.show() self.infoText = OnscreenText(text='Return completed Quests to an HQ Officer at any Toon HQ building.', pos=(0, -0.6), scale=0.045) def exitQuestPage(self): self.infoText.destroy() del self.infoText for note in self.notes: note.destroy() self.deletePageButtons(True, True) self.clearTitle() def enterInventoryPage(self): self.createPageButtons('questPage', 'mapPage') self.setTitle('Gags') self.gui = BackpackGUI() self.gui.createGUI() def exitInventoryPage(self): self.gui.deleteGUI() del self.gui self.deletePageButtons(True, True) self.clearTitle() def enterMapPage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle('') themap = loader.loadModel('phase_3.5/models/gui/toontown_map.bam') self.frame = DirectFrame(parent=aspect2d, relief=None, image=themap, image_scale=(1.8, 1, 1.35), scale=0.97, pos=(0, 0, 0.0775)) cloudpos = [[(-0.61, 0, 0.18), (0.55, 0.25, 0.37), (180, 0, 0)], [(-0.54, 0, 0.34), (0.76, 0.4, 0.55), (180, 0, 0)], [(-0.55, 0, -0.09), (0.72, 0.4, 0.55), (0, 0, 0)], [(-0.67, 0, -0.51), (0.5, 0.29, 0.38), (180, 0, 0)], [(-0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.67, 0, 0.51), (0.5, 0.29, 0.38), (0, 0, 0)], [(0.35, 0, -0.46), (0.63, 0.35, 0.45), (0, 0, 0)], [(0.18, 0, -0.45), (0.52, 0.27, 0.32), (0, 0, 0)], [(0.67, 0, -0.44), (0.63, 0.35, 0.48), (180, 0, 0)]] hoodclouds = [[(0.63, 0, -0.13), (0.63, 0.35, 0.4), (0, 0, 0), CIGlobals.DonaldsDock], [(0.51, 0, 0.25), (0.57, 0.35, 0.4), (0, 0, 0), CIGlobals.TheBrrrgh], [(0.03, 0, 0.19), (0.63, 0.35, 0.4), (180, 0, 0), CIGlobals.MinniesMelodyland], [(-0.08, 0, 0.46), (0.54, 0.35, 0.4), (0, 0, 0), CIGlobals.DonaldsDreamland], [(-0.28, 0, -0.49), (0.6, 0.35, 0.45), (0, 0, 0), CIGlobals.DaisyGardens]] self.clouds = [] self.labels = [] for pos, scale, hpr in cloudpos: cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) for pos, scale, hpr, hood in hoodclouds: if not base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(hood)): cloud = loader.loadModel('phase_3.5/models/gui/cloud.bam') cloud.reparentTo(self.frame) cloud.setPos(pos) cloud.setScale(scale) cloud.setHpr(hpr) self.clouds.append(cloud) labeldata = [[(0, 0, -0.2), CIGlobals.ToontownCentral], [(0.65, 0, -0.125), CIGlobals.DonaldsDock], [(0.07, 0, 0.18), CIGlobals.MinniesMelodyland], [(-0.1, 0, 0.45), CIGlobals.DonaldsDreamland], [(0.5, 0, 0.25), CIGlobals.TheBrrrgh], [(-0.37, 0, -0.525), CIGlobals.DaisyGardens]] for pos, name in labeldata: if base.localAvatar.hasDiscoveredHood(ZoneUtil.getZoneId(name)): text = name if base.localAvatar.hasTeleportAccess(ZoneUtil.getZoneId(name)): text = 'Go To\n' + text label = DirectButton(parent=self.frame, relief=None, pos=pos, pad=(0.2, 0.16), text=('', text, text), text_bg=Vec4(1, 1, 1, 0.4), text_scale=0.055, text_wordwrap=8, rolloverSound=None, clickSound=None, pressEffect=0, sortOrder=1, text_font=CIGlobals.getToonFont()) if base.localAvatar.hasTeleportAccess(ZoneUtil.getZoneId(name)): label['command'] = self.finished label['extraArgs'] = [ZoneUtil.getZoneId(name)] label.resetFrameSize() self.labels.append(label) currHoodName = base.cr.playGame.hood.id currLocation = '' if base.localAvatar.zoneId == CIGlobals.MinigameAreaId: currLocation = '' elif base.localAvatar.getMyBattle() != None: currLocation = 'CogTropolis' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) == 'playground': currLocation = 'Playground' elif ZoneUtil.getWhereName(base.localAvatar.zoneId) in ('street', 'interior'): currLocation = CIGlobals.BranchZone2StreetName[ZoneUtil.getBranchZone(base.localAvatar.zoneId)] self.infoLabel = DirectLabel(relief=None, text='You are in: {0}\n{1}'.format(currHoodName, currLocation), scale=0.06, pos=(-0.4, 0, -0.74), parent=self.frame, text_align=TextNode.ACenter) if currHoodName in [CIGlobals.MinigameArea, CIGlobals.BattleTTC]: currHoodName = base.cr.playGame.lastHood self.BTPButton = DirectButton(relief=None, text='Back to Playground', geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1.3, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.25, 0, -0.75), command=self.finished, extraArgs=[ZoneUtil.getZoneId(currHoodName)], scale=0.7) if base.localAvatar.zoneId != CIGlobals.MinigameAreaId: self.MGAButton = DirectButton(relief=None, text='Minigame Area', geom=CIGlobals.getDefaultBtnGeom(), text_pos=(0, -0.018), geom_scale=(1, 1.11, 1.11), text_scale=0.06, parent=self.frame, text_font=CIGlobals.getToonFont(), pos=(0.625, 0, -0.75), command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], scale=0.7) return def exitMapPage(self): for label in self.labels: label.destroy() del self.labels for cloud in self.clouds: cloud.removeNode() del self.clouds self.frame.destroy() del self.frame self.infoLabel.destroy() del self.infoLabel self.BTPButton.destroy() del self.BTPButton if hasattr(self, 'MGAButton'): self.MGAButton.destroy() del self.MGAButton self.deletePageButtons(True, True) self.clearTitle() def enterZonePage(self): self.createPageButtons('inventoryPage', 'releaseNotesPage') self.setTitle('Places') self.ttc_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.ToontownCentral, command=self.finished, extraArgs=[CIGlobals.ToontownCentralId], pos=(-0.45, 0.15, 0.5), text_pos=(0, -0.01)) self.tbr_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.TheBrrrgh, command=self.finished, extraArgs=[CIGlobals.TheBrrrghId], pos=(-0.45, 0.15, 0.38), text_pos=(0, -0.01)) self.ddl_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.044, text=CIGlobals.DonaldsDreamland, command=self.finished, extraArgs=[CIGlobals.DonaldsDreamlandId], pos=(-0.45, 0.15, 0.26), text_pos=(0, -0.01)) self.mml_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.0425, text=CIGlobals.MinniesMelodyland, command=self.finished, extraArgs=[CIGlobals.MinniesMelodylandId], pos=(-0.45, 0.35, 0.14), text_pos=(0, -0.01)) self.dg_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DaisyGardens, command=self.finished, extraArgs=[CIGlobals.DaisyGardensId], pos=(-0.45, 0.35, 0.02), text_pos=(0, -0.01)) self.dd_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.045, text=CIGlobals.DonaldsDock, command=self.finished, extraArgs=[CIGlobals.DonaldsDockId], pos=(-0.45, 0.35, -0.1), text_pos=(0, -0.01)) self.minigame_btn = DirectButton(geom=(qt_btn.find('**/QuitBtn_UP'), qt_btn.find('**/QuitBtn_DN'), qt_btn.find('**/QuitBtn_RLVR')), relief=None, scale=1.2, text_scale=0.055, text=CIGlobals.MinigameArea, command=self.finished, extraArgs=[CIGlobals.MinigameAreaId], pos=(-0.45, 0.35, -0.34), text_pos=(0, -0.01)) return def __updateGamePopulation(self, task): population = 0 for district in base.cr.activeDistricts.values(): population += district.getPopulation() self.populationLbl.setText('Game Population:\n' + str(population)) recordPopulation = base.cr.myDistrict.getPopRecord() self.popRecordLbl.setText('Record Population:\n' + str(recordPopulation)) task.delayTime = 5.0 return task.again def exitZonePage(self): self.dd_btn.destroy() del self.dd_btn self.ddl_btn.destroy() del self.ddl_btn self.ttc_btn.destroy() del self.ttc_btn self.tbr_btn.destroy() del self.tbr_btn self.minigame_btn.destroy() del self.minigame_btn self.mml_btn.destroy() del self.mml_btn self.dg_btn.destroy() del self.dg_btn self.deletePageButtons(True, True) self.clearTitle() def createPageButtons(self, back, fwd): if back: self.btn_prev = DirectButton(geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(-0.838, 0, -0.661), scale=(-0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[back]) if fwd: self.btn_next = DirectButton(geom=(self.book_contents.find('**/arrow_button'), self.book_contents.find('**/arrow_down'), self.book_contents.find('**/arrow_rollover')), relief=None, pos=(0.838, 0, -0.661), scale=(0.1, 0.1, 0.1), command=self.pageDone, extraArgs=[fwd]) return def deletePageButtons(self, back, fwd): if back: self.btn_prev.destroy() del self.btn_prev if fwd: self.btn_next.destroy() del self.btn_next def setTitle(self, title): self.page_title = OnscreenText(text=title, pos=(0, 0.62, 0), scale=0.12) def clearTitle(self): self.page_title.destroy() del self.page_title def enterReleaseNotesPage(self): if base.localAvatar.getAdminToken() > -1: self.createPageButtons('mapPage', 'adminPage') else: self.createPageButtons('mapPage', None) self.setTitle('Release Notes') self.frame = DirectScrolledFrame(canvasSize=(-1, 1, -3.5, 1), frameSize=(-1, 1, -0.6, 0.6)) self.frame.setPos(0, 0, 0) self.frame.setScale(0.8) self.release_notes = DirectLabel(text=open('release_notes.txt', 'r').read(), text_align=TextNode.ALeft, pos=(-0.955, 0, 0.93), relief=None, text_fg=(0, 0, 0, 1), text_wordwrap=37.0, text_scale=0.05, parent=self.frame.getCanvas()) return def exitReleaseNotesPage(self): self.frame.destroy() del self.frame self.release_notes.destroy() del self.release_notes self.clearTitle() if base.localAvatar.getAdminToken() > -1: self.deletePageButtons(True, True) else: self.deletePageButtons(True, False) def enterAdminPage(self): self.adminPageStateData = AdminPage(self, self.fsm) self.adminPageStateData.load() self.adminPageStateData.enter() def exitAdminPage(self): self.adminPageStateData.exit() self.adminPageStateData.unload() del self.adminPageStateData def pageDone(self, nextPage): self.fsm.request(nextPage) self.book_turn.play() def enterOptionPage(self): self.optionPageStateData = OptionPage(self, self.fsm) self.optionPageStateData.load() self.optionPageStateData.enter() def exitOptionPage(self): self.optionPageStateData.exit() self.optionPageStateData.unload() del self.optionPageStateData def prevPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 2: self.optionPage() elif self.currentPage == 3: self.zonePage() elif self.currentPage == 4: self.releaseNotesPage() def nextPage(self, currentPage): self.clearCurrentPage() if self.currentPage == 1: self.zonePage() elif self.currentPage == 2: self.releaseNotesPage() elif self.currentPage == 3: self.adminPage() def clearCurrentPage(self): self.book_turn.play() for m in base.bookpgnode.getChildren(): m.removeNode() def finished(self, zone, shardId = None): if base.localAvatar.getHealth() < 1 and type(zone) == type(1): return else: doneStatus = {} if zone in [CIGlobals.ToontownCentralId, CIGlobals.MinigameAreaId, CIGlobals.TheBrrrghId, CIGlobals.DonaldsDreamlandId, CIGlobals.MinniesMelodylandId, CIGlobals.DaisyGardensId, CIGlobals.DonaldsDockId]: doneStatus['mode'] = 'teleport' doneStatus['zoneId'] = zone doneStatus['hoodId'] = ZoneUtil.getHoodId(zone) doneStatus['where'] = ZoneUtil.getWhereName(zone) doneStatus['how'] = 'teleportIn' doneStatus['avId'] = base.localAvatar.doId doneStatus['shardId'] = None doneStatus['loader'] = ZoneUtil.getLoaderName(zone) else: doneStatus['mode'] = zone if zone == 'switchShard': doneStatus['shardId'] = shardId self.doneStatus = doneStatus messenger.send(self.doneEvent) return def closeBook(self): self.book_close.play() base.bookpgnode.removeNode() base.booknode.removeNode()